1 /****************************************************************************** 2 * Copyright (C) 2000-2014, International Business Machines 3 * Corporation and others. All Rights Reserved. 4 ******************************************************************************* 5 * file name: pkgdata.cpp 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 // Defines _XOPEN_SOURCE for access to POSIX functions. 18 // Must be before any other #includes. 19 #include "uposixdefs.h" 20 21 #include "unicode/utypes.h" 22 23 #include "unicode/putil.h" 24 #include "putilimp.h" 25 26 #if U_HAVE_POPEN 27 #if (U_PF_MINGW <= U_PLATFORM || U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__) 28 /* popen/pclose aren't defined in strict ANSI on Cygwin and MinGW */ 29 #undef __STRICT_ANSI__ 30 #endif 31 #endif 32 33 #include "cmemory.h" 34 #include "cstring.h" 35 #include "filestrm.h" 36 #include "toolutil.h" 37 #include "unicode/uclean.h" 38 #include "unewdata.h" 39 #include "uoptions.h" 40 #include "package.h" 41 #include "pkg_icu.h" 42 #include "pkg_genc.h" 43 #include "pkg_gencmn.h" 44 #include "flagparser.h" 45 #include "filetools.h" 46 47 #if U_HAVE_POPEN 48 # include <unistd.h> 49 #endif 50 51 #include <stdio.h> 52 #include <stdlib.h> 53 54 U_CDECL_BEGIN 55 #include "pkgtypes.h" 56 U_CDECL_END 57 58 59 static void loadLists(UPKGOptions *o, UErrorCode *status); 60 61 static int32_t pkg_executeOptions(UPKGOptions *o); 62 63 #ifdef WINDOWS_WITH_MSVC 64 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o); 65 #endif 66 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE); 67 static int32_t pkg_installLibrary(const char *installDir, const char *dir, UBool noVersion); 68 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName); 69 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName); 70 71 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY 72 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode); 73 #endif 74 75 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath); 76 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL, UBool specialHandling=FALSE); 77 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt); 78 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion); 79 static int32_t initializePkgDataFlags(UPKGOptions *o); 80 81 static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option); 82 static int runCommand(const char* command, UBool specialHandling=FALSE); 83 84 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c') 85 #define IN_DLL_MODE(mode) (mode == 'd' || mode == 'l') 86 #define IN_STATIC_MODE(mode) (mode == 's') 87 #define IN_FILES_MODE(mode) (mode == 'f') 88 89 enum { 90 NAME, 91 BLDOPT, 92 MODE, 93 HELP, 94 HELP_QUESTION_MARK, 95 VERBOSE, 96 COPYRIGHT, 97 COMMENT, 98 DESTDIR, 99 REBUILD, 100 TEMPDIR, 101 INSTALL, 102 SOURCEDIR, 103 ENTRYPOINT, 104 REVISION, 105 FORCE_PREFIX, 106 LIBNAME, 107 QUIET, 108 WITHOUT_ASSEMBLY, 109 PDS_BUILD 110 }; 111 112 /* This sets the modes that are available */ 113 static struct { 114 const char *name, *alt_name; 115 const char *desc; 116 } modes[] = { 117 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." }, 118 #if U_PLATFORM_HAS_WIN32_API 119 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"}, 120 { "common", "archive", "Generates just the common file, <package>.dat"}, 121 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX } 122 #else 123 #ifdef UDATA_SO_SUFFIX 124 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX }, 125 #endif 126 { "common", "archive", "Generates one common data file, <package>.dat" }, 127 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX } 128 #endif 129 }; 130 131 static UOption options[]={ 132 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG), 133 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */ 134 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG), 135 /*03*/ UOPTION_HELP_H, /* -h */ 136 /*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */ 137 /*05*/ UOPTION_VERBOSE, /* -v */ 138 /*06*/ UOPTION_COPYRIGHT, /* -c */ 139 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG), 140 /*08*/ UOPTION_DESTDIR, /* -d */ 141 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG), 142 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG), 143 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG), 144 /*14*/ UOPTION_SOURCEDIR , 145 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG), 146 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG), 147 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG), 148 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG), 149 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG), 150 /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG), 151 /*21*/ UOPTION_DEF( "zos-pds-build", 'z', UOPT_NO_ARG) 152 }; 153 154 /* This enum and the following char array should be kept in sync. */ 155 enum { 156 GENCCODE_ASSEMBLY_TYPE, 157 SO_EXT, 158 SOBJ_EXT, 159 A_EXT, 160 LIBPREFIX, 161 LIB_EXT_ORDER, 162 COMPILER, 163 LIBFLAGS, 164 GENLIB, 165 LDICUDTFLAGS, 166 LD_SONAME, 167 RPATH_FLAGS, 168 BIR_FLAGS, 169 AR, 170 ARFLAGS, 171 RANLIB, 172 INSTALL_CMD, 173 PKGDATA_FLAGS_SIZE 174 }; 175 static const char* FLAG_NAMES[PKGDATA_FLAGS_SIZE] = { 176 "GENCCODE_ASSEMBLY_TYPE", 177 "SO", 178 "SOBJ", 179 "A", 180 "LIBPREFIX", 181 "LIB_EXT_ORDER", 182 "COMPILE", 183 "LIBFLAGS", 184 "GENLIB", 185 "LDICUDTFLAGS", 186 "LD_SONAME", 187 "RPATH_FLAGS", 188 "BIR_LDFLAGS", 189 "AR", 190 "ARFLAGS", 191 "RANLIB", 192 "INSTALL_CMD" 193 }; 194 static char **pkgDataFlags = NULL; 195 196 enum { 197 LIB_FILE, 198 LIB_FILE_VERSION_MAJOR, 199 LIB_FILE_VERSION, 200 LIB_FILE_VERSION_TMP, 201 #if U_PLATFORM == U_PF_CYGWIN 202 LIB_FILE_CYGWIN, 203 LIB_FILE_CYGWIN_VERSION, 204 #elif U_PLATFORM == U_PF_MINGW 205 LIB_FILE_MINGW, 206 #elif U_PLATFORM == U_PF_OS390 207 LIB_FILE_OS390BATCH_MAJOR, 208 LIB_FILE_OS390BATCH_VERSION, 209 #endif 210 LIB_FILENAMES_SIZE 211 }; 212 static char libFileNames[LIB_FILENAMES_SIZE][256]; 213 214 static UPKGOptions *pkg_checkFlag(UPKGOptions *o); 215 216 const char options_help[][320]={ 217 "Set the data name", 218 #ifdef U_MAKE_IS_NMAKE 219 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)", 220 #else 221 "Specify options for the builder.", 222 #endif 223 "Specify the mode of building (see below; default: common)", 224 "This usage text", 225 "This usage text", 226 "Make the output verbose", 227 "Use the standard ICU copyright", 228 "Use a custom comment (instead of the copyright)", 229 "Specify the destination directory for files", 230 "Force rebuilding of all data", 231 "Specify temporary dir (default: output dir)", 232 "Install the data (specify target)", 233 "Specify a custom source directory", 234 "Specify a custom entrypoint name (default: short name)", 235 "Specify a version when packaging in dll or static mode", 236 "Add package to all file names if not present", 237 "Library name to build (if different than package name)", 238 "Quite mode. (e.g. Do not output a readme file for static libraries)", 239 "Build the data without assembly code", 240 "Build PDS dataset (zOS build only)" 241 }; 242 243 const char *progname = "PKGDATA"; 244 245 int 246 main(int argc, char* argv[]) { 247 int result = 0; 248 /* FileStream *out; */ 249 UPKGOptions o; 250 CharList *tail; 251 UBool needsHelp = FALSE; 252 UErrorCode status = U_ZERO_ERROR; 253 /* char tmp[1024]; */ 254 uint32_t i; 255 int32_t n; 256 257 U_MAIN_INIT_ARGS(argc, argv); 258 259 progname = argv[0]; 260 261 options[MODE].value = "common"; 262 263 /* read command line options */ 264 argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); 265 266 /* error handling, printing usage message */ 267 /* I've decided to simply print an error and quit. This tool has too 268 many options to just display them all of the time. */ 269 270 if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) { 271 needsHelp = TRUE; 272 } 273 else { 274 if(!needsHelp && argc<0) { 275 fprintf(stderr, 276 "%s: error in command line argument \"%s\"\n", 277 progname, 278 argv[-argc]); 279 fprintf(stderr, "Run '%s --help' for help.\n", progname); 280 return 1; 281 } 282 283 284 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 285 if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) { 286 if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) { 287 fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n"); 288 fprintf(stderr, "Run '%s --help' for help.\n", progname); 289 return 1; 290 } 291 } 292 #else 293 if(options[BLDOPT].doesOccur) { 294 fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n"); 295 } 296 #endif 297 298 if(!options[NAME].doesOccur) /* -O we already have - don't report it. */ 299 { 300 fprintf(stderr, " required parameter -p is missing \n"); 301 fprintf(stderr, "Run '%s --help' for help.\n", progname); 302 return 1; 303 } 304 305 if(argc == 1) { 306 fprintf(stderr, 307 "No input files specified.\n" 308 "Run '%s --help' for help.\n", progname); 309 return 1; 310 } 311 } /* end !needsHelp */ 312 313 if(argc<0 || needsHelp ) { 314 fprintf(stderr, 315 "usage: %s [-options] [-] [packageFile] \n" 316 "\tProduce packaged ICU data from the given list(s) of files.\n" 317 "\t'-' by itself means to read from stdin.\n" 318 "\tpackageFile is a text file containing the list of files to package.\n", 319 progname); 320 321 fprintf(stderr, "\n options:\n"); 322 for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) { 323 fprintf(stderr, "%-5s -%c %s%-10s %s\n", 324 (i<1?"[REQ]":""), 325 options[i].shortName, 326 options[i].longName ? "or --" : " ", 327 options[i].longName ? options[i].longName : "", 328 options_help[i]); 329 } 330 331 fprintf(stderr, "modes: (-m option)\n"); 332 for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) { 333 fprintf(stderr, " %-9s ", modes[i].name); 334 if (modes[i].alt_name) { 335 fprintf(stderr, "/ %-9s", modes[i].alt_name); 336 } else { 337 fprintf(stderr, " "); 338 } 339 fprintf(stderr, " %s\n", modes[i].desc); 340 } 341 return 1; 342 } 343 344 /* OK, fill in the options struct */ 345 uprv_memset(&o, 0, sizeof(o)); 346 347 o.mode = options[MODE].value; 348 o.version = options[REVISION].doesOccur ? options[REVISION].value : 0; 349 350 o.shortName = options[NAME].value; 351 { 352 int32_t len = (int32_t)uprv_strlen(o.shortName); 353 char *csname, *cp; 354 const char *sp; 355 356 cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName)); 357 if (*(sp = o.shortName)) { 358 *cp++ = isalpha(*sp) ? * sp : '_'; 359 for (++sp; *sp; ++sp) { 360 *cp++ = isalnum(*sp) ? *sp : '_'; 361 } 362 } 363 *cp = 0; 364 365 o.cShortName = csname; 366 } 367 368 if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */ 369 o.libName = options[LIBNAME].value; 370 } else { 371 o.libName = o.shortName; 372 } 373 374 if(options[QUIET].doesOccur) { 375 o.quiet = TRUE; 376 } else { 377 o.quiet = FALSE; 378 } 379 380 if(options[PDS_BUILD].doesOccur) { 381 #if U_PLATFORM == U_PF_OS390 382 o.pdsbuild = TRUE; 383 #else 384 o.pdsbuild = FALSE; 385 fprintf(stdout, "Warning: You are using the -z option which only works on z/OS.\n"); 386 387 #endif 388 } else { 389 o.pdsbuild = FALSE; 390 } 391 392 o.verbose = options[VERBOSE].doesOccur; 393 394 395 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */ 396 if (options[BLDOPT].doesOccur) { 397 o.options = options[BLDOPT].value; 398 } else { 399 o.options = NULL; 400 } 401 #endif 402 if(options[COPYRIGHT].doesOccur) { 403 o.comment = U_COPYRIGHT_STRING; 404 } else if (options[COMMENT].doesOccur) { 405 o.comment = options[COMMENT].value; 406 } 407 408 if( options[DESTDIR].doesOccur ) { 409 o.targetDir = options[DESTDIR].value; 410 } else { 411 o.targetDir = "."; /* cwd */ 412 } 413 414 o.rebuild = options[REBUILD].doesOccur; 415 416 if( options[TEMPDIR].doesOccur ) { 417 o.tmpDir = options[TEMPDIR].value; 418 } else { 419 o.tmpDir = o.targetDir; 420 } 421 422 if( options[INSTALL].doesOccur ) { 423 o.install = options[INSTALL].value; 424 } else { 425 o.install = NULL; 426 } 427 428 if( options[SOURCEDIR].doesOccur ) { 429 o.srcDir = options[SOURCEDIR].value; 430 } else { 431 o.srcDir = "."; 432 } 433 434 if( options[ENTRYPOINT].doesOccur ) { 435 o.entryName = options[ENTRYPOINT].value; 436 } else { 437 o.entryName = o.cShortName; 438 } 439 440 o.withoutAssembly = FALSE; 441 if (options[WITHOUT_ASSEMBLY].doesOccur) { 442 #ifndef BUILD_DATA_WITHOUT_ASSEMBLY 443 fprintf(stdout, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n"); 444 fprintf(stdout, "Warning: This option will be ignored.\n"); 445 #else 446 o.withoutAssembly = TRUE; 447 #endif 448 } 449 450 /* OK options are set up. Now the file lists. */ 451 tail = NULL; 452 for( n=1; n<argc; n++) { 453 o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n])); 454 } 455 456 /* load the files */ 457 loadLists(&o, &status); 458 if( U_FAILURE(status) ) { 459 fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status)); 460 return 2; 461 } 462 463 result = pkg_executeOptions(&o); 464 465 if (pkgDataFlags != NULL) { 466 for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) { 467 if (pkgDataFlags[n] != NULL) { 468 uprv_free(pkgDataFlags[n]); 469 } 470 } 471 uprv_free(pkgDataFlags); 472 } 473 474 if (o.cShortName != NULL) { 475 uprv_free((char *)o.cShortName); 476 } 477 if (o.fileListFiles != NULL) { 478 pkg_deleteList(o.fileListFiles); 479 } 480 if (o.filePaths != NULL) { 481 pkg_deleteList(o.filePaths); 482 } 483 if (o.files != NULL) { 484 pkg_deleteList(o.files); 485 } 486 487 return result; 488 } 489 490 static int runCommand(const char* command, UBool specialHandling) { 491 char *cmd = NULL; 492 char cmdBuffer[SMALL_BUFFER_MAX_SIZE]; 493 int32_t len = strlen(command); 494 495 if (len == 0) { 496 return 0; 497 } 498 499 if (!specialHandling) { 500 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400 501 if ((len + BUFFER_PADDING_SIZE) >= SMALL_BUFFER_MAX_SIZE) { 502 cmd = (char *)uprv_malloc(len + BUFFER_PADDING_SIZE); 503 } else { 504 cmd = cmdBuffer; 505 } 506 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW 507 sprintf(cmd, "bash -c \"%s\"", command); 508 509 #elif U_PLATFORM == U_PF_OS400 510 sprintf(cmd, "QSH CMD('%s')", command); 511 #endif 512 #else 513 goto normal_command_mode; 514 #endif 515 } else { 516 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400) 517 normal_command_mode: 518 #endif 519 cmd = (char *)command; 520 } 521 522 printf("pkgdata: %s\n", cmd); 523 int result = system(cmd); 524 if (result != 0) { 525 fprintf(stderr, "-- return status = %d\n", result); 526 } 527 528 if (cmd != cmdBuffer && cmd != command) { 529 uprv_free(cmd); 530 } 531 532 return result; 533 } 534 535 #define LN_CMD "ln -s" 536 #define RM_CMD "rm -f" 537 538 static int32_t pkg_executeOptions(UPKGOptions *o) { 539 int32_t result = 0; 540 541 const char mode = o->mode[0]; 542 char targetDir[SMALL_BUFFER_MAX_SIZE] = ""; 543 char tmpDir[SMALL_BUFFER_MAX_SIZE] = ""; 544 char datFileName[SMALL_BUFFER_MAX_SIZE] = ""; 545 char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = ""; 546 char checkLibFile[LARGE_BUFFER_MAX_SIZE] = ""; 547 548 initializePkgDataFlags(o); 549 550 if (IN_FILES_MODE(mode)) { 551 /* Copy the raw data to the installation directory. */ 552 if (o->install != NULL) { 553 uprv_strcpy(targetDir, o->install); 554 if (o->shortName != NULL) { 555 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING); 556 uprv_strcat(targetDir, o->shortName); 557 } 558 559 if(o->verbose) { 560 fprintf(stdout, "# Install: Files mode, copying files to %s..\n", targetDir); 561 } 562 result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str); 563 } 564 return result; 565 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ { 566 UBool noVersion = FALSE; 567 568 uprv_strcpy(targetDir, o->targetDir); 569 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING); 570 571 uprv_strcpy(tmpDir, o->tmpDir); 572 uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING); 573 574 uprv_strcpy(datFileNamePath, tmpDir); 575 576 uprv_strcpy(datFileName, o->shortName); 577 uprv_strcat(datFileName, UDATA_CMN_SUFFIX); 578 579 uprv_strcat(datFileNamePath, datFileName); 580 581 if(o->verbose) { 582 fprintf(stdout, "# Writing package file %s ..\n", datFileNamePath); 583 } 584 result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_CHARSET_FAMILY ? 'e' : U_IS_BIG_ENDIAN ? 'b' : 'l'); 585 if (result != 0) { 586 fprintf(stderr,"Error writing package dat file.\n"); 587 return result; 588 } 589 590 if (IN_COMMON_MODE(mode)) { 591 char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = ""; 592 593 uprv_strcpy(targetFileNamePath, targetDir); 594 uprv_strcat(targetFileNamePath, datFileName); 595 596 /* Move the dat file created to the target directory. */ 597 if (uprv_strcmp(datFileNamePath, targetFileNamePath) != 0) { 598 if (T_FileStream_file_exists(targetFileNamePath)) { 599 if ((result = remove(targetFileNamePath)) != 0) { 600 fprintf(stderr, "Unable to remove old dat file: %s\n", 601 targetFileNamePath); 602 return result; 603 } 604 } 605 606 result = rename(datFileNamePath, targetFileNamePath); 607 608 if (o->verbose) { 609 fprintf(stdout, "# Moving package file to %s ..\n", 610 targetFileNamePath); 611 } 612 if (result != 0) { 613 fprintf( 614 stderr, 615 "Unable to move dat file (%s) to target location (%s).\n", 616 datFileNamePath, targetFileNamePath); 617 return result; 618 } 619 } 620 621 if (o->install != NULL) { 622 result = pkg_installCommonMode(o->install, targetFileNamePath); 623 } 624 625 return result; 626 } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ { 627 char gencFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 628 char version_major[10] = ""; 629 UBool reverseExt = FALSE; 630 631 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 632 /* Get the version major number. */ 633 if (o->version != NULL) { 634 for (uint32_t i = 0;i < sizeof(version_major);i++) { 635 if (o->version[i] == '.') { 636 version_major[i] = 0; 637 break; 638 } 639 version_major[i] = o->version[i]; 640 } 641 } else { 642 noVersion = TRUE; 643 if (IN_DLL_MODE(mode)) { 644 fprintf(stdout, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n"); 645 } 646 } 647 648 #if U_PLATFORM != U_PF_OS400 649 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##) 650 * reverseExt is FALSE if the suffix should be the version number. 651 */ 652 if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) { 653 reverseExt = TRUE; 654 } 655 #endif 656 /* Using the base libName and version number, generate the library file names. */ 657 createFileNames(o, mode, version_major, o->version == NULL ? "" : o->version, o->libName, reverseExt, noVersion); 658 659 if ((o->version!=NULL || IN_STATIC_MODE(mode)) && o->rebuild == FALSE && o->pdsbuild == FALSE) { 660 /* Check to see if a previous built data library file exists and check if it is the latest. */ 661 sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]); 662 if (T_FileStream_file_exists(checkLibFile)) { 663 if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) { 664 if (o->install != NULL) { 665 if(o->verbose) { 666 fprintf(stdout, "# Installing already-built library into %s\n", o->install); 667 } 668 result = pkg_installLibrary(o->install, targetDir, noVersion); 669 } else { 670 if(o->verbose) { 671 printf("# Not rebuilding %s - up to date.\n", checkLibFile); 672 } 673 } 674 return result; 675 } else if (o->verbose && (o->install!=NULL)) { 676 fprintf(stdout, "# Not installing up-to-date library %s into %s\n", checkLibFile, o->install); 677 } 678 } else if(o->verbose && (o->install!=NULL)) { 679 fprintf(stdout, "# Not installing missing %s into %s\n", checkLibFile, o->install); 680 } 681 } 682 683 if (pkg_checkFlag(o) == NULL) { 684 /* Error occurred. */ 685 return result; 686 } 687 #endif 688 689 if (!o->withoutAssembly && pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) { 690 const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE]; 691 692 if(o->verbose) { 693 fprintf(stdout, "# Generating assembly code %s of type %s ..\n", gencFilePath, genccodeAssembly); 694 } 695 696 /* Offset genccodeAssembly by 3 because "-a " */ 697 if (genccodeAssembly && 698 (uprv_strlen(genccodeAssembly)>3) && 699 checkAssemblyHeaderName(genccodeAssembly+3)) { 700 writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath); 701 702 result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath); 703 if (result != 0) { 704 fprintf(stderr, "Error generating assembly code for data.\n"); 705 return result; 706 } else if (IN_STATIC_MODE(mode)) { 707 if(o->install != NULL) { 708 if(o->verbose) { 709 fprintf(stdout, "# Installing static library into %s\n", o->install); 710 } 711 result = pkg_installLibrary(o->install, targetDir, noVersion); 712 } 713 return result; 714 } 715 } else { 716 fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly); 717 return -1; 718 } 719 } else { 720 if(o->verbose) { 721 fprintf(stdout, "# Writing object code to %s ..\n", gencFilePath); 722 } 723 if (o->withoutAssembly) { 724 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY 725 result = pkg_createWithoutAssemblyCode(o, targetDir, mode); 726 #else 727 /* This error should not occur. */ 728 fprintf(stderr, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n"); 729 #endif 730 } else { 731 #ifdef CAN_WRITE_OBJ_CODE 732 // android-change -- removed 733 // writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath); 734 #if U_PLATFORM_IS_LINUX_BASED 735 result = pkg_generateLibraryFile(targetDir, mode, gencFilePath); 736 #elif defined(WINDOWS_WITH_MSVC) 737 result = pkg_createWindowsDLL(mode, gencFilePath, o); 738 #endif 739 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY) 740 result = pkg_createWithoutAssemblyCode(o, targetDir, mode); 741 #else 742 fprintf(stderr, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n"); 743 return 1; 744 #endif 745 } 746 747 if (result != 0) { 748 fprintf(stderr, "Error generating package data.\n"); 749 return result; 750 } 751 } 752 #if !U_PLATFORM_USES_ONLY_WIN32_API 753 if(!IN_STATIC_MODE(mode)) { 754 /* Certain platforms uses archive library. (e.g. AIX) */ 755 if(o->verbose) { 756 fprintf(stdout, "# Creating data archive library file ..\n"); 757 } 758 result = pkg_archiveLibrary(targetDir, o->version, reverseExt); 759 if (result != 0) { 760 fprintf(stderr, "Error creating data archive library file.\n"); 761 return result; 762 } 763 #if U_PLATFORM != U_PF_OS400 764 if (!noVersion) { 765 /* Create symbolic links for the final library file. */ 766 #if U_PLATFORM == U_PF_OS390 767 result = pkg_createSymLinks(targetDir, o->pdsbuild); 768 #else 769 result = pkg_createSymLinks(targetDir, noVersion); 770 #endif 771 if (result != 0) { 772 fprintf(stderr, "Error creating symbolic links of the data library file.\n"); 773 return result; 774 } 775 } 776 #endif 777 } /* !IN_STATIC_MODE */ 778 #endif 779 780 #if !U_PLATFORM_USES_ONLY_WIN32_API 781 /* Install the libraries if option was set. */ 782 if (o->install != NULL) { 783 if(o->verbose) { 784 fprintf(stdout, "# Installing library file to %s ..\n", o->install); 785 } 786 result = pkg_installLibrary(o->install, targetDir, noVersion); 787 if (result != 0) { 788 fprintf(stderr, "Error installing the data library.\n"); 789 return result; 790 } 791 } 792 #endif 793 } 794 } 795 return result; 796 } 797 798 /* Initialize the pkgDataFlags with the option file given. */ 799 static int32_t initializePkgDataFlags(UPKGOptions *o) { 800 UErrorCode status = U_ZERO_ERROR; 801 int32_t result = 0; 802 int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE; 803 int32_t tmpResult = 0; 804 805 /* Initialize pkgdataFlags */ 806 pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE); 807 808 /* If we run out of space, allocate more */ 809 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 810 do { 811 #endif 812 if (pkgDataFlags != NULL) { 813 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { 814 pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize); 815 if (pkgDataFlags[i] != NULL) { 816 pkgDataFlags[i][0] = 0; 817 } else { 818 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); 819 return -1; 820 } 821 } 822 } else { 823 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); 824 return -1; 825 } 826 827 if (o->options == NULL) { 828 return result; 829 } 830 831 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 832 /* Read in options file. */ 833 if(o->verbose) { 834 fprintf(stdout, "# Reading options file %s\n", o->options); 835 } 836 status = U_ZERO_ERROR; 837 tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, FLAG_NAMES, (int32_t)PKGDATA_FLAGS_SIZE, &status); 838 if (status == U_BUFFER_OVERFLOW_ERROR) { 839 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { 840 uprv_free(pkgDataFlags[i]); 841 } 842 currentBufferSize = tmpResult; 843 } else if (U_FAILURE(status)) { 844 fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status)); 845 return -1; 846 } 847 #endif 848 if(o->verbose) { 849 fprintf(stdout, "# pkgDataFlags=\n"); 850 for(int32_t i=0;i<PKGDATA_FLAGS_SIZE;i++) { 851 fprintf(stdout, " [%d] %s: %s\n", i, FLAG_NAMES[i], pkgDataFlags[i]); 852 } 853 fprintf(stdout, "\n"); 854 } 855 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 856 } while (status == U_BUFFER_OVERFLOW_ERROR); 857 #endif 858 859 return result; 860 } 861 862 863 /* 864 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames. 865 * Depending on the configuration, the library name may either end with version number or shared object suffix. 866 */ 867 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt, UBool noVersion) { 868 #if U_PLATFORM == U_PF_MINGW 869 /* MinGW does not need the library prefix when building in dll mode. */ 870 if (IN_DLL_MODE(mode)) { 871 sprintf(libFileNames[LIB_FILE], "%s", libName); 872 } else { 873 sprintf(libFileNames[LIB_FILE], "%s%s", 874 pkgDataFlags[LIBPREFIX], 875 libName); 876 } 877 #else 878 sprintf(libFileNames[LIB_FILE], "%s%s", 879 pkgDataFlags[LIBPREFIX], 880 libName); 881 #endif 882 883 if(o->verbose) { 884 fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]); 885 } 886 887 #if U_PLATFORM == U_PF_MINGW 888 sprintf(libFileNames[LIB_FILE_MINGW], "%s%s.lib", pkgDataFlags[LIBPREFIX], libName); 889 #elif U_PLATFORM == U_PF_CYGWIN 890 sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s.%s", 891 libName, 892 pkgDataFlags[SO_EXT]); 893 sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s.%s", 894 libName, 895 version_major, 896 pkgDataFlags[SO_EXT]); 897 898 uprv_strcat(pkgDataFlags[SO_EXT], "."); 899 uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]); 900 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX) 901 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s", 902 libFileNames[LIB_FILE], 903 pkgDataFlags[SOBJ_EXT]); 904 #elif U_PLATFORM == U_PF_OS390 905 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s", 906 libFileNames[LIB_FILE], 907 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 908 reverseExt ? version : pkgDataFlags[SOBJ_EXT], 909 reverseExt ? pkgDataFlags[SOBJ_EXT] : version); 910 911 sprintf(libFileNames[LIB_FILE_OS390BATCH_VERSION], "%s%s.x", 912 libFileNames[LIB_FILE], 913 version); 914 sprintf(libFileNames[LIB_FILE_OS390BATCH_MAJOR], "%s%s.x", 915 libFileNames[LIB_FILE], 916 version_major); 917 #else 918 if (noVersion && !reverseExt) { 919 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s", 920 libFileNames[LIB_FILE], 921 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 922 pkgDataFlags[SOBJ_EXT]); 923 } else { 924 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s", 925 libFileNames[LIB_FILE], 926 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 927 reverseExt ? version : pkgDataFlags[SOBJ_EXT], 928 reverseExt ? pkgDataFlags[SOBJ_EXT] : version); 929 } 930 #endif 931 if (noVersion && !reverseExt) { 932 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s", 933 libFileNames[LIB_FILE], 934 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 935 pkgDataFlags[SO_EXT]); 936 937 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s", 938 libFileNames[LIB_FILE], 939 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 940 pkgDataFlags[SO_EXT]); 941 } else { 942 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s", 943 libFileNames[LIB_FILE], 944 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 945 reverseExt ? version_major : pkgDataFlags[SO_EXT], 946 reverseExt ? pkgDataFlags[SO_EXT] : version_major); 947 948 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s", 949 libFileNames[LIB_FILE], 950 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 951 reverseExt ? version : pkgDataFlags[SO_EXT], 952 reverseExt ? pkgDataFlags[SO_EXT] : version); 953 } 954 955 if(o->verbose) { 956 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]); 957 } 958 959 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN 960 /* Cygwin and MinGW only deals with the version major number. */ 961 uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]); 962 #endif 963 964 if(IN_STATIC_MODE(mode)) { 965 sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]); 966 libFileNames[LIB_FILE_VERSION_MAJOR][0]=0; 967 if(o->verbose) { 968 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames[LIB_FILE_VERSION]); 969 } 970 } 971 } 972 973 /* Create the symbolic links for the final library file. */ 974 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) { 975 int32_t result = 0; 976 char cmd[LARGE_BUFFER_MAX_SIZE]; 977 char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */ 978 char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */ 979 980 #if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW 981 /* No symbolic link to make. */ 982 if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 || 983 uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) { 984 return result; 985 } 986 987 sprintf(cmd, "cd %s && %s %s && %s %s %s", 988 targetDir, 989 RM_CMD, 990 libFileNames[LIB_FILE_VERSION_MAJOR], 991 LN_CMD, 992 libFileNames[LIB_FILE_VERSION], 993 libFileNames[LIB_FILE_VERSION_MAJOR]); 994 result = runCommand(cmd); 995 if (result != 0) { 996 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd); 997 return result; 998 } 999 #endif 1000 1001 if (specialHandling) { 1002 #if U_PLATFORM == U_PF_CYGWIN 1003 sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]); 1004 sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]); 1005 #elif U_PLATFORM == U_PF_OS390 1006 /* Create the symbolic links for the import data */ 1007 /* Use the cmd buffer to store path to import data file to check its existence */ 1008 sprintf(cmd, "%s/%s", targetDir, libFileNames[LIB_FILE_OS390BATCH_VERSION]); 1009 if (T_FileStream_file_exists(cmd)) { 1010 sprintf(cmd, "cd %s && %s %s && %s %s %s", 1011 targetDir, 1012 RM_CMD, 1013 libFileNames[LIB_FILE_OS390BATCH_MAJOR], 1014 LN_CMD, 1015 libFileNames[LIB_FILE_OS390BATCH_VERSION], 1016 libFileNames[LIB_FILE_OS390BATCH_MAJOR]); 1017 result = runCommand(cmd); 1018 if (result != 0) { 1019 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd); 1020 return result; 1021 } 1022 1023 sprintf(cmd, "cd %s && %s %s.x && %s %s %s.x", 1024 targetDir, 1025 RM_CMD, 1026 libFileNames[LIB_FILE], 1027 LN_CMD, 1028 libFileNames[LIB_FILE_OS390BATCH_VERSION], 1029 libFileNames[LIB_FILE]); 1030 result = runCommand(cmd); 1031 if (result != 0) { 1032 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd); 1033 return result; 1034 } 1035 } 1036 1037 /* Needs to be set here because special handling skips it */ 1038 sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]); 1039 sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]); 1040 #else 1041 goto normal_symlink_mode; 1042 #endif 1043 } else { 1044 #if U_PLATFORM != U_PF_CYGWIN 1045 normal_symlink_mode: 1046 #endif 1047 sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]); 1048 sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]); 1049 } 1050 1051 sprintf(cmd, "cd %s && %s %s && %s %s %s", 1052 targetDir, 1053 RM_CMD, 1054 name1, 1055 LN_CMD, 1056 name2, 1057 name1); 1058 1059 result = runCommand(cmd); 1060 1061 return result; 1062 } 1063 1064 static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, UBool noVersion) { 1065 int32_t result = 0; 1066 char cmd[SMALL_BUFFER_MAX_SIZE]; 1067 1068 sprintf(cmd, "cd %s && %s %s %s%s%s", 1069 targetDir, 1070 pkgDataFlags[INSTALL_CMD], 1071 libFileNames[LIB_FILE_VERSION], 1072 installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION] 1073 ); 1074 1075 result = runCommand(cmd); 1076 1077 if (result != 0) { 1078 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1079 return result; 1080 } 1081 1082 #ifdef CYGWINMSVC 1083 sprintf(cmd, "cd %s && %s %s.lib %s", 1084 targetDir, 1085 pkgDataFlags[INSTALL_CMD], 1086 libFileNames[LIB_FILE], 1087 installDir 1088 ); 1089 result = runCommand(cmd); 1090 1091 if (result != 0) { 1092 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1093 return result; 1094 } 1095 #elif U_PLATFORM == U_PF_CYGWIN 1096 sprintf(cmd, "cd %s && %s %s %s", 1097 targetDir, 1098 pkgDataFlags[INSTALL_CMD], 1099 libFileNames[LIB_FILE_CYGWIN_VERSION], 1100 installDir 1101 ); 1102 result = runCommand(cmd); 1103 1104 if (result != 0) { 1105 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1106 return result; 1107 } 1108 1109 #elif U_PLATFORM == U_PF_OS390 1110 if (T_FileStream_file_exists(libFileNames[LIB_FILE_OS390BATCH_VERSION])) { 1111 sprintf(cmd, "%s %s %s", 1112 pkgDataFlags[INSTALL_CMD], 1113 libFileNames[LIB_FILE_OS390BATCH_VERSION], 1114 installDir 1115 ); 1116 result = runCommand(cmd); 1117 1118 if (result != 0) { 1119 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1120 return result; 1121 } 1122 } 1123 #endif 1124 1125 if (noVersion) { 1126 return result; 1127 } else { 1128 return pkg_createSymLinks(installDir, TRUE); 1129 } 1130 } 1131 1132 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) { 1133 int32_t result = 0; 1134 char cmd[SMALL_BUFFER_MAX_SIZE] = ""; 1135 1136 if (!T_FileStream_file_exists(installDir)) { 1137 UErrorCode status = U_ZERO_ERROR; 1138 1139 uprv_mkdir(installDir, &status); 1140 if (U_FAILURE(status)) { 1141 fprintf(stderr, "Error creating installation directory: %s\n", installDir); 1142 return -1; 1143 } 1144 } 1145 #ifndef U_WINDOWS_WITH_MSVC 1146 sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir); 1147 #else 1148 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS); 1149 #endif 1150 1151 result = runCommand(cmd); 1152 if (result != 0) { 1153 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 1154 } 1155 1156 return result; 1157 } 1158 1159 #ifdef U_WINDOWS_MSVC 1160 /* Copy commands for installing the raw data files on Windows. */ 1161 #define WIN_INSTALL_CMD "xcopy" 1162 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K" 1163 #endif 1164 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) { 1165 int32_t result = 0; 1166 char cmd[SMALL_BUFFER_MAX_SIZE] = ""; 1167 1168 if (!T_FileStream_file_exists(installDir)) { 1169 UErrorCode status = U_ZERO_ERROR; 1170 1171 uprv_mkdir(installDir, &status); 1172 if (U_FAILURE(status)) { 1173 fprintf(stderr, "Error creating installation directory: %s\n", installDir); 1174 return -1; 1175 } 1176 } 1177 #ifndef U_WINDOWS_WITH_MSVC 1178 char buffer[SMALL_BUFFER_MAX_SIZE] = ""; 1179 int32_t bufferLength = 0; 1180 1181 FileStream *f = T_FileStream_open(fileListName, "r"); 1182 if (f != NULL) { 1183 for(;;) { 1184 if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) { 1185 bufferLength = uprv_strlen(buffer); 1186 /* Remove new line character. */ 1187 if (bufferLength > 0) { 1188 buffer[bufferLength-1] = 0; 1189 } 1190 1191 sprintf(cmd, "%s %s%s%s %s%s%s", 1192 pkgDataFlags[INSTALL_CMD], 1193 srcDir, PKGDATA_FILE_SEP_STRING, buffer, 1194 installDir, PKGDATA_FILE_SEP_STRING, buffer); 1195 1196 result = runCommand(cmd); 1197 if (result != 0) { 1198 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 1199 break; 1200 } 1201 } else { 1202 if (!T_FileStream_eof(f)) { 1203 fprintf(stderr, "Failed to read line from file: %s\n", fileListName); 1204 result = -1; 1205 } 1206 break; 1207 } 1208 } 1209 T_FileStream_close(f); 1210 } else { 1211 result = -1; 1212 fprintf(stderr, "Unable to open list file: %s\n", fileListName); 1213 } 1214 #else 1215 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS); 1216 result = runCommand(cmd); 1217 if (result != 0) { 1218 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 1219 } 1220 #endif 1221 1222 return result; 1223 } 1224 1225 /* Archiving of the library file may be needed depending on the platform and options given. 1226 * If archiving is not needed, copy over the library file name. 1227 */ 1228 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) { 1229 int32_t result = 0; 1230 char cmd[LARGE_BUFFER_MAX_SIZE]; 1231 1232 /* If the shared object suffix and the final object suffix is different and the final object suffix and the 1233 * archive file suffix is the same, then the final library needs to be archived. 1234 */ 1235 if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) { 1236 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s", 1237 libFileNames[LIB_FILE], 1238 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 1239 reverseExt ? version : pkgDataFlags[SO_EXT], 1240 reverseExt ? pkgDataFlags[SO_EXT] : version); 1241 1242 sprintf(cmd, "%s %s %s%s %s%s", 1243 pkgDataFlags[AR], 1244 pkgDataFlags[ARFLAGS], 1245 targetDir, 1246 libFileNames[LIB_FILE_VERSION], 1247 targetDir, 1248 libFileNames[LIB_FILE_VERSION_TMP]); 1249 1250 result = runCommand(cmd); 1251 if (result != 0) { 1252 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd); 1253 return result; 1254 } 1255 1256 sprintf(cmd, "%s %s%s", 1257 pkgDataFlags[RANLIB], 1258 targetDir, 1259 libFileNames[LIB_FILE_VERSION]); 1260 1261 result = runCommand(cmd); 1262 if (result != 0) { 1263 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd); 1264 return result; 1265 } 1266 1267 /* Remove unneeded library file. */ 1268 sprintf(cmd, "%s %s%s", 1269 RM_CMD, 1270 targetDir, 1271 libFileNames[LIB_FILE_VERSION_TMP]); 1272 1273 result = runCommand(cmd); 1274 if (result != 0) { 1275 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd); 1276 return result; 1277 } 1278 1279 } else { 1280 uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]); 1281 } 1282 1283 return result; 1284 } 1285 1286 /* 1287 * Using the compiler information from the configuration file set by -O option, generate the library file. 1288 * command may be given to allow for a larger buffer for cmd. 1289 */ 1290 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command, UBool specialHandling) { 1291 int32_t result = 0; 1292 char *cmd = NULL; 1293 UBool freeCmd = FALSE; 1294 int32_t length = 0; 1295 1296 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large 1297 * containing many object files and so the calling function should supply a command buffer that is large 1298 * enough to handle this. Otherwise, use the default size. 1299 */ 1300 if (command != NULL) { 1301 cmd = command; 1302 } 1303 1304 if (IN_STATIC_MODE(mode)) { 1305 if (cmd == NULL) { 1306 length = uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) + 1307 uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE; 1308 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) { 1309 fprintf(stderr, "Unable to allocate memory for command.\n"); 1310 return -1; 1311 } 1312 freeCmd = TRUE; 1313 } 1314 sprintf(cmd, "%s %s %s%s %s", 1315 pkgDataFlags[AR], 1316 pkgDataFlags[ARFLAGS], 1317 targetDir, 1318 libFileNames[LIB_FILE_VERSION], 1319 objectFile); 1320 1321 result = runCommand(cmd); 1322 if (result == 0) { 1323 sprintf(cmd, "%s %s%s", 1324 pkgDataFlags[RANLIB], 1325 targetDir, 1326 libFileNames[LIB_FILE_VERSION]); 1327 1328 result = runCommand(cmd); 1329 } 1330 } else /* if (IN_DLL_MODE(mode)) */ { 1331 if (cmd == NULL) { 1332 length = uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) + 1333 ((uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP])) * 2) + 1334 uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) + 1335 uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) + 1336 uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE; 1337 #if U_PLATFORM == U_PF_CYGWIN 1338 length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]); 1339 #elif U_PLATFORM == U_PF_MINGW 1340 length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_MINGW]); 1341 #endif 1342 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) { 1343 fprintf(stderr, "Unable to allocate memory for command.\n"); 1344 return -1; 1345 } 1346 freeCmd = TRUE; 1347 } 1348 #if U_PLATFORM == U_PF_MINGW 1349 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s", 1350 pkgDataFlags[GENLIB], 1351 targetDir, 1352 libFileNames[LIB_FILE_MINGW], 1353 pkgDataFlags[LDICUDTFLAGS], 1354 targetDir, 1355 libFileNames[LIB_FILE_VERSION_TMP], 1356 #elif U_PLATFORM == U_PF_CYGWIN 1357 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s", 1358 pkgDataFlags[GENLIB], 1359 targetDir, 1360 libFileNames[LIB_FILE_VERSION_TMP], 1361 pkgDataFlags[LDICUDTFLAGS], 1362 targetDir, 1363 libFileNames[LIB_FILE_CYGWIN_VERSION], 1364 #elif U_PLATFORM == U_PF_AIX 1365 sprintf(cmd, "%s %s%s;%s %s -o %s%s %s %s%s %s %s", 1366 RM_CMD, 1367 targetDir, 1368 libFileNames[LIB_FILE_VERSION_TMP], 1369 pkgDataFlags[GENLIB], 1370 pkgDataFlags[LDICUDTFLAGS], 1371 targetDir, 1372 libFileNames[LIB_FILE_VERSION_TMP], 1373 #else 1374 sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s", 1375 pkgDataFlags[GENLIB], 1376 pkgDataFlags[LDICUDTFLAGS], 1377 targetDir, 1378 libFileNames[LIB_FILE_VERSION_TMP], 1379 #endif 1380 objectFile, 1381 pkgDataFlags[LD_SONAME], 1382 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR], 1383 pkgDataFlags[RPATH_FLAGS], 1384 pkgDataFlags[BIR_FLAGS]); 1385 1386 /* Generate the library file. */ 1387 result = runCommand(cmd); 1388 1389 #if U_PLATFORM == U_PF_OS390 1390 char *env_tmp; 1391 char PDS_LibName[512]; 1392 char PDS_Name[512]; 1393 1394 PDS_Name[0] = 0; 1395 PDS_LibName[0] = 0; 1396 if (specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) { 1397 if (env_tmp = getenv("ICU_PDS_NAME")) { 1398 sprintf(PDS_Name, "%s%s", 1399 env_tmp, 1400 "DA"); 1401 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX")); 1402 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) { 1403 sprintf(PDS_Name, "%s%s", 1404 env_tmp, 1405 U_ICU_VERSION_SHORT "DA"); 1406 } else { 1407 sprintf(PDS_Name, "%s%s", 1408 "IXMI", 1409 U_ICU_VERSION_SHORT "DA"); 1410 } 1411 } else if (!specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) { 1412 if (env_tmp = getenv("ICU_PDS_NAME")) { 1413 sprintf(PDS_Name, "%s%s", 1414 env_tmp, 1415 "D1"); 1416 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX")); 1417 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) { 1418 sprintf(PDS_Name, "%s%s", 1419 env_tmp, 1420 U_ICU_VERSION_SHORT "D1"); 1421 } else { 1422 sprintf(PDS_Name, "%s%s", 1423 "IXMI", 1424 U_ICU_VERSION_SHORT "D1"); 1425 } 1426 } 1427 1428 if (PDS_Name[0]) { 1429 sprintf(PDS_LibName,"%s%s%s%s%s", 1430 "\"//'", 1431 getenv("LOADMOD"), 1432 "(", 1433 PDS_Name, 1434 ")'\""); 1435 sprintf(cmd, "%s %s -o %s %s %s%s %s %s", 1436 pkgDataFlags[GENLIB], 1437 pkgDataFlags[LDICUDTFLAGS], 1438 PDS_LibName, 1439 objectFile, 1440 pkgDataFlags[LD_SONAME], 1441 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR], 1442 pkgDataFlags[RPATH_FLAGS], 1443 pkgDataFlags[BIR_FLAGS]); 1444 1445 result = runCommand(cmd); 1446 } 1447 #endif 1448 } 1449 1450 if (result != 0) { 1451 fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd); 1452 } 1453 1454 if (freeCmd) { 1455 uprv_free(cmd); 1456 } 1457 1458 return result; 1459 } 1460 1461 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) { 1462 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; 1463 char *cmd; 1464 int32_t result = 0; 1465 1466 int32_t length = 0; 1467 1468 /* Remove the ending .s and replace it with .o for the new object file. */ 1469 uprv_strcpy(tempObjectFile, gencFilePath); 1470 tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o'; 1471 1472 length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS]) 1473 + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE; 1474 1475 cmd = (char *)uprv_malloc(sizeof(char) * length); 1476 if (cmd == NULL) { 1477 return -1; 1478 } 1479 1480 /* Generate the object file. */ 1481 sprintf(cmd, "%s %s -o %s %s", 1482 pkgDataFlags[COMPILER], 1483 pkgDataFlags[LIBFLAGS], 1484 tempObjectFile, 1485 gencFilePath); 1486 1487 result = runCommand(cmd); 1488 uprv_free(cmd); 1489 if (result != 0) { 1490 fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd); 1491 return result; 1492 } 1493 1494 return pkg_generateLibraryFile(targetDir, mode, tempObjectFile); 1495 } 1496 1497 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY 1498 /* 1499 * Generation of the data library without assembly code needs to compile each data file 1500 * individually and then link it all together. 1501 * Note: Any update to the directory structure of the data needs to be reflected here. 1502 */ 1503 enum { 1504 DATA_PREFIX_BRKITR, 1505 DATA_PREFIX_COLL, 1506 DATA_PREFIX_CURR, 1507 DATA_PREFIX_LANG, 1508 DATA_PREFIX_RBNF, 1509 DATA_PREFIX_REGION, 1510 DATA_PREFIX_TRANSLIT, 1511 DATA_PREFIX_ZONE, 1512 DATA_PREFIX_LENGTH 1513 }; 1514 1515 const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = { 1516 "brkitr", 1517 "coll", 1518 "curr", 1519 "lang", 1520 "rbnf", 1521 "region", 1522 "translit", 1523 "zone" 1524 }; 1525 1526 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) { 1527 int32_t result = 0; 1528 CharList *list = o->filePaths; 1529 CharList *listNames = o->files; 1530 int32_t listSize = pkg_countCharList(list); 1531 char *buffer; 1532 char *cmd; 1533 char gencmnFile[SMALL_BUFFER_MAX_SIZE] = ""; 1534 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; 1535 #ifdef USE_SINGLE_CCODE_FILE 1536 char icudtAll[SMALL_BUFFER_MAX_SIZE] = ""; 1537 FileStream *icudtAllFile = NULL; 1538 1539 sprintf(icudtAll, "%s%s%sall.c", 1540 o->tmpDir, 1541 PKGDATA_FILE_SEP_STRING, 1542 libFileNames[LIB_FILE]); 1543 /* Remove previous icudtall.c file. */ 1544 if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) { 1545 fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll); 1546 return result; 1547 } 1548 1549 if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==NULL) { 1550 fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll); 1551 return result; 1552 } 1553 #endif 1554 1555 if (list == NULL || listNames == NULL) { 1556 /* list and listNames should never be NULL since we are looping through the CharList with 1557 * the given size. 1558 */ 1559 return -1; 1560 } 1561 1562 if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) { 1563 fprintf(stderr, "Unable to allocate memory for cmd.\n"); 1564 return -1; 1565 } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) { 1566 fprintf(stderr, "Unable to allocate memory for buffer.\n"); 1567 uprv_free(cmd); 1568 return -1; 1569 } 1570 1571 for (int32_t i = 0; i < (listSize + 1); i++) { 1572 const char *file ; 1573 const char *name; 1574 1575 if (i == 0) { 1576 /* The first iteration calls the gencmn function and initailizes the buffer. */ 1577 createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile); 1578 buffer[0] = 0; 1579 #ifdef USE_SINGLE_CCODE_FILE 1580 uprv_strcpy(tempObjectFile, gencmnFile); 1581 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1582 1583 sprintf(cmd, "%s %s -o %s %s", 1584 pkgDataFlags[COMPILER], 1585 pkgDataFlags[LIBFLAGS], 1586 tempObjectFile, 1587 gencmnFile); 1588 1589 result = runCommand(cmd); 1590 if (result != 0) { 1591 break; 1592 } 1593 1594 sprintf(buffer, "%s",tempObjectFile); 1595 #endif 1596 } else { 1597 char newName[SMALL_BUFFER_MAX_SIZE]; 1598 char dataName[SMALL_BUFFER_MAX_SIZE]; 1599 char dataDirName[SMALL_BUFFER_MAX_SIZE]; 1600 const char *pSubstring; 1601 file = list->str; 1602 name = listNames->str; 1603 1604 newName[0] = dataName[0] = 0; 1605 for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) { 1606 dataDirName[0] = 0; 1607 sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING); 1608 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */ 1609 pSubstring = uprv_strstr(name, dataDirName); 1610 if (pSubstring != NULL) { 1611 char newNameTmp[SMALL_BUFFER_MAX_SIZE] = ""; 1612 const char *p = name + uprv_strlen(dataDirName); 1613 for (int32_t i = 0;;i++) { 1614 if (p[i] == '.') { 1615 newNameTmp[i] = '_'; 1616 continue; 1617 } 1618 newNameTmp[i] = p[i]; 1619 if (p[i] == 0) { 1620 break; 1621 } 1622 } 1623 sprintf(newName, "%s_%s", 1624 DATA_PREFIX[n], 1625 newNameTmp); 1626 sprintf(dataName, "%s_%s", 1627 o->shortName, 1628 DATA_PREFIX[n]); 1629 } 1630 if (newName[0] != 0) { 1631 break; 1632 } 1633 } 1634 1635 if(o->verbose) { 1636 printf("# Generating %s \n", gencmnFile); 1637 } 1638 1639 writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile); 1640 1641 #ifdef USE_SINGLE_CCODE_FILE 1642 sprintf(cmd, "#include \"%s\"\n", gencmnFile); 1643 T_FileStream_writeLine(icudtAllFile, cmd); 1644 /* don't delete the file */ 1645 #endif 1646 } 1647 1648 #ifndef USE_SINGLE_CCODE_FILE 1649 uprv_strcpy(tempObjectFile, gencmnFile); 1650 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1651 1652 sprintf(cmd, "%s %s -o %s %s", 1653 pkgDataFlags[COMPILER], 1654 pkgDataFlags[LIBFLAGS], 1655 tempObjectFile, 1656 gencmnFile); 1657 result = runCommand(cmd); 1658 if (result != 0) { 1659 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd); 1660 break; 1661 } 1662 1663 uprv_strcat(buffer, " "); 1664 uprv_strcat(buffer, tempObjectFile); 1665 1666 #endif 1667 1668 if (i > 0) { 1669 list = list->next; 1670 listNames = listNames->next; 1671 } 1672 } 1673 1674 #ifdef USE_SINGLE_CCODE_FILE 1675 T_FileStream_close(icudtAllFile); 1676 uprv_strcpy(tempObjectFile, icudtAll); 1677 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1678 1679 sprintf(cmd, "%s %s -I. -o %s %s", 1680 pkgDataFlags[COMPILER], 1681 pkgDataFlags[LIBFLAGS], 1682 tempObjectFile, 1683 icudtAll); 1684 1685 result = runCommand(cmd); 1686 if (result == 0) { 1687 uprv_strcat(buffer, " "); 1688 uprv_strcat(buffer, tempObjectFile); 1689 } else { 1690 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd); 1691 } 1692 #endif 1693 1694 if (result == 0) { 1695 /* Generate the library file. */ 1696 #if U_PLATFORM == U_PF_OS390 1697 result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd, (o->pdsbuild && IN_DLL_MODE(mode))); 1698 #else 1699 result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd); 1700 #endif 1701 } 1702 1703 uprv_free(buffer); 1704 uprv_free(cmd); 1705 1706 return result; 1707 } 1708 #endif 1709 1710 #ifdef WINDOWS_WITH_MSVC 1711 #define LINK_CMD "link.exe /nologo /release /out:" 1712 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:" 1713 #define LIB_CMD "LIB.exe /nologo /out:" 1714 #define LIB_FILE "icudt.lib" 1715 #define LIB_EXT UDATA_LIB_SUFFIX 1716 #define DLL_EXT UDATA_SO_SUFFIX 1717 1718 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) { 1719 int32_t result = 0; 1720 char cmd[LARGE_BUFFER_MAX_SIZE]; 1721 if (IN_STATIC_MODE(mode)) { 1722 char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1723 1724 #ifdef CYGWINMSVC 1725 sprintf(staticLibFilePath, "%s%s%s%s%s", 1726 o->targetDir, 1727 PKGDATA_FILE_SEP_STRING, 1728 pkgDataFlags[LIBPREFIX], 1729 o->libName, 1730 LIB_EXT); 1731 #else 1732 sprintf(staticLibFilePath, "%s%s%s%s%s", 1733 o->targetDir, 1734 PKGDATA_FILE_SEP_STRING, 1735 (strstr(o->libName, "icudt") ? "s" : ""), 1736 o->libName, 1737 LIB_EXT); 1738 #endif 1739 1740 sprintf(cmd, "%s\"%s\" \"%s\"", 1741 LIB_CMD, 1742 staticLibFilePath, 1743 gencFilePath); 1744 } else if (IN_DLL_MODE(mode)) { 1745 char dllFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1746 char libFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1747 char resFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1748 char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1749 1750 #ifdef CYGWINMSVC 1751 uprv_strcpy(dllFilePath, o->targetDir); 1752 #else 1753 uprv_strcpy(dllFilePath, o->srcDir); 1754 #endif 1755 uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING); 1756 uprv_strcpy(libFilePath, dllFilePath); 1757 1758 #ifdef CYGWINMSVC 1759 uprv_strcat(libFilePath, o->libName); 1760 uprv_strcat(libFilePath, ".lib"); 1761 1762 uprv_strcat(dllFilePath, o->libName); 1763 uprv_strcat(dllFilePath, o->version); 1764 #else 1765 if (strstr(o->libName, "icudt")) { 1766 uprv_strcat(libFilePath, LIB_FILE); 1767 } else { 1768 uprv_strcat(libFilePath, o->libName); 1769 uprv_strcat(libFilePath, ".lib"); 1770 } 1771 uprv_strcat(dllFilePath, o->entryName); 1772 #endif 1773 uprv_strcat(dllFilePath, DLL_EXT); 1774 1775 uprv_strcpy(tmpResFilePath, o->tmpDir); 1776 uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING); 1777 uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE); 1778 1779 if (T_FileStream_file_exists(tmpResFilePath)) { 1780 sprintf(resFilePath, "\"%s\"", tmpResFilePath); 1781 } 1782 1783 /* Check if dll file and lib file exists and that it is not newer than genc file. */ 1784 if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) && 1785 (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) { 1786 if(o->verbose) { 1787 printf("# Not rebuilding %s - up to date.\n", gencFilePath); 1788 } 1789 return 0; 1790 } 1791 1792 sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" %s", 1793 LINK_CMD, 1794 dllFilePath, 1795 LINK_FLAGS, 1796 libFilePath, 1797 gencFilePath, 1798 resFilePath 1799 ); 1800 } 1801 1802 result = runCommand(cmd, TRUE); 1803 if (result != 0) { 1804 fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd); 1805 } 1806 1807 return result; 1808 } 1809 #endif 1810 1811 static UPKGOptions *pkg_checkFlag(UPKGOptions *o) { 1812 #if U_PLATFORM == U_PF_AIX 1813 /* AIX needs a map file. */ 1814 char *flag = NULL; 1815 int32_t length = 0; 1816 char tmpbuffer[SMALL_BUFFER_MAX_SIZE]; 1817 const char MAP_FILE_EXT[] = ".map"; 1818 FileStream *f = NULL; 1819 char mapFile[SMALL_BUFFER_MAX_SIZE] = ""; 1820 int32_t start = -1; 1821 uint32_t count = 0; 1822 const char rm_cmd[] = "rm -f all ;"; 1823 1824 flag = pkgDataFlags[GENLIB]; 1825 1826 /* This portion of the code removes 'rm -f all' in the GENLIB. 1827 * Only occurs in AIX. 1828 */ 1829 if (uprv_strstr(flag, rm_cmd) != NULL) { 1830 char *tmpGenlibFlagBuffer = NULL; 1831 int32_t i, offset; 1832 1833 length = uprv_strlen(flag) + 1; 1834 tmpGenlibFlagBuffer = (char *)uprv_malloc(length); 1835 if (tmpGenlibFlagBuffer == NULL) { 1836 /* Memory allocation error */ 1837 fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length); 1838 return NULL; 1839 } 1840 1841 uprv_strcpy(tmpGenlibFlagBuffer, flag); 1842 1843 offset = uprv_strlen(rm_cmd); 1844 1845 for (i = 0; i < (length - offset); i++) { 1846 flag[i] = tmpGenlibFlagBuffer[offset + i]; 1847 } 1848 1849 /* Zero terminate the string */ 1850 flag[i] = 0; 1851 1852 uprv_free(tmpGenlibFlagBuffer); 1853 } 1854 1855 flag = pkgDataFlags[BIR_FLAGS]; 1856 length = uprv_strlen(pkgDataFlags[BIR_FLAGS]); 1857 1858 for (int32_t i = 0; i < length; i++) { 1859 if (flag[i] == MAP_FILE_EXT[count]) { 1860 if (count == 0) { 1861 start = i; 1862 } 1863 count++; 1864 } else { 1865 count = 0; 1866 } 1867 1868 if (count == uprv_strlen(MAP_FILE_EXT)) { 1869 break; 1870 } 1871 } 1872 1873 if (start >= 0) { 1874 int32_t index = 0; 1875 for (int32_t i = 0;;i++) { 1876 if (i == start) { 1877 for (int32_t n = 0;;n++) { 1878 if (o->shortName[n] == 0) { 1879 break; 1880 } 1881 tmpbuffer[index++] = o->shortName[n]; 1882 } 1883 } 1884 1885 tmpbuffer[index++] = flag[i]; 1886 1887 if (flag[i] == 0) { 1888 break; 1889 } 1890 } 1891 1892 uprv_memset(flag, 0, length); 1893 uprv_strcpy(flag, tmpbuffer); 1894 1895 uprv_strcpy(mapFile, o->shortName); 1896 uprv_strcat(mapFile, MAP_FILE_EXT); 1897 1898 f = T_FileStream_open(mapFile, "w"); 1899 if (f == NULL) { 1900 fprintf(stderr,"Unable to create map file: %s.\n", mapFile); 1901 return NULL; 1902 } else { 1903 sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX); 1904 1905 T_FileStream_writeLine(f, tmpbuffer); 1906 1907 T_FileStream_close(f); 1908 } 1909 } 1910 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW 1911 /* Cygwin needs to change flag options. */ 1912 char *flag = NULL; 1913 int32_t length = 0; 1914 1915 flag = pkgDataFlags[GENLIB]; 1916 length = uprv_strlen(pkgDataFlags[GENLIB]); 1917 1918 int32_t position = length - 1; 1919 1920 for(;position >= 0;position--) { 1921 if (flag[position] == '=') { 1922 position++; 1923 break; 1924 } 1925 } 1926 1927 uprv_memset(flag + position, 0, length - position); 1928 #elif U_PLATFORM == U_PF_OS400 1929 /* OS/400 needs to fix the ld options (swap single quote with double quote) */ 1930 char *flag = NULL; 1931 int32_t length = 0; 1932 1933 flag = pkgDataFlags[GENLIB]; 1934 length = uprv_strlen(pkgDataFlags[GENLIB]); 1935 1936 int32_t position = length - 1; 1937 1938 for(int32_t i = 0; i < length; i++) { 1939 if (flag[i] == '\'') { 1940 flag[i] = '\"'; 1941 } 1942 } 1943 #endif 1944 // Don't really need a return value, just need to stop compiler warnings about 1945 // the unused parameter 'o' on platforms where it is not otherwise used. 1946 return o; 1947 } 1948 1949 static void loadLists(UPKGOptions *o, UErrorCode *status) 1950 { 1951 CharList *l, *tail = NULL, *tail2 = NULL; 1952 FileStream *in; 1953 char line[16384]; 1954 char *linePtr, *lineNext; 1955 const uint32_t lineMax = 16300; 1956 char *tmp; 1957 int32_t tmpLength = 0; 1958 char *s; 1959 int32_t ln=0; /* line number */ 1960 1961 for(l = o->fileListFiles; l; l = l->next) { 1962 if(o->verbose) { 1963 fprintf(stdout, "# pkgdata: Reading %s..\n", l->str); 1964 } 1965 /* TODO: stdin */ 1966 in = T_FileStream_open(l->str, "r"); /* open files list */ 1967 1968 if(!in) { 1969 fprintf(stderr, "Error opening <%s>.\n", l->str); 1970 *status = U_FILE_ACCESS_ERROR; 1971 return; 1972 } 1973 1974 while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */ 1975 ln++; 1976 if(uprv_strlen(line)>lineMax) { 1977 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax); 1978 exit(1); 1979 } 1980 /* remove spaces at the beginning */ 1981 linePtr = line; 1982 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */ 1983 #if U_PLATFORM != U_PF_OS390 1984 while(isspace(*linePtr)) { 1985 linePtr++; 1986 } 1987 #endif 1988 s=linePtr; 1989 /* remove trailing newline characters */ 1990 while(*s!=0) { 1991 if(*s=='\r' || *s=='\n') { 1992 *s=0; 1993 break; 1994 } 1995 ++s; 1996 } 1997 if((*linePtr == 0) || (*linePtr == '#')) { 1998 continue; /* comment or empty line */ 1999 } 2000 2001 /* Now, process the line */ 2002 lineNext = NULL; 2003 2004 while(linePtr && *linePtr) { /* process space-separated items */ 2005 while(*linePtr == ' ') { 2006 linePtr++; 2007 } 2008 /* Find the next quote */ 2009 if(linePtr[0] == '"') 2010 { 2011 lineNext = uprv_strchr(linePtr+1, '"'); 2012 if(lineNext == NULL) { 2013 fprintf(stderr, "%s:%d - missing trailing double quote (\")\n", 2014 l->str, (int)ln); 2015 exit(1); 2016 } else { 2017 lineNext++; 2018 if(*lineNext) { 2019 if(*lineNext != ' ') { 2020 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n", 2021 l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0'); 2022 exit(1); 2023 } 2024 *lineNext = 0; 2025 lineNext++; 2026 } 2027 } 2028 } else { 2029 lineNext = uprv_strchr(linePtr, ' '); 2030 if(lineNext) { 2031 *lineNext = 0; /* terminate at space */ 2032 lineNext++; 2033 } 2034 } 2035 2036 /* add the file */ 2037 s = (char*)getLongPathname(linePtr); 2038 2039 /* normal mode.. o->files is just the bare list without package names */ 2040 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr)); 2041 if(uprv_pathIsAbsolute(s) || s[0] == '.') { 2042 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); 2043 exit(U_ILLEGAL_ARGUMENT_ERROR); 2044 } 2045 tmpLength = uprv_strlen(o->srcDir) + 2046 uprv_strlen(s) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */ 2047 if((tmp = (char *)uprv_malloc(tmpLength)) == NULL) { 2048 fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength); 2049 exit(U_MEMORY_ALLOCATION_ERROR); 2050 } 2051 uprv_strcpy(tmp, o->srcDir); 2052 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING); 2053 uprv_strcat(tmp, s); 2054 o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp); 2055 linePtr = lineNext; 2056 } /* for each entry on line */ 2057 } /* for each line */ 2058 T_FileStream_close(in); 2059 } /* for each file list file */ 2060 } 2061 2062 /* Try calling icu-config directly to get the option file. */ 2063 static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) { 2064 #if U_HAVE_POPEN 2065 FILE *p = NULL; 2066 size_t n; 2067 static char buf[512] = ""; 2068 char cmdBuf[1024]; 2069 UErrorCode status = U_ZERO_ERROR; 2070 const char cmd[] = "icu-config --incpkgdatafile"; 2071 2072 /* #1 try the same path where pkgdata was called from. */ 2073 findDirname(progname, cmdBuf, 1024, &status); 2074 if(U_SUCCESS(status)) { 2075 if (cmdBuf[0] != 0) { 2076 uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024); 2077 } 2078 uprv_strncat(cmdBuf, cmd, 1023); 2079 2080 if(verbose) { 2081 fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf); 2082 } 2083 p = popen(cmdBuf, "r"); 2084 } 2085 2086 if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) { 2087 if(verbose) { 2088 fprintf(stdout, "# Calling icu-config: %s\n", cmd); 2089 } 2090 pclose(p); 2091 2092 p = popen(cmd, "r"); 2093 if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) { 2094 fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname); 2095 return -1; 2096 } 2097 } 2098 2099 pclose(p); 2100 2101 for (int32_t length = strlen(buf) - 1; length >= 0; length--) { 2102 if (buf[length] == '\n' || buf[length] == ' ') { 2103 buf[length] = 0; 2104 } else { 2105 break; 2106 } 2107 } 2108 2109 if(buf[strlen(buf)-1]=='\n') 2110 { 2111 buf[strlen(buf)-1]=0; 2112 } 2113 2114 if(buf[0] == 0) 2115 { 2116 fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname); 2117 return -1; 2118 } 2119 2120 if(verbose) { 2121 fprintf(stdout, "# icu-config said: %s\n", buf); 2122 } 2123 2124 option->value = buf; 2125 option->doesOccur = TRUE; 2126 2127 return 0; 2128 #else 2129 return -1; 2130 #endif 2131 } 2132