~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/tools/genrb/read.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
*******************************************************************************
3
 
*
4
 
*   Copyright (C) 1998-2000, International Business Machines
5
 
*   Corporation and others.  All Rights Reserved.
6
 
*
7
 
*******************************************************************************
8
 
*
9
 
* File read.c
10
 
*
11
 
* Modification History:
12
 
*
13
 
*   Date        Name        Description
14
 
*   05/26/99    stephen     Creation.
15
 
*   5/10/01     Ram         removed ustdio dependency
16
 
*******************************************************************************
17
 
*/
18
 
 
19
 
#include "read.h"
20
 
#include "error.h"
21
 
#include "unicode/ustring.h"
22
 
 
23
 
#define OPENBRACE    0x007B
24
 
#define CLOSEBRACE   0x007D
25
 
#define COMMA        0x002C
26
 
#define QUOTE        0x0022
27
 
#define ESCAPE       0x005C
28
 
#define SLASH        0x002F
29
 
#define ASTERISK     0x002A
30
 
#define SPACE        0x0020
31
 
#define COLON        0x003A
32
 
#define BADBOM       0xFFFE
33
 
 
34
 
static int32_t lineCount;
35
 
 
36
 
/* Protos */
37
 
static enum ETokenType getStringToken(UCHARBUF *buf,
38
 
                                      UChar32 initialChar,
39
 
                                      struct UString *token,
40
 
                                      UErrorCode *status);
41
 
 
42
 
static UChar32 getNextChar           (UCHARBUF *buf, UBool skipwhite, UErrorCode *status);
43
 
static void    seekUntilNewline      (UCHARBUF *buf, UErrorCode *status);
44
 
static void    seekUntilEndOfComment (UCHARBUF *buf, UErrorCode *status);
45
 
static UBool   isWhitespace          (UChar32 c);
46
 
static UBool   isNewline             (UChar32 c);
47
 
 
48
 
void resetLineNumber() {
49
 
    lineCount = 1;
50
 
}
51
 
 
52
 
/* Read and return the next token from the stream.  If the token is of
53
 
   type eString, fill in the token parameter with the token.  If the
54
 
   token is eError, then the status parameter will contain the
55
 
   specific error.  This will be eItemNotFound at the end of file,
56
 
   indicating that all tokens have been returned.  This method will
57
 
   never return eString twice in a row; instead, multiple adjacent
58
 
   string tokens will be merged into one, with no intervening
59
 
   space. */
60
 
enum ETokenType getNextToken(UCHARBUF* buf,
61
 
                             struct UString *token,
62
 
                             uint32_t *linenumber, /* out: linenumber of token */
63
 
                             UErrorCode *status) {
64
 
    enum ETokenType result;
65
 
    UChar32         c;
66
 
 
67
 
    if (U_FAILURE(*status)) {
68
 
        return TOK_ERROR;
69
 
    }
70
 
 
71
 
    /* Skip whitespace */
72
 
    c = getNextChar(buf, TRUE, status);
73
 
 
74
 
    if (U_FAILURE(*status)) {
75
 
        return TOK_ERROR;
76
 
    }
77
 
 
78
 
    *linenumber = lineCount;
79
 
 
80
 
    switch(c) {
81
 
    case BADBOM:
82
 
        return TOK_ERROR;
83
 
    case OPENBRACE:
84
 
        return TOK_OPEN_BRACE;
85
 
    case CLOSEBRACE:
86
 
        return TOK_CLOSE_BRACE;
87
 
    case COMMA:
88
 
        return TOK_COMMA;
89
 
    case U_EOF:
90
 
        return TOK_EOF;
91
 
    case COLON:
92
 
        return TOK_COLON;
93
 
 
94
 
    default:
95
 
        result = getStringToken(buf, c, token, status);
96
 
    }
97
 
 
98
 
    *linenumber = lineCount;
99
 
    return result;
100
 
}
101
 
 
102
 
/* Copy a string token into the given UnicodeString.  Upon entry, we
103
 
   have already read the first character of the string token, which is
104
 
   not a whitespace character (but may be a QUOTE or ESCAPE). This
105
 
   function reads all subsequent characters that belong with this
106
 
   string, and copy them into the token parameter. The other
107
 
   important, and slightly convoluted purpose of this function is to
108
 
   merge adjacent strings.  It looks forward a bit, and if the next
109
 
   non comment, non whitespace item is a string, it reads it in as
110
 
   well.  If two adjacent strings are quoted, they are merged without
111
 
   intervening space.  Otherwise a single SPACE character is
112
 
   inserted. */
113
 
