xref: /aosp_15_r20/external/icu/icu4c/source/tools/genrb/genrb.cpp (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker *
6*0e209d39SAndroid Build Coastguard Worker *   Copyright (C) 1998-2016, International Business Machines
7*0e209d39SAndroid Build Coastguard Worker *   Corporation and others.  All Rights Reserved.
8*0e209d39SAndroid Build Coastguard Worker *
9*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
10*0e209d39SAndroid Build Coastguard Worker *
11*0e209d39SAndroid Build Coastguard Worker * File genrb.cpp
12*0e209d39SAndroid Build Coastguard Worker *
13*0e209d39SAndroid Build Coastguard Worker * Modification History:
14*0e209d39SAndroid Build Coastguard Worker *
15*0e209d39SAndroid Build Coastguard Worker *   Date        Name        Description
16*0e209d39SAndroid Build Coastguard Worker *   05/25/99    stephen     Creation.
17*0e209d39SAndroid Build Coastguard Worker *   5/10/01     Ram         removed ustdio dependency
18*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
19*0e209d39SAndroid Build Coastguard Worker */
20*0e209d39SAndroid Build Coastguard Worker 
21*0e209d39SAndroid Build Coastguard Worker #include <fstream>
22*0e209d39SAndroid Build Coastguard Worker #include <iostream>
23*0e209d39SAndroid Build Coastguard Worker #include <list>
24*0e209d39SAndroid Build Coastguard Worker #include <string>
25*0e209d39SAndroid Build Coastguard Worker 
26*0e209d39SAndroid Build Coastguard Worker #include <assert.h>
27*0e209d39SAndroid Build Coastguard Worker #include "genrb.h"
28*0e209d39SAndroid Build Coastguard Worker #include "unicode/localpointer.h"
29*0e209d39SAndroid Build Coastguard Worker #include "unicode/uclean.h"
30*0e209d39SAndroid Build Coastguard Worker #include "unicode/utf16.h"
31*0e209d39SAndroid Build Coastguard Worker #include "charstr.h"
32*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h"
33*0e209d39SAndroid Build Coastguard Worker #include "filterrb.h"
34*0e209d39SAndroid Build Coastguard Worker #include "reslist.h"
35*0e209d39SAndroid Build Coastguard Worker #include "ucmndata.h"  /* TODO: for reading the pool bundle */
36*0e209d39SAndroid Build Coastguard Worker #include "collationroot.h"
37*0e209d39SAndroid Build Coastguard Worker 
38*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_USE
39*0e209d39SAndroid Build Coastguard Worker 
40*0e209d39SAndroid Build Coastguard Worker /* Protos */
41*0e209d39SAndroid Build Coastguard Worker void  processFile(const char *filename, const char* cp,
42*0e209d39SAndroid Build Coastguard Worker                   const char *inputDir, const char *outputDir, const char *filterDir,
43*0e209d39SAndroid Build Coastguard Worker                   const char *packageName,
44*0e209d39SAndroid Build Coastguard Worker                   SRBRoot *newPoolBundle, UBool omitBinaryCollation, UErrorCode &status);
45*0e209d39SAndroid Build Coastguard Worker static char *make_res_filename(const char *filename, const char *outputDir,
46*0e209d39SAndroid Build Coastguard Worker                                const char *packageName, UErrorCode &status);
47*0e209d39SAndroid Build Coastguard Worker 
48*0e209d39SAndroid Build Coastguard Worker /* File suffixes */
49*0e209d39SAndroid Build Coastguard Worker #define RES_SUFFIX ".res"
50*0e209d39SAndroid Build Coastguard Worker #define COL_SUFFIX ".col"
51*0e209d39SAndroid Build Coastguard Worker 
52*0e209d39SAndroid Build Coastguard Worker const char *gCurrentFileName = nullptr;
53*0e209d39SAndroid Build Coastguard Worker #ifdef XP_MAC_CONSOLE
54*0e209d39SAndroid Build Coastguard Worker #include <console.h>
55*0e209d39SAndroid Build Coastguard Worker #endif
56*0e209d39SAndroid Build Coastguard Worker 
close()57*0e209d39SAndroid Build Coastguard Worker void ResFile::close() {
58*0e209d39SAndroid Build Coastguard Worker     delete[] fBytes;
59*0e209d39SAndroid Build Coastguard Worker     fBytes = nullptr;
60*0e209d39SAndroid Build Coastguard Worker     delete fStrings;
61*0e209d39SAndroid Build Coastguard Worker     fStrings = nullptr;
62*0e209d39SAndroid Build Coastguard Worker }
63*0e209d39SAndroid Build Coastguard Worker 
64*0e209d39SAndroid Build Coastguard Worker enum
65*0e209d39SAndroid Build Coastguard Worker {
66*0e209d39SAndroid Build Coastguard Worker     HELP1,
67*0e209d39SAndroid Build Coastguard Worker     HELP2,
68*0e209d39SAndroid Build Coastguard Worker     VERBOSE,
69*0e209d39SAndroid Build Coastguard Worker     QUIET,
70*0e209d39SAndroid Build Coastguard Worker     VERSION,
71*0e209d39SAndroid Build Coastguard Worker     SOURCEDIR,
72*0e209d39SAndroid Build Coastguard Worker     DESTDIR,
73*0e209d39SAndroid Build Coastguard Worker     ENCODING,
74*0e209d39SAndroid Build Coastguard Worker     ICUDATADIR,
75*0e209d39SAndroid Build Coastguard Worker     WRITE_JAVA,
76*0e209d39SAndroid Build Coastguard Worker     COPYRIGHT,
77*0e209d39SAndroid Build Coastguard Worker     JAVA_PACKAGE,
78*0e209d39SAndroid Build Coastguard Worker     BUNDLE_NAME,
79*0e209d39SAndroid Build Coastguard Worker     WRITE_XLIFF,
80*0e209d39SAndroid Build Coastguard Worker     STRICT,
81*0e209d39SAndroid Build Coastguard Worker     NO_BINARY_COLLATION,
82*0e209d39SAndroid Build Coastguard Worker     LANGUAGE,
83*0e209d39SAndroid Build Coastguard Worker     NO_COLLATION_RULES,
84*0e209d39SAndroid Build Coastguard Worker     FORMAT_VERSION,
85*0e209d39SAndroid Build Coastguard Worker     WRITE_POOL_BUNDLE,
86*0e209d39SAndroid Build Coastguard Worker     USE_POOL_BUNDLE,
87*0e209d39SAndroid Build Coastguard Worker     INCLUDE_UNIHAN_COLL,
88*0e209d39SAndroid Build Coastguard Worker     FILTERDIR,
89*0e209d39SAndroid Build Coastguard Worker     ICU4X_MODE,
90*0e209d39SAndroid Build Coastguard Worker     UCADATA
91*0e209d39SAndroid Build Coastguard Worker };
92*0e209d39SAndroid Build Coastguard Worker 
93*0e209d39SAndroid Build Coastguard Worker UOption options[]={
94*0e209d39SAndroid Build Coastguard Worker                       UOPTION_HELP_H,
95*0e209d39SAndroid Build Coastguard Worker                       UOPTION_HELP_QUESTION_MARK,
96*0e209d39SAndroid Build Coastguard Worker                       UOPTION_VERBOSE,
97*0e209d39SAndroid Build Coastguard Worker                       UOPTION_QUIET,
98*0e209d39SAndroid Build Coastguard Worker                       UOPTION_VERSION,
99*0e209d39SAndroid Build Coastguard Worker                       UOPTION_SOURCEDIR,
100*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DESTDIR,
101*0e209d39SAndroid Build Coastguard Worker                       UOPTION_ENCODING,
102*0e209d39SAndroid Build Coastguard Worker                       UOPTION_ICUDATADIR,
103*0e209d39SAndroid Build Coastguard Worker                       UOPTION_WRITE_JAVA,
104*0e209d39SAndroid Build Coastguard Worker                       UOPTION_COPYRIGHT,
105*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("java-package", '\x01', UOPT_REQUIRES_ARG),
106*0e209d39SAndroid Build Coastguard Worker                       UOPTION_BUNDLE_NAME,
107*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("write-xliff", 'x', UOPT_OPTIONAL_ARG),
108*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("strict",    'k', UOPT_NO_ARG), /* 14 */
109*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("noBinaryCollation", 'C', UOPT_NO_ARG),/* 15 */
110*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("language",  'l', UOPT_REQUIRES_ARG), /* 16 */
111*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("omitCollationRules", 'R', UOPT_NO_ARG),/* 17 */
112*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("formatVersion", '\x01', UOPT_REQUIRES_ARG),/* 18 */
113*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("writePoolBundle", '\x01', UOPT_OPTIONAL_ARG),/* 19 */
114*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("usePoolBundle", '\x01', UOPT_OPTIONAL_ARG),/* 20 */
115*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("includeUnihanColl", '\x01', UOPT_NO_ARG),/* 21 */ /* temporary, don't display in usage info */
116*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("filterDir", '\x01', UOPT_OPTIONAL_ARG), /* 22 */
117*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("icu4xMode", 'X', UOPT_NO_ARG),/* 23 */
118*0e209d39SAndroid Build Coastguard Worker                       UOPTION_DEF("ucadata", '\x01', UOPT_REQUIRES_ARG),/* 24 */
119*0e209d39SAndroid Build Coastguard Worker                   };
120*0e209d39SAndroid Build Coastguard Worker 
121*0e209d39SAndroid Build Coastguard Worker static     UBool       write_java = false;
122*0e209d39SAndroid Build Coastguard Worker static     UBool       write_xliff = false;
123*0e209d39SAndroid Build Coastguard Worker static     const char* outputEnc ="";
124*0e209d39SAndroid Build Coastguard Worker 
125*0e209d39SAndroid Build Coastguard Worker static ResFile poolBundle;
126*0e209d39SAndroid Build Coastguard Worker 
127*0e209d39SAndroid Build Coastguard Worker /*added by Jing*/
128*0e209d39SAndroid Build Coastguard Worker static     const char* language = nullptr;
129*0e209d39SAndroid Build Coastguard Worker static     const char* xliffOutputFileName = nullptr;
130*0e209d39SAndroid Build Coastguard Worker int
main(int argc,char * argv[])131*0e209d39SAndroid Build Coastguard Worker main(int argc,
132*0e209d39SAndroid Build Coastguard Worker      char* argv[])
133*0e209d39SAndroid Build Coastguard Worker {
134*0e209d39SAndroid Build Coastguard Worker     UErrorCode  status    = U_ZERO_ERROR;
135*0e209d39SAndroid Build Coastguard Worker     const char *arg       = nullptr;
136*0e209d39SAndroid Build Coastguard Worker     const char *outputDir = nullptr; /* nullptr = no output directory, use current */
137*0e209d39SAndroid Build Coastguard Worker     const char *inputDir  = nullptr;
138*0e209d39SAndroid Build Coastguard Worker     const char *filterDir = nullptr;
139*0e209d39SAndroid Build Coastguard Worker     const char *encoding  = "";
140*0e209d39SAndroid Build Coastguard Worker     int         i;
141*0e209d39SAndroid Build Coastguard Worker     UBool illegalArg = false;
142*0e209d39SAndroid Build Coastguard Worker 
143*0e209d39SAndroid Build Coastguard Worker     U_MAIN_INIT_ARGS(argc, argv);
144*0e209d39SAndroid Build Coastguard Worker 
145*0e209d39SAndroid Build Coastguard Worker     options[JAVA_PACKAGE].value = "com.ibm.icu.impl.data";
146*0e209d39SAndroid Build Coastguard Worker     options[BUNDLE_NAME].value = "LocaleElements";
147*0e209d39SAndroid Build Coastguard Worker     argc = u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options);
148*0e209d39SAndroid Build Coastguard Worker 
149*0e209d39SAndroid Build Coastguard Worker     /* error handling, printing usage message */
150*0e209d39SAndroid Build Coastguard Worker     if(argc<0) {
151*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "%s: error in command line argument \"%s\"\n", argv[0], argv[-argc]);
152*0e209d39SAndroid Build Coastguard Worker         illegalArg = true;
153*0e209d39SAndroid Build Coastguard Worker     } else if(argc<2) {
154*0e209d39SAndroid Build Coastguard Worker         illegalArg = true;
155*0e209d39SAndroid Build Coastguard Worker     }
156*0e209d39SAndroid Build Coastguard Worker     if(options[WRITE_POOL_BUNDLE].doesOccur && options[USE_POOL_BUNDLE].doesOccur) {
157*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "%s: cannot combine --writePoolBundle and --usePoolBundle\n", argv[0]);
158*0e209d39SAndroid Build Coastguard Worker         illegalArg = true;
159*0e209d39SAndroid Build Coastguard Worker     }
160*0e209d39SAndroid Build Coastguard Worker     if (options[ICU4X_MODE].doesOccur && !options[UCADATA].doesOccur) {
161*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "%s: --icu4xMode requires --ucadata\n", argv[0]);
162*0e209d39SAndroid Build Coastguard Worker         illegalArg = true;
163*0e209d39SAndroid Build Coastguard Worker     }
164*0e209d39SAndroid Build Coastguard Worker     if(options[FORMAT_VERSION].doesOccur) {
165*0e209d39SAndroid Build Coastguard Worker         const char *s = options[FORMAT_VERSION].value;
166*0e209d39SAndroid Build Coastguard Worker         if(uprv_strlen(s) != 1 || (s[0] < '1' && '3' < s[0])) {
167*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "%s: unsupported --formatVersion %s\n", argv[0], s);
168*0e209d39SAndroid Build Coastguard Worker             illegalArg = true;
169*0e209d39SAndroid Build Coastguard Worker         } else if(s[0] == '1' &&
170*0e209d39SAndroid Build Coastguard Worker                   (options[WRITE_POOL_BUNDLE].doesOccur || options[USE_POOL_BUNDLE].doesOccur)
171*0e209d39SAndroid Build Coastguard Worker         ) {
172*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "%s: cannot combine --formatVersion 1 with --writePoolBundle or --usePoolBundle\n", argv[0]);
173*0e209d39SAndroid Build Coastguard Worker             illegalArg = true;
174*0e209d39SAndroid Build Coastguard Worker         } else {
175*0e209d39SAndroid Build Coastguard Worker             setFormatVersion(s[0] - '0');
176*0e209d39SAndroid Build Coastguard Worker         }
177*0e209d39SAndroid Build Coastguard Worker     }
178*0e209d39SAndroid Build Coastguard Worker 
179*0e209d39SAndroid Build Coastguard Worker     if((options[JAVA_PACKAGE].doesOccur || options[BUNDLE_NAME].doesOccur) &&
180*0e209d39SAndroid Build Coastguard Worker             !options[WRITE_JAVA].doesOccur) {
181*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
182*0e209d39SAndroid Build Coastguard Worker                 "%s error: command line argument --java-package or --bundle-name "
183*0e209d39SAndroid Build Coastguard Worker                 "without --write-java\n",
184*0e209d39SAndroid Build Coastguard Worker                 argv[0]);
185*0e209d39SAndroid Build Coastguard Worker         illegalArg = true;
186*0e209d39SAndroid Build Coastguard Worker     }
187*0e209d39SAndroid Build Coastguard Worker 
188*0e209d39SAndroid Build Coastguard Worker     if(options[VERSION].doesOccur) {
189*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
190*0e209d39SAndroid Build Coastguard Worker                 "%s version %s (ICU version %s).\n"
191*0e209d39SAndroid Build Coastguard Worker                 "%s\n",
192*0e209d39SAndroid Build Coastguard Worker                 argv[0], GENRB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING);
193*0e209d39SAndroid Build Coastguard Worker         if(!illegalArg) {
194*0e209d39SAndroid Build Coastguard Worker             return U_ZERO_ERROR;
195*0e209d39SAndroid Build Coastguard Worker         }
196*0e209d39SAndroid Build Coastguard Worker     }
197*0e209d39SAndroid Build Coastguard Worker 
198*0e209d39SAndroid Build Coastguard Worker     if(illegalArg || options[HELP1].doesOccur || options[HELP2].doesOccur) {
199*0e209d39SAndroid Build Coastguard Worker         /*
200*0e209d39SAndroid Build Coastguard Worker          * Broken into chunks because the C89 standard says the minimum
201*0e209d39SAndroid Build Coastguard Worker          * required supported string length is 509 bytes.
202*0e209d39SAndroid Build Coastguard Worker          */
203*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
204*0e209d39SAndroid Build Coastguard Worker                 "Usage: %s [OPTIONS] [FILES]\n"
205*0e209d39SAndroid Build Coastguard Worker                 "\tReads the list of resource bundle source files and creates\n"
206*0e209d39SAndroid Build Coastguard Worker                 "\tbinary version of resource bundles (.res files)\n",
207*0e209d39SAndroid Build Coastguard Worker                 argv[0]);
208*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
209*0e209d39SAndroid Build Coastguard Worker                 "Options:\n"
210*0e209d39SAndroid Build Coastguard Worker                 "\t-h or -? or --help       this usage text\n"
211*0e209d39SAndroid Build Coastguard Worker                 "\t-q or --quiet            do not display warnings\n"
212*0e209d39SAndroid Build Coastguard Worker                 "\t-v or --verbose          print extra information when processing files\n"
213*0e209d39SAndroid Build Coastguard Worker                 "\t-V or --version          prints out version number and exits\n"
214*0e209d39SAndroid Build Coastguard Worker                 "\t-c or --copyright        include copyright notice\n");
215*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
216*0e209d39SAndroid Build Coastguard Worker                 "\t-e or --encoding         encoding of source files\n"
217*0e209d39SAndroid Build Coastguard Worker                 "\t-d or --destdir          destination directory, followed by the path, defaults to '%s'\n"
218*0e209d39SAndroid Build Coastguard Worker                 "\t-s or --sourcedir        source directory for files followed by path, defaults to '%s'\n"
219*0e209d39SAndroid Build Coastguard Worker                 "\t-i or --icudatadir       directory for locating any needed intermediate data files,\n"
220*0e209d39SAndroid Build Coastguard Worker                 "\t                         followed by path, defaults to '%s'\n",
221*0e209d39SAndroid Build Coastguard Worker                 u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory());
222*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
223*0e209d39SAndroid Build Coastguard Worker                 "\t-j or --write-java       write a Java ListResourceBundle for ICU4J, followed by optional encoding\n"
224*0e209d39SAndroid Build Coastguard Worker                 "\t                         defaults to ASCII and \\uXXXX format.\n"
225*0e209d39SAndroid Build Coastguard Worker                 "\t      --java-package     For --write-java: package name for writing the ListResourceBundle,\n"
226*0e209d39SAndroid Build Coastguard Worker                 "\t                         defaults to com.ibm.icu.impl.data\n");
227*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
228*0e209d39SAndroid Build Coastguard Worker                 "\t-b or --bundle-name      For --write-java: root resource bundle name for writing the ListResourceBundle,\n"
229*0e209d39SAndroid Build Coastguard Worker                 "\t                         defaults to LocaleElements\n"
230*0e209d39SAndroid Build Coastguard Worker                 "\t-x or --write-xliff      write an XLIFF file for the resource bundle. Followed by\n"
231*0e209d39SAndroid Build Coastguard Worker                 "\t                         an optional output file name.\n"
232*0e209d39SAndroid Build Coastguard Worker                 "\t-k or --strict           use pedantic parsing of syntax\n"
233*0e209d39SAndroid Build Coastguard Worker                 /*added by Jing*/
234*0e209d39SAndroid Build Coastguard Worker                 "\t-l or --language         for XLIFF: language code compliant with BCP 47.\n");
235*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
236*0e209d39SAndroid Build Coastguard Worker                 "\t-C or --noBinaryCollation  do not generate binary collation image;\n"
237*0e209d39SAndroid Build Coastguard Worker                 "\t                           makes .res file smaller but collator instantiation much slower;\n"
238*0e209d39SAndroid Build Coastguard Worker                 "\t                           maintains ability to get tailoring rules\n"
239*0e209d39SAndroid Build Coastguard Worker                 "\t-R or --omitCollationRules do not include collation (tailoring) rules;\n"
240*0e209d39SAndroid Build Coastguard Worker                 "\t                           makes .res file smaller and maintains collator instantiation speed\n"
241*0e209d39SAndroid Build Coastguard Worker                 "\t                           but tailoring rules will not be available (they are rarely used)\n");
242*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
243*0e209d39SAndroid Build Coastguard Worker                 "\t      --formatVersion      write a .res file compatible with the requested formatVersion (single digit);\n"
244*0e209d39SAndroid Build Coastguard Worker                 "\t                           for example, --formatVersion 1\n");
245*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
246*0e209d39SAndroid Build Coastguard Worker                 "\t      --writePoolBundle [directory]  write a pool.res file with all of the keys of all input bundles\n"
247*0e209d39SAndroid Build Coastguard Worker                 "\t      --usePoolBundle [directory]  point to keys from the pool.res keys pool bundle if they are available there;\n"
248*0e209d39SAndroid Build Coastguard Worker                 "\t                           makes .res files smaller but dependent on the pool bundle\n"
249*0e209d39SAndroid Build Coastguard Worker                 "\t                           (--writePoolBundle and --usePoolBundle cannot be combined)\n");
250*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr,
251*0e209d39SAndroid Build Coastguard Worker                 "\t      --filterDir          Input directory where filter files are available.\n"
252*0e209d39SAndroid Build Coastguard Worker                 "\t                           For more on filter files, see ICU Data Build Tool.\n");
253*0e209d39SAndroid Build Coastguard Worker 
254*0e209d39SAndroid Build Coastguard Worker         return illegalArg ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR;
255*0e209d39SAndroid Build Coastguard Worker     }
256*0e209d39SAndroid Build Coastguard Worker 
257*0e209d39SAndroid Build Coastguard Worker     if(options[VERBOSE].doesOccur) {
258*0e209d39SAndroid Build Coastguard Worker         setVerbose(true);
259*0e209d39SAndroid Build Coastguard Worker     }
260*0e209d39SAndroid Build Coastguard Worker 
261*0e209d39SAndroid Build Coastguard Worker     if(options[QUIET].doesOccur) {
262*0e209d39SAndroid Build Coastguard Worker         setShowWarning(false);
263*0e209d39SAndroid Build Coastguard Worker     }
264*0e209d39SAndroid Build Coastguard Worker     if(options[STRICT].doesOccur) {
265*0e209d39SAndroid Build Coastguard Worker         setStrict(true);
266*0e209d39SAndroid Build Coastguard Worker     }
267*0e209d39SAndroid Build Coastguard Worker     if(options[COPYRIGHT].doesOccur){
268*0e209d39SAndroid Build Coastguard Worker         setIncludeCopyright(true);
269*0e209d39SAndroid Build Coastguard Worker     }
270*0e209d39SAndroid Build Coastguard Worker 
271*0e209d39SAndroid Build Coastguard Worker     if(options[SOURCEDIR].doesOccur) {
272*0e209d39SAndroid Build Coastguard Worker         inputDir = options[SOURCEDIR].value;
273*0e209d39SAndroid Build Coastguard Worker     }
274*0e209d39SAndroid Build Coastguard Worker 
275*0e209d39SAndroid Build Coastguard Worker     if(options[DESTDIR].doesOccur) {
276*0e209d39SAndroid Build Coastguard Worker         outputDir = options[DESTDIR].value;
277*0e209d39SAndroid Build Coastguard Worker     }
278*0e209d39SAndroid Build Coastguard Worker 
279*0e209d39SAndroid Build Coastguard Worker     if (options[FILTERDIR].doesOccur) {
280*0e209d39SAndroid Build Coastguard Worker         filterDir = options[FILTERDIR].value;
281*0e209d39SAndroid Build Coastguard Worker     }
282*0e209d39SAndroid Build Coastguard Worker 
283*0e209d39SAndroid Build Coastguard Worker     if(options[ENCODING].doesOccur) {
284*0e209d39SAndroid Build Coastguard Worker         encoding = options[ENCODING].value;
285*0e209d39SAndroid Build Coastguard Worker     }
286*0e209d39SAndroid Build Coastguard Worker 
287*0e209d39SAndroid Build Coastguard Worker     if(options[ICUDATADIR].doesOccur) {
288*0e209d39SAndroid Build Coastguard Worker         u_setDataDirectory(options[ICUDATADIR].value);
289*0e209d39SAndroid Build Coastguard Worker     }
290*0e209d39SAndroid Build Coastguard Worker     /* Initialize ICU */
291*0e209d39SAndroid Build Coastguard Worker     u_init(&status);
292*0e209d39SAndroid Build Coastguard Worker     if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
293*0e209d39SAndroid Build Coastguard Worker         /* Note: u_init() will try to open ICU property data.
294*0e209d39SAndroid Build Coastguard Worker          *       failures here are expected when building ICU from scratch.
295*0e209d39SAndroid Build Coastguard Worker          *       ignore them.
296*0e209d39SAndroid Build Coastguard Worker         */
297*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "%s: can not initialize ICU.  status = %s\n",
298*0e209d39SAndroid Build Coastguard Worker             argv[0], u_errorName(status));
299*0e209d39SAndroid Build Coastguard Worker         exit(1);
300*0e209d39SAndroid Build Coastguard Worker     }
301*0e209d39SAndroid Build Coastguard Worker     status = U_ZERO_ERROR;
302*0e209d39SAndroid Build Coastguard Worker     if(options[WRITE_JAVA].doesOccur) {
303*0e209d39SAndroid Build Coastguard Worker         write_java = true;
304*0e209d39SAndroid Build Coastguard Worker         outputEnc = options[WRITE_JAVA].value;
305*0e209d39SAndroid Build Coastguard Worker     }
306*0e209d39SAndroid Build Coastguard Worker 
307*0e209d39SAndroid Build Coastguard Worker     if(options[WRITE_XLIFF].doesOccur) {
308*0e209d39SAndroid Build Coastguard Worker         write_xliff = true;
309*0e209d39SAndroid Build Coastguard Worker         if(options[WRITE_XLIFF].value != nullptr){
310*0e209d39SAndroid Build Coastguard Worker             xliffOutputFileName = options[WRITE_XLIFF].value;
311*0e209d39SAndroid Build Coastguard Worker         }
312*0e209d39SAndroid Build Coastguard Worker     }
313*0e209d39SAndroid Build Coastguard Worker 
314*0e209d39SAndroid Build Coastguard Worker     if (options[UCADATA].doesOccur) {
315*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_COLLATION
316*0e209d39SAndroid Build Coastguard Worker         CollationRoot::forceLoadFromFile(options[UCADATA].value, status);
317*0e209d39SAndroid Build Coastguard Worker #else
318*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "--ucadata was used with UCONFIG_NO_COLLATION\n");
319*0e209d39SAndroid Build Coastguard Worker         return status;
320*0e209d39SAndroid Build Coastguard Worker #endif
321*0e209d39SAndroid Build Coastguard Worker     }
322*0e209d39SAndroid Build Coastguard Worker 
323*0e209d39SAndroid Build Coastguard Worker     initParser();
324*0e209d39SAndroid Build Coastguard Worker 
325*0e209d39SAndroid Build Coastguard Worker     /*added by Jing*/
326*0e209d39SAndroid Build Coastguard Worker     if(options[LANGUAGE].doesOccur) {
327*0e209d39SAndroid Build Coastguard Worker         language = options[LANGUAGE].value;
328*0e209d39SAndroid Build Coastguard Worker     }
329*0e209d39SAndroid Build Coastguard Worker 
330*0e209d39SAndroid Build Coastguard Worker     LocalPointer<SRBRoot> newPoolBundle;
331*0e209d39SAndroid Build Coastguard Worker     if(options[WRITE_POOL_BUNDLE].doesOccur) {
332*0e209d39SAndroid Build Coastguard Worker         newPoolBundle.adoptInsteadAndCheckErrorCode(new SRBRoot(nullptr, true, status), status);
333*0e209d39SAndroid Build Coastguard Worker         if(U_FAILURE(status)) {
334*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "unable to create an empty bundle for the pool keys: %s\n", u_errorName(status));
335*0e209d39SAndroid Build Coastguard Worker             return status;
336*0e209d39SAndroid Build Coastguard Worker         } else {
337*0e209d39SAndroid Build Coastguard Worker             const char *poolResName = "pool.res";
338*0e209d39SAndroid Build Coastguard Worker             char *nameWithoutSuffix = static_cast<char *>(uprv_malloc(uprv_strlen(poolResName) + 1));
339*0e209d39SAndroid Build Coastguard Worker             if (nameWithoutSuffix == nullptr) {
340*0e209d39SAndroid Build Coastguard Worker                 fprintf(stderr, "out of memory error\n");
341*0e209d39SAndroid Build Coastguard Worker                 return U_MEMORY_ALLOCATION_ERROR;
342*0e209d39SAndroid Build Coastguard Worker             }
343*0e209d39SAndroid Build Coastguard Worker             uprv_strcpy(nameWithoutSuffix, poolResName);
344*0e209d39SAndroid Build Coastguard Worker             *uprv_strrchr(nameWithoutSuffix, '.') = 0;
345*0e209d39SAndroid Build Coastguard Worker             newPoolBundle->fLocale = nameWithoutSuffix;
346*0e209d39SAndroid Build Coastguard Worker         }
347*0e209d39SAndroid Build Coastguard Worker     }
348*0e209d39SAndroid Build Coastguard Worker 
349*0e209d39SAndroid Build Coastguard Worker     if(options[USE_POOL_BUNDLE].doesOccur) {
350*0e209d39SAndroid Build Coastguard Worker         const char *poolResName = "pool.res";
351*0e209d39SAndroid Build Coastguard Worker         FileStream *poolFile;
352*0e209d39SAndroid Build Coastguard Worker         int32_t poolFileSize;
353*0e209d39SAndroid Build Coastguard Worker         int32_t indexLength;
354*0e209d39SAndroid Build Coastguard Worker         /*
355*0e209d39SAndroid Build Coastguard Worker          * TODO: Consolidate inputDir/filename handling from main() and processFile()
356*0e209d39SAndroid Build Coastguard Worker          * into a common function, and use it here as well.
357*0e209d39SAndroid Build Coastguard Worker          * Try to create toolutil functions for dealing with dir/filenames and
358*0e209d39SAndroid Build Coastguard Worker          * loading ICU data files without udata_open().
359*0e209d39SAndroid Build Coastguard Worker          * Share code with icupkg?
360*0e209d39SAndroid Build Coastguard Worker          * Also, make_res_filename() seems to be unused. Review and remove.
361*0e209d39SAndroid Build Coastguard Worker          */
362*0e209d39SAndroid Build Coastguard Worker         CharString poolFileName;
363*0e209d39SAndroid Build Coastguard Worker         if (options[USE_POOL_BUNDLE].value!=nullptr) {
364*0e209d39SAndroid Build Coastguard Worker             poolFileName.append(options[USE_POOL_BUNDLE].value, status);
365*0e209d39SAndroid Build Coastguard Worker         } else if (inputDir) {
366*0e209d39SAndroid Build Coastguard Worker             poolFileName.append(inputDir, status);
367*0e209d39SAndroid Build Coastguard Worker         }
368*0e209d39SAndroid Build Coastguard Worker         poolFileName.appendPathPart(poolResName, status);
369*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
370*0e209d39SAndroid Build Coastguard Worker             return status;
371*0e209d39SAndroid Build Coastguard Worker         }
372*0e209d39SAndroid Build Coastguard Worker         poolFile = T_FileStream_open(poolFileName.data(), "rb");
373*0e209d39SAndroid Build Coastguard Worker         if (poolFile == nullptr) {
374*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "unable to open pool bundle file %s\n", poolFileName.data());
375*0e209d39SAndroid Build Coastguard Worker             return 1;
376*0e209d39SAndroid Build Coastguard Worker         }
377*0e209d39SAndroid Build Coastguard Worker         poolFileSize = T_FileStream_size(poolFile);
378*0e209d39SAndroid Build Coastguard Worker         if (poolFileSize < 32) {
379*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "the pool bundle file %s is too small\n", poolFileName.data());
380*0e209d39SAndroid Build Coastguard Worker             return 1;
381*0e209d39SAndroid Build Coastguard Worker         }
382*0e209d39SAndroid Build Coastguard Worker         poolBundle.fBytes = new uint8_t[(poolFileSize + 15) & ~15];
383*0e209d39SAndroid Build Coastguard Worker         if (poolFileSize > 0 && poolBundle.fBytes == nullptr) {
384*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "unable to allocate memory for the pool bundle file %s\n", poolFileName.data());
385*0e209d39SAndroid Build Coastguard Worker             return U_MEMORY_ALLOCATION_ERROR;
386*0e209d39SAndroid Build Coastguard Worker         }
387*0e209d39SAndroid Build Coastguard Worker 
388*0e209d39SAndroid Build Coastguard Worker         UDataSwapper *ds;
389*0e209d39SAndroid Build Coastguard Worker         const DataHeader *header;
390*0e209d39SAndroid Build Coastguard Worker         int32_t bytesRead = T_FileStream_read(poolFile, poolBundle.fBytes, poolFileSize);
391*0e209d39SAndroid Build Coastguard Worker         if (bytesRead != poolFileSize) {
392*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "unable to read the pool bundle file %s\n", poolFileName.data());
393*0e209d39SAndroid Build Coastguard Worker             return 1;
394*0e209d39SAndroid Build Coastguard Worker         }
395*0e209d39SAndroid Build Coastguard Worker         /*
396*0e209d39SAndroid Build Coastguard Worker          * Swap the pool bundle so that a single checked-in file can be used.
397*0e209d39SAndroid Build Coastguard Worker          * The swapper functions also test that the data looks like
398*0e209d39SAndroid Build Coastguard Worker          * a well-formed .res file.
399*0e209d39SAndroid Build Coastguard Worker          */
400*0e209d39SAndroid Build Coastguard Worker         ds = udata_openSwapperForInputData(poolBundle.fBytes, bytesRead,
401*0e209d39SAndroid Build Coastguard Worker                                            U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &status);
402*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
403*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "udata_openSwapperForInputData(pool bundle %s) failed: %s\n",
404*0e209d39SAndroid Build Coastguard Worker                     poolFileName.data(), u_errorName(status));
405*0e209d39SAndroid Build Coastguard Worker             return status;
406*0e209d39SAndroid Build Coastguard Worker         }
407*0e209d39SAndroid Build Coastguard Worker         ures_swap(ds, poolBundle.fBytes, bytesRead, poolBundle.fBytes, &status);
408*0e209d39SAndroid Build Coastguard Worker         udata_closeSwapper(ds);
409*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
410*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "ures_swap(pool bundle %s) failed: %s\n",
411*0e209d39SAndroid Build Coastguard Worker                     poolFileName.data(), u_errorName(status));
412*0e209d39SAndroid Build Coastguard Worker             return status;
413*0e209d39SAndroid Build Coastguard Worker         }
414*0e209d39SAndroid Build Coastguard Worker         header = (const DataHeader *)poolBundle.fBytes;
415*0e209d39SAndroid Build Coastguard Worker         if (header->info.formatVersion[0] < 2) {
416*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "invalid format of pool bundle file %s\n", poolFileName.data());
417*0e209d39SAndroid Build Coastguard Worker             return U_INVALID_FORMAT_ERROR;
418*0e209d39SAndroid Build Coastguard Worker         }
419*0e209d39SAndroid Build Coastguard Worker         const int32_t *pRoot = (const int32_t *)(
420*0e209d39SAndroid Build Coastguard Worker                 (const char *)header + header->dataHeader.headerSize);
421*0e209d39SAndroid Build Coastguard Worker         poolBundle.fIndexes = pRoot + 1;
422*0e209d39SAndroid Build Coastguard Worker         indexLength = poolBundle.fIndexes[URES_INDEX_LENGTH] & 0xff;
423*0e209d39SAndroid Build Coastguard Worker         if (indexLength <= URES_INDEX_POOL_CHECKSUM) {
424*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "insufficient indexes[] in pool bundle file %s\n", poolFileName.data());
425*0e209d39SAndroid Build Coastguard Worker             return U_INVALID_FORMAT_ERROR;
426*0e209d39SAndroid Build Coastguard Worker         }
427*0e209d39SAndroid Build Coastguard Worker         int32_t keysBottom = 1 + indexLength;
428*0e209d39SAndroid Build Coastguard Worker         int32_t keysTop = poolBundle.fIndexes[URES_INDEX_KEYS_TOP];
429*0e209d39SAndroid Build Coastguard Worker         poolBundle.fKeys = (const char *)(pRoot + keysBottom);
430*0e209d39SAndroid Build Coastguard Worker         poolBundle.fKeysLength = (keysTop - keysBottom) * 4;
431*0e209d39SAndroid Build Coastguard Worker         poolBundle.fChecksum = poolBundle.fIndexes[URES_INDEX_POOL_CHECKSUM];
432*0e209d39SAndroid Build Coastguard Worker 
433*0e209d39SAndroid Build Coastguard Worker         for (i = 0; i < poolBundle.fKeysLength; ++i) {
434*0e209d39SAndroid Build Coastguard Worker             if (poolBundle.fKeys[i] == 0) {
435*0e209d39SAndroid Build Coastguard Worker                 ++poolBundle.fKeysCount;
436*0e209d39SAndroid Build Coastguard Worker             }
437*0e209d39SAndroid Build Coastguard Worker         }
438*0e209d39SAndroid Build Coastguard Worker 
439*0e209d39SAndroid Build Coastguard Worker         // 16BitUnits[] begins with strings-v2.
440*0e209d39SAndroid Build Coastguard Worker         // The strings-v2 may optionally be terminated by what looks like
441*0e209d39SAndroid Build Coastguard Worker         // an explicit string length that exceeds the number of remaining 16-bit units.
442*0e209d39SAndroid Build Coastguard Worker         int32_t stringUnitsLength = (poolBundle.fIndexes[URES_INDEX_16BIT_TOP] - keysTop) * 2;
443*0e209d39SAndroid Build Coastguard Worker         if (stringUnitsLength >= 2 && getFormatVersion() >= 3) {
444*0e209d39SAndroid Build Coastguard Worker             poolBundle.fStrings = new PseudoListResource(nullptr, status);
445*0e209d39SAndroid Build Coastguard Worker             if (poolBundle.fStrings == nullptr) {
446*0e209d39SAndroid Build Coastguard Worker                 fprintf(stderr, "unable to allocate memory for the pool bundle strings %s\n",
447*0e209d39SAndroid Build Coastguard Worker                         poolFileName.data());
448*0e209d39SAndroid Build Coastguard Worker                 return U_MEMORY_ALLOCATION_ERROR;
449*0e209d39SAndroid Build Coastguard Worker             }
450*0e209d39SAndroid Build Coastguard Worker             // The PseudoListResource constructor call did not allocate further memory.
451*0e209d39SAndroid Build Coastguard Worker             assert(U_SUCCESS(status));
452*0e209d39SAndroid Build Coastguard Worker             const char16_t *p = (const char16_t *)(pRoot + keysTop);
453*0e209d39SAndroid Build Coastguard Worker             int32_t remaining = stringUnitsLength;
454*0e209d39SAndroid Build Coastguard Worker             do {
455*0e209d39SAndroid Build Coastguard Worker                 int32_t first = *p;
456*0e209d39SAndroid Build Coastguard Worker                 int8_t numCharsForLength;
457*0e209d39SAndroid Build Coastguard Worker                 int32_t length;
458*0e209d39SAndroid Build Coastguard Worker                 if (!U16_IS_TRAIL(first)) {
459*0e209d39SAndroid Build Coastguard Worker                     // NUL-terminated
460*0e209d39SAndroid Build Coastguard Worker                     numCharsForLength = 0;
461*0e209d39SAndroid Build Coastguard Worker                     for (length = 0;
462*0e209d39SAndroid Build Coastguard Worker                          length < remaining && p[length] != 0;
463*0e209d39SAndroid Build Coastguard Worker                          ++length) {}
464*0e209d39SAndroid Build Coastguard Worker                 } else if (first < 0xdfef) {
465*0e209d39SAndroid Build Coastguard Worker                     numCharsForLength = 1;
466*0e209d39SAndroid Build Coastguard Worker                     length = first & 0x3ff;
467*0e209d39SAndroid Build Coastguard Worker                 } else if (first < 0xdfff && remaining >= 2) {
468*0e209d39SAndroid Build Coastguard Worker                     numCharsForLength = 2;
469*0e209d39SAndroid Build Coastguard Worker                     length = ((first - 0xdfef) << 16) | p[1];
470*0e209d39SAndroid Build Coastguard Worker                 } else if (first == 0xdfff && remaining >= 3) {
471*0e209d39SAndroid Build Coastguard Worker                     numCharsForLength = 3;
472*0e209d39SAndroid Build Coastguard Worker                     length = ((int32_t)p[1] << 16) | p[2];
473*0e209d39SAndroid Build Coastguard Worker                 } else {
474*0e209d39SAndroid Build Coastguard Worker                     break;  // overrun
475*0e209d39SAndroid Build Coastguard Worker                 }
476*0e209d39SAndroid Build Coastguard Worker                 // Check for overrun before changing remaining,
477*0e209d39SAndroid Build Coastguard Worker                 // so that it is always accurate after the loop body.
478*0e209d39SAndroid Build Coastguard Worker                 if ((numCharsForLength + length) >= remaining ||
479*0e209d39SAndroid Build Coastguard Worker                         p[numCharsForLength + length] != 0) {
480*0e209d39SAndroid Build Coastguard Worker                     break;  // overrun or explicitly terminated
481*0e209d39SAndroid Build Coastguard Worker                 }
482*0e209d39SAndroid Build Coastguard Worker                 int32_t poolStringIndex = stringUnitsLength - remaining;
483*0e209d39SAndroid Build Coastguard Worker                 // Maximum pool string index when suffix-sharing the last character.
484*0e209d39SAndroid Build Coastguard Worker                 int32_t maxStringIndex = poolStringIndex + numCharsForLength + length - 1;
485*0e209d39SAndroid Build Coastguard Worker                 if (maxStringIndex >= RES_MAX_OFFSET) {
486*0e209d39SAndroid Build Coastguard Worker                     // pool string index overrun
487*0e209d39SAndroid Build Coastguard Worker                     break;
488*0e209d39SAndroid Build Coastguard Worker                 }
489*0e209d39SAndroid Build Coastguard Worker                 p += numCharsForLength;
490*0e209d39SAndroid Build Coastguard Worker                 remaining -= numCharsForLength;
491*0e209d39SAndroid Build Coastguard Worker                 if (length != 0) {
492*0e209d39SAndroid Build Coastguard Worker                     StringResource *sr =
493*0e209d39SAndroid Build Coastguard Worker                             new StringResource(poolStringIndex, numCharsForLength,
494*0e209d39SAndroid Build Coastguard Worker                                                p, length, status);
495*0e209d39SAndroid Build Coastguard Worker                     if (sr == nullptr) {
496*0e209d39SAndroid Build Coastguard Worker                         fprintf(stderr, "unable to allocate memory for a pool bundle string %s\n",
497*0e209d39SAndroid Build Coastguard Worker                                 poolFileName.data());
498*0e209d39SAndroid Build Coastguard Worker                         return U_MEMORY_ALLOCATION_ERROR;
499*0e209d39SAndroid Build Coastguard Worker                     }
500*0e209d39SAndroid Build Coastguard Worker                     poolBundle.fStrings->add(sr);
501*0e209d39SAndroid Build Coastguard Worker                     poolBundle.fStringIndexLimit = maxStringIndex + 1;
502*0e209d39SAndroid Build Coastguard Worker                     // The StringResource constructor did not allocate further memory.
503*0e209d39SAndroid Build Coastguard Worker                     assert(U_SUCCESS(status));
504*0e209d39SAndroid Build Coastguard Worker                 }
505*0e209d39SAndroid Build Coastguard Worker                 p += length + 1;
506*0e209d39SAndroid Build Coastguard Worker                 remaining -= length + 1;
507*0e209d39SAndroid Build Coastguard Worker             } while (remaining > 0);
508*0e209d39SAndroid Build Coastguard Worker             if (poolBundle.fStrings->fCount == 0) {
509*0e209d39SAndroid Build Coastguard Worker                 delete poolBundle.fStrings;
510*0e209d39SAndroid Build Coastguard Worker                 poolBundle.fStrings = nullptr;
511*0e209d39SAndroid Build Coastguard Worker             }
512*0e209d39SAndroid Build Coastguard Worker         }
513*0e209d39SAndroid Build Coastguard Worker 
514*0e209d39SAndroid Build Coastguard Worker         T_FileStream_close(poolFile);
515*0e209d39SAndroid Build Coastguard Worker         setUsePoolBundle(true);
516*0e209d39SAndroid Build Coastguard Worker         if (isVerbose() && poolBundle.fStrings != nullptr) {
517*0e209d39SAndroid Build Coastguard Worker             printf("number of shared strings: %d\n", (int)poolBundle.fStrings->fCount);
518*0e209d39SAndroid Build Coastguard Worker             int32_t length = poolBundle.fStringIndexLimit + 1;  // incl. last NUL
519*0e209d39SAndroid Build Coastguard Worker             printf("16-bit units for strings: %6d = %6d bytes\n",
520*0e209d39SAndroid Build Coastguard Worker                    (int)length, (int)length * 2);
521*0e209d39SAndroid Build Coastguard Worker         }
522*0e209d39SAndroid Build Coastguard Worker     }
523*0e209d39SAndroid Build Coastguard Worker 
524*0e209d39SAndroid Build Coastguard Worker     if(!options[FORMAT_VERSION].doesOccur && getFormatVersion() == 3 &&
525*0e209d39SAndroid Build Coastguard Worker             poolBundle.fStrings == nullptr &&
526*0e209d39SAndroid Build Coastguard Worker             !options[WRITE_POOL_BUNDLE].doesOccur) {
527*0e209d39SAndroid Build Coastguard Worker         // If we just default to formatVersion 3
528*0e209d39SAndroid Build Coastguard Worker         // but there are no pool bundle strings to share
529*0e209d39SAndroid Build Coastguard Worker         // and we do not write a pool bundle,
530*0e209d39SAndroid Build Coastguard Worker         // then write formatVersion 2 which is just as good.
531*0e209d39SAndroid Build Coastguard Worker         setFormatVersion(2);
532*0e209d39SAndroid Build Coastguard Worker     }
533*0e209d39SAndroid Build Coastguard Worker 
534*0e209d39SAndroid Build Coastguard Worker     if(options[INCLUDE_UNIHAN_COLL].doesOccur) {
535*0e209d39SAndroid Build Coastguard Worker         puts("genrb option --includeUnihanColl ignored: \n"
536*0e209d39SAndroid Build Coastguard Worker                 "CLDR 26/ICU 54 unihan data is small, except\n"
537*0e209d39SAndroid Build Coastguard Worker                 "the ucadata-unihan.icu version of the collation root data\n"
538*0e209d39SAndroid Build Coastguard Worker                 "is about 300kB larger than the ucadata-implicithan.icu version.");
539*0e209d39SAndroid Build Coastguard Worker     }
540*0e209d39SAndroid Build Coastguard Worker 
541*0e209d39SAndroid Build Coastguard Worker     if((argc-1)!=1) {
542*0e209d39SAndroid Build Coastguard Worker         printf("genrb number of files: %d\n", argc - 1);
543*0e209d39SAndroid Build Coastguard Worker     }
544*0e209d39SAndroid Build Coastguard Worker     /* generate the binary files */
545*0e209d39SAndroid Build Coastguard Worker     for(i = 1; i < argc; ++i) {
546*0e209d39SAndroid Build Coastguard Worker         status = U_ZERO_ERROR;
547*0e209d39SAndroid Build Coastguard Worker         arg    = getLongPathname(argv[i]);
548*0e209d39SAndroid Build Coastguard Worker 
549*0e209d39SAndroid Build Coastguard Worker         CharString theCurrentFileName;
550*0e209d39SAndroid Build Coastguard Worker         if (inputDir) {
551*0e209d39SAndroid Build Coastguard Worker             theCurrentFileName.append(inputDir, status);
552*0e209d39SAndroid Build Coastguard Worker         }
553*0e209d39SAndroid Build Coastguard Worker         theCurrentFileName.appendPathPart(arg, status);
554*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
555*0e209d39SAndroid Build Coastguard Worker             break;
556*0e209d39SAndroid Build Coastguard Worker         }
557*0e209d39SAndroid Build Coastguard Worker 
558*0e209d39SAndroid Build Coastguard Worker         gCurrentFileName = theCurrentFileName.data();
559*0e209d39SAndroid Build Coastguard Worker         if (isVerbose()) {
560*0e209d39SAndroid Build Coastguard Worker             printf("Processing file \"%s\"\n", theCurrentFileName.data());
561*0e209d39SAndroid Build Coastguard Worker         }
562*0e209d39SAndroid Build Coastguard Worker         processFile(arg, encoding, inputDir, outputDir, filterDir, nullptr,
563*0e209d39SAndroid Build Coastguard Worker                     newPoolBundle.getAlias(),
564*0e209d39SAndroid Build Coastguard Worker                     options[NO_BINARY_COLLATION].doesOccur, status);
565*0e209d39SAndroid Build Coastguard Worker     }
566*0e209d39SAndroid Build Coastguard Worker 
567*0e209d39SAndroid Build Coastguard Worker     poolBundle.close();
568*0e209d39SAndroid Build Coastguard Worker 
569*0e209d39SAndroid Build Coastguard Worker     if(U_SUCCESS(status) && options[WRITE_POOL_BUNDLE].doesOccur) {
570*0e209d39SAndroid Build Coastguard Worker         const char* writePoolDir;
571*0e209d39SAndroid Build Coastguard Worker         if (options[WRITE_POOL_BUNDLE].value!=nullptr) {
572*0e209d39SAndroid Build Coastguard Worker             writePoolDir = options[WRITE_POOL_BUNDLE].value;
573*0e209d39SAndroid Build Coastguard Worker         } else {
574*0e209d39SAndroid Build Coastguard Worker             writePoolDir = outputDir;
575*0e209d39SAndroid Build Coastguard Worker         }
576*0e209d39SAndroid Build Coastguard Worker         char outputFileName[256];
577*0e209d39SAndroid Build Coastguard Worker         newPoolBundle->write(writePoolDir, nullptr, outputFileName, sizeof(outputFileName), status);
578*0e209d39SAndroid Build Coastguard Worker         if(U_FAILURE(status)) {
579*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "unable to write the pool bundle: %s\n", u_errorName(status));
580*0e209d39SAndroid Build Coastguard Worker         }
581*0e209d39SAndroid Build Coastguard Worker     }
582*0e209d39SAndroid Build Coastguard Worker 
583*0e209d39SAndroid Build Coastguard Worker     u_cleanup();
584*0e209d39SAndroid Build Coastguard Worker 
585*0e209d39SAndroid Build Coastguard Worker     /* Don't return warnings as a failure */
586*0e209d39SAndroid Build Coastguard Worker     if (U_SUCCESS(status)) {
587*0e209d39SAndroid Build Coastguard Worker         return 0;
588*0e209d39SAndroid Build Coastguard Worker     }
589*0e209d39SAndroid Build Coastguard Worker 
590*0e209d39SAndroid Build Coastguard Worker     return status;
591*0e209d39SAndroid Build Coastguard Worker }
592*0e209d39SAndroid Build Coastguard Worker 
593*0e209d39SAndroid Build Coastguard Worker /* Process a file */
594*0e209d39SAndroid Build Coastguard Worker void
processFile(const char * filename,const char * cp,const char * inputDir,const char * outputDir,const char * filterDir,const char * packageName,SRBRoot * newPoolBundle,UBool omitBinaryCollation,UErrorCode & status)595*0e209d39SAndroid Build Coastguard Worker processFile(const char *filename, const char *cp,
596*0e209d39SAndroid Build Coastguard Worker             const char *inputDir, const char *outputDir, const char *filterDir,
597*0e209d39SAndroid Build Coastguard Worker             const char *packageName,
598*0e209d39SAndroid Build Coastguard Worker             SRBRoot *newPoolBundle,
599*0e209d39SAndroid Build Coastguard Worker             UBool omitBinaryCollation, UErrorCode &status) {
600*0e209d39SAndroid Build Coastguard Worker     LocalPointer<SRBRoot> data;
601*0e209d39SAndroid Build Coastguard Worker     LocalUCHARBUFPointer ucbuf;
602*0e209d39SAndroid Build Coastguard Worker     CharString openFileName;
603*0e209d39SAndroid Build Coastguard Worker     CharString inputDirBuf;
604*0e209d39SAndroid Build Coastguard Worker 
605*0e209d39SAndroid Build Coastguard Worker     char outputFileName[256];
606*0e209d39SAndroid Build Coastguard Worker     int32_t dirlen  = 0;
607*0e209d39SAndroid Build Coastguard Worker 
608*0e209d39SAndroid Build Coastguard Worker     if (U_FAILURE(status)) {
609*0e209d39SAndroid Build Coastguard Worker         return;
610*0e209d39SAndroid Build Coastguard Worker     }
611*0e209d39SAndroid Build Coastguard Worker     if(filename==nullptr){
612*0e209d39SAndroid Build Coastguard Worker         status=U_ILLEGAL_ARGUMENT_ERROR;
613*0e209d39SAndroid Build Coastguard Worker         return;
614*0e209d39SAndroid Build Coastguard Worker     }
615*0e209d39SAndroid Build Coastguard Worker 
616*0e209d39SAndroid Build Coastguard Worker     if(inputDir == nullptr) {
617*0e209d39SAndroid Build Coastguard Worker         const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR);
618*0e209d39SAndroid Build Coastguard Worker         if (filenameBegin != nullptr) {
619*0e209d39SAndroid Build Coastguard Worker             /*
620*0e209d39SAndroid Build Coastguard Worker              * When a filename ../../../data/root.txt is specified,
621*0e209d39SAndroid Build Coastguard Worker              * we presume that the input directory is ../../../data
622*0e209d39SAndroid Build Coastguard Worker              * This is very important when the resource file includes
623*0e209d39SAndroid Build Coastguard Worker              * another file, like UCARules.txt or thaidict.brk.
624*0e209d39SAndroid Build Coastguard Worker              */
625*0e209d39SAndroid Build Coastguard Worker             int32_t filenameSize = (int32_t)(filenameBegin - filename + 1);
626*0e209d39SAndroid Build Coastguard Worker             inputDirBuf.append(filename, filenameSize, status);
627*0e209d39SAndroid Build Coastguard Worker 
628*0e209d39SAndroid Build Coastguard Worker             inputDir = inputDirBuf.data();
629*0e209d39SAndroid Build Coastguard Worker             dirlen  = inputDirBuf.length();
630*0e209d39SAndroid Build Coastguard Worker         }
631*0e209d39SAndroid Build Coastguard Worker     }else{
632*0e209d39SAndroid Build Coastguard Worker         dirlen  = (int32_t)uprv_strlen(inputDir);
633*0e209d39SAndroid Build Coastguard Worker 
634*0e209d39SAndroid Build Coastguard Worker         if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
635*0e209d39SAndroid Build Coastguard Worker             /*
636*0e209d39SAndroid Build Coastguard Worker              * append the input dir to openFileName if the first char in
637*0e209d39SAndroid Build Coastguard Worker              * filename is not file separation char and the last char input directory is  not '.'.
638*0e209d39SAndroid Build Coastguard Worker              * This is to support :
639*0e209d39SAndroid Build Coastguard Worker              * genrb -s. /home/icu/data
640*0e209d39SAndroid Build Coastguard Worker              * genrb -s. icu/data
641*0e209d39SAndroid Build Coastguard Worker              * The user cannot mix notations like
642*0e209d39SAndroid Build Coastguard Worker              * genrb -s. /icu/data --- the absolute path specified. -s redundant
643*0e209d39SAndroid Build Coastguard Worker              * user should use
644*0e209d39SAndroid Build Coastguard Worker              * genrb -s. icu/data  --- start from CWD and look in icu/data dir
645*0e209d39SAndroid Build Coastguard Worker              */
646*0e209d39SAndroid Build Coastguard Worker             if( (filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')){
647*0e209d39SAndroid Build Coastguard Worker                 openFileName.append(inputDir, status);
648*0e209d39SAndroid Build Coastguard Worker             }
649*0e209d39SAndroid Build Coastguard Worker         } else {
650*0e209d39SAndroid Build Coastguard Worker             openFileName.append(inputDir, status);
651*0e209d39SAndroid Build Coastguard Worker         }
652*0e209d39SAndroid Build Coastguard Worker     }
653*0e209d39SAndroid Build Coastguard Worker     openFileName.appendPathPart(filename, status);
654*0e209d39SAndroid Build Coastguard Worker 
655*0e209d39SAndroid Build Coastguard Worker     // Test for CharString failure
656*0e209d39SAndroid Build Coastguard Worker     if (U_FAILURE(status)) {
657*0e209d39SAndroid Build Coastguard Worker         return;
658*0e209d39SAndroid Build Coastguard Worker     }
659*0e209d39SAndroid Build Coastguard Worker 
660*0e209d39SAndroid Build Coastguard Worker     ucbuf.adoptInstead(ucbuf_open(openFileName.data(), &cp,getShowWarning(),true, &status));
661*0e209d39SAndroid Build Coastguard Worker     if(status == U_FILE_ACCESS_ERROR) {
662*0e209d39SAndroid Build Coastguard Worker 
663*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "couldn't open file %s\n", openFileName.data());
664*0e209d39SAndroid Build Coastguard Worker         return;
665*0e209d39SAndroid Build Coastguard Worker     }
666*0e209d39SAndroid Build Coastguard Worker     if (ucbuf.isNull() || U_FAILURE(status)) {
667*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "An error occurred processing file %s. Error: %s\n",
668*0e209d39SAndroid Build Coastguard Worker                 openFileName.data(), u_errorName(status));
669*0e209d39SAndroid Build Coastguard Worker         return;
670*0e209d39SAndroid Build Coastguard Worker     }
671*0e209d39SAndroid Build Coastguard Worker     /* auto detected popular encodings? */
672*0e209d39SAndroid Build Coastguard Worker     if (cp!=nullptr && isVerbose()) {
673*0e209d39SAndroid Build Coastguard Worker         printf("autodetected encoding %s\n", cp);
674*0e209d39SAndroid Build Coastguard Worker     }
675*0e209d39SAndroid Build Coastguard Worker     /* Parse the data into an SRBRoot */
676*0e209d39SAndroid Build Coastguard Worker     data.adoptInstead(parse(ucbuf.getAlias(), inputDir, outputDir, filename,
677*0e209d39SAndroid Build Coastguard Worker             !omitBinaryCollation, options[NO_COLLATION_RULES].doesOccur, options[ICU4X_MODE].doesOccur, &status));
678*0e209d39SAndroid Build Coastguard Worker 
679*0e209d39SAndroid Build Coastguard Worker     if (data.isNull() || U_FAILURE(status)) {
680*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "couldn't parse the file %s. Error:%s\n", filename, u_errorName(status));
681*0e209d39SAndroid Build Coastguard Worker         return;
682*0e209d39SAndroid Build Coastguard Worker     }
683*0e209d39SAndroid Build Coastguard Worker 
684*0e209d39SAndroid Build Coastguard Worker     // Run filtering before writing pool bundle
685*0e209d39SAndroid Build Coastguard Worker     if (filterDir != nullptr) {
686*0e209d39SAndroid Build Coastguard Worker         CharString filterFileName(filterDir, status);
687*0e209d39SAndroid Build Coastguard Worker         filterFileName.appendPathPart(filename, status);
688*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
689*0e209d39SAndroid Build Coastguard Worker             return;
690*0e209d39SAndroid Build Coastguard Worker         }
691*0e209d39SAndroid Build Coastguard Worker 
692*0e209d39SAndroid Build Coastguard Worker         // Open the file and read it into filter
693*0e209d39SAndroid Build Coastguard Worker         SimpleRuleBasedPathFilter filter;
694*0e209d39SAndroid Build Coastguard Worker         std::ifstream f(filterFileName.data());
695*0e209d39SAndroid Build Coastguard Worker         if (f.fail()) {
696*0e209d39SAndroid Build Coastguard Worker             std::cerr << "genrb error: unable to open " << filterFileName.data() << std::endl;
697*0e209d39SAndroid Build Coastguard Worker             status = U_FILE_ACCESS_ERROR;
698*0e209d39SAndroid Build Coastguard Worker             return;
699*0e209d39SAndroid Build Coastguard Worker         }
700*0e209d39SAndroid Build Coastguard Worker         std::string currentLine;
701*0e209d39SAndroid Build Coastguard Worker         while (std::getline(f, currentLine)) {
702*0e209d39SAndroid Build Coastguard Worker             // Ignore # comments and empty lines
703*0e209d39SAndroid Build Coastguard Worker             if (currentLine.empty() || currentLine[0] == '#') {
704*0e209d39SAndroid Build Coastguard Worker                 continue;
705*0e209d39SAndroid Build Coastguard Worker             }
706*0e209d39SAndroid Build Coastguard Worker             filter.addRule(currentLine, status);
707*0e209d39SAndroid Build Coastguard Worker             if (U_FAILURE(status)) {
708*0e209d39SAndroid Build Coastguard Worker                 return;
709*0e209d39SAndroid Build Coastguard Worker             }
710*0e209d39SAndroid Build Coastguard Worker         }
711*0e209d39SAndroid Build Coastguard Worker 
712*0e209d39SAndroid Build Coastguard Worker         if (isVerbose()) {
713*0e209d39SAndroid Build Coastguard Worker             filter.print(std::cout);
714*0e209d39SAndroid Build Coastguard Worker         }
715*0e209d39SAndroid Build Coastguard Worker 
716*0e209d39SAndroid Build Coastguard Worker         // Apply the filter to the data
717*0e209d39SAndroid Build Coastguard Worker         ResKeyPath path;
718*0e209d39SAndroid Build Coastguard Worker         data->fRoot->applyFilter(filter, path, data.getAlias());
719*0e209d39SAndroid Build Coastguard Worker     }
720*0e209d39SAndroid Build Coastguard Worker 
721*0e209d39SAndroid Build Coastguard Worker     if(options[WRITE_POOL_BUNDLE].doesOccur) {
722*0e209d39SAndroid Build Coastguard Worker         data->fWritePoolBundle = newPoolBundle;
723*0e209d39SAndroid Build Coastguard Worker         data->compactKeys(status);
724*0e209d39SAndroid Build Coastguard Worker         int32_t newKeysLength;
725*0e209d39SAndroid Build Coastguard Worker         const char *newKeys = data->getKeyBytes(&newKeysLength);
726*0e209d39SAndroid Build Coastguard Worker         newPoolBundle->addKeyBytes(newKeys, newKeysLength, status);
727*0e209d39SAndroid Build Coastguard Worker         if(U_FAILURE(status)) {
728*0e209d39SAndroid Build Coastguard Worker             fprintf(stderr, "bundle_compactKeys(%s) or bundle_getKeyBytes() failed: %s\n",
729*0e209d39SAndroid Build Coastguard Worker                     filename, u_errorName(status));
730*0e209d39SAndroid Build Coastguard Worker             return;
731*0e209d39SAndroid Build Coastguard Worker         }
732*0e209d39SAndroid Build Coastguard Worker         /* count the number of just-added key strings */
733*0e209d39SAndroid Build Coastguard Worker         for(const char *newKeysLimit = newKeys + newKeysLength; newKeys < newKeysLimit; ++newKeys) {
734*0e209d39SAndroid Build Coastguard Worker             if(*newKeys == 0) {
735*0e209d39SAndroid Build Coastguard Worker                 ++newPoolBundle->fKeysCount;
736*0e209d39SAndroid Build Coastguard Worker             }
737*0e209d39SAndroid Build Coastguard Worker         }
738*0e209d39SAndroid Build Coastguard Worker     }
739*0e209d39SAndroid Build Coastguard Worker 
740*0e209d39SAndroid Build Coastguard Worker     if(options[USE_POOL_BUNDLE].doesOccur) {
741*0e209d39SAndroid Build Coastguard Worker         data->fUsePoolBundle = &poolBundle;
742*0e209d39SAndroid Build Coastguard Worker     }
743*0e209d39SAndroid Build Coastguard Worker 
744*0e209d39SAndroid Build Coastguard Worker     /* Determine the target rb filename */
745*0e209d39SAndroid Build Coastguard Worker     uprv_free(make_res_filename(filename, outputDir, packageName, status));
746*0e209d39SAndroid Build Coastguard Worker     if(U_FAILURE(status)) {
747*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "couldn't make the res fileName for  bundle %s. Error:%s\n",
748*0e209d39SAndroid Build Coastguard Worker                 filename, u_errorName(status));
749*0e209d39SAndroid Build Coastguard Worker         return;
750*0e209d39SAndroid Build Coastguard Worker     }
751*0e209d39SAndroid Build Coastguard Worker     if(write_java== true){
752*0e209d39SAndroid Build Coastguard Worker         bundle_write_java(data.getAlias(), outputDir, outputEnc,
753*0e209d39SAndroid Build Coastguard Worker                           outputFileName, sizeof(outputFileName),
754*0e209d39SAndroid Build Coastguard Worker                           options[JAVA_PACKAGE].value, options[BUNDLE_NAME].value, &status);
755*0e209d39SAndroid Build Coastguard Worker     }else if(write_xliff ==true){
756*0e209d39SAndroid Build Coastguard Worker         bundle_write_xml(data.getAlias(), outputDir, outputEnc,
757*0e209d39SAndroid Build Coastguard Worker                          filename, outputFileName, sizeof(outputFileName),
758*0e209d39SAndroid Build Coastguard Worker                          language, xliffOutputFileName, &status);
759*0e209d39SAndroid Build Coastguard Worker     }else{
760*0e209d39SAndroid Build Coastguard Worker         /* Write the data to the file */
761*0e209d39SAndroid Build Coastguard Worker         data->write(outputDir, packageName, outputFileName, sizeof(outputFileName), status);
762*0e209d39SAndroid Build Coastguard Worker     }
763*0e209d39SAndroid Build Coastguard Worker     if (U_FAILURE(status)) {
764*0e209d39SAndroid Build Coastguard Worker         fprintf(stderr, "couldn't write bundle %s. Error:%s\n", outputFileName, u_errorName(status));
765*0e209d39SAndroid Build Coastguard Worker     }
766*0e209d39SAndroid Build Coastguard Worker }
767*0e209d39SAndroid Build Coastguard Worker 
768*0e209d39SAndroid Build Coastguard Worker /* Generate the target .res file name from the input file name */
769*0e209d39SAndroid Build Coastguard Worker static char*
make_res_filename(const char * filename,const char * outputDir,const char * packageName,UErrorCode & status)770*0e209d39SAndroid Build Coastguard Worker make_res_filename(const char *filename,
771*0e209d39SAndroid Build Coastguard Worker                   const char *outputDir,
772*0e209d39SAndroid Build Coastguard Worker                   const char *packageName,
773*0e209d39SAndroid Build Coastguard Worker                   UErrorCode &status) {
774*0e209d39SAndroid Build Coastguard Worker     char *basename;
775*0e209d39SAndroid Build Coastguard Worker     char *dirname;
776*0e209d39SAndroid Build Coastguard Worker     char *resName;
777*0e209d39SAndroid Build Coastguard Worker 
778*0e209d39SAndroid Build Coastguard Worker     int32_t pkgLen = 0; /* length of package prefix */
779*0e209d39SAndroid Build Coastguard Worker 
780*0e209d39SAndroid Build Coastguard Worker 
781*0e209d39SAndroid Build Coastguard Worker     if (U_FAILURE(status)) {
782*0e209d39SAndroid Build Coastguard Worker         return nullptr;
783*0e209d39SAndroid Build Coastguard Worker     }
784*0e209d39SAndroid Build Coastguard Worker 
785*0e209d39SAndroid Build Coastguard Worker     if(packageName != nullptr)
786*0e209d39SAndroid Build Coastguard Worker     {
787*0e209d39SAndroid Build Coastguard Worker         pkgLen = (int32_t)(1 + uprv_strlen(packageName));
788*0e209d39SAndroid Build Coastguard Worker     }
789*0e209d39SAndroid Build Coastguard Worker 
790*0e209d39SAndroid Build Coastguard Worker     /* setup */
791*0e209d39SAndroid Build Coastguard Worker     basename = dirname = resName = nullptr;
792*0e209d39SAndroid Build Coastguard Worker 
793*0e209d39SAndroid Build Coastguard Worker     /* determine basename, and compiled file names */
794*0e209d39SAndroid Build Coastguard Worker     basename = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1));
795*0e209d39SAndroid Build Coastguard Worker     if (basename == nullptr) {
796*0e209d39SAndroid Build Coastguard Worker         status = U_MEMORY_ALLOCATION_ERROR;
797*0e209d39SAndroid Build Coastguard Worker         goto finish;
798*0e209d39SAndroid Build Coastguard Worker     }
799*0e209d39SAndroid Build Coastguard Worker 
800*0e209d39SAndroid Build Coastguard Worker     get_basename(basename, filename);
801*0e209d39SAndroid Build Coastguard Worker 
802*0e209d39SAndroid Build Coastguard Worker     dirname = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1));
803*0e209d39SAndroid Build Coastguard Worker     if (dirname == nullptr) {
804*0e209d39SAndroid Build Coastguard Worker         status = U_MEMORY_ALLOCATION_ERROR;
805*0e209d39SAndroid Build Coastguard Worker         goto finish;
806*0e209d39SAndroid Build Coastguard Worker     }
807*0e209d39SAndroid Build Coastguard Worker 
808*0e209d39SAndroid Build Coastguard Worker     get_dirname(dirname, filename);
809*0e209d39SAndroid Build Coastguard Worker 
810*0e209d39SAndroid Build Coastguard Worker     if (outputDir == nullptr) {
811*0e209d39SAndroid Build Coastguard Worker         /* output in same dir as .txt */
812*0e209d39SAndroid Build Coastguard Worker         resName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(dirname)
813*0e209d39SAndroid Build Coastguard Worker                                       + pkgLen
814*0e209d39SAndroid Build Coastguard Worker                                       + uprv_strlen(basename)
815*0e209d39SAndroid Build Coastguard Worker                                       + uprv_strlen(RES_SUFFIX) + 8));
816*0e209d39SAndroid Build Coastguard Worker         if (resName == nullptr) {
817*0e209d39SAndroid Build Coastguard Worker             status = U_MEMORY_ALLOCATION_ERROR;
818*0e209d39SAndroid Build Coastguard Worker             goto finish;
819*0e209d39SAndroid Build Coastguard Worker         }
820*0e209d39SAndroid Build Coastguard Worker 
821*0e209d39SAndroid Build Coastguard Worker         uprv_strcpy(resName, dirname);
822*0e209d39SAndroid Build Coastguard Worker 
823*0e209d39SAndroid Build Coastguard Worker         if(packageName != nullptr)
824*0e209d39SAndroid Build Coastguard Worker         {
825*0e209d39SAndroid Build Coastguard Worker             uprv_strcat(resName, packageName);
826*0e209d39SAndroid Build Coastguard Worker             uprv_strcat(resName, "_");
827*0e209d39SAndroid Build Coastguard Worker         }
828*0e209d39SAndroid Build Coastguard Worker 
829*0e209d39SAndroid Build Coastguard Worker         uprv_strcat(resName, basename);
830*0e209d39SAndroid Build Coastguard Worker 
831*0e209d39SAndroid Build Coastguard Worker     } else {
832*0e209d39SAndroid Build Coastguard Worker         int32_t dirlen      = (int32_t)uprv_strlen(outputDir);
833*0e209d39SAndroid Build Coastguard Worker         int32_t basenamelen = (int32_t)uprv_strlen(basename);
834*0e209d39SAndroid Build Coastguard Worker 
835*0e209d39SAndroid Build Coastguard Worker         resName = (char*) uprv_malloc(sizeof(char) * (dirlen + pkgLen + basenamelen + 8));
836*0e209d39SAndroid Build Coastguard Worker 
837*0e209d39SAndroid Build Coastguard Worker         if (resName == nullptr) {
838*0e209d39SAndroid Build Coastguard Worker             status = U_MEMORY_ALLOCATION_ERROR;
839*0e209d39SAndroid Build Coastguard Worker             goto finish;
840*0e209d39SAndroid Build Coastguard Worker         }
841*0e209d39SAndroid Build Coastguard Worker 
842*0e209d39SAndroid Build Coastguard Worker         uprv_strcpy(resName, outputDir);
843*0e209d39SAndroid Build Coastguard Worker 
844*0e209d39SAndroid Build Coastguard Worker         if(outputDir[dirlen] != U_FILE_SEP_CHAR) {
845*0e209d39SAndroid Build Coastguard Worker             resName[dirlen]     = U_FILE_SEP_CHAR;
846*0e209d39SAndroid Build Coastguard Worker             resName[dirlen + 1] = '\0';
847*0e209d39SAndroid Build Coastguard Worker         }
848*0e209d39SAndroid Build Coastguard Worker 
849*0e209d39SAndroid Build Coastguard Worker         if(packageName != nullptr)
850*0e209d39SAndroid Build Coastguard Worker         {
851*0e209d39SAndroid Build Coastguard Worker             uprv_strcat(resName, packageName);
852*0e209d39SAndroid Build Coastguard Worker             uprv_strcat(resName, "_");
853*0e209d39SAndroid Build Coastguard Worker         }
854*0e209d39SAndroid Build Coastguard Worker 
855*0e209d39SAndroid Build Coastguard Worker         uprv_strcat(resName, basename);
856*0e209d39SAndroid Build Coastguard Worker     }
857*0e209d39SAndroid Build Coastguard Worker 
858*0e209d39SAndroid Build Coastguard Worker finish:
859*0e209d39SAndroid Build Coastguard Worker     uprv_free(basename);
860*0e209d39SAndroid Build Coastguard Worker     uprv_free(dirname);
861*0e209d39SAndroid Build Coastguard Worker 
862*0e209d39SAndroid Build Coastguard Worker     return resName;
863*0e209d39SAndroid Build Coastguard Worker }
864*0e209d39SAndroid Build Coastguard Worker 
865*0e209d39SAndroid Build Coastguard Worker /*
866*0e209d39SAndroid Build Coastguard Worker  * Local Variables:
867*0e209d39SAndroid Build Coastguard Worker  * indent-tabs-mode: nil
868*0e209d39SAndroid Build Coastguard Worker  * End:
869*0e209d39SAndroid Build Coastguard Worker  */
870