2 *******************************************************************************
4 * Copyright (C) 1998-2008, 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 *******************************************************************************
32 #include "unicode/ustring.h"
33 #include "unicode/putil.h"
36 /* Number of tokens to read ahead of the current stream position */
37 #define MAX_LOOKAHEAD 3
47 #define STARTCOMMAND 0x005B
48 #define ENDCOMMAND 0x005D
49 #define OPENSQBRACKET 0x005B
50 #define CLOSESQBRACKET 0x005D
52 typedef struct SResource
*
53 ParseResourceFunction(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
);
59 struct UString comment
;
63 /* keep in sync with token defines in read.h */
64 const char *tokenNames
[TOK_TOKEN_COUNT
] =
66 "string", /* A string token, such as "MonthNames" */
67 "'{'", /* An opening brace character */
68 "'}'", /* A closing brace character */
72 "<end of file>", /* End of the file has been reached successfully */
76 /* Just to store "TRUE" */
77 static const UChar trueValue
[] = {0x0054, 0x0052, 0x0055, 0x0045, 0x0000};
79 static struct Lookahead lookahead
[MAX_LOOKAHEAD
+ 1];
80 static uint32_t lookaheadPosition
;
81 static UCHARBUF
*buffer
;
83 static struct SRBRoot
*bundle
;
84 static const char *inputdir
;
85 static uint32_t inputdirLength
;
86 static const char *outputdir
;
87 static uint32_t outputdirLength
;
89 static UBool gMakeBinaryCollation
= TRUE
;
90 static UBool gOmitCollationRules
= FALSE
;
92 static struct SResource
*parseResource(char *tag
, const struct UString
*comment
, UErrorCode
*status
);
94 /* The nature of the lookahead buffer:
95 There are MAX_LOOKAHEAD + 1 slots, used as a circular buffer. This provides
96 MAX_LOOKAHEAD lookahead tokens and a slot for the current token and value.
97 When getToken is called, the current pointer is moved to the next slot and the
98 old slot is filled with the next token from the reader by calling getNextToken.
99 The token values are stored in the slot, which means that token values don't
100 survive a call to getToken, ie.
104 getToken(&value, NULL, status);
105 getToken(NULL, NULL, status); bad - value is now a different string
108 initLookahead(UCHARBUF
*buf
, UErrorCode
*status
)
110 static uint32_t initTypeStrings
= 0;
113 if (!initTypeStrings
)
118 lookaheadPosition
= 0;
123 for (i
= 0; i
< MAX_LOOKAHEAD
; i
++)
125 lookahead
[i
].type
= getNextToken(buffer
, &lookahead
[i
].value
, &lookahead
[i
].line
, &lookahead
[i
].comment
, status
);
126 if (U_FAILURE(*status
))
132 *status
= U_ZERO_ERROR
;
139 for (i
= 0; i
< MAX_LOOKAHEAD
; i
++)
141 ustr_deinit(&lookahead
[i
].value
);
142 ustr_deinit(&lookahead
[i
].comment
);
147 static enum ETokenType
148 getToken(struct UString
**tokenValue
, struct UString
* comment
, uint32_t *linenumber
, UErrorCode
*status
)
150 enum ETokenType result
;
153 result
= lookahead
[lookaheadPosition
].type
;
155 if (tokenValue
!= NULL
)
157 *tokenValue
= &lookahead
[lookaheadPosition
].value
;
160 if (linenumber
!= NULL
)
162 *linenumber
= lookahead
[lookaheadPosition
].line
;
167 ustr_cpy(comment
, &(lookahead
[lookaheadPosition
].comment
), status
);
170 i
= (lookaheadPosition
+ MAX_LOOKAHEAD
) % (MAX_LOOKAHEAD
+ 1);
171 lookaheadPosition
= (lookaheadPosition
+ 1) % (MAX_LOOKAHEAD
+ 1);
172 ustr_setlen(&lookahead
[i
].comment
, 0, status
);
173 ustr_setlen(&lookahead
[i
].value
, 0, status
);
174 lookahead
[i
].type
= getNextToken(buffer
, &lookahead
[i
].value
, &lookahead
[i
].line
, &lookahead
[i
].comment
, status
);
176 /* printf("getToken, returning %s\n", tokenNames[result]); */
181 static enum ETokenType
182 peekToken(uint32_t lookaheadCount
, struct UString
**tokenValue
, uint32_t *linenumber
, struct UString
*comment
, UErrorCode
*status
)
184 uint32_t i
= (lookaheadPosition
+ lookaheadCount
) % (MAX_LOOKAHEAD
+ 1);
186 if (U_FAILURE(*status
))
191 if (lookaheadCount
>= MAX_LOOKAHEAD
)
193 *status
= U_INTERNAL_PROGRAM_ERROR
;
197 if (tokenValue
!= NULL
)
199 *tokenValue
= &lookahead
[i
].value
;
202 if (linenumber
!= NULL
)
204 *linenumber
= lookahead
[i
].line
;
208 ustr_cpy(comment
, &(lookahead
[lookaheadPosition
].comment
), status
);
211 return lookahead
[i
].type
;
215 expect(enum ETokenType expectedToken
, struct UString
**tokenValue
, struct UString
*comment
, uint32_t *linenumber
, UErrorCode
*status
)
219 enum ETokenType token
= getToken(tokenValue
, comment
, &line
, status
);
221 if (linenumber
!= NULL
)
226 if (U_FAILURE(*status
))
231 if (token
!= expectedToken
)
233 *status
= U_INVALID_FORMAT_ERROR
;
234 error(line
, "expecting %s, got %s", tokenNames
[expectedToken
], tokenNames
[token
]);
238 *status
= U_ZERO_ERROR
;
242 static char *getInvariantString(uint32_t *line
, struct UString
*comment
, UErrorCode
*status
)
244 struct UString
*tokenValue
;
248 expect(TOK_STRING
, &tokenValue
, comment
, line
, status
);
250 if (U_FAILURE(*status
))
255 count
= u_strlen(tokenValue
->fChars
);
256 if(!uprv_isInvariantUString(tokenValue
->fChars
, count
)) {
257 *status
= U_INVALID_FORMAT_ERROR
;
258 error(*line
, "invariant characters required for table keys, binary data, etc.");
262 result
= uprv_malloc(count
+1);
266 *status
= U_MEMORY_ALLOCATION_ERROR
;
270 u_UCharsToChars(tokenValue
->fChars
, result
, count
+1);
274 static struct SResource
*
275 parseUCARules(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
)
277 struct SResource
*result
= NULL
;
278 struct UString
*tokenValue
;
279 FileStream
*file
= NULL
;
280 char filename
[256] = { '\0' };
281 char cs
[128] = { '\0' };
284 UBool quoted
= FALSE
;
285 UCHARBUF
*ucbuf
=NULL
;
287 const char* cp
= NULL
;
288 UChar
*pTarget
= NULL
;
289 UChar
*target
= NULL
;
290 UChar
*targetLimit
= NULL
;
293 expect(TOK_STRING
, &tokenValue
, NULL
, &line
, status
);
296 printf(" %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
299 if (U_FAILURE(*status
))
303 /* make the filename including the directory */
304 if (inputdir
!= NULL
)
306 uprv_strcat(filename
, inputdir
);
308 if (inputdir
[inputdirLength
- 1] != U_FILE_SEP_CHAR
)
310 uprv_strcat(filename
, U_FILE_SEP_STRING
);
314 u_UCharsToChars(tokenValue
->fChars
, cs
, tokenValue
->fLength
);
316 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
318 if (U_FAILURE(*status
))
322 uprv_strcat(filename
, cs
);
324 if(gOmitCollationRules
) {
328 ucbuf
= ucbuf_open(filename
, &cp
, getShowWarning(),FALSE
, status
);
330 if (U_FAILURE(*status
)) {
331 error(line
, "An error occured while opening the input file %s\n", filename
);
335 /* We allocate more space than actually required
336 * since the actual size needed for storing UChars
337 * is not known in UTF-8 byte stream
339 size
= ucbuf_size(ucbuf
) + 1;
340 pTarget
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* size
);
341 uprv_memset(pTarget
, 0, size
*U_SIZEOF_UCHAR
);
343 targetLimit
= pTarget
+size
;
345 /* read the rules into the buffer */
346 while (target
< targetLimit
)
348 c
= ucbuf_getc(ucbuf
, status
);
350 quoted
= (UBool
)!quoted
;
352 /* weiv (06/26/2002): adding the following:
353 * - preserving spaces in commands [...]
354 * - # comments until the end of line
356 if (c
== STARTCOMMAND
&& !quoted
)
359 * closing bracket will be handled by the
360 * append at the end of the loop
362 while(c
!= ENDCOMMAND
) {
363 U_APPEND_CHAR32(c
, target
,len
);
364 c
= ucbuf_getc(ucbuf
, status
);
367 else if (c
== HASH
&& !quoted
) {
369 while(c
!= CR
&& c
!= LF
) {
370 c
= ucbuf_getc(ucbuf
, status
);
374 else if (c
== ESCAPE
)
376 c
= unescape(ucbuf
, status
);
381 T_FileStream_close(file
);
385 else if (!quoted
&& (c
== SPACE
|| c
== TAB
|| c
== CR
|| c
== LF
))
387 /* ignore spaces carriage returns
388 * and line feed unless in the form \uXXXX
393 /* Append UChar * after dissembling if c > 0xffff*/
396 U_APPEND_CHAR32(c
, target
,len
);
404 /* terminate the string */
405 if(target
< targetLimit
){
409 result
= string_open(bundle
, tag
, pTarget
, (int32_t)(target
- pTarget
), NULL
, status
);
414 T_FileStream_close(file
);
419 static struct SResource
*
420 parseTransliterator(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
)
422 struct SResource
*result
= NULL
;
423 struct UString
*tokenValue
;
424 FileStream
*file
= NULL
;
425 char filename
[256] = { '\0' };
426 char cs
[128] = { '\0' };
428 UCHARBUF
*ucbuf
=NULL
;
429 const char* cp
= NULL
;
430 UChar
*pTarget
= NULL
;
431 const UChar
*pSource
= NULL
;
434 expect(TOK_STRING
, &tokenValue
, NULL
, &line
, status
);
437 printf(" %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
440 if (U_FAILURE(*status
))
444 /* make the filename including the directory */
445 if (inputdir
!= NULL
)
447 uprv_strcat(filename
, inputdir
);
449 if (inputdir
[inputdirLength
- 1] != U_FILE_SEP_CHAR
)
451 uprv_strcat(filename
, U_FILE_SEP_STRING
);
455 u_UCharsToChars(tokenValue
->fChars
, cs
, tokenValue
->fLength
);
457 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
459 if (U_FAILURE(*status
))
463 uprv_strcat(filename
, cs
);
466 ucbuf
= ucbuf_open(filename
, &cp
, getShowWarning(),FALSE
, status
);
468 if (U_FAILURE(*status
)) {
469 error(line
, "An error occured while opening the input file %s\n", filename
);
473 /* We allocate more space than actually required
474 * since the actual size needed for storing UChars
475 * is not known in UTF-8 byte stream
477 pSource
= ucbuf_getBuffer(ucbuf
, &size
, status
);
478 pTarget
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* (size
+ 1));
479 uprv_memset(pTarget
, 0, size
*U_SIZEOF_UCHAR
);
481 #if !UCONFIG_NO_TRANSLITERATION
482 size
= utrans_stripRules(pSource
, size
, pTarget
, status
);
485 fprintf(stderr
, " Warning: writing empty transliteration data ( UCONFIG_NO_TRANSLITERATION ) \n");
487 result
= string_open(bundle
, tag
, pTarget
, size
, NULL
, status
);
491 T_FileStream_close(file
);
495 static struct SResource
* dependencyArray
= NULL
;
497 static struct SResource
*
498 parseDependency(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
)
500 struct SResource
*result
= NULL
;
501 struct SResource
*elem
= NULL
;
502 struct UString
*tokenValue
;
504 char filename
[256] = { '\0' };
505 char cs
[128] = { '\0' };
507 expect(TOK_STRING
, &tokenValue
, NULL
, &line
, status
);
510 printf(" %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
513 if (U_FAILURE(*status
))
517 /* make the filename including the directory */
518 if (outputdir
!= NULL
)
520 uprv_strcat(filename
, outputdir
);
522 if (outputdir
[outputdirLength
- 1] != U_FILE_SEP_CHAR
)
524 uprv_strcat(filename
, U_FILE_SEP_STRING
);
528 u_UCharsToChars(tokenValue
->fChars
, cs
, tokenValue
->fLength
);
530 if (U_FAILURE(*status
))
534 uprv_strcat(filename
, cs
);
535 if(!T_FileStream_file_exists(filename
)){
537 error(line
, "The dependency file %s does not exist. Please make sure it exists.\n",filename
);
539 warning(line
, "The dependency file %s does not exist. Please make sure it exists.\n",filename
);
542 if(dependencyArray
==NULL
){
543 dependencyArray
= array_open(bundle
, "%%DEPENDENCY", NULL
, status
);
546 result
= string_open(bundle
, tag
, tokenValue
->fChars
, tokenValue
->fLength
, comment
, status
);
548 elem
= string_open(bundle
, NULL
, tokenValue
->fChars
, tokenValue
->fLength
, comment
, status
);
550 array_add(dependencyArray
, elem
, status
);
552 if (U_FAILURE(*status
))
556 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
559 static struct SResource
*
560 parseString(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
)
562 struct UString
*tokenValue
;
563 struct SResource
*result
= NULL
;
565 /* if (tag != NULL && uprv_strcmp(tag, "%%UCARULES") == 0)
567 return parseUCARules(tag, startline, status);
570 printf(" string %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
572 expect(TOK_STRING
, &tokenValue
, NULL
, NULL
, status
);
574 if (U_SUCCESS(*status
))
576 /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
577 doesn't survive expect either) */
579 result
= string_open(bundle
, tag
, tokenValue
->fChars
, tokenValue
->fLength
, comment
, status
);
580 if(U_SUCCESS(*status
) && result
) {
581 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
583 if (U_FAILURE(*status
))
594 static struct SResource
*
595 parseAlias(char *tag
, uint32_t startline
, const struct UString
*comment
, UErrorCode
*status
)
597 struct UString
*tokenValue
;
598 struct SResource
*result
= NULL
;
600 expect(TOK_STRING
, &tokenValue
, NULL
, NULL
, status
);
603 printf(" alias %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
606 if (U_SUCCESS(*status
))
608 /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
609 doesn't survive expect either) */
611 result
= alias_open(bundle
, tag
, tokenValue
->fChars
, tokenValue
->fLength
, comment
, status
);
613 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
615 if (U_FAILURE(*status
))
625 static struct SResource
*
626 addCollation(struct SResource
*result
, uint32_t startline
, UErrorCode
*status
)
628 struct SResource
*member
= NULL
;
629 struct UString
*tokenValue
;
630 struct UString comment
;
631 enum ETokenType token
;
633 UVersionInfo version
;
634 UBool override
= FALSE
;
636 /* '{' . (name resource)* '}' */
637 version
[0]=0; version
[1]=0; version
[2]=0; version
[3]=0;
642 token
= getToken(&tokenValue
, &comment
, &line
, status
);
644 if (token
== TOK_CLOSE_BRACE
)
649 if (token
!= TOK_STRING
)
652 *status
= U_INVALID_FORMAT_ERROR
;
654 if (token
== TOK_EOF
)
656 error(startline
, "unterminated table");
660 error(line
, "Unexpected token %s", tokenNames
[token
]);
666 u_UCharsToChars(tokenValue
->fChars
, subtag
, u_strlen(tokenValue
->fChars
) + 1);
668 if (U_FAILURE(*status
))
674 member
= parseResource(subtag
, NULL
, status
);
676 if (U_FAILURE(*status
))
682 if (uprv_strcmp(subtag
, "Version") == 0)
685 int32_t length
= member
->u
.fString
.fLength
;
687 if (length
>= (int32_t) sizeof(ver
))
689 length
= (int32_t) sizeof(ver
) - 1;
692 u_UCharsToChars(member
->u
.fString
.fChars
, ver
, length
+ 1); /* +1 for copying NULL */
693 u_versionFromString(version
, ver
);
695 table_add(result
, member
, line
, status
);
698 else if (uprv_strcmp(subtag
, "Override") == 0)
702 if (u_strncmp(member
->u
.fString
.fChars
, trueValue
, u_strlen(trueValue
)) == 0)
706 table_add(result
, member
, line
, status
);
709 else if(uprv_strcmp(subtag
, "%%CollationBin")==0)
711 /* discard duplicate %%CollationBin if any*/
713 else if (uprv_strcmp(subtag
, "Sequence") == 0)
715 #if UCONFIG_NO_COLLATION
716 warning(line
, "Not building collation elements because of UCONFIG_NO_COLLATION, see uconfig.h");
718 /* in order to achieve smaller data files, we can direct genrb */
719 /* to omit collation rules */
720 if(!gOmitCollationRules
) {
721 /* first we add the "Sequence", so that we always have rules */
722 table_add(result
, member
, line
, status
);
724 if(gMakeBinaryCollation
) {
725 UErrorCode intStatus
= U_ZERO_ERROR
;
727 /* do the collation elements */
729 uint8_t *data
= NULL
;
730 UCollator
*coll
= NULL
;
731 UParseError parseError
;
733 /*table_add(result, member, line, status);*/
735 coll
= ucol_openRules(member
->u
.fString
.fChars
, member
->u
.fString
.fLength
,
736 UCOL_OFF
, UCOL_DEFAULT_STRENGTH
,&parseError
, &intStatus
);
738 if (U_SUCCESS(intStatus
) && coll
!= NULL
)
740 len
= ucol_cloneBinary(coll
, NULL
, 0, &intStatus
);
741 data
= (uint8_t *)uprv_malloc(len
);
742 intStatus
= U_ZERO_ERROR
;
743 len
= ucol_cloneBinary(coll
, data
, len
, &intStatus
);
744 /*data = ucol_cloneRuleData(coll, &len, &intStatus);*/
746 /* tailoring rules version */
748 /*coll->dataInfo.dataVersion[1] = version[0];*/
749 /* Copy tailoring version. Builder version already */
750 /* set in ucol_openRules */
751 ((UCATableHeader
*)data
)->version
[1] = version
[0];
752 ((UCATableHeader
*)data
)->version
[2] = version
[1];
753 ((UCATableHeader
*)data
)->version
[3] = version
[2];
755 if (U_SUCCESS(intStatus
) && data
!= NULL
)
757 member
= bin_open(bundle
, "%%CollationBin", len
, data
, NULL
, NULL
, status
);
758 /*table_add(bundle->fRoot, member, line, status);*/
759 table_add(result
, member
, line
, status
);
764 warning(line
, "could not obtain rules from collator");
766 *status
= U_INVALID_FORMAT_ERROR
;
775 warning(line
, "%%Collation could not be constructed from CollationElements - check context!");
783 printf("Not building Collation binary\n");
789 /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);*/
791 /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/
793 if (U_FAILURE(*status
))
801 /* A compiler warning will appear if all paths don't contain a return statement. */
802 /* *status = U_INTERNAL_PROGRAM_ERROR;
806 static struct SResource
*
807 parseCollationElements(char *tag
, uint32_t startline
, UBool newCollation
, UErrorCode
*status
)
809 struct SResource
*result
= NULL
;
810 struct SResource
*member
= NULL
;
811 struct SResource
*collationRes
= NULL
;
812 struct UString
*tokenValue
;
813 struct UString comment
;
814 enum ETokenType token
;
815 char subtag
[1024], typeKeyword
[1024];
818 result
= table_open(bundle
, tag
, NULL
, status
);
820 if (result
== NULL
|| U_FAILURE(*status
))
825 printf(" collation elements %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
828 return addCollation(result
, startline
, status
);
833 token
= getToken(&tokenValue
, &comment
, &line
, status
);
835 if (token
== TOK_CLOSE_BRACE
)
840 if (token
!= TOK_STRING
)
843 *status
= U_INVALID_FORMAT_ERROR
;
845 if (token
== TOK_EOF
)
847 error(startline
, "unterminated table");
851 error(line
, "Unexpected token %s", tokenNames
[token
]);
857 u_UCharsToChars(tokenValue
->fChars
, subtag
, u_strlen(tokenValue
->fChars
) + 1);
859 if (U_FAILURE(*status
))
865 if (uprv_strcmp(subtag
, "default") == 0)
867 member
= parseResource(subtag
, NULL
, status
);
869 if (U_FAILURE(*status
))
875 table_add(result
, member
, line
, status
);
879 token
= peekToken(0, &tokenValue
, &line
, &comment
, status
);
880 /* this probably needs to be refactored or recursively use the parser */
881 /* first we assume that our collation table won't have the explicit type */
882 /* then, we cannot handle aliases */
883 if(token
== TOK_OPEN_BRACE
) {
884 token
= getToken(&tokenValue
, &comment
, &line
, status
);
885 collationRes
= table_open(bundle
, subtag
, NULL
, status
);
886 table_add(result
, addCollation(collationRes
, startline
, status
), startline
, status
);
887 } else if(token
== TOK_COLON
) { /* right now, we'll just try to see if we have aliases */
888 /* we could have a table too */
889 token
= peekToken(1, &tokenValue
, &line
, &comment
, status
);
890 u_UCharsToChars(tokenValue
->fChars
, typeKeyword
, u_strlen(tokenValue
->fChars
) + 1);
891 if(uprv_strcmp(typeKeyword
, "alias") == 0) {
892 member
= parseResource(subtag
, NULL
, status
);
894 if (U_FAILURE(*status
))
900 table_add(result
, member
, line
, status
);
903 *status
= U_INVALID_FORMAT_ERROR
;
908 *status
= U_INVALID_FORMAT_ERROR
;
913 /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);*/
915 /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/
917 if (U_FAILURE(*status
))
926 /* Necessary, because CollationElements requires the bundle->fRoot member to be present which,
927 if this weren't special-cased, wouldn't be set until the entire file had been processed. */
928 static struct SResource
*
929 realParseTable(struct SResource
*table
, char *tag
, uint32_t startline
, UErrorCode
*status
)
931 struct SResource
*member
= NULL
;
932 struct UString
*tokenValue
=NULL
;
933 struct UString comment
;
934 enum ETokenType token
;
937 UBool readToken
= FALSE
;
939 /* '{' . (name resource)* '}' */
941 printf(" parsing table %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
946 token
= getToken(&tokenValue
, &comment
, &line
, status
);
948 if (token
== TOK_CLOSE_BRACE
)
951 warning(startline
, "Encountered empty table");
956 if (token
!= TOK_STRING
)
958 *status
= U_INVALID_FORMAT_ERROR
;
960 if (token
== TOK_EOF
)
962 error(startline
, "unterminated table");
966 error(line
, "unexpected token %s", tokenNames
[token
]);
972 if(uprv_isInvariantUString(tokenValue
->fChars
, -1)) {
973 u_UCharsToChars(tokenValue
->fChars
, subtag
, u_strlen(tokenValue
->fChars
) + 1);
975 *status
= U_INVALID_FORMAT_ERROR
;
976 error(line
, "invariant characters required for table keys");
980 if (U_FAILURE(*status
))
982 error(line
, "parse error. Stopped parsing with %s", u_errorName(*status
));
986 member
= parseResource(subtag
, &comment
, status
);
988 if (member
== NULL
|| U_FAILURE(*status
))
990 error(line
, "parse error. Stopped parsing with %s", u_errorName(*status
));
994 table_add(table
, member
, line
, status
);
996 if (U_FAILURE(*status
))
998 error(line
, "parse error. Stopped parsing with %s", u_errorName(*status
));
1002 ustr_deinit(&comment
);
1006 /* A compiler warning will appear if all paths don't contain a return statement. */
1007 /* *status = U_INTERNAL_PROGRAM_ERROR;
1011 static struct SResource
*
1012 parseTable(char *tag
, uint32_t startline
, const struct UString
*comment
, UErrorCode
*status
)
1014 struct SResource
*result
;
1016 if (tag
!= NULL
&& uprv_strcmp(tag
, "CollationElements") == 0)
1018 return parseCollationElements(tag
, startline
, FALSE
, status
);
1020 if (tag
!= NULL
&& uprv_strcmp(tag
, "collations") == 0)
1022 return parseCollationElements(tag
, startline
, TRUE
, status
);
1025 printf(" table %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1028 result
= table_open(bundle
, tag
, comment
, status
);
1030 if (result
== NULL
|| U_FAILURE(*status
))
1035 return realParseTable(result
, tag
, startline
, status
);
1038 static struct SResource
*
1039 parseArray(char *tag
, uint32_t startline
, const struct UString
*comment
, UErrorCode
*status
)
1041 struct SResource
*result
= NULL
;
1042 struct SResource
*member
= NULL
;
1043 struct UString
*tokenValue
;
1044 struct UString memberComments
;
1045 enum ETokenType token
;
1046 UBool readToken
= FALSE
;
1048 result
= array_open(bundle
, tag
, comment
, status
);
1050 if (result
== NULL
|| U_FAILURE(*status
))
1055 printf(" array %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1058 ustr_init(&memberComments
);
1060 /* '{' . resource [','] '}' */
1064 ustr_setlen(&memberComments
, 0, status
);
1066 /* check for end of array, but don't consume next token unless it really is the end */
1067 token
= peekToken(0, &tokenValue
, NULL
, &memberComments
, status
);
1070 if (token
== TOK_CLOSE_BRACE
)
1072 getToken(NULL
, NULL
, NULL
, status
);
1074 warning(startline
, "Encountered empty array");
1079 if (token
== TOK_EOF
)
1082 *status
= U_INVALID_FORMAT_ERROR
;
1083 error(startline
, "unterminated array");
1087 /* string arrays are a special case */
1088 if (token
== TOK_STRING
)
1090 getToken(&tokenValue
, &memberComments
, NULL
, status
);
1091 member
= string_open(bundle
, NULL
, tokenValue
->fChars
, tokenValue
->fLength
, &memberComments
, status
);
1095 member
= parseResource(NULL
, &memberComments
, status
);
1098 if (member
== NULL
|| U_FAILURE(*status
))
1104 array_add(result
, member
, status
);
1106 if (U_FAILURE(*status
))
1112 /* eat optional comma if present */
1113 token
= peekToken(0, NULL
, NULL
, NULL
, status
);
1115 if (token
== TOK_COMMA
)
1117 getToken(NULL
, NULL
, NULL
, status
);
1120 if (U_FAILURE(*status
))
1128 ustr_deinit(&memberComments
);
1132 static struct SResource
*
1133 parseIntVector(char *tag
, uint32_t startline
, const struct UString
*comment
, UErrorCode
*status
)
1135 struct SResource
*result
= NULL
;
1136 enum ETokenType token
;
1139 UBool readToken
= FALSE
;
1142 struct UString memberComments
;
1144 result
= intvector_open(bundle
, tag
, comment
, status
);
1146 if (result
== NULL
|| U_FAILURE(*status
))
1152 printf(" vector %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1154 ustr_init(&memberComments
);
1155 /* '{' . string [','] '}' */
1158 ustr_setlen(&memberComments
, 0, status
);
1160 /* check for end of array, but don't consume next token unless it really is the end */
1161 token
= peekToken(0, NULL
, NULL
,&memberComments
, status
);
1163 if (token
== TOK_CLOSE_BRACE
)
1165 /* it's the end, consume the close brace */
1166 getToken(NULL
, NULL
, NULL
, status
);
1168 warning(startline
, "Encountered empty int vector");
1170 ustr_deinit(&memberComments
);
1174 string
= getInvariantString(NULL
, NULL
, status
);
1176 if (U_FAILURE(*status
))
1182 /* For handling illegal char in the Intvector */
1183 value
= uprv_strtoul(string
, &stopstring
, 0);/* make intvector support decimal,hexdigit,octal digit ranging from -2^31-2^32-1*/
1184 len
=(uint32_t)(stopstring
-string
);
1186 if(len
==uprv_strlen(string
))
1188 intvector_add(result
, value
, status
);
1190 token
= peekToken(0, NULL
, NULL
, NULL
, status
);
1195 *status
=U_INVALID_CHAR_FOUND
;
1198 if (U_FAILURE(*status
))
1204 /* the comma is optional (even though it is required to prevent the reader from concatenating
1205 consecutive entries) so that a missing comma on the last entry isn't an error */
1206 if (token
== TOK_COMMA
)
1208 getToken(NULL
, NULL
, NULL
, status
);
1214 /* A compiler warning will appear if all paths don't contain a return statement. */
1215 /* intvector_close(result, status);
1216 *status = U_INTERNAL_PROGRAM_ERROR;
1220 static struct SResource
*
1221 parseBinary(char *tag
, uint32_t startline
, const struct UString
*comment
, UErrorCode
*status
)
1223 struct SResource
*result
= NULL
;
1226 char toConv
[3] = {'\0', '\0', '\0'};
1233 string
= getInvariantString(&line
, NULL
, status
);
1235 if (string
== NULL
|| U_FAILURE(*status
))
1240 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
1242 if (U_FAILURE(*status
))
1249 printf(" binary %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1252 count
= (uint32_t)uprv_strlen(string
);
1255 value
= uprv_malloc(sizeof(uint8_t) * count
);
1260 *status
= U_MEMORY_ALLOCATION_ERROR
;
1264 for (i
= 0; i
< count
; i
+= 2)
1266 toConv
[0] = string
[i
];
1267 toConv
[1] = string
[i
+ 1];
1269 value
[i
>> 1] = (uint8_t) uprv_strtoul(toConv
, &stopstring
, 16);
1270 len
=(uint32_t)(stopstring
-toConv
);
1272 if(len
!=uprv_strlen(toConv
))
1275 *status
=U_INVALID_CHAR_FOUND
;
1280 result
= bin_open(bundle
, tag
, (i
>> 1), value
,NULL
, comment
, status
);
1286 *status
= U_INVALID_CHAR_FOUND
;
1288 error(line
, "Encountered invalid binary string");
1294 result
= bin_open(bundle
, tag
, 0, NULL
, "",comment
,status
);
1295 warning(startline
, "Encountered empty binary tag");
1302 static struct SResource
*
1303 parseInteger(char *tag
, uint32_t startline
, const struct UString
*comment
, UErrorCode
*status
)
1305 struct SResource
*result
= NULL
;
1311 string
= getInvariantString(NULL
, NULL
, status
);
1313 if (string
== NULL
|| U_FAILURE(*status
))
1318 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
1320 if (U_FAILURE(*status
))
1327 printf(" integer %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1330 if (uprv_strlen(string
) <= 0)
1332 warning(startline
, "Encountered empty integer. Default value is 0.");
1335 /* Allow integer support for hexdecimal, octal digit and decimal*/
1336 /* and handle illegal char in the integer*/
1337 value
= uprv_strtoul(string
, &stopstring
, 0);
1338 len
=(uint32_t)(stopstring
-string
);
1339 if(len
==uprv_strlen(string
))
1341 result
= int_open(bundle
, tag
, value
, comment
, status
);
1345 *status
=U_INVALID_CHAR_FOUND
;
1352 static struct SResource
*
1353 parseImport(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
)
1355 struct SResource
*result
;
1361 char *fullname
= NULL
;
1362 int32_t numRead
= 0;
1363 filename
= getInvariantString(&line
, NULL
, status
);
1365 if (U_FAILURE(*status
))
1370 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
1372 if (U_FAILURE(*status
))
1374 uprv_free(filename
);
1379 printf(" import %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1382 /* Open the input file for reading */
1383 if (inputdir
== NULL
)
1387 * Always save file file name, even if there's
1388 * no input directory specified. MIGHT BREAK SOMETHING
1390 int32_t filenameLength
= uprv_strlen(filename
);
1392 fullname
= (char *) uprv_malloc(filenameLength
+ 1);
1393 uprv_strcpy(fullname
, filename
);
1396 file
= T_FileStream_open(filename
, "rb");
1401 int32_t count
= (int32_t)uprv_strlen(filename
);
1403 if (inputdir
[inputdirLength
- 1] != U_FILE_SEP_CHAR
)
1405 fullname
= (char *) uprv_malloc(inputdirLength
+ count
+ 2);
1408 if(fullname
== NULL
)
1410 *status
= U_MEMORY_ALLOCATION_ERROR
;
1414 uprv_strcpy(fullname
, inputdir
);
1416 fullname
[inputdirLength
] = U_FILE_SEP_CHAR
;
1417 fullname
[inputdirLength
+ 1] = '\0';
1419 uprv_strcat(fullname
, filename
);
1423 fullname
= (char *) uprv_malloc(inputdirLength
+ count
+ 1);
1426 if(fullname
== NULL
)
1428 *status
= U_MEMORY_ALLOCATION_ERROR
;
1432 uprv_strcpy(fullname
, inputdir
);
1433 uprv_strcat(fullname
, filename
);
1436 file
= T_FileStream_open(fullname
, "rb");
1442 error(line
, "couldn't open input file %s", filename
);
1443 *status
= U_FILE_ACCESS_ERROR
;
1447 len
= T_FileStream_size(file
);
1448 data
= (uint8_t*)uprv_malloc(len
* sizeof(uint8_t));
1452 *status
= U_MEMORY_ALLOCATION_ERROR
;
1453 T_FileStream_close (file
);
1457 numRead
= T_FileStream_read (file
, data
, len
);
1458 T_FileStream_close (file
);
1460 result
= bin_open(bundle
, tag
, len
, data
, fullname
, comment
, status
);
1463 uprv_free(filename
);
1464 uprv_free(fullname
);
1469 static struct SResource
*
1470 parseInclude(char *tag
, uint32_t startline
, const struct UString
* comment
, UErrorCode
*status
)
1472 struct SResource
*result
;
1476 UChar
*pTarget
= NULL
;
1479 char *fullname
= NULL
;
1481 const char* cp
= NULL
;
1482 const UChar
* uBuffer
= NULL
;
1484 filename
= getInvariantString(&line
, NULL
, status
);
1485 count
= (int32_t)uprv_strlen(filename
);
1487 if (U_FAILURE(*status
))
1492 expect(TOK_CLOSE_BRACE
, NULL
, NULL
, NULL
, status
);
1494 if (U_FAILURE(*status
))
1496 uprv_free(filename
);
1501 printf(" include %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1504 fullname
= (char *) uprv_malloc(inputdirLength
+ count
+ 2);
1506 if(fullname
== NULL
)
1508 *status
= U_MEMORY_ALLOCATION_ERROR
;
1509 uprv_free(filename
);
1514 if (inputdir
[inputdirLength
- 1] != U_FILE_SEP_CHAR
)
1517 uprv_strcpy(fullname
, inputdir
);
1519 fullname
[inputdirLength
] = U_FILE_SEP_CHAR
;
1520 fullname
[inputdirLength
+ 1] = '\0';
1522 uprv_strcat(fullname
, filename
);
1526 uprv_strcpy(fullname
, inputdir
);
1527 uprv_strcat(fullname
, filename
);
1530 uprv_strcpy(fullname
,filename
);
1533 ucbuf
= ucbuf_open(fullname
, &cp
,getShowWarning(),FALSE
,status
);
1535 if (U_FAILURE(*status
)) {
1536 error(line
, "couldn't open input file %s\n", filename
);
1540 uBuffer
= ucbuf_getBuffer(ucbuf
,&len
,status
);
1541 result
= string_open(bundle
, tag
, uBuffer
, len
, comment
, status
);
1545 uprv_free(filename
);
1546 uprv_free(fullname
);
1555 U_STRING_DECL(k_type_string
, "string", 6);
1556 U_STRING_DECL(k_type_binary
, "binary", 6);
1557 U_STRING_DECL(k_type_bin
, "bin", 3);
1558 U_STRING_DECL(k_type_table
, "table", 5);
1559 U_STRING_DECL(k_type_table_no_fallback
, "table(nofallback)", 17);
1560 U_STRING_DECL(k_type_int
, "int", 3);
1561 U_STRING_DECL(k_type_integer
, "integer", 7);
1562 U_STRING_DECL(k_type_array
, "array", 5);
1563 U_STRING_DECL(k_type_alias
, "alias", 5);
1564 U_STRING_DECL(k_type_intvector
, "intvector", 9);
1565 U_STRING_DECL(k_type_import
, "import", 6);
1566 U_STRING_DECL(k_type_include
, "include", 7);
1567 U_STRING_DECL(k_type_reserved
, "reserved", 8);
1569 /* Various non-standard processing plugins that create one or more special resources. */
1570 U_STRING_DECL(k_type_plugin_uca_rules
, "process(uca_rules)", 18);
1571 U_STRING_DECL(k_type_plugin_collation
, "process(collation)", 18);
1572 U_STRING_DECL(k_type_plugin_transliterator
, "process(transliterator)", 23);
1573 U_STRING_DECL(k_type_plugin_dependency
, "process(dependency)", 19);
1575 typedef enum EResourceType
1581 RT_TABLE_NO_FALLBACK
,
1588 RT_PROCESS_UCA_RULES
,
1589 RT_PROCESS_COLLATION
,
1590 RT_PROCESS_TRANSLITERATOR
,
1591 RT_PROCESS_DEPENDENCY
,
1596 const char *nameChars
; /* only used for debugging */
1597 const UChar
*nameUChars
;
1598 ParseResourceFunction
*parseFunction
;
1599 } gResourceTypes
[] = {
1600 {"Unknown", NULL
, NULL
},
1601 {"string", k_type_string
, parseString
},
1602 {"binary", k_type_binary
, parseBinary
},
1603 {"table", k_type_table
, parseTable
},
1604 {"table(nofallback)", k_type_table_no_fallback
, NULL
}, /* parseFunction will never be called */
1605 {"integer", k_type_integer
, parseInteger
},
1606 {"array", k_type_array
, parseArray
},
1607 {"alias", k_type_alias
, parseAlias
},
1608 {"intvector", k_type_intvector
, parseIntVector
},
1609 {"import", k_type_import
, parseImport
},
1610 {"include", k_type_include
, parseInclude
},
1611 {"process(uca_rules)", k_type_plugin_uca_rules
, parseUCARules
},
1612 {"process(collation)", k_type_plugin_collation
, NULL
/* not implemented yet */},
1613 {"process(transliterator)", k_type_plugin_transliterator
, parseTransliterator
},
1614 {"process(dependency)", k_type_plugin_dependency
, parseDependency
},
1615 {"reserved", NULL
, NULL
}
1618 void initParser(UBool omitBinaryCollation
, UBool omitCollationRules
)
1622 U_STRING_INIT(k_type_string
, "string", 6);
1623 U_STRING_INIT(k_type_binary
, "binary", 6);
1624 U_STRING_INIT(k_type_bin
, "bin", 3);
1625 U_STRING_INIT(k_type_table
, "table", 5);
1626 U_STRING_INIT(k_type_table_no_fallback
, "table(nofallback)", 17);
1627 U_STRING_INIT(k_type_int
, "int", 3);
1628 U_STRING_INIT(k_type_integer
, "integer", 7);
1629 U_STRING_INIT(k_type_array
, "array", 5);
1630 U_STRING_INIT(k_type_alias
, "alias", 5);
1631 U_STRING_INIT(k_type_intvector
, "intvector", 9);
1632 U_STRING_INIT(k_type_import
, "import", 6);
1633 U_STRING_INIT(k_type_reserved
, "reserved", 8);
1634 U_STRING_INIT(k_type_include
, "include", 7);
1636 U_STRING_INIT(k_type_plugin_uca_rules
, "process(uca_rules)", 18);
1637 U_STRING_INIT(k_type_plugin_collation
, "process(collation)", 18);
1638 U_STRING_INIT(k_type_plugin_transliterator
, "process(transliterator)", 23);
1639 U_STRING_INIT(k_type_plugin_dependency
, "process(dependency)", 19);
1641 for (i
= 0; i
< MAX_LOOKAHEAD
+ 1; i
++)
1643 ustr_init(&lookahead
[i
].value
);
1645 gMakeBinaryCollation
= !omitBinaryCollation
;
1646 gOmitCollationRules
= omitCollationRules
;
1649 static U_INLINE UBool
isTable(enum EResourceType type
) {
1650 return (UBool
)(type
==RT_TABLE
|| type
==RT_TABLE_NO_FALLBACK
);
1653 static enum EResourceType
1654 parseResourceType(UErrorCode
*status
)
1656 struct UString
*tokenValue
;
1657 struct UString comment
;
1658 enum EResourceType result
= RT_UNKNOWN
;
1660 ustr_init(&comment
);
1661 expect(TOK_STRING
, &tokenValue
, &comment
, &line
, status
);
1663 if (U_FAILURE(*status
))
1668 *status
= U_ZERO_ERROR
;
1670 /* Search for normal types */
1672 while (++result
< RT_RESERVED
) {
1673 if (u_strcmp(tokenValue
->fChars
, gResourceTypes
[result
].nameUChars
) == 0) {
1677 /* Now search for the aliases */
1678 if (u_strcmp(tokenValue
->fChars
, k_type_int
) == 0) {
1679 result
= RT_INTEGER
;
1681 else if (u_strcmp(tokenValue
->fChars
, k_type_bin
) == 0) {
1684 else if (result
== RT_RESERVED
) {
1685 char tokenBuffer
[1024];
1686 u_austrncpy(tokenBuffer
, tokenValue
->fChars
, sizeof(tokenBuffer
));
1687 tokenBuffer
[sizeof(tokenBuffer
) - 1] = 0;
1688 *status
= U_INVALID_FORMAT_ERROR
;
1689 error(line
, "unknown resource type '%s'", tokenBuffer
);
1695 /* parse a non-top-level resource */
1696 static struct SResource
*
1697 parseResource(char *tag
, const struct UString
*comment
, UErrorCode
*status
)
1699 enum ETokenType token
;
1700 enum EResourceType resType
= RT_UNKNOWN
;
1701 ParseResourceFunction
*parseFunction
= NULL
;
1702 struct UString
*tokenValue
;
1706 token
= getToken(&tokenValue
, NULL
, &startline
, status
);
1709 printf(" resource %s at line %i \n", (tag
== NULL
) ? "(null)" : tag
, (int)startline
);
1712 /* name . [ ':' type ] '{' resource '}' */
1713 /* This function parses from the colon onwards. If the colon is present, parse the
1714 type then try to parse a resource of that type. If there is no explicit type,
1715 work it out using the lookahead tokens. */
1719 *status
= U_INVALID_FORMAT_ERROR
;
1720 error(startline
, "Unexpected EOF encountered");
1724 *status
= U_INVALID_FORMAT_ERROR
;
1728 resType
= parseResourceType(status
);
1729 expect(TOK_OPEN_BRACE
, &tokenValue
, NULL
, &startline
, status
);
1731 if (U_FAILURE(*status
))
1738 case TOK_OPEN_BRACE
:
1742 *status
= U_INVALID_FORMAT_ERROR
;
1743 error(startline
, "syntax error while reading a resource, expected '{' or ':'");
1747 if (resType
== RT_UNKNOWN
)
1749 /* No explicit type, so try to work it out. At this point, we've read the first '{'.
1750 We could have any of the following:
1751 { { => array (nested)
1753 { string , => string array
1757 { string :/{ => table
1758 { string } => string
1761 token
= peekToken(0, NULL
, &line
, NULL
,status
);
1763 if (U_FAILURE(*status
))
1768 if (token
== TOK_OPEN_BRACE
|| token
== TOK_COLON
||token
==TOK_CLOSE_BRACE
)
1772 else if (token
== TOK_STRING
)
1774 token
= peekToken(1, NULL
, &line
, NULL
, status
);
1776 if (U_FAILURE(*status
))
1783 case TOK_COMMA
: resType
= RT_ARRAY
; break;
1784 case TOK_OPEN_BRACE
: resType
= RT_TABLE
; break;
1785 case TOK_CLOSE_BRACE
: resType
= RT_STRING
; break;
1786 case TOK_COLON
: resType
= RT_TABLE
; break;
1788 *status
= U_INVALID_FORMAT_ERROR
;
1789 error(line
, "Unexpected token after string, expected ',', '{' or '}'");
1795 *status
= U_INVALID_FORMAT_ERROR
;
1796 error(line
, "Unexpected token after '{'");
1800 /* printf("Type guessed as %s\n", resourceNames[resType]); */
1801 } else if(resType
== RT_TABLE_NO_FALLBACK
) {
1802 *status
= U_INVALID_FORMAT_ERROR
;
1803 error(startline
, "error: %s resource type not valid except on top bundle level", gResourceTypes
[resType
].nameChars
);
1807 /* We should now know what we need to parse next, so call the appropriate parser
1808 function and return. */
1809 parseFunction
= gResourceTypes
[resType
].parseFunction
;
1810 if (parseFunction
!= NULL
) {
1811 return parseFunction(tag
, startline
, comment
, status
);
1814 *status
= U_INTERNAL_PROGRAM_ERROR
;
1815 error(startline
, "internal error: %s resource type found and not handled", gResourceTypes
[resType
].nameChars
);
1821 /* parse the top-level resource */
1823 parse(UCHARBUF
*buf
, const char *inputDir
, const char *outputDir
, UErrorCode
*status
)
1825 struct UString
*tokenValue
;
1826 struct UString comment
;
1828 enum EResourceType bundleType
;
1829 enum ETokenType token
;
1831 initLookahead(buf
, status
);
1833 inputdir
= inputDir
;
1834 inputdirLength
= (inputdir
!= NULL
) ? (uint32_t)uprv_strlen(inputdir
) : 0;
1835 outputdir
= outputDir
;
1836 outputdirLength
= (outputdir
!= NULL
) ? (uint32_t)uprv_strlen(outputdir
) : 0;
1838 ustr_init(&comment
);
1839 expect(TOK_STRING
, &tokenValue
, &comment
, NULL
, status
);
1841 bundle
= bundle_open(&comment
, status
);
1843 if (bundle
== NULL
|| U_FAILURE(*status
))
1849 bundle_setlocale(bundle
, tokenValue
->fChars
, status
);
1850 /* The following code is to make Empty bundle work no matter with :table specifer or not */
1851 token
= getToken(NULL
, NULL
, &line
, status
);
1852 if(token
==TOK_COLON
) {
1853 *status
=U_ZERO_ERROR
;
1854 bundleType
=parseResourceType(status
);
1856 if(isTable(bundleType
))
1858 expect(TOK_OPEN_BRACE
, NULL
, NULL
, &line
, status
);
1862 *status
=U_PARSE_ERROR
;
1863 error(line
, "parse error. Stopped parsing with %s", u_errorName(*status
));
1869 if(token
==TOK_OPEN_BRACE
)
1871 *status
=U_ZERO_ERROR
;
1872 bundleType
=RT_TABLE
;
1876 /* neither colon nor open brace */
1877 *status
=U_PARSE_ERROR
;
1878 bundleType
=RT_UNKNOWN
;
1879 error(line
, "parse error, did not find open-brace '{' or colon ':', stopped with %s", u_errorName(*status
));
1883 if (U_FAILURE(*status
))
1885 bundle_close(bundle
, status
);
1889 if(bundleType
==RT_TABLE_NO_FALLBACK
) {
1891 * Parse a top-level table with the table(nofallback) declaration.
1892 * This is the same as a regular table, but also sets the
1893 * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] .
1895 bundle
->noFallback
=TRUE
;
1897 /* top-level tables need not handle special table names like "collations" */
1898 realParseTable(bundle
->fRoot
, NULL
, line
, status
);
1900 if(dependencyArray
!=NULL
){
1901 table_add(bundle
->fRoot
, dependencyArray
, 0, status
);
1902 dependencyArray
= NULL
;
1904 if (U_FAILURE(*status
))
1906 bundle_close(bundle
, status
);
1907 res_close(dependencyArray
);
1911 if (getToken(NULL
, NULL
, &line
, status
) != TOK_EOF
)
1913 warning(line
, "extraneous text after resource bundle (perhaps unmatched braces)");
1915 *status
= U_INVALID_FORMAT_ERROR
;
1921 ustr_deinit(&comment
);