static enum ETokenType getStringToken(UCHARBUF* buf,
114
 
                                      UChar32 initialChar,
115
 
                                      struct UString *token,
116
 
                                      UErrorCode *status) {
117
 
    UBool    lastStringWasQuoted;
118
 
    UChar32  c;
119
 
    UChar    target[3] = { '\0' };
120
 
    UChar    *pTarget   = target;
121
 
    int      len=0;
122
 
    UBool    isFollowingCharEscaped=FALSE;
123
 
    /* We are guaranteed on entry that initialChar is not a whitespace
124
 
       character. If we are at the EOF, or have some other problem, it
125
 
       doesn't matter; we still want to validly return the initialChar
126
 
       (if nothing else) as a string token. */
127
 
 
128
 
    if (U_FAILURE(*status)) {
129
 
        return TOK_ERROR;
130
 
    }
131
 
 
132
 
    /* setup */
133
 
    lastStringWasQuoted = FALSE;
134
 
    c = initialChar;
135
 
    ustr_setlen(token, 0, status);
136
 
 
137
 
    if (U_FAILURE(*status)) {
138
 
        return TOK_ERROR;
139
 
    }
140
 
 
141
 
    for (;;) {
142
 
        if (c == QUOTE) {
143
 
            if (!lastStringWasQuoted && token->fLength > 0) {
144
 
                ustr_ucat(token, SPACE, status);
145
 
 
146
 
                if (U_FAILURE(*status)) {
147
 
                    return TOK_ERROR;
148
 
                }
149
 
            }
150
 
 
151
 
            lastStringWasQuoted = TRUE;
152
 
 
153
 
            for (;;) {
154
 
                c = ucbuf_getc(buf,status);
155
 
 
156
 
                /* EOF reached */
157
 
                if (c == U_EOF) {
158
 
                    return TOK_EOF;
159
 
                }
160
 
 
161
 
                /* Unterminated quoted strings */
162
 
                if (U_FAILURE(*status)) {
163
 
                    return TOK_ERROR;
164
 
                }
165
 
 
166
 
                if (c == QUOTE && !isFollowingCharEscaped) {
167
 
                    break;
168
 
                }
169
 
 
170
 
                if (c == ESCAPE) {
171
 
                    pTarget = target;
172
 
                    c       = unescape(buf, status);
173
 
 
174
 
                    if (c == U_ERR) {
175
 
                        return TOK_ERROR;
176
 
                    }
177
 
                }               
178
 
 
179
 
                if(c==ESCAPE && !isFollowingCharEscaped){
180
 
                    isFollowingCharEscaped = TRUE;
181
 
                }else{
182
 
                    U_APPEND_CHAR32(c, pTarget,len);
183
 
                    pTarget = target;
184
 
                    ustr_uscat(token, pTarget,len, status);
185
 
                    isFollowingCharEscaped = FALSE;
186
 
                    len=0;
187
 
                }
188
 
                
189
 
                if (U_FAILURE(*status)) {
190
 
                    return TOK_ERROR;
191
 
                }
192
 
            }
193
 
        } else {
194
 
            if (token->fLength > 0) {
195
 
                ustr_ucat(token, SPACE, status);
196
 
 
197
 
                if (U_FAILURE(*status)) {
198
 
                    return TOK_ERROR;
199
 
                }
200
 
            }
201
 
 
202
 
            lastStringWasQuoted = FALSE;
203
 
 
204
 
            if (c == ESCAPE) {
205
 
                pTarget = target;
206
 
                c       = unescape(buf, status);
207
 
 
208
 
                /* EOF reached */
209
 
                if (c == U_EOF) {
210
 
                    return TOK_ERROR;
211
 
                }
212
 
            }
213
 
 
214
 
            U_APPEND_CHAR32(c, pTarget,len);
215
 
            pTarget = target;
216
 
            ustr_uscat(token, pTarget,len, status);
217
 
            len=0;
218
 
 
219
 
            if (U_FAILURE(*status)) {
220
 
                return TOK_ERROR;
221
 
            }
222
 
 
223
 
            for (;;) {
224
 
                /* DON'T skip whitespace */
225
 
                c = getNextChar(buf, FALSE, status);
226
 
 
227
 
                /* EOF reached */
228
 
                if (c == U_EOF) {
229
 
                    ucbuf_ungetc(c, buf);
230
 
                    return TOK_STRING;
231
 
                }
232
 
 
233
 
                if (U_FAILURE(*status)) {
234
 
                    return TOK_STRING;
235
 
                }
236
 
 
237
 
                if (c == QUOTE
238
 
                        || c == OPENBRACE
239
 
                        || c == CLOSEBRACE
240
 
                        || c == COMMA
241
 
                        || c == COLON) {
242
 
                    ucbuf_ungetc(c, buf);
243
 
                    break;
244
 
                }
245
 
 
246
 
                if (isWhitespace(c)) {
247
 
                    break;
248
 
                }
249
 
 
250
 
                if (c == ESCAPE) {
251
 
                    pTarget = target;
252
 
                    c       = unescape(buf, status);
253
 
 
254
 
                    if (c == U_ERR) {
255
 
                        return TOK_ERROR;
256
 
                    }
257
 
                }
258
 
 
259
 
                U_APPEND_CHAR32(c, pTarget,len);
260
 
                pTarget = target;
261
 
                ustr_uscat(token, pTarget,len, status);
262
 
                len=0;
263
 
                if (U_FAILURE(*status)) {
264
 
                    return TOK_ERROR;
265
 
                }
266
 
            }
267
 
        }
268
 
 
269
 
        /* DO skip whitespace */
270
 
        c = getNextChar(buf, TRUE, status);
271
 
 
272
 
        if (U_FAILURE(*status)) {
273
 
            return TOK_STRING;
274
 
        }
275
 
 
276
 
        if (c == OPENBRACE || c == CLOSEBRACE || c == COMMA || c == COLON) {
277
 
            ucbuf_ungetc(c, buf);
278
 
            return TOK_STRING;
279
 
        }
280
 
    }
281
 
}
282
 
 
283
 
/* Retrieve the next character, ignoring comments.  If skipwhite is
284
 
   true, whitespace is skipped as well. */
285
 
static UChar32 getNextChar(UCHARBUF* buf,
286
 
                           UBool skipwhite,
287
 
                           UErrorCode *status) {
288
 
    UChar32 c;
289
 
 
290
 
    if (U_FAILURE(*status)) {
291
 
        return U_EOF;
292
 
    }
293
 
 
294
 
    for (;;) {
295
 
        c = ucbuf_getc(buf,status);
296
 
 
297
 
        if (c == U_EOF) {
298
 
            return U_EOF;
299
 
        }
300
 
 
301
 
        if (skipwhite && isWhitespace(c)) {
302
 
            continue;
303
 
        }
304
 
 
305
 
        /* This also handles the get() failing case */
306
 
        if (c != SLASH) {
307
 
            return c;
308
 
        }
309
 
 
310
 
        c = ucbuf_getc(buf,status);
311
 
 
312
 
        if (c == U_EOF) {
313
 
            return U_EOF;
314
 
        }
315
 
 
316
 
        switch (c) {
317
 
        case SLASH:
318
 
            seekUntilNewline(buf, status);
319
 
            break;
320
 
 
321
 
        case ASTERISK:
322
 
            seekUntilEndOfComment(buf, status);
323
 
            break;
324
 
 
325
 
        default:
326
 
            ucbuf_ungetc(c, buf);
327
 
            /* If get() failed this is a NOP */
328
 
            return SLASH;
329
 
        }
330
 
    }
331
 
}
332
 
 
333
 
static void seekUntilNewline(UCHARBUF* buf,
334
 
                             UErrorCode *status) {
335
 
    UChar32 c;
336
 
 
337
 
    if (U_FAILURE(*status)) {
338
 
        return;
339
 
    }
340
 
 
341
 
    do {
342
 
        c = ucbuf_getc(buf,status);
343
 
    } while (!isNewline(c) && c != U_EOF && *status == U_ZERO_ERROR);
344
 
}
345
 
 
346
 
static void seekUntilEndOfComment(UCHARBUF *buf,
347
 
                                  UErrorCode *status) {
348
 
    UChar32  c, d;
349
 
    uint32_t line;
350
 
 
351
 
    if (U_FAILURE(*status)) {
352
 
        return;
353
 
    }
354
 
 
355
 
    line = lineCount;
356
 
 
357
 
    do {
358
 
        c = ucbuf_getc(buf, status);
359
 
 
360
 
        if (c == ASTERISK) {
361
 
            d = ucbuf_getc(buf, status);
362
 
 
363
 
            if (d != SLASH) {
364
 
                ucbuf_ungetc(d, buf);
365
 
            } else {
366
 
                break;
367
 
            }
368
 
        }
369
 
    } while (c != U_EOF && *status == U_ZERO_ERROR);
370
 
 
371
 
    if (c == U_EOF) {
372
 
        *status = U_INVALID_FORMAT_ERROR;
373
 
        error(line, "unterminated comment detected");
374
 
    }
375
 
}
376
 
 
377
 
UChar32 unescape(UCHARBUF *buf,
378
 
                 UErrorCode *status) {
379
 
    if (U_FAILURE(*status)) {
380
 
        return U_EOF;
381
 
    }
382
 
 
383
 
    /* We expect to be called after the ESCAPE has been seen, but
384
 
     * u_fgetcx needs an ESCAPE to do its magic. */
385
 
    ucbuf_ungetc(ESCAPE, buf);
386
 
 
387
 
    return ucbuf_getcx(buf, status);
388
 
}
389
 
 
390
 
static UBool isWhitespace(UChar32 c) {
391
 
    switch (c) {
392
 
        /* ' ', '\t', '\n', '\r', 0x2029, 0xFEFF */
393
 
    case 0x000A:
394
 
    case 0x2029:
395
 
        lineCount++;
396
 
    case 0x000D:
397
 
    case 0x0020:
398
 
    case 0x0009:
399
 
    case 0xFEFF:
400
 
        return TRUE;
401
 
 
402
 
    default:
403
 
        return FALSE;
404
 
    }
405
 
}
406
 
 
407
 
static UBool isNewline(UChar32 c) {
408
 
    switch (c) {
409
 
        /* '\n', '\r', 0x2029 */
410
 
    case 0x000A:
411
 
    case 0x2029:
412
 
        lineCount++;
413
 
    case 0x000D:
414
 
        return TRUE;
415
 
 
416
 
    default:
417
 
        return FALSE;
418
 
    }
419
 
}