]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/genrb/parse.c
ICU-6.2.15.tar.gz
[apple/icu.git] / icuSources / tools / genrb / parse.c
index d6a641c5ed2bf3b20c7eeeead710c4b27ba74781..786bf67a477ec5621661f45674a73d536966664c 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 1998-2003, International Business Machines
+*   Copyright (C) 1998-2004, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -24,6 +24,7 @@
 #include "uhash.h"
 #include "cmemory.h"
 #include "cstring.h"
+#include "uinvchar.h"
 #include "read.h"
 #include "ustr.h"
 #include "reslist.h"
 #include "unicode/putil.h"
 
 /* Number of tokens to read ahead of the current stream position */
-#define MAX_LOOKAHEAD   2
+#define MAX_LOOKAHEAD   3
 
 #define U_ICU_UNIDATA   "unidata"
 #define CR               0x000D
 #define LF               0x000A
 #define SPACE            0x0020
+#define TAB              0x0009
 #define ESCAPE           0x005C
 #define HASH             0x0023
 #define QUOTE            0x0027
@@ -90,12 +92,13 @@ const char *resourceNames[] =
 struct Lookahead
 {
      enum   ETokenType type;
-     struct UString     value;
-     uint32_t            line;
+     struct UString    value;
+     struct UString    comment;
+     uint32_t          line;
 };
 
 /* keep in sync with token defines in read.h */
-const char *tokenNames[] =
+const char *tokenNames[TOK_TOKEN_COUNT] =
 {
      "string",             /* A string token, such as "MonthNames" */
      "'{'",                 /* An opening brace character */
@@ -104,7 +107,7 @@ const char *tokenNames[] =
      "':'",                 /* A colon */
 
      "<end of file>",     /* End of the file has been reached successfully */
-     "<error>",            /* An error, such an unterminated quoted string */
+     "<end of line>"
 };
 
 /* Just to store "TRUE" */
@@ -120,7 +123,7 @@ static uint32_t        inputdirLength;
 
 static UBool gMakeBinaryCollation = TRUE;
 
-static struct SResource *parseResource(char *tag, UErrorCode *status);
+static struct SResource *parseResource(char *tag, const struct UString *comment, UErrorCode *status);
 
 void initParser(UBool makeBinaryCollation)
 {
@@ -176,8 +179,7 @@ initLookahead(UCHARBUF *buf, UErrorCode *status)
 
     for (i = 0; i < MAX_LOOKAHEAD; i++)
     {
-        lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, status);
-
+        lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, &lookahead[i].comment, status);
         if (U_FAILURE(*status))
         {
             return;
@@ -188,7 +190,7 @@ initLookahead(UCHARBUF *buf, UErrorCode *status)
 }
 
 static enum ETokenType
-getToken(struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
+getToken(struct UString **tokenValue, struct UString* comment, uint32_t *linenumber, UErrorCode *status)
 {
     enum ETokenType result;
     uint32_t          i;
@@ -205,9 +207,16 @@ getToken(struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
         *linenumber = lookahead[lookaheadPosition].line;
     }
 
+    if (comment != NULL)
+    {
+        ustr_cpy(comment, &(lookahead[lookaheadPosition].comment), status);
+    }
+
     i = (lookaheadPosition + MAX_LOOKAHEAD) % (MAX_LOOKAHEAD + 1);
     lookaheadPosition = (lookaheadPosition + 1) % (MAX_LOOKAHEAD + 1);
-    lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, status);
+    ustr_setlen(&lookahead[i].comment, 0, status);
+    ustr_setlen(&lookahead[i].value, 0, status);
+    lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, &lookahead[i].comment, status);
 
     /* printf("getToken, returning %s\n", tokenNames[result]); */
 
@@ -215,7 +224,7 @@ getToken(struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
 }
 
 static enum ETokenType
