2
*******************************************************************************
4
* Copyright (C) 1998-2002, International Business Machines
5
* Corporation and others. All Rights Reserved.
7
*******************************************************************************
11
* Modification History:
13
* Date Name Description
14
* 05/26/99 stephen Creation.
15
* 02/25/00 weiv Overhaul to write udata
16
* 5/10/01 Ram removed ustdio dependency
17
* 06/10/2001 Dominic Ludlam <dom@recoil.org> Rewritten
18
*******************************************************************************
30
#include "unicode/ustring.h"
31
#include "unicode/putil.h"
33
/* Number of tokens to read ahead of the current stream position */
34
#define MAX_LOOKAHEAD 2
36
#define U_ICU_UNIDATA "unidata"
42
U_STRING_DECL(k_type_string, "string", 6);
43
U_STRING_DECL(k_type_binary, "binary", 6);
44
U_STRING_DECL(k_type_bin, "bin", 3);
45
U_STRING_DECL(k_type_table, "table", 5);
46
U_STRING_DECL(k_type_int, "int", 3);
47
U_STRING_DECL(k_type_integer, "integer", 7);
48
U_STRING_DECL(k_type_array, "array", 5);
49
U_STRING_DECL(k_type_intvector, "intvector", 9);
50
U_STRING_DECL(k_type_import, "import", 6);
51
U_STRING_DECL(k_type_reserved, "reserved", 8);
66
/* only used for debugging */
67
const char *resourceNames[] =
87
/* keep in sync with token defines in read.h */
88
const char *tokenNames[] =
90
"string", /* A string token, such as "MonthNames" */
91
"'{'", /* An opening brace character */
92
"'}'", /* A closing brace character */
96
"<end of file>", /* End of the file has been reached successfully */
97
"<error>", /* An error, such an unterminated quoted string */
100
/* Just to store "TRUE" */
101
static const UChar trueValue[] = {0x0054, 0x0052, 0x0055, 0x0045, 0x0000};
103
static struct Lookahead lookahead[MAX_LOOKAHEAD + 1];
104
static uint32_t lookaheadPosition;
105
static UCHARBUF *buffer;
107
static struct SRBRoot *bundle;
108
static const char *inputdir;
109
static uint32_t inputdirLength;
111
static struct SResource *parseResource(char *tag, UErrorCode *status);
113
void initParser(void)
117
U_STRING_INIT(k_type_string, "string", 6);
118
U_STRING_INIT(k_type_binary, "binary", 6);
119
U_STRING_INIT(k_type_bin, "bin", 3);
120
U_STRING_INIT(k_type_table, "table", 5);
121
U_STRING_INIT(k_type_int, "int", 3);
122
U_STRING_INIT(k_type_integer, "integer", 7);
123
U_STRING_INIT(k_type_array, "array", 5);
124
U_STRING_INIT(k_type_intvector, "intvector", 9);
125
U_STRING_INIT(k_type_import, "import", 6);
126
U_STRING_INIT(k_type_reserved, "reserved", 8);
128
for (i = 0; i < MAX_LOOKAHEAD + 1; i++)
130
ustr_init(&lookahead[i].value);
134
/* The nature of the lookahead buffer:
135
There are MAX_LOOKAHEAD + 1 slots, used as a circular buffer. This provides
136
MAX_LOOKAHEAD lookahead tokens and a slot for the current token and value.
137
When getToken is called, the current pointer is moved to the next slot and the
138
old slot is filled with the next token from the reader by calling getNextToken.
139
The token values are stored in the slot, which means that token values don't
140
survive a call to getToken, ie.
144
getToken(&value, NULL, status);
145
getToken(NULL, NULL, status); bad - value is now a different string
148
initLookahead(UCHARBUF *buf, UErrorCode *status)
150
static uint32_t initTypeStrings = 0;
153
if (!initTypeStrings)
158
lookaheadPosition = 0;
163
for (i = 0; i < MAX_LOOKAHEAD; i++)
165
lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, status);
167
if (U_FAILURE(*status))
173
*status = U_ZERO_ERROR;
176
static enum ETokenType
177
getToken(struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
179
enum ETokenType result;
182
result = lookahead[lookaheadPosition].type;
184
if (tokenValue != NULL)
186
*tokenValue = &lookahead[lookaheadPosition].value;
189
if (linenumber != NULL)
191
*linenumber = lookahead[lookaheadPosition].line;
194
i = (lookaheadPosition + MAX_LOOKAHEAD) % (MAX_LOOKAHEAD + 1);
195
lookaheadPosition = (lookaheadPosition + 1) % (MAX_LOOKAHEAD + 1);
196
lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, status);
198
/* printf("getToken, returning %s\n", tokenNames[result]); */
203
static enum ETokenType
204
peekToken(uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
206
uint32_t i = (lookaheadPosition + lookaheadCount) % (MAX_LOOKAHEAD + 1);
208
if (U_FAILURE(*status))
213
if (lookaheadCount >= MAX_LOOKAHEAD)
215
*status = U_INTERNAL_PROGRAM_ERROR;
219
if (tokenValue != NULL)
221
*tokenValue = &lookahead[i].value;
224
if (linenumber != NULL)
226
*linenumber = lookahead[i].line;
229
return lookahead[i].type;
233
expect(enum ETokenType expectedToken, struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
236
enum ETokenType token = getToken(tokenValue, &line, status);
238
if (U_FAILURE(*status))
243
if (linenumber != NULL)
248
if (token != expectedToken)
250
*status = U_INVALID_FORMAT_ERROR;
251
error(line, "expecting %s, got %s", tokenNames[expectedToken], tokenNames[token]);
253
else /* "else" is added by Jing/GCL */
255
*status = U_ZERO_ERROR;
259
static char *getInvariantString(uint32_t *line, UErrorCode *status)
261
struct UString *tokenValue;
265
expect(TOK_STRING, &tokenValue, line, status);
267
if (U_FAILURE(*status))
272
count = u_strlen(tokenValue->fChars) + 1;
273
result = uprv_malloc(count);
277
*status = U_MEMORY_ALLOCATION_ERROR;
281
u_UCharsToChars(tokenValue->fChars, result, count);
285
static enum EResourceType
286
parseResourceType(UErrorCode *status)
288
struct UString *tokenValue;
289
enum EResourceType result = RT_UNKNOWN;
292
expect(TOK_STRING, &tokenValue, &line, status);
294
if (U_FAILURE(*status))
299
*status = U_ZERO_ERROR;
301
if (u_strcmp(tokenValue->fChars, k_type_string) == 0) {
303
} else if (u_strcmp(tokenValue->fChars, k_type_array) == 0) {
305
} else if (u_strcmp(tokenValue->fChars, k_type_table) == 0) {
307
} else if (u_strcmp(tokenValue->fChars, k_type_binary) == 0) {
309
} else if (u_strcmp(tokenValue->fChars, k_type_bin) == 0) {
311
} else if (u_strcmp(tokenValue->fChars, k_type_int) == 0) {
313
} else if (u_strcmp(tokenValue->fChars, k_type_integer) == 0) {
315
} else if (u_strcmp(tokenValue->fChars, k_type_intvector) == 0) {
316
result = RT_INTVECTOR;
317
} else if (u_strcmp(tokenValue->fChars, k_type_import) == 0) {
319
} else if (u_strcmp(tokenValue->fChars, k_type_reserved) == 0) {
320
result = RT_RESERVED;
322
char tokenBuffer[1024];
323
u_austrncpy(tokenBuffer, tokenValue->fChars, sizeof(tokenBuffer));
324
tokenBuffer[sizeof(tokenBuffer) - 1] = 0;
325
*status = U_INVALID_FORMAT_ERROR;
326
error(line, "unknown resource type '%s'", tokenBuffer);
332
static struct SResource *
333
parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
335
struct SResource *result = NULL;
336
struct UString *tokenValue;
337
FileStream *file = NULL;
338
char filename[256] = { '\0' };
339
char cs[128] = { '\0' };
342
expect(TOK_STRING, &tokenValue, &line, status);
344
/* make the filename including the directory */
345
if (inputdir != NULL)
347
uprv_strcat(filename, inputdir);
349
if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
351
uprv_strcat(filename, U_FILE_SEP_STRING);
355
u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
357
expect(TOK_CLOSE_BRACE, NULL, NULL, status);
359
if (U_FAILURE(*status))
363
uprv_strcat(filename,"..");
364
uprv_strcat(filename,U_FILE_SEP_STRING);
365
uprv_strcat(filename, U_ICU_UNIDATA);
366
uprv_strcat(filename, U_FILE_SEP_STRING);
367
uprv_strcat(filename, cs);
370
file = T_FileStream_open(filename, "rb");
376
uint32_t size = T_FileStream_size(file);
378
/* We allocate more space than actually required
379
* since the actual size needed for storing UChars
380
* is not known in UTF-8 byte stream
382
UChar *pTarget = (UChar *) uprv_malloc(sizeof(UChar) * size);
383
UChar *target = pTarget;
384
UChar *targetLimit = pTarget + size;
386
ucbuf = ucbuf_open(file, NULL,getShowWarning(), status);
388
if (U_FAILURE(*status)) {
389
error(line, "couldn't open input file %s\n", filename);
393
/* read the rules into the buffer */
394
while (target < targetLimit)
396
c = ucbuf_getc(ucbuf, status);
400
c = unescape(ucbuf, status);
405
T_FileStream_close(file);
409
else if (c == SPACE || c == CR || c == LF)
411
/* ignore spaces carriage returns
412
* and line feed unless in the form \uXXXX
417
/* Append UChar * after dissembling if c > 0xffff*/
420
U_APPEND_CHAR32(c, target,len);
428
result = string_open(bundle, tag, pTarget, target - pTarget, status);
431
T_FileStream_close(file);
437
error(line, "couldn't open input file %s\n", filename);
438
*status = U_FILE_ACCESS_ERROR;
443
static struct SResource *
444
parseString(char *tag, uint32_t startline, UErrorCode *status)
446
struct UString *tokenValue;
447
struct SResource *result = NULL;
449
if (tag != NULL && uprv_strcmp(tag, "%%UCARULES") == 0)
451
return parseUCARules(tag, startline, status);
454
expect(TOK_STRING, &tokenValue, NULL, status);
456
if (U_SUCCESS(*status))
458
/* create the string now - tokenValue doesn't survive a call to getToken (and therefore
459
doesn't survive expect either) */
461
result = string_open(bundle, tag, tokenValue->fChars, tokenValue->fLength, status);
463
expect(TOK_CLOSE_BRACE, NULL, NULL, status);
465
if (U_FAILURE(*status))
467
string_close(result, status);
475
static struct SResource *
476
parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
478
struct SResource *result = NULL;
479
struct SResource *member = NULL;
480
struct UString *tokenValue;
481
enum ETokenType token;
483
UVersionInfo version;
484
UBool override = FALSE;
487
result = table_open(bundle, tag, status);
489
if (result == NULL || U_FAILURE(*status))
494
/* '{' . (name resource)* '}' */
497
token = getToken(&tokenValue, &line, status);
499
if (token == TOK_CLOSE_BRACE)
504
if (token != TOK_STRING)
506
table_close(result, status);
507
*status = U_INVALID_FORMAT_ERROR;
509
if (token == TOK_EOF)
511
error(startline, "unterminated table");
515
error(line, "enexpected token %s", tokenNames[token]);
521
u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
523
if (U_FAILURE(*status))
525
table_close(result, status);
529
expect(TOK_OPEN_BRACE, NULL, NULL, status);
530
expect(TOK_STRING, &tokenValue, &line, status);
532
if (U_FAILURE(*status))
534
table_close(result, status);
538
if (uprv_strcmp(subtag, "Version") == 0)
541
int32_t length = u_strlen(tokenValue->fChars);
543
if (length >= (int32_t) sizeof(ver))
545
length = (int32_t) sizeof(ver) - 1;
548
u_UCharsToChars(tokenValue->fChars, ver, length);
549
u_versionFromString(version, ver);
551
else if (uprv_strcmp(subtag, "Override") == 0)
555
if (u_strncmp(tokenValue->fChars, trueValue, u_strlen(trueValue)) == 0)
560
else if (uprv_strcmp(subtag, "Sequence") == 0)
562
UErrorCode intStatus = U_ZERO_ERROR;
564
/* do the collation elements */
566
uint8_t *data = NULL;
567
UCollator *coll = NULL;
569
UParseError parseError;
570
coll = ucol_openRules(tokenValue->fChars, tokenValue->fLength,
571
UCOL_OFF, UCOL_DEFAULT_STRENGTH,&parseError, &intStatus);
573
if (U_SUCCESS(intStatus) && coll != NULL)
575
data = ucol_cloneRuleData(coll, &len, &intStatus);
577
/* tailoring rules version */
578
coll->dataInfo.dataVersion[1] = version[0];
580
if (U_SUCCESS(intStatus) && data != NULL)
582
member = bin_open(bundle, "%%CollationBin", len, data, status);
583
table_add(bundle->fRoot, member, line, status);
588
warning(line, "could not obtain rules from collator");
595
warning(line, "%%Collation could not be constructed from CollationElements - check context!");
601
member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);
602
table_add(result, member, line, status);
604
expect(TOK_CLOSE_BRACE, NULL, NULL, status);
606
if (U_FAILURE(*status))
608
table_close(result, status);
614
*status = U_INTERNAL_PROGRAM_ERROR;
618
/* Necessary, because CollationElements requires the bundle->fRoot member to be present which,
619
if this weren't special-cased, wouldn't be set until the entire file had been processed. */
620
static struct SResource *
621
realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCode *status)
623
struct SResource *member = NULL;
624
struct UString *tokenValue;
625
enum ETokenType token;
628
UBool readToken = FALSE;
630
/* '{' . (name resource)* '}' */
633
token = getToken(&tokenValue, &line, status);
635
if (token == TOK_CLOSE_BRACE)
638
warning(startline, "Encountered empty table");
643
if (token != TOK_STRING)
645
table_close(table, status);
646
*status = U_INVALID_FORMAT_ERROR;
648
if (token == TOK_EOF)
650
error(startline, "unterminated table");
654
error(line, "enexpected token %s", tokenNames[token]);
660
u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
662
if (U_FAILURE(*status))
664
error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
665
table_close(table, status);
669
member = parseResource(subtag, status);
671
if (member == NULL || U_FAILURE(*status))
673
error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
674
table_close(table, status);
678
table_add(table, member, line, status);
680
if (U_FAILURE(*status))
682
error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
683
table_close(table, status);
690
*status = U_INTERNAL_PROGRAM_ERROR;
694
static struct SResource *
695
parseTable(char *tag, uint32_t startline, UErrorCode *status)
697
struct SResource *result;
699
if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0)
701
return parseCollationElements(tag, startline, status);
704
result = table_open(bundle, tag, status);
706
if (result == NULL || U_FAILURE(*status))
711
return realParseTable(result, tag, startline, status);
714
static struct SResource *
715
parseArray(char *tag, uint32_t startline, UErrorCode *status)
717
struct SResource *result = NULL;
718
struct SResource *member = NULL;
719
struct UString *tokenValue;
720
enum ETokenType token;
721
UBool readToken = FALSE;
723
result = array_open(bundle, tag, status);
725
if (result == NULL || U_FAILURE(*status))
730
/* '{' . resource [','] '}' */
733
/* check for end of array, but don't consume next token unless it really is the end */
734
token = peekToken(0, &tokenValue, NULL, status);
736
if (token == TOK_CLOSE_BRACE)
738
getToken(NULL, NULL, status);
740
warning(startline, "Encountered empty array");
745
if (token == TOK_EOF)
747
array_close(result, status);
748
*status = U_INVALID_FORMAT_ERROR;
749
error(startline, "unterminated array");
753
/* string arrays are a special case */
754
if (token == TOK_STRING)
756
getToken(&tokenValue, NULL, status);
757
member = string_open(bundle, NULL, tokenValue->fChars, tokenValue->fLength, status);
761
member = parseResource(NULL, status);
764
if (member == NULL || U_FAILURE(*status))
766
array_close(result, status);
770
array_add(result, member, status);
772
if (U_FAILURE(*status))
774
array_close(result, status);
778
/* eat optional comma if present */
779
token = peekToken(0, NULL, NULL, status);
781
if (token == TOK_COMMA)
783
getToken(NULL, NULL, status);
786
if (U_FAILURE(*status))
788
array_close(result, status);
797
static struct SResource *
798
parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
800
struct SResource *result = NULL;
801
enum ETokenType token;
804
UBool readToken = FALSE;
805
/* added by Jing/GCL */
809
result = intvector_open(bundle, tag, status);
811
if (result == NULL || U_FAILURE(*status))
816
/* '{' . string [','] '}' */
819
/* check for end of array, but don't consume next token unless it really is the end */
820
token = peekToken(0, NULL, NULL, status);
822
if (token == TOK_CLOSE_BRACE)
824
/* it's the end, consume the close brace */
825
getToken(NULL, NULL, status);
827
warning(startline, "Encountered empty int vector");
832
string = getInvariantString(NULL, status);
834
if (U_FAILURE(*status))
836
intvector_close(result, status);
839
/* Commented by Jing/GCL */
840
/*value = uprv_strtol(string, NULL, 10);
841
intvector_add(result, value, status);
845
token = peekToken(0, NULL, NULL, status);*/
847
/* The following is added by Jing/GCL to handle illegal char in the Intvector */
848
value = uprv_strtoul(string, &stopstring, 0);/* make intvector support decimal,hexdigit,octal digit ranging from -2^31-2^32-1*/
849
len=stopstring-string;
851
if(len==uprv_strlen(string))
853
intvector_add(result, value, status);
855
token = peekToken(0, NULL, NULL, status);
860
*status=U_INVALID_CHAR_FOUND;
862
/* The above is added by Jing/GCL */
864
if (U_FAILURE(*status))
866
intvector_close(result, status);
870
/* the comma is optional (even though it is required to prevent the reader from concatenating
871
consecutive entries) so that a missing comma on the last entry isn't an error */
872
if (token == TOK_COMMA)
874
getToken(NULL, NULL, status);
880
intvector_close(result, status);
881
*status = U_INTERNAL_PROGRAM_ERROR;
885
static struct SResource *
886
parseBinary(char *tag, uint32_t startline, UErrorCode *status)
888
struct SResource *result = NULL;
891
char toConv[3] = {'\0', '\0', '\0'};
895
/* added by Jing/GCL */
899
string = getInvariantString(&line, status);
901
if (string == NULL || U_FAILURE(*status))
906
expect(TOK_CLOSE_BRACE, NULL, NULL, status);
908
if (U_FAILURE(*status))
914
count = uprv_strlen(string);
917
value = uprv_malloc(sizeof(uint8_t) * count);
922
*status = U_MEMORY_ALLOCATION_ERROR;
926
for (i = 0; i < count; i += 2)
928
toConv[0] = string[i];
929
toConv[1] = string[i + 1];
931
value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16);
932
len=stopstring-toConv;
934
if(len!=uprv_strlen(toConv))
937
*status=U_INVALID_CHAR_FOUND;
942
result = bin_open(bundle, tag, (i >> 1), value, status);
948
*status = U_INVALID_CHAR_FOUND;
950
error(line, "Encountered invalid binary string");
956
result = bin_open(bundle, tag, 0, NULL, status);
957
warning(startline, "Encountered empty binary tag");
964
static struct SResource *
965
parseInteger(char *tag, uint32_t startline, UErrorCode *status)
967
struct SResource *result = NULL;
970
/* added by Jing/GCL */
974
string = getInvariantString(NULL, status);
976
if (string == NULL || U_FAILURE(*status))
981
expect(TOK_CLOSE_BRACE, NULL, NULL, status);
983
if (U_FAILURE(*status))
989
if (uprv_strlen(string) <= 0)
991
warning(startline, "Encountered empty integer. Default value is 0.");
994
/* commented by Jing/GCL */
995
/* value = uprv_strtol(string, NULL, 10);*/
996
/* result = int_open(bundle, tag, value, status);*/
997
/* The following is added by Jing/GCL*/
998
/* to make integer support hexdecimal, octal digit and decimal*/
999
/* to handle illegal char in the integer*/
1000
value = uprv_strtoul(string, &stopstring, 0);
1001
len=stopstring-string;
1002
if(len==uprv_strlen(string))
1004
result = int_open(bundle, tag, value, status);
1008
*status=U_INVALID_CHAR_FOUND;
1015
static struct SResource *
1016
parseImport(char *tag, uint32_t startline, UErrorCode *status)
1018
struct SResource *result;
1025
filename = getInvariantString(&line, status);
1027
if (U_FAILURE(*status))
1032
expect(TOK_CLOSE_BRACE, NULL, NULL, status);
1034
if (U_FAILURE(*status))
1036
uprv_free(filename);
1040
/* Open the input file for reading */
1041
if (inputdir == NULL)
1043
file = T_FileStream_open(filename, "rb");
1047
char *fullname = NULL;
1048
int32_t count = uprv_strlen(filename);
1050
if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
1052
fullname = (char *) uprv_malloc(inputdirLength + count + 2);
1054
uprv_strcpy(fullname, inputdir);
1056
fullname[inputdirLength] = U_FILE_SEP_CHAR;
1057
fullname[inputdirLength + 1] = '\0';
1059
uprv_strcat(fullname, filename);
1063
fullname = (char *) uprv_malloc(inputdirLength + count + 1);
1065
uprv_strcpy(fullname, inputdir);
1066
uprv_strcat(fullname, filename);
1069
file = T_FileStream_open(fullname, "rb");
1070
uprv_free(fullname);
1075
error(line, "couldn't open input file %s", filename);
1076
*status = U_FILE_ACCESS_ERROR;
1080
len = T_FileStream_size(file);
1081
data = uprv_malloc(len);
1083
T_FileStream_read (file, data, len);
1084
T_FileStream_close (file);
1086
result = bin_open(bundle, tag, len, data, status);
1089
uprv_free(filename);
1094
static struct SResource *
1095
parseResource(char *tag, UErrorCode *status)
1097
enum ETokenType token;
1098
enum EResourceType resType = RT_UNKNOWN;
1099
struct UString *tokenValue;
1103
token = getToken(&tokenValue, &startline, status);
1105
/* name . [ ':' type ] '{' resource '}' */
1106
/* This function parses from the colon onwards. If the colon is present, parse the
1107
type then try to parse a resource of that type. If there is no explicit type,
1108
work it out using the lookahead tokens. */
1112
*status = U_INVALID_FORMAT_ERROR;
1113
error(startline, "Unexpected EOF encountered");
1117
*status = U_INVALID_FORMAT_ERROR;
1121
resType = parseResourceType(status);
1122
expect(TOK_OPEN_BRACE, &tokenValue, &startline, status);
1124
if (U_FAILURE(*status))
1131
case TOK_OPEN_BRACE:
1135
*status = U_INVALID_FORMAT_ERROR;
1136
error(startline, "syntax error while reading a resource, expected '{' or ':'");
1140
if (resType == RT_UNKNOWN)
1142
/* No explicit type, so try to work it out. At this point, we've read the first '{'.
1143
We could have any of the following:
1144
{ { => array (nested)
1146
{ string , => string array
1148
commented by Jing/GCL
1153
{ string :/{ => table
1154
{ string } => string
1157
token = peekToken(0, NULL, &line, status);
1159
if (U_FAILURE(*status))
1164
/* Commented by Jing/GCL */
1165
/* if (token == TOK_OPEN_BRACE || token == TOK_COLON )*/
1166
if (token == TOK_OPEN_BRACE || token == TOK_COLON ||token ==TOK_CLOSE_BRACE )
1170
else if (token == TOK_STRING)
1172
token = peekToken(1, NULL, &line, status);
1174
if (U_FAILURE(*status))
1181
case TOK_COMMA: resType = RT_ARRAY; break;
1182
case TOK_OPEN_BRACE: resType = RT_TABLE; break;
1183
case TOK_CLOSE_BRACE: resType = RT_STRING; break;
1184
/* added by Jing/GCL to make table work when :table is omitted */
1185
case TOK_COLON: resType = RT_TABLE; break;
1187
*status = U_INVALID_FORMAT_ERROR;
1188
error(line, "Unexpected token after string, expected ',', '{' or '}'");
1194
*status = U_INVALID_FORMAT_ERROR;
1195
error(line, "Unexpected token after '{'");
1199
/* printf("Type guessed as %s\n", resourceNames[resType]); */
1202
/* We should now know what we need to parse next, so call the appropriate parser
1203
function and return. */
1206
case RT_STRING: return parseString (tag, startline, status);
1207
case RT_TABLE: return parseTable (tag, startline, status);
1208
case RT_ARRAY: return parseArray (tag, startline, status);
1209
case RT_BINARY: return parseBinary (tag, startline, status);
1210
case RT_INTEGER: return parseInteger (tag, startline, status);
1211
case RT_IMPORT: return parseImport (tag, startline, status);
1212
case RT_INTVECTOR: return parseIntVector (tag, startline, status);
1215
*status = U_INTERNAL_PROGRAM_ERROR;
1216
error(startline, "internal error: unknown resource type found and not handled");
1223
parse(UCHARBUF *buf, const char *currentInputDir, UErrorCode *status)
1225
struct UString *tokenValue;
1227
/* added by Jing/GCL */
1228
enum EResourceType bundleType;
1229
enum ETokenType token;
1231
initLookahead(buf, status);
1233
inputdir = currentInputDir;
1234
inputdirLength = (inputdir != NULL) ? uprv_strlen(inputdir) : 0;
1236
bundle = bundle_open(status);
1238
if (bundle == NULL || U_FAILURE(*status))
1243
expect(TOK_STRING, &tokenValue, NULL, status);
1244
bundle_setlocale(bundle, tokenValue->fChars, status);
1245
/* Commented by Jing/GCL */
1246
/* expect(TOK_OPEN_BRACE, NULL, &line, status); */
1247
/* The following code is to make Empty bundle work no matter with :table specifer or not */
1248
token = getToken(NULL, &line, status);
1250
if(token==TOK_COLON)
1252
*status=U_ZERO_ERROR;
1256
*status=U_PARSE_ERROR;
1259
if(U_SUCCESS(*status)){
1261
bundleType=parseResourceType(status);
1263
if(bundleType==RT_TABLE)
1265
expect(TOK_OPEN_BRACE, NULL, &line, status);
1269
*status=U_PARSE_ERROR;
1270
error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
1275
if(token==TOK_OPEN_BRACE)
1277
*status=U_ZERO_ERROR;
1281
error(line, "parse error, did not find open-brace '{' or colon ':', stopped with %s", u_errorName(*status));
1284
/* The above is added by Jing/GCL */
1286
if (U_FAILURE(*status))
1288
bundle_close(bundle, status);
1292
realParseTable(bundle->fRoot, NULL, line, status);
1294
if (U_FAILURE(*status))
1296
/* realParseTable has already closed the table */
1297
bundle->fRoot = NULL;
1298
bundle_close(bundle, status);
1302
if (getToken(NULL, &line, status) != TOK_EOF)
1304
warning(line, "extraneous text after resource bundle (perhaps unmatched braces)");