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