]> git.saurik.com Git - apple/icu.git/blame - icuSources/tools/genrb/genrb.c
ICU-8.11.1.tar.gz
[apple/icu.git] / icuSources / tools / genrb / genrb.c
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
3*
73c04bcf 4* Copyright (C) 1998-2006, International Business Machines
b75a7d8f
A
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"
374ca955 20#include "unicode/uclean.h"
b75a7d8f
A
21
22/* Protos */
23static void processFile(const char *filename, const char* cp, const char *inputDir, const char *outputDir, const char *packageName, UErrorCode *status);
374ca955 24static char *make_res_filename(const char *filename, const char *outputDir,
b75a7d8f
A
25 const char *packageName, UErrorCode *status);
26
27/* File suffixes */
28#define RES_SUFFIX ".res"
29#define COL_SUFFIX ".col"
30
374ca955 31static char theCurrentFileName[2048];
b75a7d8f
A
32const char *gCurrentFileName = theCurrentFileName;
33#ifdef XP_MAC_CONSOLE
34#include <console.h>
35#endif
36
37enum
38{
39 HELP1,
40 HELP2,
41 VERBOSE,
42 QUIET,
43 VERSION,
44 SOURCEDIR,
45 DESTDIR,
46 ENCODING,
47 ICUDATADIR,
48 WRITE_JAVA,
49 COPYRIGHT,
50 PACKAGE_NAME,
51 BUNDLE_NAME,
374ca955 52 WRITE_XLIFF,
b75a7d8f
A
53 STRICT,
54 NO_BINARY_COLLATION,
55 /*added by Jing*/
56 LANGUAGE
57};
58
59UOption options[]={
60 UOPTION_HELP_H,
61 UOPTION_HELP_QUESTION_MARK,
62 UOPTION_VERBOSE,
63 UOPTION_QUIET,
64 UOPTION_VERSION,
65 UOPTION_SOURCEDIR,
66 UOPTION_DESTDIR,
67 UOPTION_ENCODING,
68 UOPTION_ICUDATADIR,
69 UOPTION_WRITE_JAVA,
70 UOPTION_COPYRIGHT,
71 UOPTION_PACKAGE_NAME,
72 UOPTION_BUNDLE_NAME,
374ca955 73 UOPTION_DEF( "write-xliff", 'x', UOPT_OPTIONAL_ARG),
b75a7d8f
A
74 UOPTION_DEF( "strict", 'k', UOPT_NO_ARG), /* 14 */
75 UOPTION_DEF( "noBinaryCollation", 'C', UOPT_NO_ARG),/* 15 */
b75a7d8f
A
76 UOPTION_DEF( "language", 'l', UOPT_REQUIRES_ARG)
77 };
78
79static UBool write_java = FALSE;
374ca955 80static UBool write_xliff = FALSE;
b75a7d8f
A
81static const char* outputEnc ="";
82static const char* gPackageName=NULL;
83static const char* bundleName=NULL;
84/*added by Jing*/
85static const char* language = NULL;
374ca955 86static const char* xliffOutputFileName = NULL;
b75a7d8f
A
87int
88main(int argc,
89 char* argv[])
90{
91 UErrorCode status = U_ZERO_ERROR;
92 const char *arg = NULL;
93 const char *outputDir = NULL; /* NULL = no output directory, use current */
94 const char *inputDir = NULL;
95 const char *encoding = "";
96 int i;
374ca955 97
b75a7d8f
A
98 U_MAIN_INIT_ARGS(argc, argv);
99
100 argc = u_parseArgs(argc, argv, (int32_t)(sizeof(options)/sizeof(options[0])), options);
101
102 /* error handling, printing usage message */
103 if(argc<0) {
104 fprintf(stderr, "%s: error in command line argument \"%s\"\n", argv[0], argv[-argc]);
105 } else if(argc<2) {
106 argc = -1;
107 }
108
109 if(options[VERSION].doesOccur) {
110 fprintf(stderr,
111 "%s version %s (ICU version %s).\n"
112 "%s\n",
113 argv[0], GENRB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING);
114 return U_ZERO_ERROR;
115 }
116
117 if(argc<0 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
118 /*
119 * Broken into chucks because the C89 standard says the minimum
120 * required supported string length is 509 bytes.
121 */
122 fprintf(stderr,
123 "Usage: %s [OPTIONS] [FILES]\n"
124 "\tReads the list of resource bundle source files and creates\n"
125 "\tbinary version of reosurce bundles (.res files)\n",
126 argv[0]);
127 fprintf(stderr,
128 "Options:\n"
129 "\t-h or -? or --help this usage text\n"
130 "\t-q or --quiet do not display warnings\n"
131 "\t-v or --verbose print extra information when processing files\n"
132 "\t-V or --version prints out version number and exits\n"
133 "\t-c or --copyright include copyright notice\n");
134 fprintf(stderr,
135 "\t-e or --encoding encoding of source files\n"
136 "\t-d of --destdir destination directory, followed by the path, defaults to %s\n"
137 "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n"
138 "\t-i or --icudatadir directory for locating any needed intermediate data files,\n"
139 "\t followed by path, defaults to %s\n",
140 u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory());
141 fprintf(stderr,
142 "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n"
143 "\t defaults to ASCII and \\uXXXX format.\n"
144 "\t-p or --package-name For ICU4J: package name for writing the ListResourceBundle for ICU4J,\n"
73c04bcf 145 "\t defaults to com.ibm.icu.impl.data\n");
b75a7d8f
A
146 fprintf(stderr,
147 "\t-b or --bundle-name bundle name for writing the ListResourceBundle for ICU4J,\n"
148 "\t defaults to LocaleElements\n"
374ca955 149 "\t-x or --write-xliff write a XLIFF file for the resource bundle. Followed by an optional output file name.\n"
b75a7d8f
A
150 "\t-k or --strict use pedantic parsing of syntax\n"
151 /*added by Jing*/
374ca955 152 "\t-l or --language For XLIFF: language code compliant with ISO 639.\n");
b75a7d8f
A
153
154 return argc < 0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR;
155 }
156
157 if(options[VERBOSE].doesOccur) {
158 setVerbose(TRUE);
159 }
160
161 if(options[QUIET].doesOccur) {
162 setShowWarning(FALSE);
163 }
164 if(options[STRICT].doesOccur) {
165 setStrict(TRUE);
166 }
167 if(options[COPYRIGHT].doesOccur){
168 setIncludeCopyright(TRUE);
169 }
170
171 if(options[SOURCEDIR].doesOccur) {
172 inputDir = options[SOURCEDIR].value;
173 }
174
175 if(options[DESTDIR].doesOccur) {
176 outputDir = options[DESTDIR].value;
177 }
178 if(options[PACKAGE_NAME].doesOccur) {
179 gPackageName = options[PACKAGE_NAME].value;
180 if(!strcmp(gPackageName, "ICUDATA"))
181 {
182 gPackageName = U_ICUDATA_NAME;
183 }
184 if(gPackageName[0] == 0)
185 {
186 gPackageName = NULL;
187 }
188 }
189
b75a7d8f
A
190 if(options[ENCODING].doesOccur) {
191 encoding = options[ENCODING].value;
192 }
193
194 if(options[ICUDATADIR].doesOccur) {
195 u_setDataDirectory(options[ICUDATADIR].value);
196 }
374ca955
A
197 /* Initialize ICU */
198 u_init(&status);
199 if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
200 /* Note: u_init() will try to open ICU property data.
201 * failures here are expected when building ICU from scratch.
202 * ignore them.
203 */
204 fprintf(stderr, "%s: can not initialize ICU. status = %s\n",
205 argv[0], u_errorName(status));
206 exit(1);
207 }
208 status = U_ZERO_ERROR;
b75a7d8f
A
209 if(options[WRITE_JAVA].doesOccur) {
210 write_java = TRUE;
211 outputEnc = options[WRITE_JAVA].value;
212 }
213
214 if(options[BUNDLE_NAME].doesOccur) {
215 bundleName = options[BUNDLE_NAME].value;
216 }
217
374ca955
A
218 if(options[WRITE_XLIFF].doesOccur) {
219 write_xliff = TRUE;
220 if(options[WRITE_XLIFF].value != NULL){
221 xliffOutputFileName = options[WRITE_XLIFF].value;
222 }
b75a7d8f
A
223 }
224
225 if(options[NO_BINARY_COLLATION].doesOccur) {
226 initParser(FALSE);
227 } else {
228 initParser(TRUE);
229 }
374ca955 230
b75a7d8f
A
231 /*added by Jing*/
232 if(options[LANGUAGE].doesOccur) {
233 language = options[LANGUAGE].value;
234 }
235
236 /* generate the binary files */
237 for(i = 1; i < argc; ++i) {
238 status = U_ZERO_ERROR;
239 arg = getLongPathname(argv[i]);
374ca955 240
b75a7d8f
A
241 if (inputDir) {
242 uprv_strcpy(theCurrentFileName, inputDir);
243 uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING);
244 } else {
245 *theCurrentFileName = 0;
246 }
247 uprv_strcat(theCurrentFileName, arg);
248
249 if (isVerbose()) {
250 printf("Processing file \"%s\"\n", theCurrentFileName);
251 }
252 processFile(arg, encoding, inputDir, outputDir, gPackageName, &status);
253 }
254
255 return status;
256}
257
258/* Process a file */
259static void
260processFile(const char *filename, const char *cp, const char *inputDir, const char *outputDir, const char *packageName, UErrorCode *status) {
261 /*FileStream *in = NULL;*/
262 struct SRBRoot *data = NULL;
263 UCHARBUF *ucbuf = NULL;
264 char *rbname = NULL;
265 char *openFileName = NULL;
266 char *inputDirBuf = NULL;
267
268 char outputFileName[256];
374ca955 269
b75a7d8f
A
270 int32_t dirlen = 0;
271 int32_t filelen = 0;
374ca955 272
b75a7d8f
A
273 if (status==NULL || U_FAILURE(*status)) {
274 return;
275 }
276 if(filename==NULL){
277 *status=U_ILLEGAL_ARGUMENT_ERROR;
278 return;
279 }else{
280 filelen = (int32_t)uprv_strlen(filename);
281 }
282 if(inputDir == NULL) {
283 const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR);
284 openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
285 openFileName[0] = '\0';
286 if (filenameBegin != NULL) {
287 /*
374ca955 288 * When a filename ../../../data/root.txt is specified,
b75a7d8f
A
289 * we presume that the input directory is ../../../data
290 * This is very important when the resource file includes
291 * another file, like UCARules.txt or thaidict.brk.
292 */
374ca955 293 int32_t filenameSize = (int32_t)(filenameBegin - filename + 1);
b75a7d8f
A
294 inputDirBuf = uprv_strncpy((char *)uprv_malloc(filenameSize), filename, filenameSize);
295
296 /* test for NULL */
297 if(inputDirBuf == NULL) {
298 *status = U_MEMORY_ALLOCATION_ERROR;
299 goto finish;
300 }
301
302 inputDirBuf[filenameSize - 1] = 0;
303 inputDir = inputDirBuf;
304 dirlen = (int32_t)uprv_strlen(inputDir);
305 }
306 }else{
307 dirlen = (int32_t)uprv_strlen(inputDir);
308
309 if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
310 openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
311
312 /* test for NULL */
313 if(openFileName == NULL) {
314 *status = U_MEMORY_ALLOCATION_ERROR;
315 goto finish;
316 }
317
318 openFileName[0] = '\0';
319 /*
374ca955 320 * append the input dir to openFileName if the first char in
b75a7d8f
A
321 * filename is not file seperation char and the last char input directory is not '.'.
322 * This is to support :
323 * genrb -s. /home/icu/data
324 * genrb -s. icu/data
325 * The user cannot mix notations like
326 * genrb -s. /icu/data --- the absolute path specified. -s redundant
327 * user should use
328 * genrb -s. icu/data --- start from CWD and look in icu/data dir
329 */
330 if( (filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')){
331 uprv_strcpy(openFileName, inputDir);
332 openFileName[dirlen] = U_FILE_SEP_CHAR;
333 }
334 openFileName[dirlen + 1] = '\0';
335 } else {
336 openFileName = (char *) uprv_malloc(dirlen + filelen + 1);
337
338 /* test for NULL */
339 if(openFileName == NULL) {
340 *status = U_MEMORY_ALLOCATION_ERROR;
341 goto finish;
342 }
343
344 uprv_strcpy(openFileName, inputDir);
374ca955 345
b75a7d8f
A
346 }
347 }
348
349 uprv_strcat(openFileName, filename);
350
351 ucbuf = ucbuf_open(openFileName, &cp,getShowWarning(),TRUE, status);
374ca955 352
b75a7d8f 353 if(*status == U_FILE_ACCESS_ERROR) {
374ca955 354
b75a7d8f
A
355 fprintf(stderr, "couldn't open file %s\n", openFileName == NULL ? filename : openFileName);
356 goto finish;
357 }
358 if (ucbuf == NULL || U_FAILURE(*status)) {
359 fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName == NULL ? filename : openFileName,u_errorName(*status));
360 goto finish;
361 }
362 /* auto detected popular encodings? */
374ca955 363 if (cp!=NULL && isVerbose()) {
b75a7d8f
A
364 printf("autodetected encoding %s\n", cp);
365 }
366 /* Parse the data into an SRBRoot */
73c04bcf 367 data = parse(ucbuf, inputDir, outputDir, status);
b75a7d8f
A
368
369 if (data == NULL || U_FAILURE(*status)) {
370 fprintf(stderr, "couldn't parse the file %s. Error:%s\n", filename,u_errorName(*status));
371 goto finish;
372 }
373
374 /* Determine the target rb filename */
375 rbname = make_res_filename(filename, outputDir, packageName, status);
b75a7d8f
A
376 if(U_FAILURE(*status)) {
377 fprintf(stderr, "couldn't make the res fileName for bundle %s. Error:%s\n", filename,u_errorName(*status));
378 goto finish;
379 }
380 if(write_java== TRUE){
381 bundle_write_java(data,outputDir,outputEnc, outputFileName, sizeof(outputFileName),packageName,bundleName,status);
374ca955
A
382 }else if(write_xliff ==TRUE){
383 bundle_write_xml(data,outputDir,outputEnc, filename, outputFileName, sizeof(outputFileName),language, xliffOutputFileName,status);
b75a7d8f
A
384 }else{
385 /* Write the data to the file */
386 bundle_write(data, outputDir, packageName, outputFileName, sizeof(outputFileName), status);
387 }
388 if (U_FAILURE(*status)) {
389 fprintf(stderr, "couldn't write bundle %s. Error:%s\n", outputFileName,u_errorName(*status));
390 }
391 bundle_close(data, status);
392
393finish:
394
395 if (inputDirBuf != NULL) {
396 uprv_free(inputDirBuf);
397 }
398
399 if (openFileName != NULL) {
400 uprv_free(openFileName);
401 }
402
403 if(ucbuf) {
404 ucbuf_close(ucbuf);
405 }
406
407 if (rbname) {
408 uprv_free(rbname);
409 }
410}
411
412/* Generate the target .res file name from the input file name */
413static char*
414make_res_filename(const char *filename,
415 const char *outputDir,
416 const char *packageName,
417 UErrorCode *status) {
418 char *basename;
419 char *dirname;
420 char *resName;
421
422 int32_t pkgLen = 0; /* length of package prefix */
423
424 if (U_FAILURE(*status)) {
425 return 0;
426 }
427
428 if(packageName != NULL)
429 {
374ca955 430 pkgLen = (int32_t)(1 + uprv_strlen(packageName));
b75a7d8f
A
431 }
432
433 /* setup */
434 basename = dirname = resName = 0;
435
436 /* determine basename, and compiled file names */
437 basename = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1));
438 if(basename == 0) {
439 *status = U_MEMORY_ALLOCATION_ERROR;
440 goto finish;
441 }
442
443 get_basename(basename, filename);
444
445 dirname = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1));
446 if(dirname == 0) {
447 *status = U_MEMORY_ALLOCATION_ERROR;
448 goto finish;
449 }
450
451 get_dirname(dirname, filename);
452
453 if (outputDir == NULL) {
454 /* output in same dir as .txt */
455 resName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(dirname)
456 + pkgLen
457 + uprv_strlen(basename)
458 + uprv_strlen(RES_SUFFIX) + 8));
459 if(resName == 0) {
460 *status = U_MEMORY_ALLOCATION_ERROR;
461 goto finish;
462 }
463
464 uprv_strcpy(resName, dirname);
465
466 if(packageName != NULL)
467 {
468 uprv_strcat(resName, packageName);
469 uprv_strcat(resName, "_");
470 }
471
472 uprv_strcat(resName, basename);
473
474 } else {
475 int32_t dirlen = (int32_t)uprv_strlen(outputDir);
476 int32_t basenamelen = (int32_t)uprv_strlen(basename);
477
478 resName = (char*) uprv_malloc(sizeof(char) * (dirlen + pkgLen + basenamelen + 8));
479
480 if (resName == NULL) {
481 *status = U_MEMORY_ALLOCATION_ERROR;
482 goto finish;
483 }
484
485 uprv_strcpy(resName, outputDir);
486
487 if(outputDir[dirlen] != U_FILE_SEP_CHAR) {
488 resName[dirlen] = U_FILE_SEP_CHAR;
489 resName[dirlen + 1] = '\0';
490 }
491
492 if(packageName != NULL)
493 {
494 uprv_strcat(resName, packageName);
495 uprv_strcat(resName, "_");
496 }
497
498 uprv_strcat(resName, basename);
499 }
500
501finish:
502 uprv_free(basename);
503 uprv_free(dirname);
504
505 return resName;
506}
507
508/*
509 * Local Variables:
510 * indent-tabs-mode: nil
511 * End:
512 */