1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/genrb/genrb.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,733 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 1998-2014, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* 1.12 +* File genrb.c 1.13 +* 1.14 +* Modification History: 1.15 +* 1.16 +* Date Name Description 1.17 +* 05/25/99 stephen Creation. 1.18 +* 5/10/01 Ram removed ustdio dependency 1.19 +******************************************************************************* 1.20 +*/ 1.21 + 1.22 +#include "genrb.h" 1.23 +#include "unicode/uclean.h" 1.24 + 1.25 +#include "ucmndata.h" /* TODO: for reading the pool bundle */ 1.26 + 1.27 +/* Protos */ 1.28 +void processFile(const char *filename, const char* cp, const char *inputDir, const char *outputDir, 1.29 + const char *packageName, UBool omitBinaryCollation, UErrorCode *status); 1.30 +static char *make_res_filename(const char *filename, const char *outputDir, 1.31 + const char *packageName, UErrorCode *status); 1.32 + 1.33 +/* File suffixes */ 1.34 +#define RES_SUFFIX ".res" 1.35 +#define COL_SUFFIX ".col" 1.36 + 1.37 +static char theCurrentFileName[2048]; 1.38 +const char *gCurrentFileName = theCurrentFileName; 1.39 +#ifdef XP_MAC_CONSOLE 1.40 +#include <console.h> 1.41 +#endif 1.42 + 1.43 +enum 1.44 +{ 1.45 + HELP1, 1.46 + HELP2, 1.47 + VERBOSE, 1.48 + QUIET, 1.49 + VERSION, 1.50 + SOURCEDIR, 1.51 + DESTDIR, 1.52 + ENCODING, 1.53 + ICUDATADIR, 1.54 + WRITE_JAVA, 1.55 + COPYRIGHT, 1.56 + JAVA_PACKAGE, 1.57 + BUNDLE_NAME, 1.58 + WRITE_XLIFF, 1.59 + STRICT, 1.60 + NO_BINARY_COLLATION, 1.61 + LANGUAGE, 1.62 + NO_COLLATION_RULES, 1.63 + FORMAT_VERSION, 1.64 + WRITE_POOL_BUNDLE, 1.65 + USE_POOL_BUNDLE, 1.66 + INCLUDE_UNIHAN_COLL 1.67 +}; 1.68 + 1.69 +UOption options[]={ 1.70 + UOPTION_HELP_H, 1.71 + UOPTION_HELP_QUESTION_MARK, 1.72 + UOPTION_VERBOSE, 1.73 + UOPTION_QUIET, 1.74 + UOPTION_VERSION, 1.75 + UOPTION_SOURCEDIR, 1.76 + UOPTION_DESTDIR, 1.77 + UOPTION_ENCODING, 1.78 + UOPTION_ICUDATADIR, 1.79 + UOPTION_WRITE_JAVA, 1.80 + UOPTION_COPYRIGHT, 1.81 + UOPTION_DEF("java-package", '\x01', UOPT_REQUIRES_ARG), 1.82 + UOPTION_BUNDLE_NAME, 1.83 + UOPTION_DEF("write-xliff", 'x', UOPT_OPTIONAL_ARG), 1.84 + UOPTION_DEF("strict", 'k', UOPT_NO_ARG), /* 14 */ 1.85 + UOPTION_DEF("noBinaryCollation", 'C', UOPT_NO_ARG),/* 15 */ 1.86 + UOPTION_DEF("language", 'l', UOPT_REQUIRES_ARG), /* 16 */ 1.87 + UOPTION_DEF("omitCollationRules", 'R', UOPT_NO_ARG),/* 17 */ 1.88 + UOPTION_DEF("formatVersion", '\x01', UOPT_REQUIRES_ARG),/* 18 */ 1.89 + UOPTION_DEF("writePoolBundle", '\x01', UOPT_NO_ARG),/* 19 */ 1.90 + UOPTION_DEF("usePoolBundle", '\x01', UOPT_OPTIONAL_ARG),/* 20 */ 1.91 + UOPTION_DEF("includeUnihanColl", '\x01', UOPT_NO_ARG),/* 21 */ /* temporary, don't display in usage info */ 1.92 + }; 1.93 + 1.94 +static UBool write_java = FALSE; 1.95 +static UBool write_xliff = FALSE; 1.96 +static const char* outputEnc =""; 1.97 +static struct SRBRoot *newPoolBundle = NULL; 1.98 + UBool gIncludeUnihanColl = FALSE; 1.99 + 1.100 +/* TODO: separate header file for ResFile? */ 1.101 +typedef struct ResFile { 1.102 + uint8_t *fBytes; 1.103 + const int32_t *fIndexes; 1.104 + const char *fKeys; 1.105 + int32_t fKeysLength; 1.106 + int32_t fKeysCount; 1.107 + int32_t fChecksum; 1.108 +} ResFile; 1.109 + 1.110 +static ResFile poolBundle = { NULL }; 1.111 + 1.112 +/*added by Jing*/ 1.113 +static const char* language = NULL; 1.114 +static const char* xliffOutputFileName = NULL; 1.115 +int 1.116 +main(int argc, 1.117 + char* argv[]) 1.118 +{ 1.119 + UErrorCode status = U_ZERO_ERROR; 1.120 + const char *arg = NULL; 1.121 + const char *outputDir = NULL; /* NULL = no output directory, use current */ 1.122 + const char *inputDir = NULL; 1.123 + const char *encoding = ""; 1.124 + int i; 1.125 + UBool illegalArg = FALSE; 1.126 + 1.127 + U_MAIN_INIT_ARGS(argc, argv); 1.128 + 1.129 + options[JAVA_PACKAGE].value = "com.ibm.icu.impl.data"; 1.130 + options[BUNDLE_NAME].value = "LocaleElements"; 1.131 + argc = u_parseArgs(argc, argv, (int32_t)(sizeof(options)/sizeof(options[0])), options); 1.132 + 1.133 + /* error handling, printing usage message */ 1.134 + if(argc<0) { 1.135 + fprintf(stderr, "%s: error in command line argument \"%s\"\n", argv[0], argv[-argc]); 1.136 + } else if(argc<2) { 1.137 + argc = -1; 1.138 + } 1.139 + if(options[WRITE_POOL_BUNDLE].doesOccur && options[USE_POOL_BUNDLE].doesOccur) { 1.140 + fprintf(stderr, "%s: cannot combine --writePoolBundle and --usePoolBundle\n", argv[0]); 1.141 + argc = -1; 1.142 + } 1.143 + if(options[FORMAT_VERSION].doesOccur) { 1.144 + const char *s = options[FORMAT_VERSION].value; 1.145 + if(uprv_strlen(s) != 1 || (s[0] != '1' && s[0] != '2')) { 1.146 + fprintf(stderr, "%s: unsupported --formatVersion %s\n", argv[0], s); 1.147 + argc = -1; 1.148 + } else if(s[0] == '1' && 1.149 + (options[WRITE_POOL_BUNDLE].doesOccur || options[USE_POOL_BUNDLE].doesOccur) 1.150 + ) { 1.151 + fprintf(stderr, "%s: cannot combine --formatVersion 1 with --writePoolBundle or --usePoolBundle\n", argv[0]); 1.152 + argc = -1; 1.153 + } else { 1.154 + setFormatVersion(s[0] - '0'); 1.155 + } 1.156 + } 1.157 + 1.158 + if(options[VERSION].doesOccur) { 1.159 + fprintf(stderr, 1.160 + "%s version %s (ICU version %s).\n" 1.161 + "%s\n", 1.162 + argv[0], GENRB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING); 1.163 + return U_ZERO_ERROR; 1.164 + } 1.165 + 1.166 + if(argc<0) { 1.167 + illegalArg = TRUE; 1.168 + } else if((options[JAVA_PACKAGE].doesOccur || options[BUNDLE_NAME].doesOccur) && 1.169 + !options[WRITE_JAVA].doesOccur) { 1.170 + fprintf(stderr, 1.171 + "%s error: command line argument --java-package or --bundle-name " 1.172 + "without --write-java\n", 1.173 + argv[0]); 1.174 + illegalArg = TRUE; 1.175 + } 1.176 + 1.177 + if(illegalArg || options[HELP1].doesOccur || options[HELP2].doesOccur) { 1.178 + /* 1.179 + * Broken into chunks because the C89 standard says the minimum 1.180 + * required supported string length is 509 bytes. 1.181 + */ 1.182 + fprintf(stderr, 1.183 + "Usage: %s [OPTIONS] [FILES]\n" 1.184 + "\tReads the list of resource bundle source files and creates\n" 1.185 + "\tbinary version of resource bundles (.res files)\n", 1.186 + argv[0]); 1.187 + fprintf(stderr, 1.188 + "Options:\n" 1.189 + "\t-h or -? or --help this usage text\n" 1.190 + "\t-q or --quiet do not display warnings\n" 1.191 + "\t-v or --verbose print extra information when processing files\n" 1.192 + "\t-V or --version prints out version number and exits\n" 1.193 + "\t-c or --copyright include copyright notice\n"); 1.194 + fprintf(stderr, 1.195 + "\t-e or --encoding encoding of source files\n" 1.196 + "\t-d of --destdir destination directory, followed by the path, defaults to %s\n" 1.197 + "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n" 1.198 + "\t-i or --icudatadir directory for locating any needed intermediate data files,\n" 1.199 + "\t followed by path, defaults to %s\n", 1.200 + u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory()); 1.201 + fprintf(stderr, 1.202 + "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n" 1.203 + "\t defaults to ASCII and \\uXXXX format.\n" 1.204 + "\t --java-package For --write-java: package name for writing the ListResourceBundle,\n" 1.205 + "\t defaults to com.ibm.icu.impl.data\n"); 1.206 + fprintf(stderr, 1.207 + "\t-b or --bundle-name For --write-java: root resource bundle name for writing the ListResourceBundle,\n" 1.208 + "\t defaults to LocaleElements\n" 1.209 + "\t-x or --write-xliff write an XLIFF file for the resource bundle. Followed by\n" 1.210 + "\t an optional output file name.\n" 1.211 + "\t-k or --strict use pedantic parsing of syntax\n" 1.212 + /*added by Jing*/ 1.213 + "\t-l or --language for XLIFF: language code compliant with BCP 47.\n"); 1.214 + fprintf(stderr, 1.215 + "\t-C or --noBinaryCollation do not generate binary collation image;\n" 1.216 + "\t makes .res file smaller but collator instantiation much slower;\n" 1.217 + "\t maintains ability to get tailoring rules\n" 1.218 + "\t-R or --omitCollationRules do not include collation (tailoring) rules;\n" 1.219 + "\t makes .res file smaller and maintains collator instantiation speed\n" 1.220 + "\t but tailoring rules will not be available (they are rarely used)\n"); 1.221 + fprintf(stderr, 1.222 + "\t --formatVersion write a .res file compatible with the requested formatVersion (single digit);\n" 1.223 + "\t for example, --formatVersion 1\n"); 1.224 + fprintf(stderr, 1.225 + "\t --writePoolBundle write a pool.res file with all of the keys of all input bundles\n" 1.226 + "\t --usePoolBundle [path-to-pool.res] point to keys from the pool.res keys pool bundle if they are available there;\n" 1.227 + "\t makes .res files smaller but dependent on the pool bundle\n" 1.228 + "\t (--writePoolBundle and --usePoolBundle cannot be combined)\n"); 1.229 + 1.230 + return illegalArg ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; 1.231 + } 1.232 + 1.233 + if(options[VERBOSE].doesOccur) { 1.234 + setVerbose(TRUE); 1.235 + } 1.236 + 1.237 + if(options[QUIET].doesOccur) { 1.238 + setShowWarning(FALSE); 1.239 + } 1.240 + if(options[STRICT].doesOccur) { 1.241 + setStrict(TRUE); 1.242 + } 1.243 + if(options[COPYRIGHT].doesOccur){ 1.244 + setIncludeCopyright(TRUE); 1.245 + } 1.246 + 1.247 + if(options[SOURCEDIR].doesOccur) { 1.248 + inputDir = options[SOURCEDIR].value; 1.249 + } 1.250 + 1.251 + if(options[DESTDIR].doesOccur) { 1.252 + outputDir = options[DESTDIR].value; 1.253 + } 1.254 + 1.255 + if(options[ENCODING].doesOccur) { 1.256 + encoding = options[ENCODING].value; 1.257 + } 1.258 + 1.259 + if(options[ICUDATADIR].doesOccur) { 1.260 + u_setDataDirectory(options[ICUDATADIR].value); 1.261 + } 1.262 + /* Initialize ICU */ 1.263 + u_init(&status); 1.264 + if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) { 1.265 + /* Note: u_init() will try to open ICU property data. 1.266 + * failures here are expected when building ICU from scratch. 1.267 + * ignore them. 1.268 + */ 1.269 + fprintf(stderr, "%s: can not initialize ICU. status = %s\n", 1.270 + argv[0], u_errorName(status)); 1.271 + exit(1); 1.272 + } 1.273 + status = U_ZERO_ERROR; 1.274 + if(options[WRITE_JAVA].doesOccur) { 1.275 + write_java = TRUE; 1.276 + outputEnc = options[WRITE_JAVA].value; 1.277 + } 1.278 + 1.279 + if(options[WRITE_XLIFF].doesOccur) { 1.280 + write_xliff = TRUE; 1.281 + if(options[WRITE_XLIFF].value != NULL){ 1.282 + xliffOutputFileName = options[WRITE_XLIFF].value; 1.283 + } 1.284 + } 1.285 + 1.286 + initParser(); 1.287 + 1.288 + /*added by Jing*/ 1.289 + if(options[LANGUAGE].doesOccur) { 1.290 + language = options[LANGUAGE].value; 1.291 + } 1.292 + 1.293 + if(options[WRITE_POOL_BUNDLE].doesOccur) { 1.294 + newPoolBundle = bundle_open(NULL, TRUE, &status); 1.295 + if(U_FAILURE(status)) { 1.296 + fprintf(stderr, "unable to create an empty bundle for the pool keys: %s\n", u_errorName(status)); 1.297 + return status; 1.298 + } else { 1.299 + const char *poolResName = "pool.res"; 1.300 + char *nameWithoutSuffix = uprv_malloc(uprv_strlen(poolResName) + 1); 1.301 + if (nameWithoutSuffix == NULL) { 1.302 + fprintf(stderr, "out of memory error\n"); 1.303 + return U_MEMORY_ALLOCATION_ERROR; 1.304 + } 1.305 + uprv_strcpy(nameWithoutSuffix, poolResName); 1.306 + *uprv_strrchr(nameWithoutSuffix, '.') = 0; 1.307 + newPoolBundle->fLocale = nameWithoutSuffix; 1.308 + } 1.309 + } 1.310 + 1.311 + if(options[USE_POOL_BUNDLE].doesOccur) { 1.312 + const char *poolResName = "pool.res"; 1.313 + FileStream *poolFile; 1.314 + int32_t poolFileSize; 1.315 + int32_t indexLength; 1.316 + /* 1.317 + * TODO: Consolidate inputDir/filename handling from main() and processFile() 1.318 + * into a common function, and use it here as well. 1.319 + * Try to create toolutil functions for dealing with dir/filenames and 1.320 + * loading ICU data files without udata_open(). 1.321 + * Share code with icupkg? 1.322 + * Also, make_res_filename() seems to be unused. Review and remove. 1.323 + */ 1.324 + if (options[USE_POOL_BUNDLE].value!=NULL) { 1.325 + uprv_strcpy(theCurrentFileName, options[USE_POOL_BUNDLE].value); 1.326 + uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING); 1.327 + } else if (inputDir) { 1.328 + uprv_strcpy(theCurrentFileName, inputDir); 1.329 + uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING); 1.330 + } else { 1.331 + *theCurrentFileName = 0; 1.332 + } 1.333 + uprv_strcat(theCurrentFileName, poolResName); 1.334 + poolFile = T_FileStream_open(theCurrentFileName, "rb"); 1.335 + if (poolFile == NULL) { 1.336 + fprintf(stderr, "unable to open pool bundle file %s\n", theCurrentFileName); 1.337 + return 1; 1.338 + } 1.339 + poolFileSize = T_FileStream_size(poolFile); 1.340 + if (poolFileSize < 32) { 1.341 + fprintf(stderr, "the pool bundle file %s is too small\n", theCurrentFileName); 1.342 + return 1; 1.343 + } 1.344 + poolBundle.fBytes = (uint8_t *)uprv_malloc((poolFileSize + 15) & ~15); 1.345 + if (poolFileSize > 0 && poolBundle.fBytes == NULL) { 1.346 + fprintf(stderr, "unable to allocate memory for the pool bundle file %s\n", theCurrentFileName); 1.347 + return U_MEMORY_ALLOCATION_ERROR; 1.348 + } else { 1.349 + UDataSwapper *ds; 1.350 + const DataHeader *header; 1.351 + int32_t bytesRead = T_FileStream_read(poolFile, poolBundle.fBytes, poolFileSize); 1.352 + int32_t keysBottom; 1.353 + if (bytesRead != poolFileSize) { 1.354 + fprintf(stderr, "unable to read the pool bundle file %s\n", theCurrentFileName); 1.355 + return 1; 1.356 + } 1.357 + /* 1.358 + * Swap the pool bundle so that a single checked-in file can be used. 1.359 + * The swapper functions also test that the data looks like 1.360 + * a well-formed .res file. 1.361 + */ 1.362 + ds = udata_openSwapperForInputData(poolBundle.fBytes, bytesRead, 1.363 + U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &status); 1.364 + if (U_FAILURE(status)) { 1.365 + fprintf(stderr, "udata_openSwapperForInputData(pool bundle %s) failed: %s\n", 1.366 + theCurrentFileName, u_errorName(status)); 1.367 + return status; 1.368 + } 1.369 + ures_swap(ds, poolBundle.fBytes, bytesRead, poolBundle.fBytes, &status); 1.370 + udata_closeSwapper(ds); 1.371 + if (U_FAILURE(status)) { 1.372 + fprintf(stderr, "ures_swap(pool bundle %s) failed: %s\n", 1.373 + theCurrentFileName, u_errorName(status)); 1.374 + return status; 1.375 + } 1.376 + header = (const DataHeader *)poolBundle.fBytes; 1.377 + if (header->info.formatVersion[0]!=2) { 1.378 + fprintf(stderr, "invalid format of pool bundle file %s\n", theCurrentFileName); 1.379 + return U_INVALID_FORMAT_ERROR; 1.380 + } 1.381 + poolBundle.fKeys = (const char *)header + header->dataHeader.headerSize; 1.382 + poolBundle.fIndexes = (const int32_t *)poolBundle.fKeys + 1; 1.383 + indexLength = poolBundle.fIndexes[URES_INDEX_LENGTH] & 0xff; 1.384 + if (indexLength <= URES_INDEX_POOL_CHECKSUM) { 1.385 + fprintf(stderr, "insufficient indexes[] in pool bundle file %s\n", theCurrentFileName); 1.386 + return U_INVALID_FORMAT_ERROR; 1.387 + } 1.388 + keysBottom = (1 + indexLength) * 4; 1.389 + poolBundle.fKeys += keysBottom; 1.390 + poolBundle.fKeysLength = (poolBundle.fIndexes[URES_INDEX_KEYS_TOP] * 4) - keysBottom; 1.391 + poolBundle.fChecksum = poolBundle.fIndexes[URES_INDEX_POOL_CHECKSUM]; 1.392 + } 1.393 + for (i = 0; i < poolBundle.fKeysLength; ++i) { 1.394 + if (poolBundle.fKeys[i] == 0) { 1.395 + ++poolBundle.fKeysCount; 1.396 + } 1.397 + } 1.398 + T_FileStream_close(poolFile); 1.399 + setUsePoolBundle(TRUE); 1.400 + } 1.401 + 1.402 + if(options[INCLUDE_UNIHAN_COLL].doesOccur) { 1.403 + gIncludeUnihanColl = TRUE; 1.404 + } 1.405 + 1.406 + if((argc-1)!=1) { 1.407 + printf("genrb number of files: %d\n", argc - 1); 1.408 + } 1.409 + /* generate the binary files */ 1.410 + for(i = 1; i < argc; ++i) { 1.411 + status = U_ZERO_ERROR; 1.412 + arg = getLongPathname(argv[i]); 1.413 + 1.414 + if (inputDir) { 1.415 + uprv_strcpy(theCurrentFileName, inputDir); 1.416 + uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING); 1.417 + } else { 1.418 + *theCurrentFileName = 0; 1.419 + } 1.420 + uprv_strcat(theCurrentFileName, arg); 1.421 + 1.422 + if (isVerbose()) { 1.423 + printf("Processing file \"%s\"\n", theCurrentFileName); 1.424 + } 1.425 + processFile(arg, encoding, inputDir, outputDir, NULL, 1.426 + options[NO_BINARY_COLLATION].doesOccur, 1.427 + &status); 1.428 + } 1.429 + 1.430 + uprv_free(poolBundle.fBytes); 1.431 + 1.432 + if(options[WRITE_POOL_BUNDLE].doesOccur) { 1.433 + char outputFileName[256]; 1.434 + bundle_write(newPoolBundle, outputDir, NULL, outputFileName, sizeof(outputFileName), &status); 1.435 + bundle_close(newPoolBundle, &status); 1.436 + if(U_FAILURE(status)) { 1.437 + fprintf(stderr, "unable to write the pool bundle: %s\n", u_errorName(status)); 1.438 + } 1.439 + } 1.440 + 1.441 + u_cleanup(); 1.442 + 1.443 + /* Dont return warnings as a failure */ 1.444 + if (U_SUCCESS(status)) { 1.445 + return 0; 1.446 + } 1.447 + 1.448 + return status; 1.449 +} 1.450 + 1.451 +/* Process a file */ 1.452 +void 1.453 +processFile( 1.454 + const char *filename, const char *cp, const char *inputDir, const char *outputDir, const char *packageName, 1.455 + UBool omitBinaryCollation, UErrorCode *status) { 1.456 + /*FileStream *in = NULL;*/ 1.457 + struct SRBRoot *data = NULL; 1.458 + UCHARBUF *ucbuf = NULL; 1.459 + char *rbname = NULL; 1.460 + char *openFileName = NULL; 1.461 + char *inputDirBuf = NULL; 1.462 + 1.463 + char outputFileName[256]; 1.464 + 1.465 + int32_t dirlen = 0; 1.466 + int32_t filelen = 0; 1.467 + 1.468 + 1.469 + if (status==NULL || U_FAILURE(*status)) { 1.470 + return; 1.471 + } 1.472 + if(filename==NULL){ 1.473 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.474 + return; 1.475 + }else{ 1.476 + filelen = (int32_t)uprv_strlen(filename); 1.477 + } 1.478 + 1.479 + if(inputDir == NULL) { 1.480 + const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR); 1.481 + openFileName = (char *) uprv_malloc(dirlen + filelen + 2); 1.482 + openFileName[0] = '\0'; 1.483 + if (filenameBegin != NULL) { 1.484 + /* 1.485 + * When a filename ../../../data/root.txt is specified, 1.486 + * we presume that the input directory is ../../../data 1.487 + * This is very important when the resource file includes 1.488 + * another file, like UCARules.txt or thaidict.brk. 1.489 + */ 1.490 + int32_t filenameSize = (int32_t)(filenameBegin - filename + 1); 1.491 + inputDirBuf = uprv_strncpy((char *)uprv_malloc(filenameSize), filename, filenameSize); 1.492 + 1.493 + /* test for NULL */ 1.494 + if(inputDirBuf == NULL) { 1.495 + *status = U_MEMORY_ALLOCATION_ERROR; 1.496 + goto finish; 1.497 + } 1.498 + 1.499 + inputDirBuf[filenameSize - 1] = 0; 1.500 + inputDir = inputDirBuf; 1.501 + dirlen = (int32_t)uprv_strlen(inputDir); 1.502 + } 1.503 + }else{ 1.504 + dirlen = (int32_t)uprv_strlen(inputDir); 1.505 + 1.506 + if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) { 1.507 + openFileName = (char *) uprv_malloc(dirlen + filelen + 2); 1.508 + 1.509 + /* test for NULL */ 1.510 + if(openFileName == NULL) { 1.511 + *status = U_MEMORY_ALLOCATION_ERROR; 1.512 + goto finish; 1.513 + } 1.514 + 1.515 + openFileName[0] = '\0'; 1.516 + /* 1.517 + * append the input dir to openFileName if the first char in 1.518 + * filename is not file seperation char and the last char input directory is not '.'. 1.519 + * This is to support : 1.520 + * genrb -s. /home/icu/data 1.521 + * genrb -s. icu/data 1.522 + * The user cannot mix notations like 1.523 + * genrb -s. /icu/data --- the absolute path specified. -s redundant 1.524 + * user should use 1.525 + * genrb -s. icu/data --- start from CWD and look in icu/data dir 1.526 + */ 1.527 + if( (filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')){ 1.528 + uprv_strcpy(openFileName, inputDir); 1.529 + openFileName[dirlen] = U_FILE_SEP_CHAR; 1.530 + } 1.531 + openFileName[dirlen + 1] = '\0'; 1.532 + } else { 1.533 + openFileName = (char *) uprv_malloc(dirlen + filelen + 1); 1.534 + 1.535 + /* test for NULL */ 1.536 + if(openFileName == NULL) { 1.537 + *status = U_MEMORY_ALLOCATION_ERROR; 1.538 + goto finish; 1.539 + } 1.540 + 1.541 + uprv_strcpy(openFileName, inputDir); 1.542 + 1.543 + } 1.544 + } 1.545 + 1.546 + uprv_strcat(openFileName, filename); 1.547 + 1.548 + ucbuf = ucbuf_open(openFileName, &cp,getShowWarning(),TRUE, status); 1.549 + if(*status == U_FILE_ACCESS_ERROR) { 1.550 + 1.551 + fprintf(stderr, "couldn't open file %s\n", openFileName == NULL ? filename : openFileName); 1.552 + goto finish; 1.553 + } 1.554 + if (ucbuf == NULL || U_FAILURE(*status)) { 1.555 + fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName == NULL ? filename : openFileName,u_errorName(*status)); 1.556 + goto finish; 1.557 + } 1.558 + /* auto detected popular encodings? */ 1.559 + if (cp!=NULL && isVerbose()) { 1.560 + printf("autodetected encoding %s\n", cp); 1.561 + } 1.562 + /* Parse the data into an SRBRoot */ 1.563 + data = parse(ucbuf, inputDir, outputDir, 1.564 + !omitBinaryCollation, options[NO_COLLATION_RULES].doesOccur, status); 1.565 + 1.566 + if (data == NULL || U_FAILURE(*status)) { 1.567 + fprintf(stderr, "couldn't parse the file %s. Error:%s\n", filename,u_errorName(*status)); 1.568 + goto finish; 1.569 + } 1.570 + if(options[WRITE_POOL_BUNDLE].doesOccur) { 1.571 + int32_t newKeysLength; 1.572 + const char *newKeys, *newKeysLimit; 1.573 + bundle_compactKeys(data, status); 1.574 + newKeys = bundle_getKeyBytes(data, &newKeysLength); 1.575 + bundle_addKeyBytes(newPoolBundle, newKeys, newKeysLength, status); 1.576 + if(U_FAILURE(*status)) { 1.577 + fprintf(stderr, "bundle_compactKeys(%s) or bundle_getKeyBytes() failed: %s\n", 1.578 + filename, u_errorName(*status)); 1.579 + goto finish; 1.580 + } 1.581 + /* count the number of just-added key strings */ 1.582 + for(newKeysLimit = newKeys + newKeysLength; newKeys < newKeysLimit; ++newKeys) { 1.583 + if(*newKeys == 0) { 1.584 + ++newPoolBundle->fKeysCount; 1.585 + } 1.586 + } 1.587 + } 1.588 + 1.589 + if(options[USE_POOL_BUNDLE].doesOccur) { 1.590 + data->fPoolBundleKeys = poolBundle.fKeys; 1.591 + data->fPoolBundleKeysLength = poolBundle.fKeysLength; 1.592 + data->fPoolBundleKeysCount = poolBundle.fKeysCount; 1.593 + data->fPoolChecksum = poolBundle.fChecksum; 1.594 + } 1.595 + 1.596 + /* Determine the target rb filename */ 1.597 + rbname = make_res_filename(filename, outputDir, packageName, status); 1.598 + if(U_FAILURE(*status)) { 1.599 + fprintf(stderr, "couldn't make the res fileName for bundle %s. Error:%s\n", filename,u_errorName(*status)); 1.600 + goto finish; 1.601 + } 1.602 + if(write_java== TRUE){ 1.603 + bundle_write_java(data,outputDir,outputEnc, outputFileName, sizeof(outputFileName), 1.604 + options[JAVA_PACKAGE].value, options[BUNDLE_NAME].value, status); 1.605 + }else if(write_xliff ==TRUE){ 1.606 + bundle_write_xml(data,outputDir,outputEnc, filename, outputFileName, sizeof(outputFileName),language, xliffOutputFileName,status); 1.607 + }else{ 1.608 + /* Write the data to the file */ 1.609 + bundle_write(data, outputDir, packageName, outputFileName, sizeof(outputFileName), status); 1.610 + } 1.611 + if (U_FAILURE(*status)) { 1.612 + fprintf(stderr, "couldn't write bundle %s. Error:%s\n", outputFileName,u_errorName(*status)); 1.613 + } 1.614 + bundle_close(data, status); 1.615 + 1.616 +finish: 1.617 + 1.618 + if (inputDirBuf != NULL) { 1.619 + uprv_free(inputDirBuf); 1.620 + } 1.621 + 1.622 + if (openFileName != NULL) { 1.623 + uprv_free(openFileName); 1.624 + } 1.625 + 1.626 + if(ucbuf) { 1.627 + ucbuf_close(ucbuf); 1.628 + } 1.629 + 1.630 + if (rbname) { 1.631 + uprv_free(rbname); 1.632 + } 1.633 +} 1.634 + 1.635 +/* Generate the target .res file name from the input file name */ 1.636 +static char* 1.637 +make_res_filename(const char *filename, 1.638 + const char *outputDir, 1.639 + const char *packageName, 1.640 + UErrorCode *status) { 1.641 + char *basename; 1.642 + char *dirname; 1.643 + char *resName; 1.644 + 1.645 + int32_t pkgLen = 0; /* length of package prefix */ 1.646 + 1.647 + 1.648 + if (U_FAILURE(*status)) { 1.649 + return 0; 1.650 + } 1.651 + 1.652 + if(packageName != NULL) 1.653 + { 1.654 + pkgLen = (int32_t)(1 + uprv_strlen(packageName)); 1.655 + } 1.656 + 1.657 + /* setup */ 1.658 + basename = dirname = resName = 0; 1.659 + 1.660 + /* determine basename, and compiled file names */ 1.661 + basename = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1)); 1.662 + if(basename == 0) { 1.663 + *status = U_MEMORY_ALLOCATION_ERROR; 1.664 + goto finish; 1.665 + } 1.666 + 1.667 + get_basename(basename, filename); 1.668 + 1.669 + dirname = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(filename) + 1)); 1.670 + if(dirname == 0) { 1.671 + *status = U_MEMORY_ALLOCATION_ERROR; 1.672 + goto finish; 1.673 + } 1.674 + 1.675 + get_dirname(dirname, filename); 1.676 + 1.677 + if (outputDir == NULL) { 1.678 + /* output in same dir as .txt */ 1.679 + resName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(dirname) 1.680 + + pkgLen 1.681 + + uprv_strlen(basename) 1.682 + + uprv_strlen(RES_SUFFIX) + 8)); 1.683 + if(resName == 0) { 1.684 + *status = U_MEMORY_ALLOCATION_ERROR; 1.685 + goto finish; 1.686 + } 1.687 + 1.688 + uprv_strcpy(resName, dirname); 1.689 + 1.690 + if(packageName != NULL) 1.691 + { 1.692 + uprv_strcat(resName, packageName); 1.693 + uprv_strcat(resName, "_"); 1.694 + } 1.695 + 1.696 + uprv_strcat(resName, basename); 1.697 + 1.698 + } else { 1.699 + int32_t dirlen = (int32_t)uprv_strlen(outputDir); 1.700 + int32_t basenamelen = (int32_t)uprv_strlen(basename); 1.701 + 1.702 + resName = (char*) uprv_malloc(sizeof(char) * (dirlen + pkgLen + basenamelen + 8)); 1.703 + 1.704 + if (resName == NULL) { 1.705 + *status = U_MEMORY_ALLOCATION_ERROR; 1.706 + goto finish; 1.707 + } 1.708 + 1.709 + uprv_strcpy(resName, outputDir); 1.710 + 1.711 + if(outputDir[dirlen] != U_FILE_SEP_CHAR) { 1.712 + resName[dirlen] = U_FILE_SEP_CHAR; 1.713 + resName[dirlen + 1] = '\0'; 1.714 + } 1.715 + 1.716 + if(packageName != NULL) 1.717 + { 1.718 + uprv_strcat(resName, packageName); 1.719 + uprv_strcat(resName, "_"); 1.720 + } 1.721 + 1.722 + uprv_strcat(resName, basename); 1.723 + } 1.724 + 1.725 +finish: 1.726 + uprv_free(basename); 1.727 + uprv_free(dirname); 1.728 + 1.729 + return resName; 1.730 +} 1.731 + 1.732 +/* 1.733 + * Local Variables: 1.734 + * indent-tabs-mode: nil 1.735 + * End: 1.736 + */