2 *******************************************************************************
4 * Copyright (C) 1998-2008, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 05/25/99 stephen Creation.
15 * 5/10/01 Ram removed ustdio dependency
16 *******************************************************************************
20 #include "unicode/uclean.h"
23 static void processFile(const char *filename
, const char* cp
, const char *inputDir
, const char *outputDir
, const char *packageName
, UErrorCode
*status
);
24 static char *make_res_filename(const char *filename
, const char *outputDir
,
25 const char *packageName
, UErrorCode
*status
);
28 #define RES_SUFFIX ".res"
29 #define COL_SUFFIX ".col"
31 static char theCurrentFileName
[2048];
32 const char *gCurrentFileName
= theCurrentFileName
;
50 /* PACKAGE_NAME, This option is deprecated and should not be used ever. */
62 UOPTION_HELP_QUESTION_MARK
,
72 /* UOPTION_PACKAGE_NAME, This option is deprecated and should not be used ever. */
74 UOPTION_DEF( "write-xliff", 'x', UOPT_OPTIONAL_ARG
),
75 UOPTION_DEF( "strict", 'k', UOPT_NO_ARG
), /* 14 */
76 UOPTION_DEF( "noBinaryCollation", 'C', UOPT_NO_ARG
),/* 15 */
77 UOPTION_DEF( "language", 'l', UOPT_REQUIRES_ARG
), /* 16 */
78 UOPTION_DEF( "omitCollationRules", 'R', UOPT_NO_ARG
),/* 17 */
81 static UBool write_java
= FALSE
;
82 static UBool write_xliff
= FALSE
;
83 static const char* outputEnc
="";
84 static const char* gPackageName
=NULL
;
85 static const char* bundleName
=NULL
;
87 static const char* language
= NULL
;
88 static const char* xliffOutputFileName
= NULL
;
93 UErrorCode status
= U_ZERO_ERROR
;
94 const char *arg
= NULL
;
95 const char *outputDir
= NULL
; /* NULL = no output directory, use current */
96 const char *inputDir
= NULL
;
97 const char *encoding
= "";
100 U_MAIN_INIT_ARGS(argc
, argv
);
102 argc
= u_parseArgs(argc
, argv
, (int32_t)(sizeof(options
)/sizeof(options
[0])), options
);
104 /* error handling, printing usage message */
106 fprintf(stderr
, "%s: error in command line argument \"%s\"\n", argv
[0], argv
[-argc
]);
111 if(options
[VERSION
].doesOccur
) {
113 "%s version %s (ICU version %s).\n"
115 argv
[0], GENRB_VERSION
, U_ICU_VERSION
, U_COPYRIGHT_STRING
);
119 if(argc
<0 || options
[HELP1
].doesOccur
|| options
[HELP2
].doesOccur
) {
121 * Broken into chucks because the C89 standard says the minimum
122 * required supported string length is 509 bytes.
125 "Usage: %s [OPTIONS] [FILES]\n"
126 "\tReads the list of resource bundle source files and creates\n"
127 "\tbinary version of reosurce bundles (.res files)\n",
131 "\t-h or -? or --help this usage text\n"
132 "\t-q or --quiet do not display warnings\n"
133 "\t-v or --verbose print extra information when processing files\n"
134 "\t-V or --version prints out version number and exits\n"
135 "\t-c or --copyright include copyright notice\n");
137 "\t-e or --encoding encoding of source files\n"
138 "\t-d of --destdir destination directory, followed by the path, defaults to %s\n"
139 "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n"
140 "\t-i or --icudatadir directory for locating any needed intermediate data files,\n"
141 "\t followed by path, defaults to %s\n",
142 u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory());
144 "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n"
145 "\t defaults to ASCII and \\uXXXX format.\n");
146 /* This option is deprecated and should not be used ever.
147 "\t-p or --package-name For ICU4J: package name for writing the ListResourceBundle for ICU4J,\n"
148 "\t defaults to com.ibm.icu.impl.data\n"); */
150 "\t-b or --bundle-name bundle name for writing the ListResourceBundle for ICU4J,\n"
151 "\t defaults to LocaleElements\n"
152 "\t-x or --write-xliff write an XLIFF file for the resource bundle. Followed by\n"
153 "\t an optional output file name.\n"
154 "\t-k or --strict use pedantic parsing of syntax\n"
156 "\t-l or --language for XLIFF: language code compliant with BCP 47.\n");
158 "\t-C or --noBinaryCollation do not generate binary collation image;\n"
159 "\t makes .res file smaller but collator instantiation much slower;\n"
160 "\t maintains ability to get tailoring rules\n"
161 "\t-R or --omitCollationRules do not include collation (tailoring) rules;\n"
162 "\t makes .res file smaller and maintains collator instantiation speed\n"
163 "\t but tailoring rules will not be available (they are rarely used)\n");
165 return argc
< 0 ? U_ILLEGAL_ARGUMENT_ERROR
: U_ZERO_ERROR
;
168 if(options
[VERBOSE
].doesOccur
) {
172 if(options
[QUIET
].doesOccur
) {
173 setShowWarning(FALSE
);
175 if(options
[STRICT
].doesOccur
) {
178 if(options
[COPYRIGHT
].doesOccur
){
179 setIncludeCopyright(TRUE
);
182 if(options
[SOURCEDIR
].doesOccur
) {
183 inputDir
= options
[SOURCEDIR
].value
;
186 if(options
[DESTDIR
].doesOccur
) {
187 outputDir
= options
[DESTDIR
].value
;
189 /* This option is deprecated and should never be used.
190 if(options[PACKAGE_NAME].doesOccur) {
191 gPackageName = options[PACKAGE_NAME].value;
192 if(!strcmp(gPackageName, "ICUDATA"))
194 gPackageName = U_ICUDATA_NAME;
196 if(gPackageName[0] == 0)
202 if(options
[ENCODING
].doesOccur
) {
203 encoding
= options
[ENCODING
].value
;
206 if(options
[ICUDATADIR
].doesOccur
) {
207 u_setDataDirectory(options
[ICUDATADIR
].value
);
211 if (U_FAILURE(status
) && status
!= U_FILE_ACCESS_ERROR
) {
212 /* Note: u_init() will try to open ICU property data.
213 * failures here are expected when building ICU from scratch.
216 fprintf(stderr
, "%s: can not initialize ICU. status = %s\n",
217 argv
[0], u_errorName(status
));
220 status
= U_ZERO_ERROR
;
221 if(options
[WRITE_JAVA
].doesOccur
) {
223 outputEnc
= options
[WRITE_JAVA
].value
;
226 if(options
[BUNDLE_NAME
].doesOccur
) {
227 bundleName
= options
[BUNDLE_NAME
].value
;
230 if(options
[WRITE_XLIFF
].doesOccur
) {
232 if(options
[WRITE_XLIFF
].value
!= NULL
){
233 xliffOutputFileName
= options
[WRITE_XLIFF
].value
;
237 initParser(options
[NO_BINARY_COLLATION
].doesOccur
, options
[NO_COLLATION_RULES
].doesOccur
);
240 if(options
[LANGUAGE
].doesOccur
) {
241 language
= options
[LANGUAGE
].value
;
244 /* generate the binary files */
245 for(i
= 1; i
< argc
; ++i
) {
246 status
= U_ZERO_ERROR
;
247 arg
= getLongPathname(argv
[i
]);
250 uprv_strcpy(theCurrentFileName
, inputDir
);
251 uprv_strcat(theCurrentFileName
, U_FILE_SEP_STRING
);
253 *theCurrentFileName
= 0;
255 uprv_strcat(theCurrentFileName
, arg
);
258 printf("Processing file \"%s\"\n", theCurrentFileName
);
260 processFile(arg
, encoding
, inputDir
, outputDir
, gPackageName
, &status
);
263 /* Dont return warnings as a failure */
264 if (! U_FAILURE(status
)) {
273 processFile(const char *filename
, const char *cp
, const char *inputDir
, const char *outputDir
, const char *packageName
, UErrorCode
*status
) {
274 /*FileStream *in = NULL;*/
275 struct SRBRoot
*data
= NULL
;
276 UCHARBUF
*ucbuf
= NULL
;
278 char *openFileName
= NULL
;
279 char *inputDirBuf
= NULL
;
281 char outputFileName
[256];
286 if (status
==NULL
|| U_FAILURE(*status
)) {
290 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
293 filelen
= (int32_t)uprv_strlen(filename
);
295 if(inputDir
== NULL
) {
296 const char *filenameBegin
= uprv_strrchr(filename
, U_FILE_SEP_CHAR
);
297 openFileName
= (char *) uprv_malloc(dirlen
+ filelen
+ 2);
298 openFileName
[0] = '\0';
299 if (filenameBegin
!= NULL
) {
301 * When a filename ../../../data/root.txt is specified,
302 * we presume that the input directory is ../../../data
303 * This is very important when the resource file includes
304 * another file, like UCARules.txt or thaidict.brk.
306 int32_t filenameSize
= (int32_t)(filenameBegin
- filename
+ 1);
307 inputDirBuf
= uprv_strncpy((char *)uprv_malloc(filenameSize
), filename
, filenameSize
);
310 if(inputDirBuf
== NULL
) {
311 *status
= U_MEMORY_ALLOCATION_ERROR
;
315 inputDirBuf
[filenameSize
- 1] = 0;
316 inputDir
= inputDirBuf
;
317 dirlen
= (int32_t)uprv_strlen(inputDir
);
320 dirlen
= (int32_t)uprv_strlen(inputDir
);
322 if(inputDir
[dirlen
-1] != U_FILE_SEP_CHAR
) {
323 openFileName
= (char *) uprv_malloc(dirlen
+ filelen
+ 2);
326 if(openFileName
== NULL
) {
327 *status
= U_MEMORY_ALLOCATION_ERROR
;
331 openFileName
[0] = '\0';
333 * append the input dir to openFileName if the first char in
334 * filename is not file seperation char and the last char input directory is not '.'.
335 * This is to support :
336 * genrb -s. /home/icu/data
338 * The user cannot mix notations like
339 * genrb -s. /icu/data --- the absolute path specified. -s redundant
341 * genrb -s. icu/data --- start from CWD and look in icu/data dir
343 if( (filename
[0] != U_FILE_SEP_CHAR
) && (inputDir
[dirlen
-1] !='.')){
344 uprv_strcpy(openFileName
, inputDir
);
345 openFileName
[dirlen
] = U_FILE_SEP_CHAR
;
347 openFileName
[dirlen
+ 1] = '\0';
349 openFileName
= (char *) uprv_malloc(dirlen
+ filelen
+ 1);
352 if(openFileName
== NULL
) {
353 *status
= U_MEMORY_ALLOCATION_ERROR
;
357 uprv_strcpy(openFileName
, inputDir
);
362 uprv_strcat(openFileName
, filename
);
364 ucbuf
= ucbuf_open(openFileName
, &cp
,getShowWarning(),TRUE
, status
);
366 if(*status
== U_FILE_ACCESS_ERROR
) {
368 fprintf(stderr
, "couldn't open file %s\n", openFileName
== NULL
? filename
: openFileName
);
371 if (ucbuf
== NULL
|| U_FAILURE(*status
)) {
372 fprintf(stderr
, "An error occured processing file %s. Error: %s\n", openFileName
== NULL
? filename
: openFileName
,u_errorName(*status
));
375 /* auto detected popular encodings? */
376 if (cp
!=NULL
&& isVerbose()) {
377 printf("autodetected encoding %s\n", cp
);
379 /* Parse the data into an SRBRoot */
380 data
= parse(ucbuf
, inputDir
, outputDir
, status
);
382 if (data
== NULL
|| U_FAILURE(*status
)) {
383 fprintf(stderr
, "couldn't parse the file %s. Error:%s\n", filename
,u_errorName(*status
));
387 /* Determine the target rb filename */
388 rbname
= make_res_filename(filename
, outputDir
, packageName
, status
);
389 if(U_FAILURE(*status
)) {
390 fprintf(stderr
, "couldn't make the res fileName for bundle %s. Error:%s\n", filename
,u_errorName(*status
));
393 if(write_java
== TRUE
){
394 bundle_write_java(data
,outputDir
,outputEnc
, outputFileName
, sizeof(outputFileName
),packageName
,bundleName
,status
);
395 }else if(write_xliff
==TRUE
){
396 bundle_write_xml(data
,outputDir
,outputEnc
, filename
, outputFileName
, sizeof(outputFileName
),language
, xliffOutputFileName
,status
);
398 /* Write the data to the file */
399 bundle_write(data
, outputDir
, packageName
, outputFileName
, sizeof(outputFileName
), status
);
401 if (U_FAILURE(*status
)) {
402 fprintf(stderr
, "couldn't write bundle %s. Error:%s\n", outputFileName
,u_errorName(*status
));
404 bundle_close(data
, status
);
408 if (inputDirBuf
!= NULL
) {
409 uprv_free(inputDirBuf
);
412 if (openFileName
!= NULL
) {
413 uprv_free(openFileName
);
425 /* Generate the target .res file name from the input file name */
427 make_res_filename(const char *filename
,
428 const char *outputDir
,
429 const char *packageName
,
430 UErrorCode
*status
) {
435 int32_t pkgLen
= 0; /* length of package prefix */
437 if (U_FAILURE(*status
)) {
441 if(packageName
!= NULL
)
443 pkgLen
= (int32_t)(1 + uprv_strlen(packageName
));
447 basename
= dirname
= resName
= 0;
449 /* determine basename, and compiled file names */
450 basename
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename
) + 1));
452 *status
= U_MEMORY_ALLOCATION_ERROR
;
456 get_basename(basename
, filename
);
458 dirname
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename
) + 1));
460 *status
= U_MEMORY_ALLOCATION_ERROR
;
464 get_dirname(dirname
, filename
);
466 if (outputDir
== NULL
) {
467 /* output in same dir as .txt */
468 resName
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(dirname
)
470 + uprv_strlen(basename
)
471 + uprv_strlen(RES_SUFFIX
) + 8));
473 *status
= U_MEMORY_ALLOCATION_ERROR
;
477 uprv_strcpy(resName
, dirname
);
479 if(packageName
!= NULL
)
481 uprv_strcat(resName
, packageName
);
482 uprv_strcat(resName
, "_");
485 uprv_strcat(resName
, basename
);
488 int32_t dirlen
= (int32_t)uprv_strlen(outputDir
);
489 int32_t basenamelen
= (int32_t)uprv_strlen(basename
);
491 resName
= (char*) uprv_malloc(sizeof(char) * (dirlen
+ pkgLen
+ basenamelen
+ 8));
493 if (resName
== NULL
) {
494 *status
= U_MEMORY_ALLOCATION_ERROR
;
498 uprv_strcpy(resName
, outputDir
);
500 if(outputDir
[dirlen
] != U_FILE_SEP_CHAR
) {
501 resName
[dirlen
] = U_FILE_SEP_CHAR
;
502 resName
[dirlen
+ 1] = '\0';
505 if(packageName
!= NULL
)
507 uprv_strcat(resName
, packageName
);
508 uprv_strcat(resName
, "_");
511 uprv_strcat(resName
, basename
);
523 * indent-tabs-mode: nil