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