]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/genrb/parse.c
ICU-461.12.tar.gz
[apple/icu.git] / icuSources / tools / genrb / parse.c
index f7b1a63a607d25a65e4a75ac838dafbe008e00e7..dae7254b2ac0f0a2cb4b6f2442d927fd44b1c00d 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 1998-2008, International Business Machines
+*   Copyright (C) 1998-2010, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 #include "ustr.h"
 #include "reslist.h"
 #include "rbt_pars.h"
+#include "genrb.h"
 #include "unicode/ustring.h"
+#include "unicode/uscript.h"
 #include "unicode/putil.h"
 #include <stdio.h>
 
+extern UBool gIncludeUnihanColl;
+
 /* Number of tokens to read ahead of the current stream position */
 #define MAX_LOOKAHEAD   3
 
@@ -49,9 +53,6 @@
 #define OPENSQBRACKET    0x005B
 #define CLOSESQBRACKET   0x005D
 
-typedef struct SResource *
-ParseResourceFunction(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status);
-
 struct Lookahead
 {
      enum   ETokenType type;
@@ -76,20 +77,24 @@ const char *tokenNames[TOK_TOKEN_COUNT] =
 /* Just to store "TRUE" */
 static const UChar trueValue[] = {0x0054, 0x0052, 0x0055, 0x0045, 0x0000};
 
-static struct Lookahead  lookahead[MAX_LOOKAHEAD + 1];
-static uint32_t          lookaheadPosition;
-static UCHARBUF         *buffer;
-
-static struct SRBRoot *bundle;
-static const char     *inputdir;
-static uint32_t        inputdirLength;
-static const char     *outputdir;
-static uint32_t        outputdirLength;
+typedef struct {
+    struct Lookahead  lookahead[MAX_LOOKAHEAD + 1];
+    uint32_t          lookaheadPosition;
+    UCHARBUF         *buffer;
+    struct SRBRoot *bundle;
+    const char     *inputdir;
+    uint32_t        inputdirLength;
+    const char     *outputdir;
+    uint32_t        outputdirLength;
+} ParseState;
 
 static UBool gMakeBinaryCollation = TRUE;
 static UBool gOmitCollationRules  = FALSE;
 
-static struct SResource *parseResource(char *tag, const struct UString *comment, UErrorCode *status);
+typedef struct SResource *
+ParseResourceFunction(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status);
+
+static struct SResource *parseResource(ParseState* state, char *tag, const struct UString *comment, UErrorCode *status);
 
 /* The nature of the lookahead buffer:
    There are MAX_LOOKAHEAD + 1 slots, used as a circular buffer.  This provides
@@ -105,7 +110,7 @@ static struct SResource *parseResource(char *tag, const struct UString *comment,
    getToken(NULL,   NULL, status);       bad - value is now a different string
 */
 static void
-initLookahead(UCHARBUF *buf, UErrorCode *status)
+initLookahead(ParseState* state, UCHARBUF *buf, UErrorCode *status)
 {
     static uint32_t initTypeStrings = 0;
     uint32_t i;
@@ -115,14 +120,14 @@ initLookahead(UCHARBUF *buf, UErrorCode *status)
         initTypeStrings = 1;
     }
 
-    lookaheadPosition   = 0;
-    buffer              = buf;
+    state->lookaheadPosition   = 0;
+    state->buffer              = buf;
 
     resetLineNumber();
 
     for (i = 0; i < MAX_LOOKAHEAD; i++)
     {
-        lookahead[i].type = getNextToken(buffer, &lookahead[i].value, &lookahead[i].line, &lookahead[i].comment, status);
+        state->lookahead[i].type = getNextToken(state->buffer, &state->lookahead[i].value, &state->lookahead[i].line, &state->lookahead[i].comment, status);
         if (U_FAILURE(*status))
         {
             return;
@@ -133,45 +138,45 @@ initLookahead(UCHARBUF *buf, UErrorCode *status)
 }
 
 static void
-cleanupLookahead()
+cleanupLookahead(ParseState* state)
 {
     uint32_t i;
     for (i = 0; i < MAX_LOOKAHEAD; i++)
     {
-        ustr_deinit(&lookahead[i].value);
-        ustr_deinit(&lookahead[i].comment);
+        ustr_deinit(&state->lookahead[i].value);
+        ustr_deinit(&state->lookahead[i].comment);
     }
 
 }
 
 static enum ETokenType
-getToken(struct UString **tokenValue, struct UString* comment, uint32_t *linenumber, UErrorCode *status)
+getToken(ParseState* state, struct UString **tokenValue, struct UString* comment, uint32_t *linenumber, UErrorCode *status)
 {
     enum ETokenType result;
     uint32_t          i;
 
-    result = lookahead[lookaheadPosition].type;
+    result = state->lookahead[state->lookaheadPosition].type;
 
     if (tokenValue != NULL)
     {
-        *tokenValue = &lookahead[lookaheadPosition].value;
+        *tokenValue = &state->lookahead[state->lookaheadPosition].value;
     }
 
     if (linenumber != NULL)
     {
-        *linenumber = lookahead[lookaheadPosition].line;
+        *linenumber = state->lookahead[state->lookaheadPosition].line;
     }
 
     if (comment != NULL)
     {
-        ustr_cpy(comment, &(lookahead[lookaheadPosition].comment), status);
+        ustr_cpy(comment, &(state->lookahead[state->lookaheadPosition].comment), status);
     }
 
-    i = (lookaheadPosition + MAX_LOOKAHEAD) % (MAX_LOOKAHEAD + 1);
-    lookaheadPosition = (lookaheadPosition + 1) % (MAX_LOOKAHEAD + 1);
-    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);
+    i = (state->lookaheadPosition + MAX_LOOKAHEAD) % (MAX_LOOKAHEAD + 1);
+    state->lookaheadPosition = (state->lookaheadPosition + 1) % (MAX_LOOKAHEAD + 1);
+    ustr_setlen(&state->lookahead[i].comment, 0, status);
+    ustr_setlen(&state->lookahead[i].value, 0, status);
+    state->lookahead[i].type = getNextToken(state->buffer, &state->lookahead[i].value, &state->lookahead[i].line, &state->lookahead[i].comment, status);
 
     /* printf("getToken, returning %s\n", tokenNames[result]); */
 
@@ -179,9 +184,9 @@ getToken(struct UString **tokenValue, struct UString* comment, uint32_t *linenum
 }
 
 static enum ETokenType
-peekToken(uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, struct UString *comment, UErrorCode *status)
+peekToken(ParseState* state, uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, struct UString *comment, UErrorCode *status)
 {
-    uint32_t i = (lookaheadPosition + lookaheadCount) % (MAX_LOOKAHEAD + 1);
+    uint32_t i = (state->lookaheadPosition + lookaheadCount) % (MAX_LOOKAHEAD + 1);
 
     if (U_FAILURE(*status))
     {
@@ -196,27 +201,27 @@ peekToken(uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenu
 
     if (tokenValue != NULL)
     {
-        *tokenValue = &lookahead[i].value;
+        *tokenValue = &state->lookahead[i].value;
     }
 
     if (linenumber != NULL)
     {
-        *linenumber = lookahead[i].line;
+        *linenumber = state->lookahead[i].line;
     }
 
     if(comment != NULL){
-        ustr_cpy(comment, &(lookahead[lookaheadPosition].comment), status);
+        ustr_cpy(comment, &(state->lookahead[state->lookaheadPosition].comment), status);
     }
 
-    return lookahead[i].type;
+    return state->lookahead[i].type;
 }
 
 static void
-expect(enum ETokenType expectedToken, struct UString **tokenValue, struct UString *comment, uint32_t *linenumber, UErrorCode *status)
+expect(ParseState* state, enum ETokenType expectedToken, struct UString **tokenValue, struct UString *comment, uint32_t *linenumber, UErrorCode *status)
 {
     uint32_t        line;
 
-    enum ETokenType token = getToken(tokenValue, comment, &line, status);
+    enum ETokenType token = getToken(state, tokenValue, comment, &line, status);
 
     if (linenumber != NULL)
     {
@@ -239,13 +244,13 @@ expect(enum ETokenType expectedToken, struct UString **tokenValue, struct UStrin
     }
 }
 
-static char *getInvariantString(uint32_t *line, struct UString *comment, UErrorCode *status)
+static char *getInvariantString(ParseState* state, uint32_t *line, struct UString *comment, UErrorCode *status)
 {
     struct UString *tokenValue;
     char           *result;
     uint32_t        count;
 
-    expect(TOK_STRING, &tokenValue, comment, line, status);
+    expect(state, TOK_STRING, &tokenValue, comment, line, status);
 
     if (U_FAILURE(*status))
     {
@@ -272,7 +277,7 @@ static char *getInvariantString(uint32_t *line, struct UString *comment, UErrorC
 }
 
 static struct SResource *
-parseUCARules(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
+parseUCARules(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     struct UString   *tokenValue;
@@ -290,7 +295,7 @@ parseUCARules(char *tag, uint32_t startline, const struct UString* comment, UErr
     UChar *targetLimit = NULL;
     int32_t size = 0;
 
-    expect(TOK_STRING, &tokenValue, NULL, &line, status);
+    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
 
     if(isVerbose()){
         printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
@@ -301,11 +306,11 @@ parseUCARules(char *tag, uint32_t startline, const struct UString* comment, UErr
         return NULL;
     }
     /* make the filename including the directory */
-    if (inputdir != NULL)
+    if (state->inputdir != NULL)
     {
-        uprv_strcat(filename, inputdir);
+        uprv_strcat(filename, state->inputdir);
 
-        if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
+        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
         {
             uprv_strcat(filename, U_FILE_SEP_STRING);
         }
@@ -313,7 +318,7 @@ parseUCARules(char *tag, uint32_t startline, const struct UString* comment, UErr
 
     u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -406,7 +411,7 @@ parseUCARules(char *tag, uint32_t startline, const struct UString* comment, UErr
         *target = 0x0000;
     }
 
-    result = string_open(bundle, tag, pTarget, (int32_t)(target - pTarget), NULL, status);
+    result = string_open(state->bundle, tag, pTarget, (int32_t)(target - pTarget), NULL, status);
 
 
     ucbuf_close(ucbuf);
@@ -417,7 +422,7 @@ parseUCARules(char *tag, uint32_t startline, const struct UString* comment, UErr
 }
 
 static struct SResource *
-parseTransliterator(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
+parseTransliterator(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     struct UString   *tokenValue;
@@ -431,7 +436,7 @@ parseTransliterator(char *tag, uint32_t startline, const struct UString* comment
     const UChar *pSource     = NULL;
     int32_t size = 0;
 
-    expect(TOK_STRING, &tokenValue, NULL, &line, status);
+    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
 
     if(isVerbose()){
         printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
@@ -442,11 +447,11 @@ parseTransliterator(char *tag, uint32_t startline, const struct UString* comment
         return NULL;
     }
     /* make the filename including the directory */
-    if (inputdir != NULL)
+    if (state->inputdir != NULL)
     {
-        uprv_strcat(filename, inputdir);
+        uprv_strcat(filename, state->inputdir);
 
-        if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
+        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
         {
             uprv_strcat(filename, U_FILE_SEP_STRING);
         }
@@ -454,7 +459,7 @@ parseTransliterator(char *tag, uint32_t startline, const struct UString* comment
 
     u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -484,7 +489,7 @@ parseTransliterator(char *tag, uint32_t startline, const struct UString* comment
     size = 0;
     fprintf(stderr, " Warning: writing empty transliteration data ( UCONFIG_NO_TRANSLITERATION ) \n");
 #endif
-    result = string_open(bundle, tag, pTarget, size, NULL, status);
+    result = string_open(state->bundle, tag, pTarget, size, NULL, status);
 
     ucbuf_close(ucbuf);
     uprv_free(pTarget);
@@ -495,7 +500,7 @@ parseTransliterator(char *tag, uint32_t startline, const struct UString* comment
 static struct SResource* dependencyArray = NULL;
 
 static struct SResource *
-parseDependency(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
+parseDependency(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     struct SResource *elem = NULL;
@@ -504,7 +509,7 @@ parseDependency(char *tag, uint32_t startline, const struct UString* comment, UE
     char              filename[256] = { '\0' };
     char              cs[128]       = { '\0' };
     
-    expect(TOK_STRING, &tokenValue, NULL, &line, status);
+    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
 
     if(isVerbose()){
         printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
@@ -515,11 +520,11 @@ parseDependency(char *tag, uint32_t startline, const struct UString* comment, UE
         return NULL;
     }
     /* make the filename including the directory */
-    if (outputdir != NULL)
+    if (state->outputdir != NULL)
     {
-        uprv_strcat(filename, outputdir);
+        uprv_strcat(filename, state->outputdir);
 
-        if (outputdir[outputdirLength - 1] != U_FILE_SEP_CHAR)
+        if (state->outputdir[state->outputdirLength - 1] != U_FILE_SEP_CHAR)
         {
             uprv_strcat(filename, U_FILE_SEP_STRING);
         }
@@ -540,12 +545,12 @@ parseDependency(char *tag, uint32_t startline, const struct UString* comment, UE
         }
     }
     if(dependencyArray==NULL){
-        dependencyArray = array_open(bundle, "%%DEPENDENCY", NULL, status);
+        dependencyArray = array_open(state->bundle, "%%DEPENDENCY", NULL, status);
     }
     if(tag!=NULL){
-        result = string_open(bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
+        result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
     }
-    elem = string_open(bundle, NULL, tokenValue->fChars, tokenValue->fLength, comment, status);
+    elem = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, comment, status);
 
     array_add(dependencyArray, elem, status);
 
@@ -553,11 +558,11 @@ parseDependency(char *tag, uint32_t startline, const struct UString* comment, UE
     {
         return NULL;
     }
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
     return result;
 }
 static struct SResource *
-parseString(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
+parseString(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct UString   *tokenValue;
     struct SResource *result = NULL;
@@ -569,16 +574,16 @@ parseString(char *tag, uint32_t startline, const struct UString* comment, UError
     if(isVerbose()){
         printf(" string %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
-    expect(TOK_STRING, &tokenValue, NULL, NULL, status);
+    expect(state, 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, comment, status);
+        result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
         if(U_SUCCESS(*status) && result) {
-            expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+            expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
             if (U_FAILURE(*status))
             {
@@ -592,12 +597,12 @@ parseString(char *tag, uint32_t startline, const struct UString* comment, UError
 }
 
 static struct SResource *
-parseAlias(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
+parseAlias(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct UString   *tokenValue;
     struct SResource *result  = NULL;
 
-    expect(TOK_STRING, &tokenValue, NULL, NULL, status);
+    expect(state, TOK_STRING, &tokenValue, NULL, NULL, status);
 
     if(isVerbose()){
         printf(" alias %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
@@ -608,9 +613,9 @@ parseAlias(char *tag, uint32_t startline, const struct UString *comment, UErrorC
         /* 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, comment, status);
+        result = alias_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
 
-        expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+        expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
         if (U_FAILURE(*status))
         {
@@ -622,8 +627,182 @@ parseAlias(char *tag, uint32_t startline, const struct UString *comment, UErrorC
     return result;
 }
 
+typedef struct{
+    const char* inputDir;
+    const char* outputDir;
+} GenrbData;
+
+static struct SResource* resLookup(struct SResource* res, const char* key){
+    struct SResource *current = NULL;
+    struct SResTable *list;
+    if (res == res_none()) {
+        return NULL;
+    }
+
+    list = &(res->u.fTable);
+
+    current = list->fFirst;
+    while (current != NULL) {
+        if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), key) == 0) {
+            return current;
+        }
+        current = current->fNext;
+    }
+    return NULL;
+}
+
+static const UChar* importFromDataFile(void* context, const char* locale, const char* type, int32_t* pLength, UErrorCode* status){
+    struct SRBRoot *data         = NULL;
+    UCHARBUF       *ucbuf        = NULL;
+    GenrbData* genrbdata = (GenrbData*) context;
+    int localeLength = strlen(locale);
+    char* filename = (char*)uprv_malloc(localeLength+5);
+    char           *inputDirBuf  = NULL;
+    char           *openFileName = NULL;
+    const char* cp = "";
+    UChar* urules = NULL;
+    int32_t urulesLength = 0;
+    int32_t i = 0;
+    int32_t dirlen  = 0;
+    int32_t filelen = 0;
+    struct SResource* root;
+    struct SResource* collations;
+    struct SResource* collation;
+    struct SResource* sequence;
+
+    memcpy(filename, locale, localeLength);
+    for(i = 0; i < localeLength; i++){
+        if(filename[i] == '-'){
+            filename[i] = '_';
+        }
+    }
+    filename[localeLength]   = '.';
+    filename[localeLength+1] = 't';
+    filename[localeLength+2] = 'x';
+    filename[localeLength+3] = 't';
+    filename[localeLength+4] = 0;
+
+
+    if (status==NULL || U_FAILURE(*status)) {
+        return NULL;
+    }
+    if(filename==NULL){
+        *status=U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }else{
+        filelen = (int32_t)uprv_strlen(filename);
+    }
+    if(genrbdata->inputDir == NULL) {
+        const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR);
+        openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
+        openFileName[0] = '\0';
+        if (filenameBegin != NULL) {
+            /*
+             * When a filename ../../../data/root.txt is specified,
+             * we presume that the input directory is ../../../data
+             * This is very important when the resource file includes
+             * another file, like UCARules.txt or thaidict.brk.
+             */
+            int32_t filenameSize = (int32_t)(filenameBegin - filename + 1);
+            inputDirBuf = uprv_strncpy((char *)uprv_malloc(filenameSize), filename, filenameSize);
+
+            /* test for NULL */
+            if(inputDirBuf == NULL) {
+                *status = U_MEMORY_ALLOCATION_ERROR;
+                goto finish;
+            }
+
+            inputDirBuf[filenameSize - 1] = 0;
+            genrbdata->inputDir = inputDirBuf;
+            dirlen  = (int32_t)uprv_strlen(genrbdata->inputDir);
+        }
+    }else{
+        dirlen  = (int32_t)uprv_strlen(genrbdata->inputDir);
+
+        if(genrbdata->inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
+            openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
+
+            /* test for NULL */
+            if(openFileName == NULL) {
+                *status = U_MEMORY_ALLOCATION_ERROR;
+                goto finish;
+            }
+
+            openFileName[0] = '\0';
+            /*
+             * append the input dir to openFileName if the first char in
+             * filename is not file seperation char and the last char input directory is  not '.'.
+             * This is to support :
+             * genrb -s. /home/icu/data
+             * genrb -s. icu/data
+             * The user cannot mix notations like
+             * genrb -s. /icu/data --- the absolute path specified. -s redundant
+             * user should use
+             * genrb -s. icu/data  --- start from CWD and look in icu/data dir
+             */
+            if( (filename[0] != U_FILE_SEP_CHAR) && (genrbdata->inputDir[dirlen-1] !='.')){
+                uprv_strcpy(openFileName, genrbdata->inputDir);
+                openFileName[dirlen]     = U_FILE_SEP_CHAR;
+            }
+            openFileName[dirlen + 1] = '\0';
+        } else {
+            openFileName = (char *) uprv_malloc(dirlen + filelen + 1);
+
+            /* test for NULL */
+            if(openFileName == NULL) {
+                *status = U_MEMORY_ALLOCATION_ERROR;
+                goto finish;
+            }
+
+            uprv_strcpy(openFileName, genrbdata->inputDir);
+
+        }
+    }
+    uprv_strcat(openFileName, filename);
+    /* printf("%s\n", openFileName);  */
+    *status = U_ZERO_ERROR;
+    ucbuf = ucbuf_open(openFileName, &cp,getShowWarning(),TRUE, status);
+
+    if(*status == U_FILE_ACCESS_ERROR) {
+
+        fprintf(stderr, "couldn't open file %s\n", openFileName == NULL ? filename : openFileName);
+        goto finish;
+    }
+    if (ucbuf == NULL || U_FAILURE(*status)) {
+        fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName == NULL ? filename : openFileName,u_errorName(*status));
+        goto finish;
+    }
+
+    /* Parse the data into an SRBRoot */
+    data = parse(ucbuf, genrbdata->inputDir, genrbdata->outputDir, status);
+
+    root = data->fRoot;
+    collations = resLookup(root, "collations");
+    collation = resLookup(collations, type);
+    sequence = resLookup(collation, "Sequence");
+    urules = sequence->u.fString.fChars;
+    urulesLength = sequence->u.fString.fLength;
+    *pLength = urulesLength;
+
+finish:
+
+    if (inputDirBuf != NULL) {
+        uprv_free(inputDirBuf);
+    }
+
+    if (openFileName != NULL) {
+        uprv_free(openFileName);
+    }
+
+    if(ucbuf) {
+        ucbuf_close(ucbuf);
+    }
+
+    return urules;
+}
+
 static struct SResource *
-addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
+addCollation(ParseState* state, struct SResource  *result, uint32_t startline, UErrorCode *status)
 {
     struct SResource  *member = NULL;
     struct UString    *tokenValue;
@@ -633,13 +812,14 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
     UVersionInfo       version;
     UBool              override = FALSE;
     uint32_t           line;
+    GenrbData genrbdata;
     /* '{' . (name resource)* '}' */
     version[0]=0; version[1]=0; version[2]=0; version[3]=0;
 
     for (;;)
     {
         ustr_init(&comment);
-        token = getToken(&tokenValue, &comment, &line, status);
+        token = getToken(state, &tokenValue, &comment, &line, status);
 
         if (token == TOK_CLOSE_BRACE)
         {
@@ -671,7 +851,7 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
             return NULL;
         }
 
-        member = parseResource(subtag, NULL, status);
+        member = parseResource(state, subtag, NULL, status);
 
         if (U_FAILURE(*status))
         {
@@ -712,15 +892,9 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
         }
         else if (uprv_strcmp(subtag, "Sequence") == 0)
         {
-#if UCONFIG_NO_COLLATION
-            warning(line, "Not building collation elements because of UCONFIG_NO_COLLATION, see uconfig.h");
+#if UCONFIG_NO_COLLATION || UCONFIG_NO_FILE_IO
+            warning(line, "Not building collation elements because of UCONFIG_NO_COLLATION and/or UCONFIG_NO_FILE_IO, see uconfig.h");
 #else
-            /* in order to achieve smaller data files, we can direct genrb */
-            /* to omit collation rules */
-            if(!gOmitCollationRules) {
-              /* first we add the "Sequence", so that we always have rules */
-              table_add(result, member, line, status);
-            }
             if(gMakeBinaryCollation) {
                 UErrorCode intStatus = U_ZERO_ERROR;
 
@@ -728,12 +902,16 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
                 int32_t     len   = 0;
                 uint8_t   *data  = NULL;
                 UCollator *coll  = NULL;
+                int32_t reorderCodes[USCRIPT_CODE_LIMIT + (UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST)];
+                uint32_t reorderCodeCount;
+                int32_t reorderCodeIndex;
                 UParseError parseError;
-                /* add sequence */
-                /*table_add(result, member, line, status);*/
 
-                coll = ucol_openRules(member->u.fString.fChars, member->u.fString.fLength,
-                    UCOL_OFF, UCOL_DEFAULT_STRENGTH,&parseError, &intStatus);
+                genrbdata.inputDir = state->inputdir;
+                genrbdata.outputDir = state->outputdir;
+
+                coll = ucol_openRulesForImport(member->u.fString.fChars, member->u.fString.fLength,
+                                               UCOL_OFF, UCOL_DEFAULT_STRENGTH,&parseError, importFromDataFile, &genrbdata, &intStatus);
 
                 if (U_SUCCESS(intStatus) && coll != NULL)
                 {
@@ -754,10 +932,19 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
 
                     if (U_SUCCESS(intStatus) && data != NULL)
                     {
-                        member = bin_open(bundle, "%%CollationBin", len, data, NULL, NULL, status);
-                        /*table_add(bundle->fRoot, member, line, status);*/
-                        table_add(result, member, line, status);
+                        struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", len, data, NULL, NULL, status);
+                        table_add(result, collationBin, line, status);
                         uprv_free(data);
+                        
+                        reorderCodeCount = ucol_getReorderCodes(
+                            coll, reorderCodes, USCRIPT_CODE_LIMIT + (UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST), &intStatus);
+                        if (U_SUCCESS(intStatus) && reorderCodeCount > 0) {
+                            struct SResource *reorderCodeRes = intvector_open(state->bundle, "%%ReorderCodes", NULL, status);
+                            for (reorderCodeIndex = 0; reorderCodeIndex < reorderCodeCount; reorderCodeIndex++) {
+                                intvector_add(reorderCodeRes, reorderCodes[reorderCodeIndex], status);
+                            }
+                            table_add(result, reorderCodeRes, line, status);
+                        }
                     }
                     else
                     {
@@ -772,6 +959,11 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
                 }
                 else
                 {
+                    if(intStatus == U_FILE_ACCESS_ERROR) {
+                      error(startline, "Collation could not be built- U_FILE_ACCESS_ERROR. Make sure ICU's data has been built and is loading properly.");
+                      *status = intStatus;
+                      return NULL;
+                    }
                     warning(line, "%%Collation could not be constructed from CollationElements - check context!");
                     if(isStrict()){
                         *status = intStatus;
@@ -784,6 +976,13 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
                 }
             }
 #endif
+            /* in order to achieve smaller data files, we can direct genrb */
+            /* to omit collation rules */
+            if(gOmitCollationRules) {
+                bundle_closeString(state->bundle, member);
+            } else {
+                table_add(result, member, line, status);
+            }
         }
 
         /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);*/
@@ -804,7 +1003,7 @@ addCollation(struct SResource  *result, uint32_t startline, UErrorCode *status)
 }
 
 static struct SResource *
-parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UErrorCode *status)
+parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool newCollation, UErrorCode *status)
 {
     struct SResource  *result = NULL;
     struct SResource  *member = NULL;
@@ -815,7 +1014,7 @@ parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UError
     char               subtag[1024], typeKeyword[1024];
     uint32_t           line;
 
-    result = table_open(bundle, tag, NULL, status);
+    result = table_open(state->bundle, tag, NULL, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
@@ -825,12 +1024,12 @@ parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UError
         printf(" collation elements %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
     if(!newCollation) {
-        return addCollation(result, startline, status);
+        return addCollation(state, result, startline, status);
     }
     else {
         for(;;) {
             ustr_init(&comment);
-            token = getToken(&tokenValue, &comment, &line, status);
+            token = getToken(state, &tokenValue, &comment, &line, status);
 
             if (token == TOK_CLOSE_BRACE)
             {
@@ -864,7 +1063,7 @@ parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UError
 
             if (uprv_strcmp(subtag, "default") == 0)
             {
-                member = parseResource(subtag, NULL, status);
+                member = parseResource(state, subtag, NULL, status);
 
                 if (U_FAILURE(*status))
                 {
@@ -876,20 +1075,23 @@ parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UError
             }
             else
             {
-                token = peekToken(0, &tokenValue, &line, &comment, status);
+                token = peekToken(state, 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);
+                    token = getToken(state, &tokenValue, &comment, &line, status);
+                    collationRes = table_open(state->bundle, subtag, NULL, status);
+                    collationRes = addCollation(state, collationRes, startline, status); /* need to parse the collation data regardless */
+                    if (gIncludeUnihanColl || uprv_strcmp(subtag, "unihan") != 0) {
+                        table_add(result, collationRes, 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);
+                    token = peekToken(state, 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);
+                        member = parseResource(state, subtag, NULL, status);
 
                         if (U_FAILURE(*status))
                         {
@@ -926,7 +1128,7 @@ parseCollationElements(char *tag, uint32_t startline, UBool newCollation, UError
 /* 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 *
-realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCode *status)
+realParseTable(ParseState* state, struct SResource *table, char *tag, uint32_t startline, UErrorCode *status)
 {
     struct SResource  *member = NULL;
     struct UString    *tokenValue=NULL;
@@ -943,7 +1145,7 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
     for (;;)
     {
         ustr_init(&comment);
-        token = getToken(&tokenValue, &comment, &line, status);
+        token = getToken(state, &tokenValue, &comment, &line, status);
 
         if (token == TOK_CLOSE_BRACE)
         {
@@ -979,15 +1181,15 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
 
         if (U_FAILURE(*status))
         {
-            error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
+            error(line, "parse error. Stopped parsing tokens with %s", u_errorName(*status));
             return NULL;
         }
 
-        member = parseResource(subtag, &comment, status);
+        member = parseResource(state, subtag, &comment, status);
 
         if (member == NULL || U_FAILURE(*status))
         {
-            error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
+            error(line, "parse error. Stopped parsing resource with %s", u_errorName(*status));
             return NULL;
         }
 
@@ -995,7 +1197,7 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
 
         if (U_FAILURE(*status))
         {
-            error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
+            error(line, "parse error. Stopped parsing table with %s", u_errorName(*status));
             return NULL;
         }
         readToken = TRUE;
@@ -1009,34 +1211,34 @@ realParseTable(struct SResource *table, char *tag, uint32_t startline, UErrorCod
 }
 
 static struct SResource *
-parseTable(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
+parseTable(ParseState* state, 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, FALSE, status);
+        return parseCollationElements(state, tag, startline, FALSE, status);
     }
     if (tag != NULL && uprv_strcmp(tag, "collations") == 0)
     {
-        return parseCollationElements(tag, startline, TRUE, status);
+        return parseCollationElements(state, tag, startline, TRUE, status);
     }
     if(isVerbose()){
         printf(" table %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
-    result = table_open(bundle, tag, comment, status);
+    result = table_open(state->bundle, tag, comment, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    return realParseTable(result, tag, startline,  status);
+    return realParseTable(state, result, tag, startline,  status);
 }
 
 static struct SResource *
-parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
+parseArray(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource  *result = NULL;
     struct SResource  *member = NULL;
@@ -1045,7 +1247,7 @@ parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorC
     enum   ETokenType token;
     UBool             readToken = FALSE;
 
-    result = array_open(bundle, tag, comment, status);
+    result = array_open(state->bundle, tag, comment, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
@@ -1064,12 +1266,12 @@ parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorC
         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, &memberComments, status);
+        token = peekToken(state, 0, &tokenValue, NULL, &memberComments, status);
 
 
         if (token == TOK_CLOSE_BRACE)
         {
-            getToken(NULL, NULL, NULL, status);
+            getToken(state, NULL, NULL, NULL, status);
             if (!readToken) {
                 warning(startline, "Encountered empty array");
             }
@@ -1087,12 +1289,12 @@ parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorC
         /* string arrays are a special case */
         if (token == TOK_STRING)
         {
-            getToken(&tokenValue, &memberComments, NULL, status);
-            member = string_open(bundle, NULL, tokenValue->fChars, tokenValue->fLength, &memberComments, status);
+            getToken(state, &tokenValue, &memberComments, NULL, status);
+            member = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, &memberComments, status);
         }
         else
         {
-            member = parseResource(NULL, &memberComments, status);
+            member = parseResource(state, NULL, &memberComments, status);
         }
 
         if (member == NULL || U_FAILURE(*status))
@@ -1110,11 +1312,11 @@ parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorC
         }
 
         /* eat optional comma if present */
-        token = peekToken(0, NULL, NULL, NULL, status);
+        token = peekToken(state, 0, NULL, NULL, NULL, status);
 
         if (token == TOK_COMMA)
         {
-            getToken(NULL, NULL, NULL, status);
+            getToken(state, NULL, NULL, NULL, status);
         }
 
         if (U_FAILURE(*status))
@@ -1130,7 +1332,7 @@ parseArray(char *tag, uint32_t startline, const struct UString *comment, UErrorC
 }
 
 static struct SResource *
-parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
+parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource  *result = NULL;
     enum   ETokenType  token;
@@ -1141,7 +1343,7 @@ parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UEr
     uint32_t           len;
     struct UString     memberComments;
 
-    result = intvector_open(bundle, tag, comment, status);
+    result = intvector_open(state->bundle, tag, comment, status);
 
     if (result == NULL || U_FAILURE(*status))
     {
@@ -1158,12 +1360,12 @@ parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UEr
         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,&memberComments, status);
+        token = peekToken(state, 0, NULL, NULL,&memberComments, status);
 
         if (token == TOK_CLOSE_BRACE)
         {
             /* it's the end, consume the close brace */
-            getToken(NULL, NULL, NULL, status);
+            getToken(state, NULL, NULL, NULL, status);
             if (!readToken) {
                 warning(startline, "Encountered empty int vector");
             }
@@ -1171,7 +1373,7 @@ parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UEr
             return result;
         }
 
-        string = getInvariantString(NULL, NULL, status);
+        string = getInvariantString(state, NULL, NULL, status);
 
         if (U_FAILURE(*status))
         {
@@ -1187,7 +1389,7 @@ parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UEr
         {
             intvector_add(result, value, status);
             uprv_free(string);
-            token = peekToken(0, NULL, NULL, NULL, status);
+            token = peekToken(state, 0, NULL, NULL, NULL, status);
         }
         else
         {
@@ -1205,7 +1407,7 @@ parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UEr
         consecutive entries) so that a missing comma on the last entry isn't an error */
         if (token == TOK_COMMA)
         {
-            getToken(NULL, NULL, NULL, status);
+            getToken(state, NULL, NULL, NULL, status);
         }
         readToken = TRUE;
     }
@@ -1218,7 +1420,7 @@ parseIntVector(char *tag, uint32_t startline, const struct UString *comment, UEr
 }
 
 static struct SResource *
-parseBinary(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
+parseBinary(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     uint8_t          *value;
@@ -1230,14 +1432,14 @@ parseBinary(char *tag, uint32_t startline, const struct UString *comment, UError
     char             *stopstring;
     uint32_t          len;
 
-    string = getInvariantString(&line, NULL, status);
+    string = getInvariantString(state, &line, NULL, status);
 
     if (string == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1277,7 +1479,7 @@ parseBinary(char *tag, uint32_t startline, const struct UString *comment, UError
                 }
             }
 
-            result = bin_open(bundle, tag, (i >> 1), value,NULL, comment, status);
+            result = bin_open(state->bundle, tag, (i >> 1), value,NULL, comment, status);
 
             uprv_free(value);
         }
@@ -1291,7 +1493,7 @@ parseBinary(char *tag, uint32_t startline, const struct UString *comment, UError
     }
     else
     {
-        result = bin_open(bundle, tag, 0, NULL, "",comment,status);
+        result = bin_open(state->bundle, tag, 0, NULL, "",comment,status);
         warning(startline, "Encountered empty binary tag");
     }
     uprv_free(string);
@@ -1300,7 +1502,7 @@ parseBinary(char *tag, uint32_t startline, const struct UString *comment, UError
 }
 
 static struct SResource *
-parseInteger(char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
+parseInteger(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
 {
     struct SResource *result = NULL;
     int32_t           value;
@@ -1308,14 +1510,14 @@ parseInteger(char *tag, uint32_t startline, const struct UString *comment, UErro
     char             *stopstring;
     uint32_t          len;
 
-    string = getInvariantString(NULL, NULL, status);
+    string = getInvariantString(state, NULL, NULL, status);
 
     if (string == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1338,7 +1540,7 @@ parseInteger(char *tag, uint32_t startline, const struct UString *comment, UErro
     len=(uint32_t)(stopstring-string);
     if(len==uprv_strlen(string))
     {
-        result = int_open(bundle, tag, value, comment, status);
+        result = int_open(state->bundle, tag, value, comment, status);
     }
     else
     {
@@ -1350,7 +1552,7 @@ parseInteger(char *tag, uint32_t startline, const struct UString *comment, UErro
 }
 
 static struct SResource *
-parseImport(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
+parseImport(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result;
     FileStream       *file;
@@ -1360,14 +1562,14 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
     uint32_t          line;
     char     *fullname = NULL;
     int32_t numRead = 0;
-    filename = getInvariantString(&line, NULL, status);
+    filename = getInvariantString(state, &line, NULL, status);
 
     if (U_FAILURE(*status))
     {
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1380,7 +1582,7 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
     }
 
     /* Open the input file for reading */
-    if (inputdir == NULL)
+    if (state->inputdir == NULL)
     {
 #if 1
         /* 
@@ -1400,9 +1602,9 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
 
         int32_t  count     = (int32_t)uprv_strlen(filename);
 
-        if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
+        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
         {
-            fullname = (char *) uprv_malloc(inputdirLength + count + 2);
+            fullname = (char *) uprv_malloc(state->inputdirLength + count + 2);
 
             /* test for NULL */
             if(fullname == NULL)
@@ -1411,16 +1613,16 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
                 return NULL;
             }
 
-            uprv_strcpy(fullname, inputdir);
+            uprv_strcpy(fullname, state->inputdir);
 
-            fullname[inputdirLength]      = U_FILE_SEP_CHAR;
-            fullname[inputdirLength + 1] = '\0';
+            fullname[state->inputdirLength]      = U_FILE_SEP_CHAR;
+            fullname[state->inputdirLength + 1] = '\0';
 
             uprv_strcat(fullname, filename);
         }
         else
         {
-            fullname = (char *) uprv_malloc(inputdirLength + count + 1);
+            fullname = (char *) uprv_malloc(state->inputdirLength + count + 1);
 
             /* test for NULL */
             if(fullname == NULL)
@@ -1429,7 +1631,7 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
                 return NULL;
             }
 
-            uprv_strcpy(fullname, inputdir);
+            uprv_strcpy(fullname, state->inputdir);
             uprv_strcat(fullname, filename);
         }
 
@@ -1457,7 +1659,7 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
     numRead = T_FileStream_read  (file, data, len);
     T_FileStream_close (file);
 
-    result = bin_open(bundle, tag, len, data, fullname, comment, status);
+    result = bin_open(state->bundle, tag, len, data, fullname, comment, status);
 
     uprv_free(data);
     uprv_free(filename);
@@ -1467,7 +1669,7 @@ parseImport(char *tag, uint32_t startline, const struct UString* comment, UError
 }
 
 static struct SResource *
-parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
+parseInclude(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
 {
     struct SResource *result;
     int32_t           len=0;
@@ -1481,7 +1683,7 @@ parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErro
     const char* cp = NULL;
     const UChar* uBuffer = NULL;
 
-    filename = getInvariantString(&line, NULL, status);
+    filename = getInvariantString(state, &line, NULL, status);
     count     = (int32_t)uprv_strlen(filename);
 
     if (U_FAILURE(*status))
@@ -1489,7 +1691,7 @@ parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErro
         return NULL;
     }
 
-    expect(TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
+    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
 
     if (U_FAILURE(*status))
     {
@@ -1501,7 +1703,7 @@ parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErro
         printf(" include %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
     }
 
-    fullname = (char *) uprv_malloc(inputdirLength + count + 2);
+    fullname = (char *) uprv_malloc(state->inputdirLength + count + 2);
     /* test for NULL */
     if(fullname == NULL)
     {
@@ -1510,20 +1712,20 @@ parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErro
         return NULL;
     }
 
-    if(inputdir!=NULL){
-        if (inputdir[inputdirLength - 1] != U_FILE_SEP_CHAR)
+    if(state->inputdir!=NULL){
+        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
         {
 
-            uprv_strcpy(fullname, inputdir);
+            uprv_strcpy(fullname, state->inputdir);
 
-            fullname[inputdirLength]      = U_FILE_SEP_CHAR;
-            fullname[inputdirLength + 1] = '\0';
+            fullname[state->inputdirLength]      = U_FILE_SEP_CHAR;
+            fullname[state->inputdirLength + 1] = '\0';
 
             uprv_strcat(fullname, filename);
         }
         else
         {
-            uprv_strcpy(fullname, inputdir);
+            uprv_strcpy(fullname, state->inputdir);
             uprv_strcat(fullname, filename);
         }
     }else{
@@ -1538,7 +1740,7 @@ parseInclude(char *tag, uint32_t startline, const struct UString* comment, UErro
     }
 
     uBuffer = ucbuf_getBuffer(ucbuf,&len,status);
-    result = string_open(bundle, tag, uBuffer, len, comment, status);
+    result = string_open(state->bundle, tag, uBuffer, len, comment, status);
 
     uprv_free(pTarget);
 
@@ -1617,8 +1819,6 @@ static struct {
 
 void initParser(UBool omitBinaryCollation, UBool omitCollationRules)
 {
-    uint32_t i;
-
     U_STRING_INIT(k_type_string,    "string",    6);
     U_STRING_INIT(k_type_binary,    "binary",    6);
     U_STRING_INIT(k_type_bin,       "bin",       3);
@@ -1637,11 +1837,7 @@ void initParser(UBool omitBinaryCollation, UBool omitCollationRules)
     U_STRING_INIT(k_type_plugin_collation,      "process(collation)",        18);
     U_STRING_INIT(k_type_plugin_transliterator, "process(transliterator)",   23);
     U_STRING_INIT(k_type_plugin_dependency,     "process(dependency)",       19);
-    
-    for (i = 0; i < MAX_LOOKAHEAD + 1; i++)
-    {
-        ustr_init(&lookahead[i].value);
-    }
+
     gMakeBinaryCollation = !omitBinaryCollation;
     gOmitCollationRules = omitCollationRules;
 }
@@ -1651,14 +1847,14 @@ static U_INLINE UBool isTable(enum EResourceType type) {
 }
 
 static enum EResourceType
-parseResourceType(UErrorCode *status)
+parseResourceType(ParseState* state, UErrorCode *status)
 {
     struct UString        *tokenValue;
     struct UString        comment;
     enum   EResourceType  result = RT_UNKNOWN;
     uint32_t              line=0;
     ustr_init(&comment);
-    expect(TOK_STRING, &tokenValue, &comment, &line, status);
+    expect(state, TOK_STRING, &tokenValue, &comment, &line, status);
 
     if (U_FAILURE(*status))
     {
@@ -1694,7 +1890,7 @@ parseResourceType(UErrorCode *status)
 
 /* parse a non-top-level resource */
 static struct SResource *
-parseResource(char *tag, const struct UString *comment, UErrorCode *status)
+parseResource(ParseState* state, char *tag, const struct UString *comment, UErrorCode *status)
 {
     enum   ETokenType      token;
     enum   EResourceType  resType = RT_UNKNOWN;
@@ -1703,7 +1899,7 @@ parseResource(char *tag, const struct UString *comment, UErrorCode *status)
     uint32_t                 startline;
     uint32_t                 line;
 
-    token = getToken(&tokenValue, NULL, &startline, status);
+    token = getToken(state, &tokenValue, NULL, &startline, status);
 
     if(isVerbose()){
         printf(" resource %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
@@ -1725,8 +1921,8 @@ parseResource(char *tag, const struct UString *comment, UErrorCode *status)
         return NULL;
 
     case TOK_COLON:
-        resType = parseResourceType(status);
-        expect(TOK_OPEN_BRACE, &tokenValue, NULL, &startline, status);
+        resType = parseResourceType(state, status);
+        expect(state, TOK_OPEN_BRACE, &tokenValue, NULL, &startline, status);
 
         if (U_FAILURE(*status))
         {
@@ -1758,7 +1954,7 @@ parseResource(char *tag, const struct UString *comment, UErrorCode *status)
         { string }      => string
         */
 
-        token = peekToken(0, NULL, &line, NULL,status);
+        token = peekToken(state, 0, NULL, &line, NULL,status);
 
         if (U_FAILURE(*status))
         {
@@ -1771,7 +1967,7 @@ parseResource(char *tag, const struct UString *comment, UErrorCode *status)
         }
         else if (token == TOK_STRING)
         {
-            token = peekToken(1, NULL, &line, NULL, status);
+            token = peekToken(state, 1, NULL, &line, NULL, status);
 
             if (U_FAILURE(*status))
             {
@@ -1808,7 +2004,7 @@ parseResource(char *tag, const struct UString *comment, UErrorCode *status)
     function and return. */
     parseFunction = gResourceTypes[resType].parseFunction;
     if (parseFunction != NULL) {
-        return parseFunction(tag, startline, comment, status);
+        return parseFunction(state, tag, startline, comment, status);
     }
     else {
         *status = U_INTERNAL_PROGRAM_ERROR;
@@ -1827,39 +2023,51 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, UErrorCode *st
     uint32_t           line;
     enum EResourceType bundleType;
     enum ETokenType    token;
+    ParseState state;
+    uint32_t i;
+    int encLength;
+    char* enc;
+    for (i = 0; i < MAX_LOOKAHEAD + 1; i++)
+    {
+        ustr_init(&state.lookahead[i].value);
+        ustr_init(&state.lookahead[i].comment);
+    }
 
-    initLookahead(buf, status);
+    initLookahead(&state, buf, status);
 
-    inputdir       = inputDir;
-    inputdirLength = (inputdir != NULL) ? (uint32_t)uprv_strlen(inputdir) : 0;
-    outputdir       = outputDir;
-    outputdirLength = (outputdir != NULL) ? (uint32_t)uprv_strlen(outputdir) : 0;
+    state.inputdir       = inputDir;
+    state.inputdirLength = (state.inputdir != NULL) ? (uint32_t)uprv_strlen(state.inputdir) : 0;
+    state.outputdir       = outputDir;
+    state.outputdirLength = (state.outputdir != NULL) ? (uint32_t)uprv_strlen(state.outputdir) : 0;
 
     ustr_init(&comment);
-    expect(TOK_STRING, &tokenValue, &comment, NULL, status);
+    expect(&state, TOK_STRING, &tokenValue, &comment, NULL, status);
 
-    bundle = bundle_open(&comment, status);
+    state.bundle = bundle_open(&comment, FALSE, status);
 
-    if (bundle == NULL || U_FAILURE(*status))
+    if (state.bundle == NULL || U_FAILURE(*status))
     {
         return NULL;
     }
 
 
-    bundle_setlocale(bundle, tokenValue->fChars, status);
+    bundle_setlocale(state.bundle, tokenValue->fChars, status);
+
     /* The following code is to make Empty bundle work no matter with :table specifer or not */
-    token = getToken(NULL, NULL, &line, status);
+    token = getToken(&state, NULL, NULL, &line, status);
     if(token==TOK_COLON) {
         *status=U_ZERO_ERROR;
-        bundleType=parseResourceType(status);
+        bundleType=parseResourceType(&state, status);
 
         if(isTable(bundleType))
         {
-            expect(TOK_OPEN_BRACE, NULL, NULL, &line, status);
+            expect(&state, TOK_OPEN_BRACE, NULL, NULL, &line, status);
         }
         else
         {
             *status=U_PARSE_ERROR;
+            /* printf("asdsdweqdasdad\n"); */
+
             error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
         }
     }
@@ -1882,7 +2090,7 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, UErrorCode *st
 
     if (U_FAILURE(*status))
     {
-        bundle_close(bundle, status);
+        bundle_close(state.bundle, status);
         return NULL;
     }
 
@@ -1892,23 +2100,23 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, UErrorCode *st
          * This is the same as a regular table, but also sets the
          * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] .
          */
-        bundle->noFallback=TRUE;
+        state.bundle->noFallback=TRUE;
     }
     /* top-level tables need not handle special table names like "collations" */
-    realParseTable(bundle->fRoot, NULL, line, status);
-    
+    realParseTable(&state, state.bundle->fRoot, NULL, line, status);
+
     if(dependencyArray!=NULL){
-        table_add(bundle->fRoot, dependencyArray, 0, status);
+        table_add(state.bundle->fRoot, dependencyArray, 0, status);
         dependencyArray = NULL;
     }
     if (U_FAILURE(*status))
     {
-        bundle_close(bundle, status);
+        bundle_close(state.bundle, status);
         res_close(dependencyArray);
         return NULL;
     }
 
-    if (getToken(NULL, NULL, &line, status) != TOK_EOF)
+    if (getToken(&state, NULL, NULL, &line, status) != TOK_EOF)
     {
         warning(line, "extraneous text after resource bundle (perhaps unmatched braces)");
         if(isStrict()){
@@ -1917,8 +2125,7 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, UErrorCode *st
         }
     }
 
-    cleanupLookahead();
+    cleanupLookahead(&state);
     ustr_deinit(&comment);
-    return bundle;
+    return state.bundle;
 }
-