-peekToken(uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
+peekToken(uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, struct UString *comment, UErrorCode *status)
 {
     uint32_t i = (lookaheadPosition + lookaheadCount) % (MAX_LOOKAHEAD + 1);
 
@@ -240,14 +249,19 @@ peekToken(uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenu
         *linenumber = lookahead[i].line;
     }
 
+    if(comment != NULL){
+        ustr_cpy(comment, &(lookahead[lookaheadPosition].comment), status);
+    }
+
     return lookahead[i].type;
 }
 
 static void
-expect(enum ETokenType expectedToken, struct UString **tokenValue, uint32_t *linenumber, UErrorCode *status)
+expect(enum ETokenType expectedToken, struct UString **tokenValue, struct UString *comment, uint32_t *linenumber, UErrorCode *status)
 {
     uint32_t        line;
-    enum ETokenType token = getToken(tokenValue, &line, status);
+
+    enum ETokenType token = getToken(tokenValue, comment, &line, status);
 
     if (U_FAILURE(*status))
     {
@@ -270,21 +284,27 @@ expect(enum ETokenType expectedToken, struct UString **tokenValue, uint32_t *lin
     }
 }
 
-static char *getInvariantString(uint32_t *line, UErrorCode *status)
+static char *getInvariantString(uint32_t *line, struct UString *comment, UErrorCode *status)
 {
     struct UString *tokenValue;
     char           *result;
     uint32_t        count;
 
-    expect(TOK_STRING, &tokenValue, line, status);
+    expect(TOK_STRING, &tokenValue, comment, line, status);
 
     if (U_FAILURE(*status))
     {
         return NULL;
     }
 
-    count  = u_strlen(tokenValue->fChars) + 1;
-    result = uprv_malloc(count);
+    count = u_strlen(tokenValue->fChars);
+    if(!uprv_isInvariantUString(tokenValue->fChars, count)) {
+        *status = U_INVALID_FORMAT_ERROR;
+        error(*line, "invariant characters required for table keys, binary data, etc.");
+        return NULL;
+    }
+
+    result = uprv_malloc(count+1);
 
     if (result == NULL)
     {
@@ -292,7 +312,7 @@ static char *getInvariantString(uint32_t *line, UErrorCode *status)
         return NULL;
     }
 
-    u_UCharsToChars(tokenValue->fChars, result, count);
+    u_UCharsToChars(tokenValue->fChars, result, count+1);
     return result;
 }
 
@@ -300,10 +320,11 @@ static enum EResourceType
 parseResourceType(UErrorCode *status)
 {
     struct UString        *tokenValue;
+    struct UString        comment;
     enum   EResourceType  result = RT_UNKNOWN;
     uint32_t              line=0;
-
-    expect(TOK_STRING, &tokenValue, &line, status);
+    ustr_init(&comment);
+    expect(TOK_STRING, &tokenValue, &comment, &line, status);
 
     if (U_FAILURE(*status))
     {
@@ -352,6 +373,7 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
 {
     struct SResource *result = NULL;
     struct UString   *tokenValue;
+    struct UString   comment;
     FileStream       *file          = NULL;
     char              filename[256] = { '\0' };
     char              cs[128]       = { '\0' };
@@ -366,10 +388,11 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
     UChar *targetLimit = NULL;
     int32_t size = 0;
 
-    expect(TOK_STRING, &tokenValue, &line, status);
+    ustr_init(&comment);
+    expect(TOK_STRING, &tokenValue, &comment, &line, status);
 
     if(isVerbose()){
-        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
     if (U_FAILURE(*status))
@@ -389,7 +412,7 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
 
     u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -415,6 +438,7 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
     */
     size = ucbuf_size(ucbuf);
     pTarget     = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * size);
+    uprv_memset(pTarget, 0, size*U_SIZEOF_UCHAR);
     target      = pTarget;
     targetLimit = pTarget+size;
 
@@ -423,16 +447,16 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
     {
         c = ucbuf_getc(ucbuf, status);
         if(c == QUOTE) {
-          quoted = !quoted;
+          quoted = (UBool)!quoted;
         }
         /* weiv (06/26/2002): adding the following:
          * - preserving spaces in commands [...]
          * - # comments until the end of line
          */
-        if (c == STARTCOMMAND)
+        if (c == STARTCOMMAND && !quoted)
         {
-          /* preserve commands 
-           * closing bracket will be handled by the 
+          /* preserve commands
+           * closing bracket will be handled by the
            * append at the end of the loop
            */
           while(c != ENDCOMMAND) {
@@ -444,6 +468,7 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
           while(c != CR && c != LF) {
             c = ucbuf_getc(ucbuf, status);
           }
+          continue;
         } else if (c == ESCAPE)
         {
             c = unescape(ucbuf, status);
@@ -455,7 +480,7 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
                 return NULL;
             }
         }
-        else if (c == SPACE || c == CR || c == LF)
+        else if (!quoted && (c == SPACE || c == TAB || c == CR || c == LF))
         {
         /* ignore spaces carriage returns
         * and line feed unless in the form \uXXXX
@@ -474,7 +499,13 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
         }
     }
 
-    result = string_open(bundle, tag, pTarget, target - pTarget, status);
+    /* terminate the string */
+    if(target < targetLimit){
+        *target = 0x0000;
+    }
+
+    result = string_open(bundle, tag, pTarget, (int32_t)(target - pTarget), NULL, status);
+
 
     ucbuf_close(ucbuf);
     uprv_free(pTarget);
@@ -484,7 +515,7 @@ parseUCARules(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseString(char *tag, uint32_t startline, UErrorCode *status)
+parseString(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct UString   *tokenValue;
     struct SResource *result = NULL;
@@ -494,18 +525,18 @@ parseString(char *tag, uint32_t startline, UErrorCode *status)
         return parseUCARules(tag, startline, status);
     }
     if(isVerbose()){
-        printf(" string %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" string %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
-    expect(TOK_STRING, &tokenValue, NULL, status);
+    expect(TOK_STRING, &tokenValue, NULL, NULL, status);
 
     if (U_SUCCESS(*status))
     {
         /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
         doesn't survive expect either) */
 
-        result = string_open(bundle, tag, tokenValue->fChars, tokenValue->fLength, status);
+        result = string_open(bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
         if(U_SUCCESS(*status) && result) {
-          expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+          expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
           if (U_FAILURE(*status))
           {
@@ -519,15 +550,15 @@ parseString(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseAlias(char *tag, uint32_t startline, UErrorCode *status)
+parseAlias(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct UString   *tokenValue;
-    struct SResource *result = NULL;
+    struct SResource *result  = NULL;
 
-    expect(TOK_STRING, &tokenValue, NULL, status);
+    expect(TOK_STRING, &tokenValue, NULL, NULL, status);
 
     if(isVerbose()){
-        printf(" alias %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" alias %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
     if (U_SUCCESS(*status))
@@ -535,9 +566,9 @@ parseAlias(char *tag, uint32_t startline, UErrorCode *status)
         /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
         doesn't survive expect either) */
 
-        result = alias_open(bundle, tag, tokenValue->fChars, tokenValue->fLength, status);
+        result = alias_open(bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
 
-        expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+        expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
         if (U_FAILURE(*status))
         {
@@ -550,30 +581,23 @@ parseAlias(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
+addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
 {
-    struct SResource  *result = NULL;
     struct SResource  *member = NULL;
     struct UString    *tokenValue;
+    struct UString     comment;
     enum   ETokenType  token;
     char               subtag[1024];
     UVersionInfo       version;
     UBool              override = FALSE;
     uint32_t           line;
-
-    result = table_open(bundle, tag, status);
-
-    if (result == NULL || U_FAILURE(*status))
-    {
-        return NULL;
-    }
-    if(isVerbose()){
-        printf(" collation elements %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
-    }
     /* '{' . (name resource)* '}' */
+    version[0]=0; version[1]=0; version[2]=0; version[3]=0;
+
     for (;;)
     {
-        token = getToken(&tokenValue, &line, status);
+        ustr_init(&comment);
+        token = getToken(&tokenValue, &comment, &line, status);
 
         if (token == TOK_CLOSE_BRACE)
         {
@@ -605,7 +629,7 @@ parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
             return NULL;
         }
 
-        member = parseResource(subtag, status);
+        member = parseResource(subtag, NULL, status);
 
         if (U_FAILURE(*status))
         {
@@ -667,7 +691,10 @@ parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
 
                 if (U_SUCCESS(intStatus) && coll != NULL)
                 {
-                    data = ucol_cloneRuleData(coll, &len, &intStatus);
+                    len = ucol_cloneBinary(coll, NULL, 0, &intStatus);
+                    data = (uint8_t *)uprv_malloc(len);
+                    len = ucol_cloneBinary(coll, data, len, &intStatus);
+                    /*data = ucol_cloneRuleData(coll, &len, &intStatus);*/
 
                     /* tailoring rules version */
                     /* This is wrong! */
@@ -680,7 +707,7 @@ parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
 
                     if (U_SUCCESS(intStatus) && data != NULL)
                     {
-                        member = bin_open(bundle, "%%CollationBin", len, data, NULL, status);
+                        member = bin_open(bundle, "%%CollationBin", len, data, NULL, NULL, status);
                         /*table_add(bundle->fRoot, member, line, status);*/
                         table_add(result, member, line, status);
                         uprv_free(data);
@@ -700,7 +727,7 @@ parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
                 {
                     warning(line, "%%Collation could not be constructed from CollationElements - check context!");
                     if(isStrict()){
-                        *status = U_INVALID_FORMAT_ERROR;
+                        *status = intStatus;
                         return NULL;
                     }
                 }
@@ -729,6 +756,124 @@ parseCollationElements(char *tag, uint32_t startline, UErrorCode *status)
     return NULL;*/
 }
 
+static struct SResource *
+parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UErrorCode *status)
+{
+    struct SResource  *result = NULL;
+    struct SResource  *member = NULL;
+    struct SResource  *collationRes = NULL;
+    struct UString    *tokenValue;
+    struct UString     comment;
+    enum   ETokenType  token;
+    char               subtag[1024], typeKeyword[1024];
+    uint32_t           line;
+
+    result = table_open(bundle, tag, NULL, status);
+
+    if (result == NULL || U_FAILURE(*status))
+    {
+        return NULL;
+    }
+    if(isVerbose()){
+        printf(" collation elements %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
+    }
+    if(!newCollation) {
+      return addCollation(result, startline, status);
+    } else {
+      for(;;) {
+        ustr_init(&comment);
+        token = getToken(&tokenValue, &comment, &line, status);
+
+        if (token == TOK_CLOSE_BRACE)
+        {
+            return result;
+        }
+
+        if (token != TOK_STRING)
+        {
+            table_close(result, status);
+            *status = U_INVALID_FORMAT_ERROR;
+
+            if (token == TOK_EOF)
+            {
+                error(startline, "unterminated table");
+            }
+            else
+            {
+                error(line, "Unexpected token %s", tokenNames[token]);
+            }
+
+            return NULL;
+        }
+
+        u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
+
+        if (U_FAILURE(*status))
+        {
+            table_close(result, status);
+            return NULL;
+        }
+
+        if (uprv_strcmp(subtag, "default") == 0)
+        {
+          member = parseResource(subtag, NULL, status);
+
+          if (U_FAILURE(*status))
+          {
+              table_close(result, status);
+              return NULL;
+          }
+
+          table_add(result, member, line, status);
+        }
+        else
+        {
+          token = peekToken(0, &tokenValue, &line, &comment, status);
+          /* this probably needs to be refactored or recursively use the parser */
+          /* first we assume that our collation table won't have the explicit type */
+          /* then, we cannot handle aliases */
+          if(token == TOK_OPEN_BRACE) {
+            token = getToken(&tokenValue, &comment, &line, status);
+            collationRes = table_open(bundle, subtag, NULL, status);
+            table_add(result, addCollation(collationRes, startline, status), startline, status);
+          } else if(token == TOK_COLON) { /* right now, we'll just try to see if we have aliases */
+            /* we could have a table too */
+            token = peekToken(1, &tokenValue, &line, &comment, status);
+            u_UCharsToChars(tokenValue->fChars, typeKeyword, u_strlen(tokenValue->fChars) + 1);
+            if(uprv_strcmp(typeKeyword, "alias") == 0) {
+              member = parseResource(subtag, NULL, status);
+
+              if (U_FAILURE(*status))
+              {
+                  table_close(result, status);
+                  return NULL;
+              }
+
+              table_add(result, member, line, status);
+            } else {
+              *status = U_INVALID_FORMAT_ERROR;
+              return NULL;
+            }
+          } else {
+            *status = U_INVALID_FORMAT_ERROR;
+            return NULL;
+          }
+        }
+
+        /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);*/
+
+        /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/
+
+        if (U_FAILURE(*status))
+        {
+            table_close(result, status);
+            return NULL;
+        }
+
+      }
+    }
+}
+
 /* Necessary, because CollationElements requires the bundle->fRoot member to be present which,
    if this weren't special-cased, wouldn't be set until the entire file had been processed. */
 static struct SResource *
@@ -736,6 +881,7 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
 {
     struct SResource  *member = NULL;
     struct UString    *tokenValue=NULL;
+    struct UString    comment;
     enum   ETokenType token;
     char              subtag[1024];
     uint32_t          line;
@@ -743,11 +889,12 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
 
     /* '{' . (name resource)* '}' */
     if(isVerbose()){
-        printf(" parsing table %s at line %i \n", (tag == NULL) ? "(null)" : tag,startline);
+        printf(" parsing table %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline);
     }
     for (;;)
     {
-        token = getToken(&tokenValue, &line, status);
+        ustr_init(&comment);
+        token = getToken(&tokenValue, &comment, &line, status);
 
         if (token == TOK_CLOSE_BRACE)
         {
@@ -768,13 +915,20 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
             }
             else
             {
-                error(line, "enexpected token %s", tokenNames[token]);
+                error(line, "unexpected token %s", tokenNames[token]);
             }
 
             return NULL;
         }
 
-        u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
+        if(uprv_isInvariantUString(tokenValue->fChars, -1)) {
+            u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
+        } else {
+            *status = U_INVALID_FORMAT_ERROR;
+            error(line, "invariant characters required for table keys");
+            table_close(table, status);
+            return NULL;
+        }
 
         if (U_FAILURE(*status))
         {
@@ -783,7 +937,7 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
             return NULL;
         }
 
-        member = parseResource(subtag, status);
+        member = parseResource(subtag, &comment, status);
 
         if (member == NULL || U_FAILURE(*status))
         {
@@ -810,54 +964,67 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
 }
 
 static struct SResource *
-parseTable(char *tag, uint32_t startline, UErrorCode *status)
+parseTable(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource *result;
 
     if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0)
     {
-        return parseCollationElements(tag, startline, status);
+        return parseCollationElements(tag, startline, FALSE, status);
+    }
+    if (tag != NULL && uprv_strcmp(tag, "collations") == 0)
+    {
+        return parseCollationElements(tag, startline, TRUE, status);
     }
     if(isVerbose()){
-        printf(" table %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" table %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
-    result = table_open(bundle, tag, status);
+
+    result = table_open(bundle, tag, comment, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    return realParseTable(result, tag, startline, status);
+    return realParseTable(result, tag, startline,  status);
 }
 
 static struct SResource *
-parseArray(char *tag, uint32_t startline, UErrorCode *status)
+parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource  *result = NULL;
     struct SResource  *member = NULL;
     struct UString    *tokenValue;
+    struct UString    memberComments;
     enum   ETokenType token;
     UBool             readToken = FALSE;
 
-    result = array_open(bundle, tag, status);
+    result = array_open(bundle, tag, comment, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
     if(isVerbose()){
-        printf(" array %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" array %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
+
+    ustr_init(&memberComments);
+
     /* '{' . resource [','] '}' */
     for (;;)
     {
+        /* reset length */
+        ustr_setlen(&memberComments, 0, status);
+
         /* check for end of array, but don't consume next token unless it really is the end */
-        token = peekToken(0, &tokenValue, NULL, status);
+        token = peekToken(0, &tokenValue, NULL, &memberComments, status);
+
 
         if (token == TOK_CLOSE_BRACE)
         {
-            getToken(NULL, NULL, status);
+            getToken(NULL, NULL, NULL, status);
             if (!readToken) {
                 warning(startline, "Encountered empty array");
             }
@@ -875,12 +1042,12 @@ parseArray(char *tag, uint32_t startline, UErrorCode *status)
         /* string arrays are a special case */
         if (token == TOK_STRING)
         {
-            getToken(&tokenValue, NULL, status);
-            member = string_open(bundle, NULL, tokenValue->fChars, tokenValue->fLength, status);
+            getToken(&tokenValue, &memberComments, NULL, status);
+            member = string_open(bundle, NULL, tokenValue->fChars, tokenValue->fLength, &memberComments, status);
         }
         else
         {
-            member = parseResource(NULL, status);
+            member = parseResource(NULL, &memberComments, status);
         }
 
         if (member == NULL || U_FAILURE(*status))
@@ -898,11 +1065,11 @@ parseArray(char *tag, uint32_t startline, UErrorCode *status)
         }
 
         /* eat optional comma if present */
-        token = peekToken(0, NULL, NULL, status);
+        token = peekToken(0, NULL, NULL, NULL, status);
 
         if (token == TOK_COMMA)
         {
-            getToken(NULL, NULL, status);
+            getToken(NULL, NULL, NULL, status);
         }
 
         if (U_FAILURE(*status))
@@ -917,7 +1084,7 @@ parseArray(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
+parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource  *result = NULL;
     enum   ETokenType  token;
@@ -927,8 +1094,9 @@ parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
     /* added by Jing/GCL */
     char              *stopstring;
     uint32_t           len;
+    struct UString     memberComments;
 
-    result = intvector_open(bundle, tag, status);
+    result = intvector_open(bundle, tag, comment, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
@@ -936,26 +1104,28 @@ parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
     }
 
     if(isVerbose()){
-        printf(" vector %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" vector %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
-
+    ustr_init(&memberComments);
     /* '{' . string [','] '}' */
     for (;;)
     {
+        ustr_setlen(&memberComments, 0, status);
+
         /* check for end of array, but don't consume next token unless it really is the end */
-        token = peekToken(0, NULL, NULL, status);
+        token = peekToken(0, NULL, NULL,&memberComments, status);
 
         if (token == TOK_CLOSE_BRACE)
         {
             /* it's the end, consume the close brace */
-            getToken(NULL, NULL, status);
+            getToken(NULL, NULL, NULL, status);
             if (!readToken) {
                 warning(startline, "Encountered empty int vector");
             }
             return result;
         }
 
-        string = getInvariantString(NULL, status);
+        string = getInvariantString(NULL, NULL, status);
 
         if (U_FAILURE(*status))
         {
@@ -972,13 +1142,13 @@ parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
 
         /* The following is added by Jing/GCL to handle illegal char in the Intvector */
         value = uprv_strtoul(string, &stopstring, 0);/* make intvector support decimal,hexdigit,octal digit ranging from -2^31-2^32-1*/
-        len=stopstring-string;
+        len=(uint32_t)(stopstring-string);
 
         if(len==uprv_strlen(string))
         {
             intvector_add(result, value, status);
             uprv_free(string);
-            token = peekToken(0, NULL, NULL, status);
+            token = peekToken(0, NULL, NULL, NULL, status);
         }
         else
         {
@@ -997,7 +1167,7 @@ parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
         consecutive entries) so that a missing comma on the last entry isn't an error */
         if (token == TOK_COMMA)
         {
-            getToken(NULL, NULL, status);
+            getToken(NULL, NULL, NULL, status);
         }
         readToken = TRUE;
     }
@@ -1010,7 +1180,7 @@ parseIntVector(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseBinary(char *tag, uint32_t startline, UErrorCode *status)
+parseBinary(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     uint8_t          *value;
@@ -1023,14 +1193,14 @@ parseBinary(char *tag, uint32_t startline, UErrorCode *status)
     char             *stopstring;
     uint32_t          len;
 
-    string = getInvariantString(&line, status);
+    string = getInvariantString(&line, NULL, status);
 
     if (string == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1039,10 +1209,10 @@ parseBinary(char *tag, uint32_t startline, UErrorCode *status)
     }
 
     if(isVerbose()){
-        printf(" binary %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" binary %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
-    count = uprv_strlen(string);
+    count = (uint32_t)uprv_strlen(string);
     if (count > 0){
         if((count % 2)==0){
             value = uprv_malloc(sizeof(uint8_t) * count);
@@ -1060,7 +1230,7 @@ parseBinary(char *tag, uint32_t startline, UErrorCode *status)
                 toConv[1] = string[i + 1];
 
                 value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16);
-                len=stopstring-toConv;
+                len=(uint32_t)(stopstring-toConv);
 
                 if(len!=uprv_strlen(toConv))
                 {
@@ -1070,7 +1240,7 @@ parseBinary(char *tag, uint32_t startline, UErrorCode *status)
                 }
             }
 
-            result = bin_open(bundle, tag, (i >> 1), value,NULL, status);
+            result = bin_open(bundle, tag, (i >> 1), value,NULL, comment, status);
 
             uprv_free(value);
         }
@@ -1084,7 +1254,7 @@ parseBinary(char *tag, uint32_t startline, UErrorCode *status)
     }
     else
     {
-        result = bin_open(bundle, tag, 0, NULL, "",status);
+        result = bin_open(bundle, tag, 0, NULL, "",comment,status);
         warning(startline, "Encountered empty binary tag");
     }
     uprv_free(string);
@@ -1093,7 +1263,7 @@ parseBinary(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseInteger(char *tag, uint32_t startline, UErrorCode *status)
+parseInteger(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     int32_t           value;
@@ -1102,14 +1272,14 @@ parseInteger(char *tag, uint32_t startline, UErrorCode *status)
     char             *stopstring;
     uint32_t          len;
 
-    string = getInvariantString(NULL, status);
+    string = getInvariantString(NULL, NULL, status);
 
     if (string == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1118,7 +1288,7 @@ parseInteger(char *tag, uint32_t startline, UErrorCode *status)
     }
 
     if(isVerbose()){
-        printf(" integer %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" integer %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
     if (uprv_strlen(string) <= 0)
@@ -1133,10 +1303,10 @@ parseInteger(char *tag, uint32_t startline, UErrorCode *status)
     /* to make integer support hexdecimal, octal digit and decimal*/
     /* to handle illegal char in the integer*/
     value = uprv_strtoul(string, &stopstring, 0);
-    len=stopstring-string;
+    len=(uint32_t)(stopstring-string);
     if(len==uprv_strlen(string))
     {
-        result = int_open(bundle, tag, value, status);
+        result = int_open(bundle, tag, value, comment, status);
     }
     else
     {
@@ -1148,7 +1318,7 @@ parseInteger(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseImport(char *tag, uint32_t startline, UErrorCode *status)
+parseImport(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result;
     FileStream       *file;
@@ -1158,14 +1328,14 @@ parseImport(char *tag, uint32_t startline, UErrorCode *status)
     uint32_t          line;
     char     *fullname = NULL;
     int32_t numRead = 0;
-    filename = getInvariantString(&line, status);
+    filename = getInvariantString(&line, NULL, status);
 
     if (U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1174,7 +1344,7 @@ parseImport(char *tag, uint32_t startline, UErrorCode *status)
     }
 
     if(isVerbose()){
-        printf(" import %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" import %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
     /* Open the input file for reading */
@@ -1185,7 +1355,7 @@ parseImport(char *tag, uint32_t startline, UErrorCode *status)
     else
     {
 
-        int32_t  count     = uprv_strlen(filename);
+        int32_t  count     = (int32_t)uprv_strlen(filename);
 
         if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
         {
@@ -1244,7 +1414,7 @@ parseImport(char *tag, uint32_t startline, UErrorCode *status)
     numRead = T_FileStream_read  (file, data, len);
     T_FileStream_close (file);
 
-    result = bin_open(bundle, tag, len, data, fullname, status);
+    result = bin_open(bundle, tag, len, data, fullname, comment, status);
 
     uprv_free(data);
     uprv_free(filename);
@@ -1254,7 +1424,7 @@ parseImport(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseInclude(char *tag, uint32_t startline, UErrorCode *status)
+parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result;
     int32_t           len=0;
@@ -1268,15 +1438,15 @@ parseInclude(char *tag, uint32_t startline, UErrorCode *status)
     const char* cp = NULL;
     const UChar* uBuffer = NULL;
 
-    filename = getInvariantString(&line, status);
-    count     = uprv_strlen(filename);
+    filename = getInvariantString(&line, NULL, status);
+    count     = (int32_t)uprv_strlen(filename);
 
     if (U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, status);
+    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1285,7 +1455,7 @@ parseInclude(char *tag, uint32_t startline, UErrorCode *status)
     }
 
     if(isVerbose()){
-        printf(" include %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" include %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
     fullname = (char *) uprv_malloc(inputdirLength + count + 2);
@@ -1295,7 +1465,7 @@ parseInclude(char *tag, uint32_t startline, UErrorCode *status)
         *status = U_MEMORY_ALLOCATION_ERROR;
         uprv_free(filename);
         return NULL;
-       }
+    }
 
     if(inputdir!=NULL){
         if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
@@ -1325,7 +1495,7 @@ parseInclude(char *tag, uint32_t startline, UErrorCode *status)
     }
 
     uBuffer = ucbuf_getBuffer(ucbuf,&len,status);
-    result = string_open(bundle, tag, uBuffer, len, status);
+    result = string_open(bundle, tag, uBuffer, len, comment, status);
 
     uprv_free(pTarget);
 
@@ -1336,7 +1506,7 @@ parseInclude(char *tag, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseResource(char *tag, UErrorCode *status)
+parseResource(char *tag, const struct UString *comment, UErrorCode *status)
 {
     enum   ETokenType      token;
     enum   EResourceType  resType = RT_UNKNOWN;
@@ -1344,10 +1514,10 @@ parseResource(char *tag, UErrorCode *status)
     uint32_t                 startline;
     uint32_t                 line;
 
-    token = getToken(&tokenValue, &startline, status);
+    token = getToken(&tokenValue, NULL, &startline, status);
 
     if(isVerbose()){
-        printf(" resource %s at line %i \n",  (tag == NULL) ? "(null)" : tag,startline);
+        printf(" resource %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
     /* name . [ ':' type ] '{' resource '}' */
@@ -1367,7 +1537,7 @@ parseResource(char *tag, UErrorCode *status)
 
     case TOK_COLON:
         resType = parseResourceType(status);
-        expect(TOK_OPEN_BRACE, &tokenValue, &startline, status);
+        expect(TOK_OPEN_BRACE, &tokenValue, NULL, &startline, status);
 
         if (U_FAILURE(*status))
         {
@@ -1402,7 +1572,7 @@ parseResource(char *tag, UErrorCode *status)
         { string }      => string
         */
 
-        token = peekToken(0, NULL, &line, status);
+        token = peekToken(0, NULL, &line, NULL,status);
 
         if (U_FAILURE(*status))
         {
@@ -1417,7 +1587,7 @@ parseResource(char *tag, UErrorCode *status)
         }
         else if (token == TOK_STRING)
         {
-            token = peekToken(1, NULL, &line, status);
+            token = peekToken(1, NULL, &line, NULL, status);
 
             if (U_FAILURE(*status))
             {
@@ -1451,15 +1621,15 @@ parseResource(char *tag, UErrorCode *status)
     function and return. */
     switch (resType)
     {
-    case RT_STRING:     return parseString    (tag, startline, status);
-    case RT_TABLE:      return parseTable     (tag, startline, status);
-    case RT_ARRAY:      return parseArray     (tag, startline, status);
-    case RT_ALIAS:      return parseAlias     (tag, startline, status);
-    case RT_BINARY:     return parseBinary    (tag, startline, status);
-    case RT_INTEGER:    return parseInteger   (tag, startline, status);
-    case RT_IMPORT:     return parseImport    (tag, startline, status);
-    case RT_INCLUDE:    return parseInclude   (tag, startline, status);
-    case RT_INTVECTOR:  return parseIntVector (tag, startline, status);
+    case RT_STRING:     return parseString    (tag, startline, comment, status);
+    case RT_TABLE:      return parseTable     (tag, startline, comment, status);
+    case RT_ARRAY:      return parseArray     (tag, startline, comment, status);
+    case RT_ALIAS:      return parseAlias     (tag, startline, comment, status);
+    case RT_BINARY:     return parseBinary    (tag, startline, comment, status);
+    case RT_INTEGER:    return parseInteger   (tag, startline, comment, status);
+    case RT_IMPORT:     return parseImport    (tag, startline, comment, status);
+    case RT_INCLUDE:    return parseInclude   (tag, startline, comment, status);
+    case RT_INTVECTOR:  return parseIntVector (tag, startline, comment, status);
 
     default:
         *status = U_INTERNAL_PROGRAM_ERROR;
@@ -1473,6 +1643,7 @@ struct SRBRoot *
 parse(UCHARBUF *buf, const char *currentInputDir, UErrorCode *status)
 {
     struct UString    *tokenValue;
+    struct UString    comment;
     uint32_t           line;
     /* added by Jing/GCL */
     enum EResourceType bundleType;
@@ -1481,21 +1652,24 @@ parse(UCHARBUF *buf, const char *currentInputDir, UErrorCode *status)
     initLookahead(buf, status);
 
     inputdir       = currentInputDir;
-    inputdirLength = (inputdir != NULL) ? uprv_strlen(inputdir) : 0;
+    inputdirLength = (inputdir != NULL) ? (uint32_t)uprv_strlen(inputdir) : 0;
+
+    ustr_init(&comment);
+    expect(TOK_STRING, &tokenValue, &comment, NULL, status);
 
-    bundle = bundle_open(status);
+    bundle = bundle_open(&comment, status);
 
     if (bundle == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_STRING, &tokenValue, NULL, status);
+
     bundle_setlocale(bundle, tokenValue->fChars, status);
     /* Commented by Jing/GCL */
     /* expect(TOK_OPEN_BRACE, NULL, &line, status); */
     /* The following code is to make Empty bundle work no matter with :table specifer or not */
-    token = getToken(NULL, &line, status);
+    token = getToken(NULL, NULL, &line, status);
 
     if(token==TOK_COLON)
     {
@@ -1512,7 +1686,7 @@ parse(UCHARBUF *buf, const char *currentInputDir, UErrorCode *status)
 
         if(bundleType==RT_TABLE)
         {
-            expect(TOK_OPEN_BRACE, NULL, &line, status);
+            expect(TOK_OPEN_BRACE, NULL, NULL, &line, status);
         }
         else
         {
@@ -1547,7 +1721,7 @@ parse(UCHARBUF *buf, const char *currentInputDir, UErrorCode *status)
         return NULL;
     }
 
-    if (getToken(NULL, &line, status) != TOK_EOF)
+    if (getToken(NULL, NULL, &line, status) != TOK_EOF)
     {
         warning(line, "extraneous text after resource bundle (perhaps unmatched braces)");
         if(isStrict()){