2 *******************************************************************************
4 * Copyright (C) 1998-2004, 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
;
62 UOPTION_HELP_QUESTION_MARK
,
74 UOPTION_DEF( "write-xliff", 'x', UOPT_OPTIONAL_ARG
),
75 UOPTION_DEF( "touchfile", 't', UOPT_NO_ARG
),
76 UOPTION_DEF( "strict", 'k', UOPT_NO_ARG
), /* 14 */
77 UOPTION_DEF( "noBinaryCollation", 'C', UOPT_NO_ARG
),/* 15 */
79 UOPTION_DEF( "language", 'l', UOPT_REQUIRES_ARG
)
82 static UBool write_java
= FALSE
;
83 static UBool write_xliff
= FALSE
;
84 static UBool touchfile
= FALSE
;
85 static const char* outputEnc
="";
86 static const char* gPackageName
=NULL
;
87 static const char* bundleName
=NULL
;
89 static const char* language
= NULL
;
90 static const char* xliffOutputFileName
= NULL
;
95 UErrorCode status
= U_ZERO_ERROR
;
96 const char *arg
= NULL
;
97 const char *outputDir
= NULL
; /* NULL = no output directory, use current */
98 const char *inputDir
= NULL
;
99 const char *encoding
= "";
102 U_MAIN_INIT_ARGS(argc
, argv
);
104 argc
= u_parseArgs(argc
, argv
, (int32_t)(sizeof(options
)/sizeof(options
[0])), options
);
106 /* error handling, printing usage message */
108 fprintf(stderr
, "%s: error in command line argument \"%s\"\n", argv
[0], argv
[-argc
]);
113 if(options
[VERSION
].doesOccur
) {
115 "%s version %s (ICU version %s).\n"
117 argv
[0], GENRB_VERSION
, U_ICU_VERSION
, U_COPYRIGHT_STRING
);
121 if(argc
<0 || options
[HELP1
].doesOccur
|| options
[HELP2
].doesOccur
) {
123 * Broken into chucks because the C89 standard says the minimum
124 * required supported string length is 509 bytes.
127 "Usage: %s [OPTIONS] [FILES]\n"
128 "\tReads the list of resource bundle source files and creates\n"
129 "\tbinary version of reosurce bundles (.res files)\n",
133 "\t-h or -? or --help this usage text\n"
134 "\t-q or --quiet do not display warnings\n"
135 "\t-v or --verbose print extra information when processing files\n"
136 "\t-V or --version prints out version number and exits\n"
137 "\t-c or --copyright include copyright notice\n");
139 "\t-e or --encoding encoding of source files\n"
140 "\t-d of --destdir destination directory, followed by the path, defaults to %s\n"
141 "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n"
142 "\t-i or --icudatadir directory for locating any needed intermediate data files,\n"
143 "\t followed by path, defaults to %s\n",
144 u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory());
146 "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n"
147 "\t defaults to ASCII and \\uXXXX format.\n"
148 "\t-p or --package-name For ICU4J: package name for writing the ListResourceBundle for ICU4J,\n"
149 "\t defaults to com.ibm.icu.impl.data\n"
150 "\t For ICU4C: Package name for the .res files on output. Specfiying\n"
151 "\t 'ICUDATA' defaults to the current ICU4C data name.\n");
153 "\t-b or --bundle-name bundle name for writing the ListResourceBundle for ICU4J,\n"
154 "\t defaults to LocaleElements\n"
155 "\t-x or --write-xliff write a XLIFF file for the resource bundle. Followed by an optional output file name.\n"
156 "\t-k or --strict use pedantic parsing of syntax\n"
158 "\t-l or --language For XLIFF: language code compliant with ISO 639.\n");
160 return argc
< 0 ? U_ILLEGAL_ARGUMENT_ERROR
: U_ZERO_ERROR
;
163 if(options
[VERBOSE
].doesOccur
) {
167 if(options
[QUIET
].doesOccur
) {
168 setShowWarning(FALSE
);
170 if(options
[STRICT
].doesOccur
) {
173 if(options
[COPYRIGHT
].doesOccur
){
174 setIncludeCopyright(TRUE
);
177 if(options
[SOURCEDIR
].doesOccur
) {
178 inputDir
= options
[SOURCEDIR
].value
;
181 if(options
[DESTDIR
].doesOccur
) {
182 outputDir
= options
[DESTDIR
].value
;
184 if(options
[PACKAGE_NAME
].doesOccur
) {
185 gPackageName
= options
[PACKAGE_NAME
].value
;
186 if(!strcmp(gPackageName
, "ICUDATA"))
188 gPackageName
= U_ICUDATA_NAME
;
190 if(gPackageName
[0] == 0)
196 if(options
[TOUCHFILE
].doesOccur
) {
197 if(gPackageName
== NULL
) {
198 fprintf(stderr
, "%s: Don't use touchfile (-t) option with no package.\n",
205 if(options
[ENCODING
].doesOccur
) {
206 encoding
= options
[ENCODING
].value
;
209 if(options
[ICUDATADIR
].doesOccur
) {
210 u_setDataDirectory(options
[ICUDATADIR
].value
);
214 if (U_FAILURE(status
) && status
!= U_FILE_ACCESS_ERROR
) {
215 /* Note: u_init() will try to open ICU property data.
216 * failures here are expected when building ICU from scratch.
219 fprintf(stderr
, "%s: can not initialize ICU. status = %s\n",
220 argv
[0], u_errorName(status
));
223 status
= U_ZERO_ERROR
;
224 if(options
[WRITE_JAVA
].doesOccur
) {
226 outputEnc
= options
[WRITE_JAVA
].value
;
229 if(options
[BUNDLE_NAME
].doesOccur
) {
230 bundleName
= options
[BUNDLE_NAME
].value
;
233 if(options
[WRITE_XLIFF
].doesOccur
) {
235 if(options
[WRITE_XLIFF
].value
!= NULL
){
236 xliffOutputFileName
= options
[WRITE_XLIFF
].value
;
240 if(options
[NO_BINARY_COLLATION
].doesOccur
) {
247 if(options
[LANGUAGE
].doesOccur
) {
248 language
= options
[LANGUAGE
].value
;
251 /* generate the binary files */
252 for(i
= 1; i
< argc
; ++i
) {
253 status
= U_ZERO_ERROR
;
254 arg
= getLongPathname(argv
[i
]);
257 uprv_strcpy(theCurrentFileName
, inputDir
);
258 uprv_strcat(theCurrentFileName
, U_FILE_SEP_STRING
);
260 *theCurrentFileName
= 0;
262 uprv_strcat(theCurrentFileName
, arg
);
265 printf("Processing file \"%s\"\n", theCurrentFileName
);
267 processFile(arg
, encoding
, inputDir
, outputDir
, gPackageName
, &status
);
275 processFile(const char *filename
, const char *cp
, const char *inputDir
, const char *outputDir
, const char *packageName
, UErrorCode
*status
) {
276 /*FileStream *in = NULL;*/
277 struct SRBRoot
*data
= NULL
;
278 UCHARBUF
*ucbuf
= NULL
;
280 char *openFileName
= NULL
;
281 char *inputDirBuf
= NULL
;
283 char outputFileName
[256];
288 if (status
==NULL
|| U_FAILURE(*status
)) {
292 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
295 filelen
= (int32_t)uprv_strlen(filename
);
297 if(inputDir
== NULL
) {
298 const char *filenameBegin
= uprv_strrchr(filename
, U_FILE_SEP_CHAR
);
299 openFileName
= (char *) uprv_malloc(dirlen
+ filelen
+ 2);
300 openFileName
[0] = '\0';
301 if (filenameBegin
!= NULL
) {
303 * When a filename ../../../data/root.txt is specified,
304 * we presume that the input directory is ../../../data
305 * This is very important when the resource file includes
306 * another file, like UCARules.txt or thaidict.brk.
308 int32_t filenameSize
= (int32_t)(filenameBegin
- filename
+ 1);
309 inputDirBuf
= uprv_strncpy((char *)uprv_malloc(filenameSize
), filename
, filenameSize
);
312 if(inputDirBuf
== NULL
) {
313 *status
= U_MEMORY_ALLOCATION_ERROR
;
317 inputDirBuf
[filenameSize
- 1] = 0;
318 inputDir
= inputDirBuf
;
319 dirlen
= (int32_t)uprv_strlen(inputDir
);
322 dirlen
= (int32_t)uprv_strlen(inputDir
);
324 if(inputDir
[dirlen
-1] != U_FILE_SEP_CHAR
) {
325 openFileName
= (char *) uprv_malloc(dirlen
+ filelen
+ 2);
328 if(openFileName
== NULL
) {
329 *status
= U_MEMORY_ALLOCATION_ERROR
;
333 openFileName
[0] = '\0';
335 * append the input dir to openFileName if the first char in
336 * filename is not file seperation char and the last char input directory is not '.'.
337 * This is to support :
338 * genrb -s. /home/icu/data
340 * The user cannot mix notations like
341 * genrb -s. /icu/data --- the absolute path specified. -s redundant
343 * genrb -s. icu/data --- start from CWD and look in icu/data dir
345 if( (filename
[0] != U_FILE_SEP_CHAR
) && (inputDir
[dirlen
-1] !='.')){
346 uprv_strcpy(openFileName
, inputDir
);
347 openFileName
[dirlen
] = U_FILE_SEP_CHAR
;
349 openFileName
[dirlen
+ 1] = '\0';
351 openFileName
= (char *) uprv_malloc(dirlen
+ filelen
+ 1);
354 if(openFileName
== NULL
) {
355 *status
= U_MEMORY_ALLOCATION_ERROR
;
359 uprv_strcpy(openFileName
, inputDir
);
364 uprv_strcat(openFileName
, filename
);
366 ucbuf
= ucbuf_open(openFileName
, &cp
,getShowWarning(),TRUE
, status
);
368 if(*status
== U_FILE_ACCESS_ERROR
) {
370 fprintf(stderr
, "couldn't open file %s\n", openFileName
== NULL
? filename
: openFileName
);
373 if (ucbuf
== NULL
|| U_FAILURE(*status
)) {
374 fprintf(stderr
, "An error occured processing file %s. Error: %s\n", openFileName
== NULL
? filename
: openFileName
,u_errorName(*status
));
377 /* auto detected popular encodings? */
378 if (cp
!=NULL
&& isVerbose()) {
379 printf("autodetected encoding %s\n", cp
);
381 /* Parse the data into an SRBRoot */
382 data
= parse(ucbuf
, inputDir
, status
);
384 if (data
== NULL
|| U_FAILURE(*status
)) {
385 fprintf(stderr
, "couldn't parse the file %s. Error:%s\n", filename
,u_errorName(*status
));
389 /* Determine the target rb filename */
390 rbname
= make_res_filename(filename
, outputDir
, packageName
, status
);
391 if(touchfile
== TRUE
) {
396 tfname
= make_res_filename(filename
, outputDir
, NULL
, status
);
398 if(U_FAILURE(*status
))
400 fprintf(stderr
, "Error writing touchfile for \"%s\"\n", filename
);
401 *status
= U_FILE_ACCESS_ERROR
;
403 uprv_strcat(tfname
, ".res");
404 sprintf(msg
, "This empty file tells nmake that %s in package %s has been updated.\n",
405 filename
, packageName
);
407 q
= T_FileStream_open(tfname
, "w");
410 fprintf(stderr
, "Error writing touchfile \"%s\"\n", tfname
);
411 *status
= U_FILE_ACCESS_ERROR
;
415 T_FileStream_write(q
, msg
, (int32_t)uprv_strlen(msg
));
416 T_FileStream_close(q
);
422 if(U_FAILURE(*status
)) {
423 fprintf(stderr
, "couldn't make the res fileName for bundle %s. Error:%s\n", filename
,u_errorName(*status
));
426 if(write_java
== TRUE
){
427 bundle_write_java(data
,outputDir
,outputEnc
, outputFileName
, sizeof(outputFileName
),packageName
,bundleName
,status
);
428 }else if(write_xliff
==TRUE
){
429 bundle_write_xml(data
,outputDir
,outputEnc
, filename
, outputFileName
, sizeof(outputFileName
),language
, xliffOutputFileName
,status
);
431 /* Write the data to the file */
432 bundle_write(data
, outputDir
, packageName
, outputFileName
, sizeof(outputFileName
), status
);
434 if (U_FAILURE(*status
)) {
435 fprintf(stderr
, "couldn't write bundle %s. Error:%s\n", outputFileName
,u_errorName(*status
));
437 bundle_close(data
, status
);
441 if (inputDirBuf
!= NULL
) {
442 uprv_free(inputDirBuf
);
445 if (openFileName
!= NULL
) {
446 uprv_free(openFileName
);
458 /* Generate the target .res file name from the input file name */
460 make_res_filename(const char *filename
,
461 const char *outputDir
,
462 const char *packageName
,
463 UErrorCode
*status
) {
468 int32_t pkgLen
= 0; /* length of package prefix */
470 if (U_FAILURE(*status
)) {
474 if(packageName
!= NULL
)
476 pkgLen
= (int32_t)(1 + uprv_strlen(packageName
));
480 basename
= dirname
= resName
= 0;
482 /* determine basename, and compiled file names */
483 basename
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename
) + 1));
485 *status
= U_MEMORY_ALLOCATION_ERROR
;
489 get_basename(basename
, filename
);
491 dirname
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename
) + 1));
493 *status
= U_MEMORY_ALLOCATION_ERROR
;
497 get_dirname(dirname
, filename
);
499 if (outputDir
== NULL
) {
500 /* output in same dir as .txt */
501 resName
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(dirname
)
503 + uprv_strlen(basename
)
504 + uprv_strlen(RES_SUFFIX
) + 8));
506 *status
= U_MEMORY_ALLOCATION_ERROR
;
510 uprv_strcpy(resName
, dirname
);
512 if(packageName
!= NULL
)
514 uprv_strcat(resName
, packageName
);
515 uprv_strcat(resName
, "_");
518 uprv_strcat(resName
, basename
);
521 int32_t dirlen
= (int32_t)uprv_strlen(outputDir
);
522 int32_t basenamelen
= (int32_t)uprv_strlen(basename
);
524 resName
= (char*) uprv_malloc(sizeof(char) * (dirlen
+ pkgLen
+ basenamelen
+ 8));
526 if (resName
== NULL
) {
527 *status
= U_MEMORY_ALLOCATION_ERROR
;
531 uprv_strcpy(resName
, outputDir
);
533 if(outputDir
[dirlen
] != U_FILE_SEP_CHAR
) {
534 resName
[dirlen
] = U_FILE_SEP_CHAR
;
535 resName
[dirlen
+ 1] = '\0';
538 if(packageName
!= NULL
)
540 uprv_strcat(resName
, packageName
);
541 uprv_strcat(resName
, "_");
544 uprv_strcat(resName
, basename
);
556 * indent-tabs-mode: nil