intl/icu/source/tools/genrb/genrb.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial