Home | History | Annotate | Download | only in genrb
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 1998-2010, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *
      9 * File genrb.c
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   05/25/99    stephen     Creation.
     15 *   5/10/01     Ram         removed ustdio dependency
     16 *******************************************************************************
     17 */
     18 
     19 #include "genrb.h"
     20 #include "unicode/uclean.h"
     21 
     22 #include "ucmndata.h"  /* TODO: for reading the pool bundle */
     23 
     24 /* Protos */
     25 void  processFile(const char *filename, const char* cp, const char *inputDir, const char *outputDir, const char *packageName, UErrorCode *status);
     26 static char *make_res_filename(const char *filename, const char *outputDir,
     27                                const char *packageName, UErrorCode *status);
     28 
     29 /* File suffixes */
     30 #define RES_SUFFIX ".res"
     31 #define COL_SUFFIX ".col"
     32 
     33 static char theCurrentFileName[2048];
     34 const char *gCurrentFileName = theCurrentFileName;
     35 #ifdef XP_MAC_CONSOLE
     36 #include <console.h>
     37 #endif
     38 
     39 enum
     40 {
     41     HELP1,
     42     HELP2,
     43     VERBOSE,
     44     QUIET,
     45     VERSION,
     46     SOURCEDIR,
     47     DESTDIR,
     48     ENCODING,
     49     ICUDATADIR,
     50     WRITE_JAVA,
     51     COPYRIGHT,
     52     /* PACKAGE_NAME, This option is deprecated and should not be used ever. */
     53     BUNDLE_NAME,
     54     WRITE_XLIFF,
     55     STRICT,
     56     NO_BINARY_COLLATION,
     57     /*added by Jing*/
     58     LANGUAGE,
     59     NO_COLLATION_RULES,
     60     FORMAT_VERSION,
     61     WRITE_POOL_BUNDLE,
     62     USE_POOL_BUNDLE,
     63     INCLUDE_UNIHAN_COLL
     64 };
     65 
     66 UOption options[]={
     67                       UOPTION_HELP_H,
     68                       UOPTION_HELP_QUESTION_MARK,
     69                       UOPTION_VERBOSE,
     70                       UOPTION_QUIET,
     71                       UOPTION_VERSION,
     72                       UOPTION_SOURCEDIR,
     73                       UOPTION_DESTDIR,
     74                       UOPTION_ENCODING,
     75                       UOPTION_ICUDATADIR,
     76                       UOPTION_WRITE_JAVA,
     77                       UOPTION_COPYRIGHT,
     78                       /* UOPTION_PACKAGE_NAME, This option is deprecated and should not be used ever. */
     79                       UOPTION_BUNDLE_NAME,
     80                       UOPTION_DEF("write-xliff", 'x', UOPT_OPTIONAL_ARG),
     81                       UOPTION_DEF("strict",    'k', UOPT_NO_ARG), /* 14 */
     82                       UOPTION_DEF("noBinaryCollation", 'C', UOPT_NO_ARG),/* 15 */
     83                       UOPTION_DEF("language",  'l', UOPT_REQUIRES_ARG), /* 16 */
     84                       UOPTION_DEF("omitCollationRules", 'R', UOPT_NO_ARG),/* 17 */
     85                       UOPTION_DEF("formatVersion", '\x01', UOPT_REQUIRES_ARG),/* 18 */
     86                       UOPTION_DEF("writePoolBundle", '\x01', UOPT_NO_ARG),/* 19 */
     87                       UOPTION_DEF("usePoolBundle", '\x01', UOPT_OPTIONAL_ARG),/* 20 */
     88                       UOPTION_DEF("includeUnihanColl", '\x01', UOPT_NO_ARG),/* 21 */ /* temporary, don't display in usage info */
     89                   };
     90 
     91 static     UBool       write_java = FALSE;
     92 static     UBool       write_xliff = FALSE;
     93 static     const char* outputEnc ="";
     94 static     const char* gPackageName=NULL;
     95 static     const char* bundleName=NULL;
     96 static     struct SRBRoot *newPoolBundle = NULL;
     97            UBool       gIncludeUnihanColl = FALSE;
     98 
     99 /* TODO: separate header file for ResFile? */
    100 typedef struct ResFile {
    101   uint8_t *fBytes;
    102   const int32_t *fIndexes;
    103   const char *fKeys;
    104   int32_t fKeysLength;
    105   int32_t fKeysCount;
    106   int32_t fChecksum;
    107 } ResFile;
    108 
    109 static ResFile poolBundle = { NULL };
    110 
    111 /*added by Jing*/
    112 static     const char* language = NULL;
    113 static     const char* xliffOutputFileName = NULL;
    114 int
    115 main(int argc,
    116      char* argv[])
    117 {
    118     UErrorCode  status    = U_ZERO_ERROR;
    119     const char *arg       = NULL;
    120     const char *outputDir = NULL; /* NULL = no output directory, use current */
    121     const char *inputDir  = NULL;
    122     const char *encoding  = "";
    123     int         i;
    124 
    125     U_MAIN_INIT_ARGS(argc, argv);
    126 
    127     argc = u_parseArgs(argc, argv, (int32_t)(sizeof(options)/sizeof(options[0])), options);
    128 
    129     /* error handling, printing usage message */
    130     if(argc<0) {
    131         fprintf(stderr, "%s: error in command line argument \"%s\"\n", argv[0], argv[-argc]);
    132     } else if(argc<2) {
    133         argc = -1;
    134     }
    135     if(options[WRITE_POOL_BUNDLE].doesOccur && options[USE_POOL_BUNDLE].doesOccur) {
    136         fprintf(stderr, "%s: cannot combine --writePoolBundle and --usePoolBundle\n", argv[0]);
    137         argc = -1;
    138     }
    139     if(options[FORMAT_VERSION].doesOccur) {
    140         const char *s = options[FORMAT_VERSION].value;
    141         if(uprv_strlen(s) != 1 || (s[0] != '1' && s[0] != '2')) {
    142             fprintf(stderr, "%s: unsupported --formatVersion %s\n", argv[0], s);
    143             argc = -1;
    144         } else if(s[0] == '1' &&
    145                   (options[WRITE_POOL_BUNDLE].doesOccur || options[USE_POOL_BUNDLE].doesOccur)
    146         ) {
    147             fprintf(stderr, "%s: cannot combine --formatVersion 1 with --writePoolBundle or --usePoolBundle\n", argv[0]);
    148             argc = -1;
    149         } else {
    150             setFormatVersion(s[0] - '0');
    151         }
    152     }
    153 
    154     if(options[VERSION].doesOccur) {
    155         fprintf(stderr,
    156                 "%s version %s (ICU version %s).\n"
    157                 "%s\n",
    158                 argv[0], GENRB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING);
    159         return U_ZERO_ERROR;
    160     }
    161 
    162     if(argc<0 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
    163         /*
    164          * Broken into chunks because the C89 standard says the minimum
    165          * required supported string length is 509 bytes.
    166          */
    167         fprintf(stderr,
    168                 "Usage: %s [OPTIONS] [FILES]\n"
    169                 "\tReads the list of resource bundle source files and creates\n"
    170                 "\tbinary version of reosurce bundles (.res files)\n",
    171                 argv[0]);
    172         fprintf(stderr,
    173                 "Options:\n"
    174                 "\t-h or -? or --help       this usage text\n"
    175                 "\t-q or --quiet            do not display warnings\n"
    176                 "\t-v or --verbose          print extra information when processing files\n"
    177                 "\t-V or --version          prints out version number and exits\n"
    178                 "\t-c or --copyright        include copyright notice\n");
    179         fprintf(stderr,
    180                 "\t-e or --encoding         encoding of source files\n"
    181                 "\t-d of --destdir          destination directory, followed by the path, defaults to %s\n"
    182                 "\t-s or --sourcedir        source directory for files followed by path, defaults to %s\n"
    183                 "\t-i or --icudatadir       directory for locating any needed intermediate data files,\n"
    184                 "\t                         followed by path, defaults to %s\n",
    185                 u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory());
    186         fprintf(stderr,
    187                 "\t-j or --write-java       write a Java ListResourceBundle for ICU4J, followed by optional encoding\n"
    188                 "\t                         defaults to ASCII and \\uXXXX format.\n");
    189                 /* This option is deprecated and should not be used ever.
    190                 "\t-p or --package-name     For ICU4J: package name for writing the ListResourceBundle for ICU4J,\n"
    191                 "\t                         defaults to com.ibm.icu.impl.data\n"); */
    192         fprintf(stderr,
    193                 "\t-b or --bundle-name      bundle name for writing the ListResourceBundle for ICU4J,\n"
    194                 "\t                         defaults to LocaleElements\n"
    195                 "\t-x or --write-xliff      write an XLIFF file for the resource bundle. Followed by\n"
    196                 "\t                         an optional output file name.\n"
    197                 "\t-k or --strict           use pedantic parsing of syntax\n"
    198                 /*added by Jing*/
    199                 "\t-l or --language         for XLIFF: language code compliant with BCP 47.\n");
    200         fprintf(stderr,
    201                 "\t-C or --noBinaryCollation  do not generate binary collation image;\n"
    202                 "\t                           makes .res file smaller but collator instantiation much slower;\n"
    203                 "\t                           maintains ability to get tailoring rules\n"
    204                 "\t-R or --omitCollationRules do not include collation (tailoring) rules;\n"
    205                 "\t                           makes .res file smaller and maintains collator instantiation speed\n"
    206                 "\t                           but tailoring rules will not be available (they are rarely used)\n");
    207         fprintf(stderr,
    208                 "\t      --formatVersion      write a .res file compatible with the requested formatVersion (single digit);\n"
    209                 "\t                           for example, --formatVersion 1\n");
    210         fprintf(stderr,
    211                 "\t      --writePoolBundle    write a pool.res file with all of the keys of all input bundles\n"
    212                 "\t      --usePoolBundle [path-to-pool.res]  point to keys from the pool.res keys pool bundle if they are available there;\n"
    213                 "\t                           makes .res files smaller but dependent on the pool bundle\n"
    214                 "\t                           (--writePoolBundle and --usePoolBundle cannot be combined)\n");
    215 
    216         return argc < 0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR;
    217     }
    218 
    219     if(options[VERBOSE].doesOccur) {
    220         setVerbose(TRUE);
    221     }
    222 
    223     if(options[QUIET].doesOccur) {
    224         setShowWarning(FALSE);
    225     }
    226     if(options[STRICT].doesOccur) {
    227         setStrict(TRUE);
    228     }
    229     if(options[COPYRIGHT].doesOccur){
    230         setIncludeCopyright(TRUE);
    231     }
    232 
    233     if(options[SOURCEDIR].doesOccur) {
    234         inputDir = options[SOURCEDIR].value;
    235     }
    236 
    237     if(options[DESTDIR].doesOccur) {
    238         outputDir = options[DESTDIR].value;
    239     }
    240     /* This option is deprecated and should never be used.
    241     if(options[PACKAGE_NAME].doesOccur) {
    242         gPackageName = options[PACKAGE_NAME].value;
    243         if(!strcmp(gPackageName, "ICUDATA"))
    244         {
    245             gPackageName = U_ICUDATA_NAME;
    246         }
    247         if(gPackageName[0] == 0)
    248         {
    249             gPackageName = NULL;
    250         }
    251     }*/
    252 
    253     if(options[ENCODING].doesOccur) {
    254         encoding = options[ENCODING].value;
    255     }
    256 
    257     if(options[ICUDATADIR].doesOccur) {
    258         u_setDataDirectory(options[ICUDATADIR].value);
    259     }
    260     /* Initialize ICU */
    261     u_init(&status);
    262     if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
    263         /* Note: u_init() will try to open ICU property data.
    264          *       failures here are expected when building ICU from scratch.
    265          *       ignore them.
    266         */
    267         fprintf(stderr, "%s: can not initialize ICU.  status = %s\n",
    268             argv[0], u_errorName(status));
    269         exit(1);
    270     }
    271     status = U_ZERO_ERROR;
    272     if(options[WRITE_JAVA].doesOccur) {
    273         write_java = TRUE;
    274         outputEnc = options[WRITE_JAVA].value;
    275     }
    276 
    277     if(options[BUNDLE_NAME].doesOccur) {
    278         bundleName = options[BUNDLE_NAME].value;
    279     }
    280 
    281     if(options[WRITE_XLIFF].doesOccur) {
    282         write_xliff = TRUE;
    283         if(options[WRITE_XLIFF].value != NULL){
    284             xliffOutputFileName = options[WRITE_XLIFF].value;
    285         }
    286     }
    287 
    288     initParser(options[NO_BINARY_COLLATION].doesOccur, options[NO_COLLATION_RULES].doesOccur);
    289 
    290     /*added by Jing*/
    291     if(options[LANGUAGE].doesOccur) {
    292         language = options[LANGUAGE].value;
    293     }
    294 
    295     if(options[WRITE_POOL_BUNDLE].doesOccur) {
    296         newPoolBundle = bundle_open(NULL, TRUE, &status);
    297         if(U_FAILURE(status)) {
    298             fprintf(stderr, "unable to create an empty bundle for the pool keys: %s\n", u_errorName(status));
    299             return status;
    300         } else {
    301             const char *poolResName = "pool.res";
    302             char *nameWithoutSuffix = uprv_malloc(uprv_strlen(poolResName) + 1);
    303             if (nameWithoutSuffix == NULL) {
    304                 fprintf(stderr, "out of memory error\n");
    305                 return U_MEMORY_ALLOCATION_ERROR;
    306             }
    307             uprv_strcpy(nameWithoutSuffix, poolResName);
    308             *uprv_strrchr(nameWithoutSuffix, '.') = 0;
    309             newPoolBundle->fLocale = nameWithoutSuffix;
    310         }
    311     }
    312 
    313     if(options[USE_POOL_BUNDLE].doesOccur) {
    314         const char *poolResName = "pool.res";
    315         FileStream *poolFile;
    316         int32_t poolFileSize;
    317         int32_t indexLength;
    318         /*
    319          * TODO: Consolidate inputDir/filename handling from main() and processFile()
    320          * into a common function, and use it here as well.
    321          * Try to create toolutil functions for dealing with dir/filenames and
    322          * loading ICU data files without udata_open().
    323          * Share code with icupkg?
    324          * Also, make_res_filename() seems to be unused. Review and remove.
    325          */
    326         if (options[USE_POOL_BUNDLE].value!=NULL) {
    327             uprv_strcpy(theCurrentFileName, options[USE_POOL_BUNDLE].value);
    328             uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING);
    329         } else if (inputDir) {
    330             uprv_strcpy(theCurrentFileName, inputDir);
    331             uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING);
    332         } else {
    333             *theCurrentFileName = 0;
    334         }
    335         uprv_strcat(theCurrentFileName, poolResName);
    336         poolFile = T_FileStream_open(theCurrentFileName, "rb");
    337         if (poolFile == NULL) {
    338             fprintf(stderr, "unable to open pool bundle file %s\n", theCurrentFileName);
    339             return 1;
    340         }
    341         poolFileSize = T_FileStream_size(poolFile);
    342         if (poolFileSize < 32) {
    343             fprintf(stderr, "the pool bundle file %s is too small\n", theCurrentFileName);
    344             return 1;
    345         }
    346         poolBundle.fBytes = (uint8_t *)uprv_malloc((poolFileSize + 15) & ~15);
    347         if (poolFileSize > 0 && poolBundle.fBytes == NULL) {
    348             fprintf(stderr, "unable to allocate memory for the pool bundle file %s\n", theCurrentFileName);
    349             return U_MEMORY_ALLOCATION_ERROR;
    350         } else {
    351             UDataSwapper *ds;
    352             const DataHeader *header;
    353             int32_t bytesRead = T_FileStream_read(poolFile, poolBundle.fBytes, poolFileSize);
    354             int32_t keysBottom;
    355             if (bytesRead != poolFileSize) {
    356                 fprintf(stderr, "unable to read the pool bundle file %s\n", theCurrentFileName);
    357                 return 1;
    358             }
    359             /*
    360              * Swap the pool bundle so that a single checked-in file can be used.
    361              * The swapper functions also test that the data looks like
    362              * a well-formed .res file.
    363              */
    364             ds = udata_openSwapperForInputData(poolBundle.fBytes, bytesRead,
    365                                                U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &status);
    366             if (U_FAILURE(status)) {
    367                 fprintf(stderr, "udata_openSwapperForInputData(pool bundle %s) failed: %s\n",
    368                         theCurrentFileName, u_errorName(status));
    369                 return status;
    370             }
    371             ures_swap(ds, poolBundle.fBytes, bytesRead, poolBundle.fBytes, &status);
    372             udata_closeSwapper(ds);
    373             if (U_FAILURE(status)) {
    374                 fprintf(stderr, "ures_swap(pool bundle %s) failed: %s\n",
    375                         theCurrentFileName, u_errorName(status));
    376                 return status;
    377             }
    378             header = (const DataHeader *)poolBundle.fBytes;
    379             if (header->info.formatVersion[0]!=2) {
    380                 fprintf(stderr, "invalid format of pool bundle file %s\n", theCurrentFileName);
    381                 return U_INVALID_FORMAT_ERROR;
    382             }
    383             poolBundle.fKeys = (const char *)header + header->dataHeader.headerSize;
    384             poolBundle.fIndexes = (const int32_t *)poolBundle.fKeys + 1;
    385             indexLength = poolBundle.fIndexes[URES_INDEX_LENGTH] & 0xff;
    386             if (indexLength <= URES_INDEX_POOL_CHECKSUM) {
    387                 fprintf(stderr, "insufficient indexes[] in pool bundle file %s\n", theCurrentFileName);
    388                 return U_INVALID_FORMAT_ERROR;
    389             }
    390             keysBottom = (1 + indexLength) * 4;
    391             poolBundle.fKeys += keysBottom;
    392             poolBundle.fKeysLength = (poolBundle.fIndexes[URES_INDEX_KEYS_TOP] * 4) - keysBottom;
    393             poolBundle.fChecksum = poolBundle.fIndexes[URES_INDEX_POOL_CHECKSUM];
    394         }
    395         for (i = 0; i < poolBundle.fKeysLength; ++i) {
    396             if (poolBundle.fKeys[i] == 0) {
    397                 ++poolBundle.fKeysCount;
    398             }
    399         }
    400         T_FileStream_close(poolFile);
    401         setUsePoolBundle(TRUE);
    402     }
    403 
    404     if(options[INCLUDE_UNIHAN_COLL].doesOccur) {
    405         gIncludeUnihanColl = TRUE;
    406     }
    407 
    408     if((argc-1)!=1) {
    409         printf("genrb number of files: %d\n", argc - 1);
    410     }
    411     /* generate the binary files */
    412     for(i = 1; i < argc; ++i) {
    413         status = U_ZERO_ERROR;
    414         arg    = getLongPathname(argv[i]);
    415 
    416         if (inputDir) {
    417             uprv_strcpy(theCurrentFileName, inputDir);
    418             uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING);
    419         } else {
    420             *theCurrentFileName = 0;
    421         }
    422         uprv_strcat(theCurrentFileName, arg);
    423 
    424         if (isVerbose()) {
    425             printf("Processing file \"%s\"\n", theCurrentFileName);
    426         }
    427         processFile(arg, encoding, inputDir, outputDir, gPackageName, &status);
    428     }
    429 
    430     uprv_free(poolBundle.fBytes);
    431 
    432     if(options[WRITE_POOL_BUNDLE].doesOccur) {
    433         char outputFileName[256];
    434         bundle_write(newPoolBundle, outputDir, NULL, outputFileName, sizeof(outputFileName), &status);
    435         bundle_close(newPoolBundle, &status);
    436         if(U_FAILURE(status)) {
    437             fprintf(stderr, "unable to write the pool bundle: %s\n", u_errorName(status));
    438         }
    439     }
    440 
    441     /* Dont return warnings as a failure */
    442     if (U_SUCCESS(status)) {
    443         return 0;
    444     }
    445 
    446     return status;
    447 }
    448 
    449 /* Process a file */
    450 void
    451 processFile(const char *filename, const char *cp, const char *inputDir, const char *outputDir, const char *packageName, UErrorCode *status) {
    452     /*FileStream     *in           = NULL;*/
    453     struct SRBRoot *data         = NULL;
    454     UCHARBUF       *ucbuf        = NULL;
    455     char           *rbname       = NULL;
    456     char           *openFileName = NULL;
    457     char           *inputDirBuf  = NULL;
    458 
    459     char           outputFileName[256];
    460 
    461     int32_t dirlen  = 0;
    462     int32_t filelen = 0;
    463 
    464 
    465     if (status==NULL || U_FAILURE(*status)) {
    466         return;
    467     }
    468     if(filename==NULL){
    469         *status=U_ILLEGAL_ARGUMENT_ERROR;
    470         return;
    471     }else{
    472         filelen = (int32_t)uprv_strlen(filename);
    473     }
    474     if(inputDir == NULL) {
    475         const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR);
    476         openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
    477         openFileName[0] = '\0';
    478         if (filenameBegin != NULL) {
    479             /*
    480              * When a filename ../../../data/root.txt is specified,
    481              * we presume that the input directory is ../../../data
    482              * This is very important when the resource file includes
    483              * another file, like UCARules.txt or thaidict.brk.
    484              */
    485             int32_t filenameSize = (int32_t)(filenameBegin - filename + 1);
    486             inputDirBuf = uprv_strncpy((char *)uprv_malloc(filenameSize), filename, filenameSize);
    487 
    488             /* test for NULL */
    489             if(inputDirBuf == NULL) {
    490                 *status = U_MEMORY_ALLOCATION_ERROR;
    491                 goto finish;
    492             }
    493 
    494             inputDirBuf[filenameSize - 1] = 0;
    495             inputDir = inputDirBuf;
    496             dirlen  = (int32_t)uprv_strlen(inputDir);
    497         }
    498     }else{
    499         dirlen  = (int32_t)uprv_strlen(inputDir);
    500 
    501         if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
    502             openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
    503 
    504             /* test for NULL */
    505             if(openFileName == NULL) {
    506                 *status = U_MEMORY_ALLOCATION_ERROR;
    507                 goto finish;
    508             }
    509 
    510             openFileName[0] = '\0';
    511             /*
    512              * append the input dir to openFileName if the first char in
    513              * filename is not file seperation char and the last char input directory is  not '.'.
    514              * This is to support :
    515              * genrb -s. /home/icu/data
    516              * genrb -s. icu/data
    517              * The user cannot mix notations like
    518              * genrb -s. /icu/data --- the absolute path specified. -s redundant
    519              * user should use
    520              * genrb -s. icu/data  --- start from CWD and look in icu/data dir
    521              */
    522             if( (filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')){
    523                 uprv_strcpy(openFileName, inputDir);
    524                 openFileName[dirlen]     = U_FILE_SEP_CHAR;
    525             }
    526             openFileName[dirlen + 1] = '\0';
    527         } else {
    528             openFileName = (char *) uprv_malloc(dirlen + filelen + 1);
    529 
    530             /* test for NULL */
    531             if(openFileName == NULL) {
    532                 *status = U_MEMORY_ALLOCATION_ERROR;
    533                 goto finish;
    534             }
    535 
    536             uprv_strcpy(openFileName, inputDir);
    537 
    538         }
    539     }
    540 
    541     uprv_strcat(openFileName, filename);
    542 
    543     ucbuf = ucbuf_open(openFileName, &cp,getShowWarning(),TRUE, status);
    544     if(*status == U_FILE_ACCESS_ERROR) {
    545 
    546         fprintf(stderr, "couldn't open file %s\n", openFileName == NULL ? filename : openFileName);
    547         goto finish;
    548     }
    549     if (ucbuf == NULL || U_FAILURE(*status)) {
    550         fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName == NULL ? filename : openFileName,u_errorName(*status));
    551         goto finish;
    552     }
    553     /* auto detected popular encodings? */
    554     if (cp!=NULL && isVerbose()) {
    555         printf("autodetected encoding %s\n", cp);
    556     }
    557     /* Parse the data into an SRBRoot */
    558     data = parse(ucbuf, inputDir, outputDir, status);
    559 
    560     if (data == NULL || U_FAILURE(*status)) {
    561         fprintf(stderr, "couldn't parse the file %s. Error:%s\n", filename,u_errorName(*status));
    562         goto finish;
    563     }
    564     if(options[WRITE_POOL_BUNDLE].doesOccur) {
    565         int32_t newKeysLength;
    566         const char *newKeys, *newKeysLimit;
    567         bundle_compactKeys(data, status);
    568         newKeys = bundle_getKeyBytes(data, &newKeysLength);
    569         bundle_addKeyBytes(newPoolBundle, newKeys, newKeysLength, status);
    570         if(U_FAILURE(*status)) {
    571             fprintf(stderr, "bundle_compactKeys(%s) or bundle_getKeyBytes() failed: %s\n",
    572                     filename, u_errorName(*status));
    573             goto finish;
    574         }
    575         /* count the number of just-added key strings */
    576         for(newKeysLimit = newKeys + newKeysLength; newKeys < newKeysLimit; ++newKeys) {
    577             if(*newKeys == 0) {
    578                 ++newPoolBundle->fKeysCount;
    579             }
    580         }
    581     }
    582 
    583     if(options[USE_POOL_BUNDLE].doesOccur) {
    584         data->fPoolBundleKeys = poolBundle.fKeys;
    585         data->fPoolBundleKeysLength = poolBundle.fKeysLength;
    586         data->fPoolBundleKeysCount = poolBundle.fKeysCount;
    587         data->fPoolChecksum = poolBundle.fChecksum;
    588     }
    589 
    590     /* Determine the target rb filename */
    591     rbname = make_res_filename(filename, outputDir, packageName, status);
    592     if(U_FAILURE(*status)) {
    593         fprintf(stderr, "couldn't make the res fileName for  bundle %s. Error:%s\n", filename,u_errorName(*status));
    594         goto finish;
    595     }
    596     if(write_java== TRUE){
    597         bundle_write_java(data,outputDir,outputEnc, outputFileName, sizeof(outputFileName),packageName,bundleName,status);
    598     }else if(write_xliff ==TRUE){
    599         bundle_write_xml(data,outputDir,outputEnc, filename, outputFileName, sizeof(outputFileName),language, xliffOutputFileName,status);
    600     }else{
    601         /* Write the data to the file */
    602         bundle_write(data, outputDir, packageName, outputFileName, sizeof(outputFileName), status);
    603     }
    604     if (U_FAILURE(*status)) {
    605         fprintf(stderr, "couldn't write bundle %s. Error:%s\n", outputFileName,u_errorName(*status));
    606     }
    607     bundle_close(data, status);
    608 
    609 finish:
    610 
    611     if (inputDirBuf != NULL) {
    612         uprv_free(inputDirBuf);
    613     }
    614 
    615     if (openFileName != NULL) {
    616         uprv_free(openFileName);
    617     }
    618 
    619     if(ucbuf) {
    620         ucbuf_close(ucbuf);
    621     }
    622 
    623     if (rbname) {
    624         uprv_free(rbname);
    625     }
    626 }
    627 
    628 /* Generate the target .res file name from the input file name */
    629 static char*
    630 make_res_filename(const char *filename,
    631                   const char *outputDir,
    632                   const char *packageName,
    633                   UErrorCode *status) {
    634     char *basename;
    635     char *dirname;
    636     char *resName;
    637 
    638     int32_t pkgLen = 0; /* length of package prefix */
    639 
    640     if (U_FAILURE(*status)) {
    641         return 0;
    642     }
    643 
    644     if(packageName != NULL)
    645     {
    646         pkgLen = (int32_t)(1 + uprv_strlen(packageName));
    647     }
    648 
    649     /* setup */
    650     basename = dirname = resName = 0;
    651 
    652     /* determine basename, and compiled file names */
    653     basename = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1));
    654     if(basename == 0) {
    655         *status = U_MEMORY_ALLOCATION_ERROR;
    656         goto finish;
    657     }
    658 
    659     get_basename(basename, filename);
    660 
    661     dirname = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1));
    662     if(dirname == 0) {
    663         *status = U_MEMORY_ALLOCATION_ERROR;
    664         goto finish;
    665     }
    666 
    667     get_dirname(dirname, filename);
    668 
    669     if (outputDir == NULL) {
    670         /* output in same dir as .txt */
    671         resName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(dirname)
    672                                       + pkgLen
    673                                       + uprv_strlen(basename)
    674                                       + uprv_strlen(RES_SUFFIX) + 8));
    675         if(resName == 0) {
    676             *status = U_MEMORY_ALLOCATION_ERROR;
    677             goto finish;
    678         }
    679 
    680         uprv_strcpy(resName, dirname);
    681 
    682         if(packageName != NULL)
    683         {
    684             uprv_strcat(resName, packageName);
    685             uprv_strcat(resName, "_");
    686         }
    687 
    688         uprv_strcat(resName, basename);
    689 
    690     } else {
    691         int32_t dirlen      = (int32_t)uprv_strlen(outputDir);
    692         int32_t basenamelen = (int32_t)uprv_strlen(basename);
    693 
    694         resName = (char*) uprv_malloc(sizeof(char) * (dirlen + pkgLen + basenamelen + 8));
    695 
    696         if (resName == NULL) {
    697             *status = U_MEMORY_ALLOCATION_ERROR;
    698             goto finish;
    699         }
    700 
    701         uprv_strcpy(resName, outputDir);
    702 
    703         if(outputDir[dirlen] != U_FILE_SEP_CHAR) {
    704             resName[dirlen]     = U_FILE_SEP_CHAR;
    705             resName[dirlen + 1] = '\0';
    706         }
    707 
    708         if(packageName != NULL)
    709         {
    710             uprv_strcat(resName, packageName);
    711             uprv_strcat(resName, "_");
    712         }
    713 
    714         uprv_strcat(resName, basename);
    715     }
    716 
    717 finish:
    718     uprv_free(basename);
    719     uprv_free(dirname);
    720 
    721     return resName;
    722 }
    723 
    724 /*
    725  * Local Variables:
    726  * indent-tabs-mode: nil
    727  * End:
    728  */
    729