1 /****************************************************************************** 2 * Copyright (C) 2000-2009, International Business Machines 3 * Corporation and others. All Rights Reserved. 4 ******************************************************************************* 5 * file name: pkgdata.c 6 * encoding: ANSI X3.4 (1968) 7 * tab size: 8 (not used) 8 * indentation:4 9 * 10 * created on: 2000may15 11 * created by: Steven \u24C7 Loomis 12 * 13 * This program packages the ICU data into different forms 14 * (DLL, common data, etc.) 15 */ 16 17 /* 18 * We define _XOPEN_SOURCE so that we can get popen and pclose. 19 */ 20 #if !defined(_XOPEN_SOURCE) 21 #if __STDC_VERSION__ >= 199901L 22 /* It is invalid to compile an XPG3, XPG4, XPG4v2 or XPG5 application using c99 on Solaris */ 23 #define _XOPEN_SOURCE 600 24 #else 25 #define _XOPEN_SOURCE 4 26 #endif 27 #endif 28 29 30 #include "unicode/utypes.h" 31 32 #if U_HAVE_POPEN 33 #if defined(U_CYGWIN) && defined(__STRICT_ANSI__) 34 /* popen/pclose aren't defined in strict ANSI on Cygwin */ 35 #undef __STRICT_ANSI__ 36 #endif 37 #endif 38 39 #include "unicode/putil.h" 40 #include "cmemory.h" 41 #include "cstring.h" 42 #include "filestrm.h" 43 #include "toolutil.h" 44 #include "unicode/uclean.h" 45 #include "unewdata.h" 46 #include "uoptions.h" 47 #include "putilimp.h" 48 #include "package.h" 49 #include "pkg_icu.h" 50 #include "pkg_genc.h" 51 #include "pkg_gencmn.h" 52 #include "flagparser.h" 53 #include "filetools.h" 54 55 56 #if U_HAVE_POPEN 57 # include <unistd.h> 58 #endif 59 #include <stdio.h> 60 #include <stdlib.h> 61 62 U_CDECL_BEGIN 63 #include "pkgtypes.h" 64 U_CDECL_END 65 66 #ifdef U_WINDOWS 67 #ifdef __GNUC__ 68 #define WINDOWS_WITH_GNUC 69 #else 70 #define WINDOWS_WITH_MSVC 71 #endif 72 #endif 73 #if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX) 74 #define BUILD_DATA_WITHOUT_ASSEMBLY 75 #endif 76 #if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX) 77 #define CAN_WRITE_OBJ_CODE 78 #endif 79 80 /* 81 * When building the data library without assembly, 82 * some platforms use a single c code file for all of 83 * the data to generate the final data library. This can 84 * increase the performance of the pkdata tool. 85 */ 86 #if defined(OS400) 87 #define USE_SINGLE_CCODE_FILE 88 #endif 89 90 /* Need to fix the file seperator character when using MinGW. */ 91 #ifdef WINDOWS_WITH_GNUC 92 #define PKGDATA_FILE_SEP_STRING "/" 93 #else 94 #define PKGDATA_FILE_SEP_STRING U_FILE_SEP_STRING 95 #endif 96 97 #define LARGE_BUFFER_MAX_SIZE 2048 98 #define SMALL_BUFFER_MAX_SIZE 512 99 100 static void loadLists(UPKGOptions *o, UErrorCode *status); 101 102 static int32_t pkg_executeOptions(UPKGOptions *o); 103 104 #ifdef WINDOWS_WITH_MSVC 105 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o); 106 #endif 107 static int32_t pkg_createSymLinks(const char *targetDir); 108 static int32_t pkg_installLibrary(const char *installDir, const char *dir); 109 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName); 110 111 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY 112 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode); 113 #endif 114 115 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath); 116 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL); 117 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt); 118 static void createFileNames(const char *version_major, const char *version, const char *libName, const UBool reverseExt); 119 120 static int32_t pkg_getOptionsFromICUConfig(UOption *option); 121 122 enum { 123 NAME, 124 BLDOPT, 125 MODE, 126 HELP, 127 HELP_QUESTION_MARK, 128 VERBOSE, 129 COPYRIGHT, 130 COMMENT, 131 DESTDIR, 132 REBUILD, 133 TEMPDIR, 134 INSTALL, 135 SOURCEDIR, 136 ENTRYPOINT, 137 REVISION, 138 FORCE_PREFIX, 139 LIBNAME, 140 QUIET 141 }; 142 143 /* This sets the modes that are available */ 144 static struct { 145 const char *name, *alt_name; 146 const char *desc; 147 } modes[] = { 148 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." }, 149 #ifdef U_WINDOWS 150 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"}, 151 { "common", "archive", "Generates just the common file, <package>.dat"}, 152 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX } 153 #else 154 #ifdef UDATA_SO_SUFFIX 155 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX }, 156 #endif 157 { "common", "archive", "Generates one common data file, <package>.dat" }, 158 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX } 159 #endif 160 }; 161 162 static UOption options[]={ 163 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG), 164 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */ 165 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG), 166 /*03*/ UOPTION_HELP_H, /* -h */ 167 /*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */ 168 /*05*/ UOPTION_VERBOSE, /* -v */ 169 /*06*/ UOPTION_COPYRIGHT, /* -c */ 170 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG), 171 /*08*/ UOPTION_DESTDIR, /* -d */ 172 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG), 173 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG), 174 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG), 175 /*14*/ UOPTION_SOURCEDIR , 176 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG), 177 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG), 178 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG), 179 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG), 180 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG) 181 }; 182 183 enum { 184 GENCCODE_ASSEMBLY_TYPE, 185 SO_EXT, 186 SOBJ_EXT, 187 A_EXT, 188 LIBPREFIX, 189 LIB_EXT_ORDER, 190 COMPILER, 191 LIBFLAGS, 192 GENLIB, 193 LDICUDTFLAGS, 194 LD_SONAME, 195 RPATH_FLAGS, 196 BIR_FLAGS, 197 AR, 198 ARFLAGS, 199 RANLIB, 200 INSTALL_CMD, 201 PKGDATA_FLAGS_SIZE 202 }; 203 static char **pkgDataFlags = NULL; 204 205 enum { 206 LIB_FILE, 207 LIB_FILE_VERSION_MAJOR, 208 LIB_FILE_VERSION, 209 LIB_FILE_VERSION_TMP, 210 #ifdef U_CYGWIN 211 LIB_FILE_CYGWIN, 212 #endif 213 LIB_FILENAMES_SIZE 214 }; 215 static char libFileNames[LIB_FILENAMES_SIZE][256]; 216 217 static void pkg_checkFlag(UPKGOptions *o); 218 219 const char options_help[][320]={ 220 "Set the data name", 221 #ifdef U_MAKE_IS_NMAKE 222 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)", 223 #else 224 "Specify options for the builder.", 225 #endif 226 "Specify the mode of building (see below; default: common)", 227 "This usage text", 228 "This usage text", 229 "Make the output verbose", 230 "Use the standard ICU copyright", 231 "Use a custom comment (instead of the copyright)", 232 "Specify the destination directory for files", 233 "Force rebuilding of all data", 234 "Specify temporary dir (default: output dir)", 235 "Install the data (specify target)", 236 "Specify a custom source directory", 237 "Specify a custom entrypoint name (default: short name)", 238 "Specify a version when packaging in DLL or static mode", 239 "Add package to all file names if not present", 240 "Library name to build (if different than package name)", 241 "Quite mode. (e.g. Do not output a readme file for static libraries)" 242 }; 243 244 const char *progname = "PKGDATA"; 245 246 int 247 main(int argc, char* argv[]) { 248 int result = 0; 249 /* FileStream *out; */ 250 UPKGOptions o; 251 CharList *tail; 252 UBool needsHelp = FALSE; 253 UErrorCode status = U_ZERO_ERROR; 254 /* char tmp[1024]; */ 255 uint32_t i; 256 int32_t n; 257 258 U_MAIN_INIT_ARGS(argc, argv); 259 260 progname = argv[0]; 261 262 options[MODE].value = "common"; 263 264 /* read command line options */ 265 argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); 266 267 /* error handling, printing usage message */ 268 /* I've decided to simply print an error and quit. This tool has too 269 many options to just display them all of the time. */ 270 271 if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) { 272 needsHelp = TRUE; 273 } 274 else { 275 if(!needsHelp && argc<0) { 276 fprintf(stderr, 277 "%s: error in command line argument \"%s\"\n", 278 progname, 279 argv[-argc]); 280 fprintf(stderr, "Run '%s --help' for help.\n", progname); 281 return 1; 282 } 283 284 285 #ifndef WINDOWS_WITH_MSVC 286 if(!options[BLDOPT].doesOccur) { 287 if (pkg_getOptionsFromICUConfig(&options[BLDOPT]) != 0) { 288 fprintf(stderr, " required parameter is missing: -O is required \n"); 289 fprintf(stderr, "Run '%s --help' for help.\n", progname); 290 return 1; 291 } 292 } 293 #else 294 if(options[BLDOPT].doesOccur) { 295 fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n"); 296 } 297 #endif 298 299 if(!options[NAME].doesOccur) /* -O we already have - don't report it. */ 300 { 301 fprintf(stderr, " required parameter -p is missing \n"); 302 fprintf(stderr, "Run '%s --help' for help.\n", progname); 303 return 1; 304 } 305 306 if(argc == 1) { 307 fprintf(stderr, 308 "No input files specified.\n" 309 "Run '%s --help' for help.\n", progname); 310 return 1; 311 } 312 } /* end !needsHelp */ 313 314 if(argc<0 || needsHelp ) { 315 fprintf(stderr, 316 "usage: %s [-options] [-] [packageFile] \n" 317 "\tProduce packaged ICU data from the given list(s) of files.\n" 318 "\t'-' by itself means to read from stdin.\n" 319 "\tpackageFile is a text file containing the list of files to package.\n", 320 progname); 321 322 fprintf(stderr, "\n options:\n"); 323 for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) { 324 fprintf(stderr, "%-5s -%c %s%-10s %s\n", 325 (i<1?"[REQ]":""), 326 options[i].shortName, 327 options[i].longName ? "or --" : " ", 328 options[i].longName ? options[i].longName : "", 329 options_help[i]); 330 } 331 332 fprintf(stderr, "modes: (-m option)\n"); 333 for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) { 334 fprintf(stderr, " %-9s ", modes[i].name); 335 if (modes[i].alt_name) { 336 fprintf(stderr, "/ %-9s", modes[i].alt_name); 337 } else { 338 fprintf(stderr, " "); 339 } 340 fprintf(stderr, " %s\n", modes[i].desc); 341 } 342 return 1; 343 } 344 345 /* OK, fill in the options struct */ 346 uprv_memset(&o, 0, sizeof(o)); 347 348 o.mode = options[MODE].value; 349 o.version = options[REVISION].doesOccur ? options[REVISION].value : 0; 350 351 o.shortName = options[NAME].value; 352 { 353 int32_t len = (int32_t)uprv_strlen(o.shortName); 354 char *csname, *cp; 355 const char *sp; 356 357 cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName)); 358 if (*(sp = o.shortName)) { 359 *cp++ = isalpha(*sp) ? * sp : '_'; 360 for (++sp; *sp; ++sp) { 361 *cp++ = isalnum(*sp) ? *sp : '_'; 362 } 363 } 364 *cp = 0; 365 366 o.cShortName = csname; 367 } 368 369 if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */ 370 o.libName = options[LIBNAME].value; 371 } else { 372 o.libName = o.shortName; 373 } 374 375 if(options[QUIET].doesOccur) { 376 o.quiet = TRUE; 377 } else { 378 o.quiet = FALSE; 379 } 380 381 o.verbose = options[VERBOSE].doesOccur; 382 383 #ifndef WINDOWS_WITH_MSVC /* on UNIX, we'll just include the file... */ 384 o.options = options[BLDOPT].value; 385 #endif 386 if(options[COPYRIGHT].doesOccur) { 387 o.comment = U_COPYRIGHT_STRING; 388 } else if (options[COMMENT].doesOccur) { 389 o.comment = options[COMMENT].value; 390 } 391 392 if( options[DESTDIR].doesOccur ) { 393 o.targetDir = options[DESTDIR].value; 394 } else { 395 o.targetDir = "."; /* cwd */ 396 } 397 398 o.rebuild = options[REBUILD].doesOccur; 399 400 if( options[TEMPDIR].doesOccur ) { 401 o.tmpDir = options[TEMPDIR].value; 402 } else { 403 o.tmpDir = o.targetDir; 404 } 405 406 if( options[INSTALL].doesOccur ) { 407 o.install = options[INSTALL].value; 408 } else { 409 o.install = NULL; 410 } 411 412 if( options[SOURCEDIR].doesOccur ) { 413 o.srcDir = options[SOURCEDIR].value; 414 } else { 415 o.srcDir = "."; 416 } 417 418 if( options[ENTRYPOINT].doesOccur ) { 419 o.entryName = options[ENTRYPOINT].value; 420 } else { 421 o.entryName = o.cShortName; 422 } 423 424 /* OK options are set up. Now the file lists. */ 425 tail = NULL; 426 for( n=1; n<argc; n++) { 427 o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n])); 428 } 429 430 /* load the files */ 431 loadLists(&o, &status); 432 if( U_FAILURE(status) ) { 433 fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status)); 434 return 2; 435 } 436 437 result = pkg_executeOptions(&o); 438 439 if (pkgDataFlags != NULL) { 440 for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) { 441 if (pkgDataFlags[n] != NULL) { 442 uprv_free(pkgDataFlags[n]); 443 } 444 } 445 uprv_free(pkgDataFlags); 446 } 447 448 if (o.cShortName != NULL) { 449 uprv_free((char *)o.cShortName); 450 } 451 if (o.fileListFiles != NULL) { 452 pkg_deleteList(o.fileListFiles); 453 } 454 if (o.filePaths != NULL) { 455 pkg_deleteList(o.filePaths); 456 } 457 if (o.files != NULL) { 458 pkg_deleteList(o.files); 459 } 460 461 return result; 462 } 463 464 #define LN_CMD "ln -s" 465 #define RM_CMD "rm -f" 466 467 #define MODE_COMMON 'c' 468 #define MODE_STATIC 's' 469 #define MODE_DLL 'd' 470 #define MODE_FILES 'f' 471 472 static int32_t pkg_executeOptions(UPKGOptions *o) { 473 UErrorCode status = U_ZERO_ERROR; 474 int32_t result = 0; 475 // char cmd[SMALL_BUFFER_MAX_SIZE] = ""; 476 const char mode = o->mode[0]; 477 char targetDir[SMALL_BUFFER_MAX_SIZE] = ""; 478 char tmpDir[SMALL_BUFFER_MAX_SIZE] = ""; 479 char datFileName[SMALL_BUFFER_MAX_SIZE] = ""; 480 char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = ""; 481 char checkLibFile[LARGE_BUFFER_MAX_SIZE] = ""; 482 483 /* Initialize pkgdataFlags */ 484 pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE); 485 if (pkgDataFlags != NULL) { 486 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { 487 pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * SMALL_BUFFER_MAX_SIZE); 488 if (pkgDataFlags[i] != NULL) { 489 pkgDataFlags[i][0] = 0; 490 } else { 491 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); 492 return -1; 493 } 494 } 495 } else { 496 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); 497 return -1; 498 } 499 #ifndef WINDOWS_WITH_MSVC 500 /* Read in options file. */ 501 parseFlagsFile(o->options, pkgDataFlags, SMALL_BUFFER_MAX_SIZE, (int32_t)PKGDATA_FLAGS_SIZE, &status); 502 if (U_FAILURE(status)) { 503 fprintf(stderr,"Unable to open or read \"%s\" option file.\n", o->options); 504 return -1; 505 } 506 #endif 507 if (mode == MODE_FILES) { 508 /* Copy the raw data to the installation directory. */ 509 if (o->install != NULL) { 510 uprv_strcpy(targetDir, o->install); 511 if (o->shortName != NULL) { 512 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING); 513 uprv_strcat(targetDir, o->shortName); 514 } 515 result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str); 516 } 517 return result; 518 } else /* if (mode == MODE_COMMON || mode == MODE_STATIC || mode == MODE_DLL) */ { 519 uprv_strcpy(targetDir, o->targetDir); 520 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING); 521 522 uprv_strcpy(tmpDir, o->tmpDir); 523 uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING); 524 525 uprv_strcpy(datFileNamePath, tmpDir); 526 527 uprv_strcpy(datFileName, o->shortName); 528 uprv_strcat(datFileName, UDATA_CMN_SUFFIX); 529 530 uprv_strcat(datFileNamePath, datFileName); 531 532 result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_IS_BIG_ENDIAN ? 'b' : 'l'); 533 if (result != 0) { 534 fprintf(stderr,"Error writing package dat file.\n"); 535 return result; 536 } 537 538 if (mode == MODE_COMMON) { 539 char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = ""; 540 541 uprv_strcpy(targetFileNamePath, targetDir); 542 uprv_strcat(targetFileNamePath, datFileName); 543 544 if (T_FileStream_file_exists(targetFileNamePath)) { 545 if ((result = remove(targetFileNamePath)) != 0) { 546 fprintf(stderr, "Unable to remove old dat file: %s\n", targetFileNamePath); 547 return result; 548 } 549 } 550 551 /* Move the dat file created to the target directory. */ 552 result = rename(datFileNamePath, targetFileNamePath); 553 if (result != 0) { 554 fprintf(stderr, "Unable to move dat file (%s) to target location (%s).\n", datFileNamePath, targetFileNamePath); 555 } 556 557 return result; 558 } else /* if (mode[0] == MODE_STATIC || mode[0] == MODE_DLL) */ { 559 char gencFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 560 char version_major[10] = ""; 561 UBool reverseExt = FALSE; 562 563 #ifndef WINDOWS_WITH_MSVC 564 /* Get the version major number. */ 565 if (o->version != NULL) { 566 for (uint32_t i = 0;i < sizeof(version_major);i++) { 567 if (o->version[i] == '.') { 568 version_major[i] = 0; 569 break; 570 } 571 version_major[i] = o->version[i]; 572 } 573 } 574 575 #ifndef OS400 576 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##) 577 * reverseExt is FALSE if the suffix should be the version number. 578 */ 579 if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) { 580 reverseExt = TRUE; 581 } 582 #endif 583 /* Using the base libName and version number, generate the library file names. */ 584 createFileNames(version_major, o->version, o->libName, reverseExt); 585 586 if (o->version != 0 && o->rebuild == FALSE) { 587 /* Check to see if a previous built data library file exists and check if it is the latest. */ 588 sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION_TMP]); 589 if (T_FileStream_file_exists(checkLibFile)) { 590 if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) { 591 if (o->install != NULL) { 592 uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]); 593 result = pkg_installLibrary(o->install, targetDir); 594 } 595 return result; 596 } 597 } 598 } 599 600 pkg_checkFlag(o); 601 #endif 602 603 if (pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) { 604 const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE]; 605 606 /* Offset genccodeAssembly by 3 because "-a " */ 607 if (checkAssemblyHeaderName(genccodeAssembly+3)) { 608 writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath); 609 610 result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath); 611 if (result != 0) { 612 fprintf(stderr, "Error generating assembly code for data.\n"); 613 return result; 614 } else if (mode == MODE_STATIC) { 615 return result; 616 } 617 } else { 618 fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly); 619 return -1; 620 } 621 } else { 622 #ifdef CAN_WRITE_OBJ_CODE 623 writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath); 624 #ifdef U_LINUX 625 result = pkg_generateLibraryFile(targetDir, mode, gencFilePath); 626 #elif defined(WINDOWS_WITH_MSVC) 627 return pkg_createWindowsDLL(mode, gencFilePath, o); 628 #endif 629 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY) 630 result = pkg_createWithoutAssemblyCode(o, targetDir, mode); 631 #endif 632 if (result != 0) { 633 fprintf(stderr, "Error generating package data.\n"); 634 return result; 635 } 636 } 637 #ifndef U_WINDOWS 638 /* Certain platforms uses archive library. (e.g. AIX) */ 639 result = pkg_archiveLibrary(targetDir, o->version, reverseExt); 640 if (result != 0) { 641 fprintf(stderr, "Error creating data archive library file.\n"); 642 return result; 643 } 644 #ifndef OS400 645 /* Create symbolic links for the final library file. */ 646 result = pkg_createSymLinks(targetDir); 647 if (result != 0) { 648 fprintf(stderr, "Error creating symbolic links of the data library file.\n"); 649 return result; 650 } 651 #endif 652 /* Install the libraries if option was set. */ 653 if (o->install != NULL) { 654 result = pkg_installLibrary(o->install, targetDir); 655 if (result != 0) { 656 fprintf(stderr, "Error installing the data library.\n"); 657 return result; 658 } 659 } 660 #endif 661 } 662 } 663 return result; 664 } 665 /* 666 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames. 667 * Depending on the configuration, the library name may either end with version number or shared object suffix. 668 */ 669 static void createFileNames(const char *version_major, const char *version, const char *libName, UBool reverseExt) { 670 sprintf(libFileNames[LIB_FILE], "%s%s", 671 pkgDataFlags[LIBPREFIX], 672 libName); 673 if (version != NULL) { 674 #ifdef U_CYGWIN 675 sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s%s.%s", 676 libName, 677 version_major, 678 pkgDataFlags[SO_EXT]); 679 680 sprintf(pkgDataFlags[SO_EXT], "%s.%s", 681 pkgDataFlags[SO_EXT], 682 pkgDataFlags[A_EXT]); 683 #elif defined(OS400) 684 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s", 685 libFileNames[LIB_FILE], 686 pkgDataFlags[SOBJ_EXT]); 687 #else 688 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s", 689 libFileNames[LIB_FILE], 690 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 691 reverseExt ? version : pkgDataFlags[SOBJ_EXT], 692 reverseExt ? pkgDataFlags[SOBJ_EXT] : version); 693 #endif 694 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s", 695 libFileNames[LIB_FILE], 696 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 697 reverseExt ? version_major : pkgDataFlags[SO_EXT], 698 reverseExt ? pkgDataFlags[SO_EXT] : version_major); 699 700 libFileNames[LIB_FILE_VERSION][0] = 0; 701 702 #ifdef U_CYGWIN 703 /* Cygwin only deals with the version major number. */ 704 uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]); 705 #endif 706 } 707 } 708 709 /* Create the symbolic links for the final library file. */ 710 static int32_t pkg_createSymLinks(const char *targetDir) { 711 int32_t result = 0; 712 char cmd[LARGE_BUFFER_MAX_SIZE]; 713 714 #ifndef U_CYGWIN 715 /* No symbolic link to make. */ 716 if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) { 717 return result; 718 } 719 720 sprintf(cmd, "cd %s && %s %s && %s %s %s", 721 targetDir, 722 RM_CMD, 723 libFileNames[LIB_FILE_VERSION_MAJOR], 724 LN_CMD, 725 libFileNames[LIB_FILE_VERSION], 726 libFileNames[LIB_FILE_VERSION_MAJOR]); 727 result = system(cmd); 728 if (result != 0) { 729 return result; 730 } 731 #endif 732 sprintf(cmd, "cd %s && %s %s.%s && %s %s %s.%s", 733 targetDir, 734 RM_CMD, 735 libFileNames[LIB_FILE], pkgDataFlags[SO_EXT], 736 LN_CMD, 737 libFileNames[LIB_FILE_VERSION], 738 libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]); 739 740 result = system(cmd); 741 742 return result; 743 } 744 745 static int32_t pkg_installLibrary(const char *installDir, const char *targetDir) { 746 int32_t result = 0; 747 char cmd[SMALL_BUFFER_MAX_SIZE]; 748 749 sprintf(cmd, "cd %s && %s %s %s%s%s", 750 targetDir, 751 pkgDataFlags[INSTALL_CMD], 752 libFileNames[LIB_FILE_VERSION], 753 installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION] 754 ); 755 756 result = system(cmd); 757 758 if (result != 0) { 759 return result; 760 } 761 762 return pkg_createSymLinks(installDir); 763 } 764 765 #ifdef U_WINDOWS_MSVC 766 /* Copy commands for installing the raw data files on Windows. */ 767 #define WIN_INSTALL_CMD "xcopy" 768 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K" 769 #endif 770 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) { 771 int32_t result = 0; 772 char cmd[SMALL_BUFFER_MAX_SIZE] = ""; 773 774 if (!T_FileStream_file_exists(installDir)) { 775 UErrorCode status = U_ZERO_ERROR; 776 777 uprv_mkdir(installDir, &status); 778 if (U_FAILURE(status)) { 779 fprintf(stderr, "Error creating installation directory: %s\n", installDir); 780 return -1; 781 } 782 } 783 #ifndef U_WINDOWS_WITH_MSVC 784 char buffer[SMALL_BUFFER_MAX_SIZE] = ""; 785 786 FileStream *f = T_FileStream_open(fileListName, "r"); 787 if (f != NULL) { 788 for(;;) { 789 if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) { 790 /* Remove new line character. */ 791 buffer[uprv_strlen(buffer)-1] = 0; 792 793 sprintf(cmd, "%s %s%s%s %s%s%s", 794 pkgDataFlags[INSTALL_CMD], 795 srcDir, PKGDATA_FILE_SEP_STRING, buffer, 796 installDir, PKGDATA_FILE_SEP_STRING, buffer); 797 798 result = system(cmd); 799 if (result != 0) { 800 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 801 break; 802 } 803 } else { 804 if (!T_FileStream_eof(f)) { 805 fprintf(stderr, "Failed to read line from file: %s\n", fileListName); 806 result = -1; 807 } 808 break; 809 } 810 } 811 T_FileStream_close(f); 812 } else { 813 result = -1; 814 fprintf(stderr, "Unable to open list file: %s\n", fileListName); 815 } 816 #else 817 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS); 818 result = system(cmd); 819 if (result != 0) { 820 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 821 } 822 #endif 823 824 return result; 825 } 826 827 /* Archiving of the library file may be needed depending on the platform and options given. 828 * If archiving is not needed, copy over the library file name. 829 */ 830 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) { 831 int32_t result = 0; 832 char cmd[LARGE_BUFFER_MAX_SIZE]; 833 834 /* If the shard object suffix and the final object suffix is different and the final object suffix and the 835 * archive file suffix is the same, then the final library needs to be archived. 836 */ 837 if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) { 838 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s", 839 libFileNames[LIB_FILE], 840 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 841 reverseExt ? version : pkgDataFlags[SO_EXT], 842 reverseExt ? pkgDataFlags[SO_EXT] : version); 843 844 sprintf(cmd, "%s %s %s%s %s%s", 845 pkgDataFlags[AR], 846 pkgDataFlags[ARFLAGS], 847 targetDir, 848 libFileNames[LIB_FILE_VERSION], 849 targetDir, 850 libFileNames[LIB_FILE_VERSION_TMP]); 851 852 result = system(cmd); 853 if (result != 0) { 854 return result; 855 } 856 857 /* Remove unneeded library file. */ 858 sprintf(cmd, "%s %s%s", 859 RM_CMD, 860 targetDir, 861 libFileNames[LIB_FILE_VERSION_TMP]); 862 863 result = system(cmd); 864 if (result != 0) { 865 return result; 866 } 867 868 } else { 869 uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]); 870 } 871 872 return result; 873 } 874 875 /* 876 * Using the compiler information from the configuration file set by -O option, generate the library file. 877 * command may be given to allow for a larger buffer for cmd. 878 */ 879 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) { 880 int32_t result = 0; 881 char *cmd = NULL; 882 UBool freeCmd = FALSE; 883 884 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large 885 * containing many object files and so the calling function should supply a command buffer that is large 886 * enough to handle this. Otherwise, use the default size. 887 */ 888 if (command != NULL) { 889 cmd = command; 890 } else { 891 if ((cmd = (char *)uprv_malloc(sizeof(char) * LARGE_BUFFER_MAX_SIZE)) == NULL) { 892 fprintf(stderr, "Unable to allocate memory for command.\n"); 893 return -1; 894 } 895 freeCmd = TRUE; 896 } 897 898 if (mode == MODE_STATIC) { 899 #ifdef OS400 900 sprintf(cmd, "QSH CMD('%s %s %s%s.%s %s')", 901 #else 902 sprintf(cmd, "%s %s %s%s.%s %s", 903 #endif 904 pkgDataFlags[AR], 905 pkgDataFlags[ARFLAGS], 906 targetDir, 907 libFileNames[LIB_FILE], 908 pkgDataFlags[A_EXT], 909 objectFile); 910 911 result = system(cmd); 912 } else /* if (mode == MODE_DLL) */ { 913 #ifdef U_CYGWIN 914 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s", 915 pkgDataFlags[GENLIB], 916 targetDir, 917 libFileNames[LIB_FILE_VERSION_TMP], 918 pkgDataFlags[LDICUDTFLAGS], 919 targetDir, libFileNames[LIB_FILE_CYGWIN], 920 #else 921 #ifdef OS400 922 sprintf(cmd, "QSH CMD('%s %s -o %s%s %s %s%s %s %s')", 923 #else 924 sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s", 925 #endif 926 pkgDataFlags[GENLIB], 927 pkgDataFlags[LDICUDTFLAGS], 928 targetDir, 929 libFileNames[LIB_FILE_VERSION_TMP], 930 #endif 931 objectFile, 932 pkgDataFlags[LD_SONAME], 933 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR], 934 pkgDataFlags[RPATH_FLAGS], 935 pkgDataFlags[BIR_FLAGS]); 936 937 /* Generate the library file. */ 938 result = system(cmd); 939 } 940 941 if (freeCmd) { 942 uprv_free(cmd); 943 } 944 945 return result; 946 } 947 948 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) { 949 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; 950 char cmd[LARGE_BUFFER_MAX_SIZE] = ""; 951 int32_t result = 0; 952 953 /* Remove the ending .s and replace it with .o for the new object file. */ 954 uprv_strcpy(tempObjectFile, gencFilePath); 955 tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o'; 956 957 /* Generate the object file. */ 958 sprintf(cmd, "%s %s -o %s %s", 959 pkgDataFlags[COMPILER], 960 pkgDataFlags[LIBFLAGS], 961 tempObjectFile, 962 gencFilePath); 963 964 result = system(cmd); 965 if (result != 0) { 966 return result; 967 } 968 969 return pkg_generateLibraryFile(targetDir, mode, tempObjectFile); 970 } 971 972 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY 973 /* 974 * Generation of the data library without assembly code needs to compile each data file 975 * individually and then link it all together. 976 */ 977 enum { 978 DATA_PREFIX_BRKITR, 979 DATA_PREFIX_COLL, 980 DATA_PREFIX_RBNF, 981 DATA_PREFIX_TRANSLIT, 982 DATA_PREFIX_LENGTH 983 }; 984 const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = { 985 "brkitr", 986 "coll", 987 "rbnf", 988 "translit" 989 }; 990 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) { 991 int32_t result = 0; 992 CharList *list = o->filePaths; 993 CharList *listNames = o->files; 994 int32_t listSize = pkg_countCharList(list); 995 char *buffer; 996 char *cmd; 997 char gencmnFile[SMALL_BUFFER_MAX_SIZE] = ""; 998 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; 999 #ifdef USE_SINGLE_CCODE_FILE 1000 char icudtAll[SMALL_BUFFER_MAX_SIZE] = ""; 1001 1002 sprintf(icudtAll, "%s%s%sall.c", 1003 o->tmpDir, 1004 PKGDATA_FILE_SEP_STRING, 1005 libFileNames[LIB_FILE]); 1006 #endif 1007 1008 if (list == NULL || listNames == NULL) { 1009 /* list and listNames should never be NULL since we are looping through the CharList with 1010 * the given size. 1011 */ 1012 return -1; 1013 } 1014 1015 if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) { 1016 fprintf(stderr, "Unable to allocate memory for cmd.\n"); 1017 return -1; 1018 } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) { 1019 fprintf(stderr, "Unable to allocate memory for buffer.\n"); 1020 uprv_free(cmd); 1021 return -1; 1022 } 1023 1024 for (int32_t i = 0; i < (listSize + 1); i++) { 1025 const char *file ; 1026 const char *name; 1027 1028 if (i == 0) { 1029 /* The first iteration calls the gencmn function and initailizes the buffer. */ 1030 createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile); 1031 buffer[0] = 0; 1032 #ifdef USE_SINGLE_CCODE_FILE 1033 uprv_strcpy(tempObjectFile, gencmnFile); 1034 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1035 1036 #ifdef OS400 1037 sprintf(cmd, "QSH CMD('%s %s -o %s %s')", 1038 #else 1039 sprintf(cmd, "%s %s -o %s %s" 1040 #endif 1041 pkgDataFlags[COMPILER], 1042 pkgDataFlags[LIBFLAGS], 1043 tempObjectFile, 1044 gencmnFile); 1045 1046 result = system(cmd); 1047 if (result != 0) { 1048 break; 1049 } 1050 1051 sprintf(buffer, "%s",tempObjectFile); 1052 #endif 1053 } else { 1054 char newName[SMALL_BUFFER_MAX_SIZE]; 1055 char dataName[SMALL_BUFFER_MAX_SIZE]; 1056 const char *pSubstring; 1057 file = list->str; 1058 name = listNames->str; 1059 1060 newName[0] = dataName[0] = 0; 1061 for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) { 1062 /* If the name contains a prefix, alter the new name accordingly. */ 1063 pSubstring = uprv_strstr(name, DATA_PREFIX[n]); 1064 if (pSubstring != NULL) { 1065 char newNameTmp[SMALL_BUFFER_MAX_SIZE] = ""; 1066 const char *p = name + uprv_strlen(DATA_PREFIX[n]) + 1; 1067 for (int32_t i = 0;;i++) { 1068 if (p[i] == '.') { 1069 newNameTmp[i] = '_'; 1070 continue; 1071 } 1072 newNameTmp[i] = p[i]; 1073 if (p[i] == 0) { 1074 break; 1075 } 1076 } 1077 sprintf(newName, "%s_%s", 1078 DATA_PREFIX[n], 1079 newNameTmp); 1080 sprintf(dataName, "%s_%s", 1081 o->shortName, 1082 DATA_PREFIX[n]); 1083 } 1084 if (newName[0] != 0) { 1085 break; 1086 } 1087 } 1088 1089 writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile); 1090 #ifdef USE_SINGLE_CCODE_FILE 1091 #ifdef OS400 1092 sprintf(cmd, "QSH CMD('cat %s >> %s')", gencmnFile, icudtAll); 1093 #else 1094 sprintf(cmd, "cat %s >> %s", gencmnFile, icudtAll); 1095 #endif 1096 1097 result = system(cmd); 1098 if (result != 0) { 1099 break; 1100 } 1101 #endif 1102 } 1103 1104 #ifndef USE_SINGLE_CCODE_FILE 1105 uprv_strcpy(tempObjectFile, gencmnFile); 1106 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1107 1108 sprintf(cmd, "%s %s -o %s %s", 1109 pkgDataFlags[COMPILER], 1110 pkgDataFlags[LIBFLAGS], 1111 tempObjectFile, 1112 gencmnFile); 1113 result = system(cmd); 1114 if (result != 0) { 1115 break; 1116 } 1117 1118 sprintf(buffer, "%s %s", 1119 buffer, 1120 tempObjectFile); 1121 #endif 1122 1123 if (i > 0) { 1124 list = list->next; 1125 listNames = listNames->next; 1126 } 1127 } 1128 1129 #ifdef USE_SINGLE_CCODE_FILE 1130 uprv_strcpy(tempObjectFile, icudtAll); 1131 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1132 #ifdef OS400 1133 sprintf(cmd, "QSH CMD('%s %s -o %s %s')", 1134 #else 1135 sprintf(cmd, "%s %s -o %s %s", 1136 #endif 1137 pkgDataFlags[COMPILER], 1138 pkgDataFlags[LIBFLAGS], 1139 tempObjectFile, 1140 icudtAll); 1141 1142 result = system(cmd); 1143 if (result == 0) { 1144 sprintf(buffer, "%s %s", 1145 buffer, 1146 tempObjectFile); 1147 } 1148 #endif 1149 1150 if (result == 0) { 1151 /* Generate the library file. */ 1152 result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd); 1153 } 1154 uprv_free(buffer); 1155 uprv_free(cmd); 1156 1157 return result; 1158 } 1159 #endif 1160 1161 #ifdef WINDOWS_WITH_MSVC 1162 #define LINK_CMD "link.exe /nologo /release /out:" 1163 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:" 1164 #define LIB_CMD "LIB.exe /nologo /out:" 1165 #define LIB_FILE "icudt.lib" 1166 #define LIB_EXT UDATA_LIB_SUFFIX 1167 #define DLL_EXT UDATA_SO_SUFFIX 1168 1169 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) { 1170 char cmd[LARGE_BUFFER_MAX_SIZE]; 1171 if (mode == MODE_STATIC) { 1172 char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1173 1174 uprv_strcpy(staticLibFilePath, o->tmpDir); 1175 uprv_strcat(staticLibFilePath, PKGDATA_FILE_SEP_STRING); 1176 1177 uprv_strcat(staticLibFilePath, o->entryName); 1178 uprv_strcat(staticLibFilePath, LIB_EXT); 1179 1180 sprintf(cmd, "%s\"%s\" \"%s\"", 1181 LIB_CMD, 1182 staticLibFilePath, 1183 gencFilePath); 1184 } else if (mode == MODE_DLL) { 1185 char dllFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1186 char libFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1187 char resFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1188 1189 #ifdef CYGWINMSVC 1190 uprv_strcpy(dllFilePath, o->targetDir); 1191 #else 1192 uprv_strcpy(dllFilePath, o->srcDir); 1193 #endif 1194 uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING); 1195 uprv_strcpy(libFilePath, dllFilePath); 1196 1197 uprv_strcpy(resFilePath, o->tmpDir); 1198 uprv_strcat(resFilePath, PKGDATA_FILE_SEP_STRING); 1199 1200 uprv_strcat(dllFilePath, o->entryName); 1201 uprv_strcat(dllFilePath, DLL_EXT); 1202 uprv_strcat(libFilePath, LIB_FILE); 1203 uprv_strcat(resFilePath, ICUDATA_RES_FILE); 1204 1205 if (!T_FileStream_file_exists(resFilePath)) { 1206 uprv_memset(resFilePath, 0, sizeof(resFilePath)); 1207 } 1208 1209 /* Check if dll file and lib file exists and that it is not newer than genc file. */ 1210 if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) && 1211 (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) { 1212 return 0; 1213 } 1214 1215 sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" \"%s\"", 1216 LINK_CMD, 1217 dllFilePath, 1218 LINK_FLAGS, 1219 libFilePath, 1220 gencFilePath, 1221 resFilePath 1222 ); 1223 } 1224 1225 return system(cmd); 1226 } 1227 #endif 1228 1229 static void pkg_checkFlag(UPKGOptions *o) { 1230 #ifdef U_AIX 1231 /* AIX needs a map file. */ 1232 char *flag = NULL; 1233 int32_t length = 0; 1234 char tmpbuffer[SMALL_BUFFER_MAX_SIZE]; 1235 const char MAP_FILE_EXT[] = ".map"; 1236 FileStream *f = NULL; 1237 char mapFile[SMALL_BUFFER_MAX_SIZE] = ""; 1238 int32_t start = -1; 1239 int32_t count = 0; 1240 1241 flag = pkgDataFlags[BIR_FLAGS]; 1242 length = uprv_strlen(pkgDataFlags[BIR_FLAGS]); 1243 1244 for (int32_t i = 0; i < length; i++) { 1245 if (flag[i] == MAP_FILE_EXT[count]) { 1246 if (count == 0) { 1247 start = i; 1248 } 1249 count++; 1250 } else { 1251 count = 0; 1252 } 1253 1254 if (count == uprv_strlen(MAP_FILE_EXT)) { 1255 break; 1256 } 1257 } 1258 1259 if (start >= 0) { 1260 int32_t index = 0; 1261 for (int32_t i = 0;;i++) { 1262 if (i == start) { 1263 for (int32_t n = 0;;n++) { 1264 if (o->shortName[n] == 0) { 1265 break; 1266 } 1267 tmpbuffer[index++] = o->shortName[n]; 1268 } 1269 } 1270 1271 tmpbuffer[index++] = flag[i]; 1272 1273 if (flag[i] == 0) { 1274 break; 1275 } 1276 } 1277 1278 uprv_memset(flag, 0, length); 1279 uprv_strcpy(flag, tmpbuffer); 1280 1281 uprv_strcpy(mapFile, o->shortName); 1282 uprv_strcat(mapFile, MAP_FILE_EXT); 1283 1284 f = T_FileStream_open(mapFile, "w"); 1285 if (f == NULL) { 1286 fprintf(stderr,"Unable to create map file: %s.\n", mapFile); 1287 return; 1288 } 1289 1290 sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX); 1291 1292 T_FileStream_writeLine(f, tmpbuffer); 1293 1294 T_FileStream_close(f); 1295 } 1296 #elif defined(U_CYGWIN) 1297 /* Cygwin needs to change flag options. */ 1298 char *flag = NULL; 1299 int32_t length = 0; 1300 1301 flag = pkgDataFlags[GENLIB]; 1302 length = uprv_strlen(pkgDataFlags[GENLIB]); 1303 1304 int32_t position = length - 1; 1305 1306 for(;position >= 0;position--) { 1307 if (flag[position] == '=') { 1308 position++; 1309 break; 1310 } 1311 } 1312 1313 uprv_memset(flag + position, 0, length - position); 1314 #elif defined(OS400) 1315 /* OS400 needs to fix the ld options (swap single quote with double quote) */ 1316 char *flag = NULL; 1317 int32_t length = 0; 1318 1319 flag = pkgDataFlags[GENLIB]; 1320 length = uprv_strlen(pkgDataFlags[GENLIB]); 1321 1322 int32_t position = length - 1; 1323 1324 for(int32_t i = 0; i < length; i++) { 1325 if (flag[i] == '\'') { 1326 flag[i] = '\"'; 1327 } 1328 } 1329 #endif 1330 } 1331 1332 static void loadLists(UPKGOptions *o, UErrorCode *status) 1333 { 1334 CharList *l, *tail = NULL, *tail2 = NULL; 1335 FileStream *in; 1336 char line[16384]; 1337 char *linePtr, *lineNext; 1338 const uint32_t lineMax = 16300; 1339 char tmp[1024]; 1340 char *s; 1341 int32_t ln=0; /* line number */ 1342 1343 for(l = o->fileListFiles; l; l = l->next) { 1344 if(o->verbose) { 1345 fprintf(stdout, "# Reading %s..\n", l->str); 1346 } 1347 /* TODO: stdin */ 1348 in = T_FileStream_open(l->str, "r"); /* open files list */ 1349 1350 if(!in) { 1351 fprintf(stderr, "Error opening <%s>.\n", l->str); 1352 *status = U_FILE_ACCESS_ERROR; 1353 return; 1354 } 1355 1356 while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */ 1357 ln++; 1358 if(uprv_strlen(line)>lineMax) { 1359 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax); 1360 exit(1); 1361 } 1362 /* remove spaces at the beginning */ 1363 linePtr = line; 1364 while(isspace(*linePtr)) { 1365 linePtr++; 1366 } 1367 s=linePtr; 1368 /* remove trailing newline characters */ 1369 while(*s!=0) { 1370 if(*s=='\r' || *s=='\n') { 1371 *s=0; 1372 break; 1373 } 1374 ++s; 1375 } 1376 if((*linePtr == 0) || (*linePtr == '#')) { 1377 continue; /* comment or empty line */ 1378 } 1379 1380 /* Now, process the line */ 1381 lineNext = NULL; 1382 1383 while(linePtr && *linePtr) { /* process space-separated items */ 1384 while(*linePtr == ' ') { 1385 linePtr++; 1386 } 1387 /* Find the next quote */ 1388 if(linePtr[0] == '"') 1389 { 1390 lineNext = uprv_strchr(linePtr+1, '"'); 1391 if(lineNext == NULL) { 1392 fprintf(stderr, "%s:%d - missing trailing double quote (\")\n", 1393 l->str, (int)ln); 1394 exit(1); 1395 } else { 1396 lineNext++; 1397 if(*lineNext) { 1398 if(*lineNext != ' ') { 1399 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n", 1400 l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0'); 1401 exit(1); 1402 } 1403 *lineNext = 0; 1404 lineNext++; 1405 } 1406 } 1407 } else { 1408 lineNext = uprv_strchr(linePtr, ' '); 1409 if(lineNext) { 1410 *lineNext = 0; /* terminate at space */ 1411 lineNext++; 1412 } 1413 } 1414 1415 /* add the file */ 1416 s = (char*)getLongPathname(linePtr); 1417 1418 /* normal mode.. o->files is just the bare list without package names */ 1419 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr)); 1420 if(uprv_pathIsAbsolute(s)) { 1421 fprintf(stderr, "pkgdata: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, s); 1422 exit(U_ILLEGAL_ARGUMENT_ERROR); 1423 } 1424 uprv_strcpy(tmp, o->srcDir); 1425 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" :PKGDATA_FILE_SEP_STRING); 1426 uprv_strcat(tmp, s); 1427 o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp)); 1428 linePtr = lineNext; 1429 } /* for each entry on line */ 1430 } /* for each line */ 1431 T_FileStream_close(in); 1432 } /* for each file list file */ 1433 } 1434 1435 /* Try calling icu-config directly to get the option file. */ 1436 static int32_t pkg_getOptionsFromICUConfig(UOption *option) { 1437 #if U_HAVE_POPEN 1438 FILE *p; 1439 size_t n; 1440 static char buf[512] = ""; 1441 const char cmd[] = "icu-config --incpkgdatafile"; 1442 1443 p = popen(cmd, "r"); 1444 1445 if(p == NULL) 1446 { 1447 fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname); 1448 return -1; 1449 } 1450 1451 n = fread(buf, 1, 511, p); 1452 1453 pclose(p); 1454 1455 if(n<=0) 1456 { 1457 fprintf(stderr,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname); 1458 return -1; 1459 } 1460 1461 for (int32_t length = strlen(buf) - 1; length >= 0; length--) { 1462 if (buf[length] == '\n' || buf[length] == ' ') { 1463 buf[length] = 0; 1464 } else { 1465 break; 1466 } 1467 } 1468 1469 if(buf[strlen(buf)-1]=='\n') 1470 { 1471 buf[strlen(buf)-1]=0; 1472 } 1473 1474 if(buf[0] == 0) 1475 { 1476 fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname); 1477 return -1; 1478 } 1479 1480 option->value = buf; 1481 option->doesOccur = TRUE; 1482 1483 return 0; 1484 #endif 1485 return -1; 1486 } 1487