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