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 54U_CDECL_BEGIN 55#include "pkgtypes.h" 56U_CDECL_END 57 58 59static void loadLists(UPKGOptions *o, UErrorCode *status); 60 61static int32_t pkg_executeOptions(UPKGOptions *o); 62 63#ifdef WINDOWS_WITH_MSVC 64static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o); 65#endif 66static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE); 67static int32_t pkg_installLibrary(const char *installDir, const char *dir, UBool noVersion); 68static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName); 69static int32_t pkg_installCommonMode(const char *installDir, const char *fileName); 70 71#ifdef BUILD_DATA_WITHOUT_ASSEMBLY 72static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode); 73#endif 74 75static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath); 76static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL, UBool specialHandling=FALSE); 77static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt); 78static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion); 79static int32_t initializePkgDataFlags(UPKGOptions *o); 80 81static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option); 82static 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 89enum { 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 */ 113static 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 131static 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. */ 155enum { 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}; 175static 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}; 194static char **pkgDataFlags = NULL; 195 196enum { 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}; 212static char libFileNames[LIB_FILENAMES_SIZE][256]; 213 214static UPKGOptions *pkg_checkFlag(UPKGOptions *o); 215 216const 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 243const char *progname = "PKGDATA"; 244 245int 246main(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 490static 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) 517normal_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 538static 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 writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath); 733#if U_PLATFORM_IS_LINUX_BASED 734 result = pkg_generateLibraryFile(targetDir, mode, gencFilePath); 735#elif defined(WINDOWS_WITH_MSVC) 736 result = pkg_createWindowsDLL(mode, gencFilePath, o); 737#endif 738#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY) 739 result = pkg_createWithoutAssemblyCode(o, targetDir, mode); 740#else 741 fprintf(stderr, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n"); 742 return 1; 743#endif 744 } 745 746 if (result != 0) { 747 fprintf(stderr, "Error generating package data.\n"); 748 return result; 749 } 750 } 751#if !U_PLATFORM_USES_ONLY_WIN32_API 752 if(!IN_STATIC_MODE(mode)) { 753 /* Certain platforms uses archive library. (e.g. AIX) */ 754 if(o->verbose) { 755 fprintf(stdout, "# Creating data archive library file ..\n"); 756 } 757 result = pkg_archiveLibrary(targetDir, o->version, reverseExt); 758 if (result != 0) { 759 fprintf(stderr, "Error creating data archive library file.\n"); 760 return result; 761 } 762#if U_PLATFORM != U_PF_OS400 763 if (!noVersion) { 764 /* Create symbolic links for the final library file. */ 765#if U_PLATFORM == U_PF_OS390 766 result = pkg_createSymLinks(targetDir, o->pdsbuild); 767#else 768 result = pkg_createSymLinks(targetDir, noVersion); 769#endif 770 if (result != 0) { 771 fprintf(stderr, "Error creating symbolic links of the data library file.\n"); 772 return result; 773 } 774 } 775#endif 776 } /* !IN_STATIC_MODE */ 777#endif 778 779#if !U_PLATFORM_USES_ONLY_WIN32_API 780 /* Install the libraries if option was set. */ 781 if (o->install != NULL) { 782 if(o->verbose) { 783 fprintf(stdout, "# Installing library file to %s ..\n", o->install); 784 } 785 result = pkg_installLibrary(o->install, targetDir, noVersion); 786 if (result != 0) { 787 fprintf(stderr, "Error installing the data library.\n"); 788 return result; 789 } 790 } 791#endif 792 } 793 } 794 return result; 795} 796 797/* Initialize the pkgDataFlags with the option file given. */ 798static int32_t initializePkgDataFlags(UPKGOptions *o) { 799 UErrorCode status = U_ZERO_ERROR; 800 int32_t result = 0; 801 int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE; 802 int32_t tmpResult = 0; 803 804 /* Initialize pkgdataFlags */ 805 pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE); 806 807 /* If we run out of space, allocate more */ 808#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 809 do { 810#endif 811 if (pkgDataFlags != NULL) { 812 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { 813 pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize); 814 if (pkgDataFlags[i] != NULL) { 815 pkgDataFlags[i][0] = 0; 816 } else { 817 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); 818 return -1; 819 } 820 } 821 } else { 822 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); 823 return -1; 824 } 825 826 if (o->options == NULL) { 827 return result; 828 } 829 830#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 831 /* Read in options file. */ 832 if(o->verbose) { 833 fprintf(stdout, "# Reading options file %s\n", o->options); 834 } 835 status = U_ZERO_ERROR; 836 tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, FLAG_NAMES, (int32_t)PKGDATA_FLAGS_SIZE, &status); 837 if (status == U_BUFFER_OVERFLOW_ERROR) { 838 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { 839 uprv_free(pkgDataFlags[i]); 840 } 841 currentBufferSize = tmpResult; 842 } else if (U_FAILURE(status)) { 843 fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status)); 844 return -1; 845 } 846#endif 847 if(o->verbose) { 848 fprintf(stdout, "# pkgDataFlags=\n"); 849 for(int32_t i=0;i<PKGDATA_FLAGS_SIZE;i++) { 850 fprintf(stdout, " [%d] %s: %s\n", i, FLAG_NAMES[i], pkgDataFlags[i]); 851 } 852 fprintf(stdout, "\n"); 853 } 854#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) 855 } while (status == U_BUFFER_OVERFLOW_ERROR); 856#endif 857 858 return result; 859} 860 861 862/* 863 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames. 864 * Depending on the configuration, the library name may either end with version number or shared object suffix. 865 */ 866static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt, UBool noVersion) { 867#if U_PLATFORM == U_PF_MINGW 868 /* MinGW does not need the library prefix when building in dll mode. */ 869 if (IN_DLL_MODE(mode)) { 870 sprintf(libFileNames[LIB_FILE], "%s", libName); 871 } else { 872 sprintf(libFileNames[LIB_FILE], "%s%s", 873 pkgDataFlags[LIBPREFIX], 874 libName); 875 } 876#else 877 sprintf(libFileNames[LIB_FILE], "%s%s", 878 pkgDataFlags[LIBPREFIX], 879 libName); 880#endif 881 882 if(o->verbose) { 883 fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]); 884 } 885 886#if U_PLATFORM == U_PF_MINGW 887 sprintf(libFileNames[LIB_FILE_MINGW], "%s%s.lib", pkgDataFlags[LIBPREFIX], libName); 888#elif U_PLATFORM == U_PF_CYGWIN 889 sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s.%s", 890 libName, 891 pkgDataFlags[SO_EXT]); 892 sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s.%s", 893 libName, 894 version_major, 895 pkgDataFlags[SO_EXT]); 896 897 uprv_strcat(pkgDataFlags[SO_EXT], "."); 898 uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]); 899#elif U_PLATFORM == U_PF_OS400 || defined(_AIX) 900 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s", 901 libFileNames[LIB_FILE], 902 pkgDataFlags[SOBJ_EXT]); 903#elif U_PLATFORM == U_PF_OS390 904 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s", 905 libFileNames[LIB_FILE], 906 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 907 reverseExt ? version : pkgDataFlags[SOBJ_EXT], 908 reverseExt ? pkgDataFlags[SOBJ_EXT] : version); 909 910 sprintf(libFileNames[LIB_FILE_OS390BATCH_VERSION], "%s%s.x", 911 libFileNames[LIB_FILE], 912 version); 913 sprintf(libFileNames[LIB_FILE_OS390BATCH_MAJOR], "%s%s.x", 914 libFileNames[LIB_FILE], 915 version_major); 916#else 917 if (noVersion && !reverseExt) { 918 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s", 919 libFileNames[LIB_FILE], 920 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 921 pkgDataFlags[SOBJ_EXT]); 922 } else { 923 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s", 924 libFileNames[LIB_FILE], 925 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 926 reverseExt ? version : pkgDataFlags[SOBJ_EXT], 927 reverseExt ? pkgDataFlags[SOBJ_EXT] : version); 928 } 929#endif 930 if (noVersion && !reverseExt) { 931 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s", 932 libFileNames[LIB_FILE], 933 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 934 pkgDataFlags[SO_EXT]); 935 936 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s", 937 libFileNames[LIB_FILE], 938 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 939 pkgDataFlags[SO_EXT]); 940 } else { 941 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s", 942 libFileNames[LIB_FILE], 943 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 944 reverseExt ? version_major : pkgDataFlags[SO_EXT], 945 reverseExt ? pkgDataFlags[SO_EXT] : version_major); 946 947 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s", 948 libFileNames[LIB_FILE], 949 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 950 reverseExt ? version : pkgDataFlags[SO_EXT], 951 reverseExt ? pkgDataFlags[SO_EXT] : version); 952 } 953 954 if(o->verbose) { 955 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]); 956 } 957 958#if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN 959 /* Cygwin and MinGW only deals with the version major number. */ 960 uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]); 961#endif 962 963 if(IN_STATIC_MODE(mode)) { 964 sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]); 965 libFileNames[LIB_FILE_VERSION_MAJOR][0]=0; 966 if(o->verbose) { 967 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames[LIB_FILE_VERSION]); 968 } 969 } 970} 971 972/* Create the symbolic links for the final library file. */ 973static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) { 974 int32_t result = 0; 975 char cmd[LARGE_BUFFER_MAX_SIZE]; 976 char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */ 977 char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */ 978 979#if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW 980 /* No symbolic link to make. */ 981 if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 || 982 uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) { 983 return result; 984 } 985 986 sprintf(cmd, "cd %s && %s %s && %s %s %s", 987 targetDir, 988 RM_CMD, 989 libFileNames[LIB_FILE_VERSION_MAJOR], 990 LN_CMD, 991 libFileNames[LIB_FILE_VERSION], 992 libFileNames[LIB_FILE_VERSION_MAJOR]); 993 result = runCommand(cmd); 994 if (result != 0) { 995 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd); 996 return result; 997 } 998#endif 999 1000 if (specialHandling) { 1001#if U_PLATFORM == U_PF_CYGWIN 1002 sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]); 1003 sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]); 1004#elif U_PLATFORM == U_PF_OS390 1005 /* Create the symbolic links for the import data */ 1006 /* Use the cmd buffer to store path to import data file to check its existence */ 1007 sprintf(cmd, "%s/%s", targetDir, libFileNames[LIB_FILE_OS390BATCH_VERSION]); 1008 if (T_FileStream_file_exists(cmd)) { 1009 sprintf(cmd, "cd %s && %s %s && %s %s %s", 1010 targetDir, 1011 RM_CMD, 1012 libFileNames[LIB_FILE_OS390BATCH_MAJOR], 1013 LN_CMD, 1014 libFileNames[LIB_FILE_OS390BATCH_VERSION], 1015 libFileNames[LIB_FILE_OS390BATCH_MAJOR]); 1016 result = runCommand(cmd); 1017 if (result != 0) { 1018 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd); 1019 return result; 1020 } 1021 1022 sprintf(cmd, "cd %s && %s %s.x && %s %s %s.x", 1023 targetDir, 1024 RM_CMD, 1025 libFileNames[LIB_FILE], 1026 LN_CMD, 1027 libFileNames[LIB_FILE_OS390BATCH_VERSION], 1028 libFileNames[LIB_FILE]); 1029 result = runCommand(cmd); 1030 if (result != 0) { 1031 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd); 1032 return result; 1033 } 1034 } 1035 1036 /* Needs to be set here because special handling skips it */ 1037 sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]); 1038 sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]); 1039#else 1040 goto normal_symlink_mode; 1041#endif 1042 } else { 1043#if U_PLATFORM != U_PF_CYGWIN 1044normal_symlink_mode: 1045#endif 1046 sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]); 1047 sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]); 1048 } 1049 1050 sprintf(cmd, "cd %s && %s %s && %s %s %s", 1051 targetDir, 1052 RM_CMD, 1053 name1, 1054 LN_CMD, 1055 name2, 1056 name1); 1057 1058 result = runCommand(cmd); 1059 1060 return result; 1061} 1062 1063static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, UBool noVersion) { 1064 int32_t result = 0; 1065 char cmd[SMALL_BUFFER_MAX_SIZE]; 1066 1067 sprintf(cmd, "cd %s && %s %s %s%s%s", 1068 targetDir, 1069 pkgDataFlags[INSTALL_CMD], 1070 libFileNames[LIB_FILE_VERSION], 1071 installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION] 1072 ); 1073 1074 result = runCommand(cmd); 1075 1076 if (result != 0) { 1077 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1078 return result; 1079 } 1080 1081#ifdef CYGWINMSVC 1082 sprintf(cmd, "cd %s && %s %s.lib %s", 1083 targetDir, 1084 pkgDataFlags[INSTALL_CMD], 1085 libFileNames[LIB_FILE], 1086 installDir 1087 ); 1088 result = runCommand(cmd); 1089 1090 if (result != 0) { 1091 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1092 return result; 1093 } 1094#elif U_PLATFORM == U_PF_CYGWIN 1095 sprintf(cmd, "cd %s && %s %s %s", 1096 targetDir, 1097 pkgDataFlags[INSTALL_CMD], 1098 libFileNames[LIB_FILE_CYGWIN_VERSION], 1099 installDir 1100 ); 1101 result = runCommand(cmd); 1102 1103 if (result != 0) { 1104 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1105 return result; 1106 } 1107 1108#elif U_PLATFORM == U_PF_OS390 1109 if (T_FileStream_file_exists(libFileNames[LIB_FILE_OS390BATCH_VERSION])) { 1110 sprintf(cmd, "%s %s %s", 1111 pkgDataFlags[INSTALL_CMD], 1112 libFileNames[LIB_FILE_OS390BATCH_VERSION], 1113 installDir 1114 ); 1115 result = runCommand(cmd); 1116 1117 if (result != 0) { 1118 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd); 1119 return result; 1120 } 1121 } 1122#endif 1123 1124 if (noVersion) { 1125 return result; 1126 } else { 1127 return pkg_createSymLinks(installDir, TRUE); 1128 } 1129} 1130 1131static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) { 1132 int32_t result = 0; 1133 char cmd[SMALL_BUFFER_MAX_SIZE] = ""; 1134 1135 if (!T_FileStream_file_exists(installDir)) { 1136 UErrorCode status = U_ZERO_ERROR; 1137 1138 uprv_mkdir(installDir, &status); 1139 if (U_FAILURE(status)) { 1140 fprintf(stderr, "Error creating installation directory: %s\n", installDir); 1141 return -1; 1142 } 1143 } 1144#ifndef U_WINDOWS_WITH_MSVC 1145 sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir); 1146#else 1147 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS); 1148#endif 1149 1150 result = runCommand(cmd); 1151 if (result != 0) { 1152 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 1153 } 1154 1155 return result; 1156} 1157 1158#ifdef U_WINDOWS_MSVC 1159/* Copy commands for installing the raw data files on Windows. */ 1160#define WIN_INSTALL_CMD "xcopy" 1161#define WIN_INSTALL_CMD_FLAGS "/E /Y /K" 1162#endif 1163static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) { 1164 int32_t result = 0; 1165 char cmd[SMALL_BUFFER_MAX_SIZE] = ""; 1166 1167 if (!T_FileStream_file_exists(installDir)) { 1168 UErrorCode status = U_ZERO_ERROR; 1169 1170 uprv_mkdir(installDir, &status); 1171 if (U_FAILURE(status)) { 1172 fprintf(stderr, "Error creating installation directory: %s\n", installDir); 1173 return -1; 1174 } 1175 } 1176#ifndef U_WINDOWS_WITH_MSVC 1177 char buffer[SMALL_BUFFER_MAX_SIZE] = ""; 1178 int32_t bufferLength = 0; 1179 1180 FileStream *f = T_FileStream_open(fileListName, "r"); 1181 if (f != NULL) { 1182 for(;;) { 1183 if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) { 1184 bufferLength = uprv_strlen(buffer); 1185 /* Remove new line character. */ 1186 if (bufferLength > 0) { 1187 buffer[bufferLength-1] = 0; 1188 } 1189 1190 sprintf(cmd, "%s %s%s%s %s%s%s", 1191 pkgDataFlags[INSTALL_CMD], 1192 srcDir, PKGDATA_FILE_SEP_STRING, buffer, 1193 installDir, PKGDATA_FILE_SEP_STRING, buffer); 1194 1195 result = runCommand(cmd); 1196 if (result != 0) { 1197 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 1198 break; 1199 } 1200 } else { 1201 if (!T_FileStream_eof(f)) { 1202 fprintf(stderr, "Failed to read line from file: %s\n", fileListName); 1203 result = -1; 1204 } 1205 break; 1206 } 1207 } 1208 T_FileStream_close(f); 1209 } else { 1210 result = -1; 1211 fprintf(stderr, "Unable to open list file: %s\n", fileListName); 1212 } 1213#else 1214 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS); 1215 result = runCommand(cmd); 1216 if (result != 0) { 1217 fprintf(stderr, "Failed to install data file with command: %s\n", cmd); 1218 } 1219#endif 1220 1221 return result; 1222} 1223 1224/* Archiving of the library file may be needed depending on the platform and options given. 1225 * If archiving is not needed, copy over the library file name. 1226 */ 1227static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) { 1228 int32_t result = 0; 1229 char cmd[LARGE_BUFFER_MAX_SIZE]; 1230 1231 /* If the shared object suffix and the final object suffix is different and the final object suffix and the 1232 * archive file suffix is the same, then the final library needs to be archived. 1233 */ 1234 if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) { 1235 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s", 1236 libFileNames[LIB_FILE], 1237 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "", 1238 reverseExt ? version : pkgDataFlags[SO_EXT], 1239 reverseExt ? pkgDataFlags[SO_EXT] : version); 1240 1241 sprintf(cmd, "%s %s %s%s %s%s", 1242 pkgDataFlags[AR], 1243 pkgDataFlags[ARFLAGS], 1244 targetDir, 1245 libFileNames[LIB_FILE_VERSION], 1246 targetDir, 1247 libFileNames[LIB_FILE_VERSION_TMP]); 1248 1249 result = runCommand(cmd); 1250 if (result != 0) { 1251 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd); 1252 return result; 1253 } 1254 1255 sprintf(cmd, "%s %s%s", 1256 pkgDataFlags[RANLIB], 1257 targetDir, 1258 libFileNames[LIB_FILE_VERSION]); 1259 1260 result = runCommand(cmd); 1261 if (result != 0) { 1262 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd); 1263 return result; 1264 } 1265 1266 /* Remove unneeded library file. */ 1267 sprintf(cmd, "%s %s%s", 1268 RM_CMD, 1269 targetDir, 1270 libFileNames[LIB_FILE_VERSION_TMP]); 1271 1272 result = runCommand(cmd); 1273 if (result != 0) { 1274 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd); 1275 return result; 1276 } 1277 1278 } else { 1279 uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]); 1280 } 1281 1282 return result; 1283} 1284 1285/* 1286 * Using the compiler information from the configuration file set by -O option, generate the library file. 1287 * command may be given to allow for a larger buffer for cmd. 1288 */ 1289static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command, UBool specialHandling) { 1290 int32_t result = 0; 1291 char *cmd = NULL; 1292 UBool freeCmd = FALSE; 1293 int32_t length = 0; 1294 1295 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large 1296 * containing many object files and so the calling function should supply a command buffer that is large 1297 * enough to handle this. Otherwise, use the default size. 1298 */ 1299 if (command != NULL) { 1300 cmd = command; 1301 } 1302 1303 if (IN_STATIC_MODE(mode)) { 1304 if (cmd == NULL) { 1305 length = uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) + 1306 uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE; 1307 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) { 1308 fprintf(stderr, "Unable to allocate memory for command.\n"); 1309 return -1; 1310 } 1311 freeCmd = TRUE; 1312 } 1313 sprintf(cmd, "%s %s %s%s %s", 1314 pkgDataFlags[AR], 1315 pkgDataFlags[ARFLAGS], 1316 targetDir, 1317 libFileNames[LIB_FILE_VERSION], 1318 objectFile); 1319 1320 result = runCommand(cmd); 1321 if (result == 0) { 1322 sprintf(cmd, "%s %s%s", 1323 pkgDataFlags[RANLIB], 1324 targetDir, 1325 libFileNames[LIB_FILE_VERSION]); 1326 1327 result = runCommand(cmd); 1328 } 1329 } else /* if (IN_DLL_MODE(mode)) */ { 1330 if (cmd == NULL) { 1331 length = uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) + 1332 ((uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP])) * 2) + 1333 uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) + 1334 uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) + 1335 uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE; 1336#if U_PLATFORM == U_PF_CYGWIN 1337 length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]); 1338#elif U_PLATFORM == U_PF_MINGW 1339 length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_MINGW]); 1340#endif 1341 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) { 1342 fprintf(stderr, "Unable to allocate memory for command.\n"); 1343 return -1; 1344 } 1345 freeCmd = TRUE; 1346 } 1347#if U_PLATFORM == U_PF_MINGW 1348 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s", 1349 pkgDataFlags[GENLIB], 1350 targetDir, 1351 libFileNames[LIB_FILE_MINGW], 1352 pkgDataFlags[LDICUDTFLAGS], 1353 targetDir, 1354 libFileNames[LIB_FILE_VERSION_TMP], 1355#elif U_PLATFORM == U_PF_CYGWIN 1356 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s", 1357 pkgDataFlags[GENLIB], 1358 targetDir, 1359 libFileNames[LIB_FILE_VERSION_TMP], 1360 pkgDataFlags[LDICUDTFLAGS], 1361 targetDir, 1362 libFileNames[LIB_FILE_CYGWIN_VERSION], 1363#elif U_PLATFORM == U_PF_AIX 1364 sprintf(cmd, "%s %s%s;%s %s -o %s%s %s %s%s %s %s", 1365 RM_CMD, 1366 targetDir, 1367 libFileNames[LIB_FILE_VERSION_TMP], 1368 pkgDataFlags[GENLIB], 1369 pkgDataFlags[LDICUDTFLAGS], 1370 targetDir, 1371 libFileNames[LIB_FILE_VERSION_TMP], 1372#else 1373 sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s", 1374 pkgDataFlags[GENLIB], 1375 pkgDataFlags[LDICUDTFLAGS], 1376 targetDir, 1377 libFileNames[LIB_FILE_VERSION_TMP], 1378#endif 1379 objectFile, 1380 pkgDataFlags[LD_SONAME], 1381 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR], 1382 pkgDataFlags[RPATH_FLAGS], 1383 pkgDataFlags[BIR_FLAGS]); 1384 1385 /* Generate the library file. */ 1386 result = runCommand(cmd); 1387 1388#if U_PLATFORM == U_PF_OS390 1389 char *env_tmp; 1390 char PDS_LibName[512]; 1391 char PDS_Name[512]; 1392 1393 PDS_Name[0] = 0; 1394 PDS_LibName[0] = 0; 1395 if (specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) { 1396 if (env_tmp = getenv("ICU_PDS_NAME")) { 1397 sprintf(PDS_Name, "%s%s", 1398 env_tmp, 1399 "DA"); 1400 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX")); 1401 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) { 1402 sprintf(PDS_Name, "%s%s", 1403 env_tmp, 1404 U_ICU_VERSION_SHORT "DA"); 1405 } else { 1406 sprintf(PDS_Name, "%s%s", 1407 "IXMI", 1408 U_ICU_VERSION_SHORT "DA"); 1409 } 1410 } else if (!specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) { 1411 if (env_tmp = getenv("ICU_PDS_NAME")) { 1412 sprintf(PDS_Name, "%s%s", 1413 env_tmp, 1414 "D1"); 1415 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX")); 1416 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) { 1417 sprintf(PDS_Name, "%s%s", 1418 env_tmp, 1419 U_ICU_VERSION_SHORT "D1"); 1420 } else { 1421 sprintf(PDS_Name, "%s%s", 1422 "IXMI", 1423 U_ICU_VERSION_SHORT "D1"); 1424 } 1425 } 1426 1427 if (PDS_Name[0]) { 1428 sprintf(PDS_LibName,"%s%s%s%s%s", 1429 "\"//'", 1430 getenv("LOADMOD"), 1431 "(", 1432 PDS_Name, 1433 ")'\""); 1434 sprintf(cmd, "%s %s -o %s %s %s%s %s %s", 1435 pkgDataFlags[GENLIB], 1436 pkgDataFlags[LDICUDTFLAGS], 1437 PDS_LibName, 1438 objectFile, 1439 pkgDataFlags[LD_SONAME], 1440 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR], 1441 pkgDataFlags[RPATH_FLAGS], 1442 pkgDataFlags[BIR_FLAGS]); 1443 1444 result = runCommand(cmd); 1445 } 1446#endif 1447 } 1448 1449 if (result != 0) { 1450 fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd); 1451 } 1452 1453 if (freeCmd) { 1454 uprv_free(cmd); 1455 } 1456 1457 return result; 1458} 1459 1460static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) { 1461 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; 1462 char *cmd; 1463 int32_t result = 0; 1464 1465 int32_t length = 0; 1466 1467 /* Remove the ending .s and replace it with .o for the new object file. */ 1468 uprv_strcpy(tempObjectFile, gencFilePath); 1469 tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o'; 1470 1471 length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS]) 1472 + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE; 1473 1474 cmd = (char *)uprv_malloc(sizeof(char) * length); 1475 if (cmd == NULL) { 1476 return -1; 1477 } 1478 1479 /* Generate the object file. */ 1480 sprintf(cmd, "%s %s -o %s %s", 1481 pkgDataFlags[COMPILER], 1482 pkgDataFlags[LIBFLAGS], 1483 tempObjectFile, 1484 gencFilePath); 1485 1486 result = runCommand(cmd); 1487 uprv_free(cmd); 1488 if (result != 0) { 1489 fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd); 1490 return result; 1491 } 1492 1493 return pkg_generateLibraryFile(targetDir, mode, tempObjectFile); 1494} 1495 1496#ifdef BUILD_DATA_WITHOUT_ASSEMBLY 1497/* 1498 * Generation of the data library without assembly code needs to compile each data file 1499 * individually and then link it all together. 1500 * Note: Any update to the directory structure of the data needs to be reflected here. 1501 */ 1502enum { 1503 DATA_PREFIX_BRKITR, 1504 DATA_PREFIX_COLL, 1505 DATA_PREFIX_CURR, 1506 DATA_PREFIX_LANG, 1507 DATA_PREFIX_RBNF, 1508 DATA_PREFIX_REGION, 1509 DATA_PREFIX_TRANSLIT, 1510 DATA_PREFIX_ZONE, 1511 DATA_PREFIX_LENGTH 1512}; 1513 1514const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = { 1515 "brkitr", 1516 "coll", 1517 "curr", 1518 "lang", 1519 "rbnf", 1520 "region", 1521 "translit", 1522 "zone" 1523}; 1524 1525static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) { 1526 int32_t result = 0; 1527 CharList *list = o->filePaths; 1528 CharList *listNames = o->files; 1529 int32_t listSize = pkg_countCharList(list); 1530 char *buffer; 1531 char *cmd; 1532 char gencmnFile[SMALL_BUFFER_MAX_SIZE] = ""; 1533 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; 1534#ifdef USE_SINGLE_CCODE_FILE 1535 char icudtAll[SMALL_BUFFER_MAX_SIZE] = ""; 1536 FileStream *icudtAllFile = NULL; 1537 1538 sprintf(icudtAll, "%s%s%sall.c", 1539 o->tmpDir, 1540 PKGDATA_FILE_SEP_STRING, 1541 libFileNames[LIB_FILE]); 1542 /* Remove previous icudtall.c file. */ 1543 if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) { 1544 fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll); 1545 return result; 1546 } 1547 1548 if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==NULL) { 1549 fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll); 1550 return result; 1551 } 1552#endif 1553 1554 if (list == NULL || listNames == NULL) { 1555 /* list and listNames should never be NULL since we are looping through the CharList with 1556 * the given size. 1557 */ 1558 return -1; 1559 } 1560 1561 if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) { 1562 fprintf(stderr, "Unable to allocate memory for cmd.\n"); 1563 return -1; 1564 } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) { 1565 fprintf(stderr, "Unable to allocate memory for buffer.\n"); 1566 uprv_free(cmd); 1567 return -1; 1568 } 1569 1570 for (int32_t i = 0; i < (listSize + 1); i++) { 1571 const char *file ; 1572 const char *name; 1573 1574 if (i == 0) { 1575 /* The first iteration calls the gencmn function and initailizes the buffer. */ 1576 createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile); 1577 buffer[0] = 0; 1578#ifdef USE_SINGLE_CCODE_FILE 1579 uprv_strcpy(tempObjectFile, gencmnFile); 1580 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1581 1582 sprintf(cmd, "%s %s -o %s %s", 1583 pkgDataFlags[COMPILER], 1584 pkgDataFlags[LIBFLAGS], 1585 tempObjectFile, 1586 gencmnFile); 1587 1588 result = runCommand(cmd); 1589 if (result != 0) { 1590 break; 1591 } 1592 1593 sprintf(buffer, "%s",tempObjectFile); 1594#endif 1595 } else { 1596 char newName[SMALL_BUFFER_MAX_SIZE]; 1597 char dataName[SMALL_BUFFER_MAX_SIZE]; 1598 char dataDirName[SMALL_BUFFER_MAX_SIZE]; 1599 const char *pSubstring; 1600 file = list->str; 1601 name = listNames->str; 1602 1603 newName[0] = dataName[0] = 0; 1604 for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) { 1605 dataDirName[0] = 0; 1606 sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING); 1607 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */ 1608 pSubstring = uprv_strstr(name, dataDirName); 1609 if (pSubstring != NULL) { 1610 char newNameTmp[SMALL_BUFFER_MAX_SIZE] = ""; 1611 const char *p = name + uprv_strlen(dataDirName); 1612 for (int32_t i = 0;;i++) { 1613 if (p[i] == '.') { 1614 newNameTmp[i] = '_'; 1615 continue; 1616 } 1617 newNameTmp[i] = p[i]; 1618 if (p[i] == 0) { 1619 break; 1620 } 1621 } 1622 sprintf(newName, "%s_%s", 1623 DATA_PREFIX[n], 1624 newNameTmp); 1625 sprintf(dataName, "%s_%s", 1626 o->shortName, 1627 DATA_PREFIX[n]); 1628 } 1629 if (newName[0] != 0) { 1630 break; 1631 } 1632 } 1633 1634 if(o->verbose) { 1635 printf("# Generating %s \n", gencmnFile); 1636 } 1637 1638 writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile); 1639 1640#ifdef USE_SINGLE_CCODE_FILE 1641 sprintf(cmd, "#include \"%s\"\n", gencmnFile); 1642 T_FileStream_writeLine(icudtAllFile, cmd); 1643 /* don't delete the file */ 1644#endif 1645 } 1646 1647#ifndef USE_SINGLE_CCODE_FILE 1648 uprv_strcpy(tempObjectFile, gencmnFile); 1649 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1650 1651 sprintf(cmd, "%s %s -o %s %s", 1652 pkgDataFlags[COMPILER], 1653 pkgDataFlags[LIBFLAGS], 1654 tempObjectFile, 1655 gencmnFile); 1656 result = runCommand(cmd); 1657 if (result != 0) { 1658 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd); 1659 break; 1660 } 1661 1662 uprv_strcat(buffer, " "); 1663 uprv_strcat(buffer, tempObjectFile); 1664 1665#endif 1666 1667 if (i > 0) { 1668 list = list->next; 1669 listNames = listNames->next; 1670 } 1671 } 1672 1673#ifdef USE_SINGLE_CCODE_FILE 1674 T_FileStream_close(icudtAllFile); 1675 uprv_strcpy(tempObjectFile, icudtAll); 1676 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o'; 1677 1678 sprintf(cmd, "%s %s -I. -o %s %s", 1679 pkgDataFlags[COMPILER], 1680 pkgDataFlags[LIBFLAGS], 1681 tempObjectFile, 1682 icudtAll); 1683 1684 result = runCommand(cmd); 1685 if (result == 0) { 1686 uprv_strcat(buffer, " "); 1687 uprv_strcat(buffer, tempObjectFile); 1688 } else { 1689 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd); 1690 } 1691#endif 1692 1693 if (result == 0) { 1694 /* Generate the library file. */ 1695#if U_PLATFORM == U_PF_OS390 1696 result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd, (o->pdsbuild && IN_DLL_MODE(mode))); 1697#else 1698 result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd); 1699#endif 1700 } 1701 1702 uprv_free(buffer); 1703 uprv_free(cmd); 1704 1705 return result; 1706} 1707#endif 1708 1709#ifdef WINDOWS_WITH_MSVC 1710#define LINK_CMD "link.exe /nologo /release /out:" 1711#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:" 1712#define LIB_CMD "LIB.exe /nologo /out:" 1713#define LIB_FILE "icudt.lib" 1714#define LIB_EXT UDATA_LIB_SUFFIX 1715#define DLL_EXT UDATA_SO_SUFFIX 1716 1717static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) { 1718 int32_t result = 0; 1719 char cmd[LARGE_BUFFER_MAX_SIZE]; 1720 if (IN_STATIC_MODE(mode)) { 1721 char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1722 1723#ifdef CYGWINMSVC 1724 sprintf(staticLibFilePath, "%s%s%s%s%s", 1725 o->targetDir, 1726 PKGDATA_FILE_SEP_STRING, 1727 pkgDataFlags[LIBPREFIX], 1728 o->libName, 1729 LIB_EXT); 1730#else 1731 sprintf(staticLibFilePath, "%s%s%s%s%s", 1732 o->targetDir, 1733 PKGDATA_FILE_SEP_STRING, 1734 (strstr(o->libName, "icudt") ? "s" : ""), 1735 o->libName, 1736 LIB_EXT); 1737#endif 1738 1739 sprintf(cmd, "%s\"%s\" \"%s\"", 1740 LIB_CMD, 1741 staticLibFilePath, 1742 gencFilePath); 1743 } else if (IN_DLL_MODE(mode)) { 1744 char dllFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1745 char libFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1746 char resFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1747 char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = ""; 1748 1749#ifdef CYGWINMSVC 1750 uprv_strcpy(dllFilePath, o->targetDir); 1751#else 1752 uprv_strcpy(dllFilePath, o->srcDir); 1753#endif 1754 uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING); 1755 uprv_strcpy(libFilePath, dllFilePath); 1756 1757#ifdef CYGWINMSVC 1758 uprv_strcat(libFilePath, o->libName); 1759 uprv_strcat(libFilePath, ".lib"); 1760 1761 uprv_strcat(dllFilePath, o->libName); 1762 uprv_strcat(dllFilePath, o->version); 1763#else 1764 if (strstr(o->libName, "icudt")) { 1765 uprv_strcat(libFilePath, LIB_FILE); 1766 } else { 1767 uprv_strcat(libFilePath, o->libName); 1768 uprv_strcat(libFilePath, ".lib"); 1769 } 1770 uprv_strcat(dllFilePath, o->entryName); 1771#endif 1772 uprv_strcat(dllFilePath, DLL_EXT); 1773 1774 uprv_strcpy(tmpResFilePath, o->tmpDir); 1775 uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING); 1776 uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE); 1777 1778 if (T_FileStream_file_exists(tmpResFilePath)) { 1779 sprintf(resFilePath, "\"%s\"", tmpResFilePath); 1780 } 1781 1782 /* Check if dll file and lib file exists and that it is not newer than genc file. */ 1783 if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) && 1784 (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) { 1785 if(o->verbose) { 1786 printf("# Not rebuilding %s - up to date.\n", gencFilePath); 1787 } 1788 return 0; 1789 } 1790 1791 sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" %s", 1792 LINK_CMD, 1793 dllFilePath, 1794 LINK_FLAGS, 1795 libFilePath, 1796 gencFilePath, 1797 resFilePath 1798 ); 1799 } 1800 1801 result = runCommand(cmd, TRUE); 1802 if (result != 0) { 1803 fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd); 1804 } 1805 1806 return result; 1807} 1808#endif 1809 1810static UPKGOptions *pkg_checkFlag(UPKGOptions *o) { 1811#if U_PLATFORM == U_PF_AIX 1812 /* AIX needs a map file. */ 1813 char *flag = NULL; 1814 int32_t length = 0; 1815 char tmpbuffer[SMALL_BUFFER_MAX_SIZE]; 1816 const char MAP_FILE_EXT[] = ".map"; 1817 FileStream *f = NULL; 1818 char mapFile[SMALL_BUFFER_MAX_SIZE] = ""; 1819 int32_t start = -1; 1820 uint32_t count = 0; 1821 const char rm_cmd[] = "rm -f all ;"; 1822 1823 flag = pkgDataFlags[GENLIB]; 1824 1825 /* This portion of the code removes 'rm -f all' in the GENLIB. 1826 * Only occurs in AIX. 1827 */ 1828 if (uprv_strstr(flag, rm_cmd) != NULL) { 1829 char *tmpGenlibFlagBuffer = NULL; 1830 int32_t i, offset; 1831 1832 length = uprv_strlen(flag) + 1; 1833 tmpGenlibFlagBuffer = (char *)uprv_malloc(length); 1834 if (tmpGenlibFlagBuffer == NULL) { 1835 /* Memory allocation error */ 1836 fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length); 1837 return NULL; 1838 } 1839 1840 uprv_strcpy(tmpGenlibFlagBuffer, flag); 1841 1842 offset = uprv_strlen(rm_cmd); 1843 1844 for (i = 0; i < (length - offset); i++) { 1845 flag[i] = tmpGenlibFlagBuffer[offset + i]; 1846 } 1847 1848 /* Zero terminate the string */ 1849 flag[i] = 0; 1850 1851 uprv_free(tmpGenlibFlagBuffer); 1852 } 1853 1854 flag = pkgDataFlags[BIR_FLAGS]; 1855 length = uprv_strlen(pkgDataFlags[BIR_FLAGS]); 1856 1857 for (int32_t i = 0; i < length; i++) { 1858 if (flag[i] == MAP_FILE_EXT[count]) { 1859 if (count == 0) { 1860 start = i; 1861 } 1862 count++; 1863 } else { 1864 count = 0; 1865 } 1866 1867 if (count == uprv_strlen(MAP_FILE_EXT)) { 1868 break; 1869 } 1870 } 1871 1872 if (start >= 0) { 1873 int32_t index = 0; 1874 for (int32_t i = 0;;i++) { 1875 if (i == start) { 1876 for (int32_t n = 0;;n++) { 1877 if (o->shortName[n] == 0) { 1878 break; 1879 } 1880 tmpbuffer[index++] = o->shortName[n]; 1881 } 1882 } 1883 1884 tmpbuffer[index++] = flag[i]; 1885 1886 if (flag[i] == 0) { 1887 break; 1888 } 1889 } 1890 1891 uprv_memset(flag, 0, length); 1892 uprv_strcpy(flag, tmpbuffer); 1893 1894 uprv_strcpy(mapFile, o->shortName); 1895 uprv_strcat(mapFile, MAP_FILE_EXT); 1896 1897 f = T_FileStream_open(mapFile, "w"); 1898 if (f == NULL) { 1899 fprintf(stderr,"Unable to create map file: %s.\n", mapFile); 1900 return NULL; 1901 } else { 1902 sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX); 1903 1904 T_FileStream_writeLine(f, tmpbuffer); 1905 1906 T_FileStream_close(f); 1907 } 1908 } 1909#elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW 1910 /* Cygwin needs to change flag options. */ 1911 char *flag = NULL; 1912 int32_t length = 0; 1913 1914 flag = pkgDataFlags[GENLIB]; 1915 length = uprv_strlen(pkgDataFlags[GENLIB]); 1916 1917 int32_t position = length - 1; 1918 1919 for(;position >= 0;position--) { 1920 if (flag[position] == '=') { 1921 position++; 1922 break; 1923 } 1924 } 1925 1926 uprv_memset(flag + position, 0, length - position); 1927#elif U_PLATFORM == U_PF_OS400 1928 /* OS/400 needs to fix the ld options (swap single quote with double quote) */ 1929 char *flag = NULL; 1930 int32_t length = 0; 1931 1932 flag = pkgDataFlags[GENLIB]; 1933 length = uprv_strlen(pkgDataFlags[GENLIB]); 1934 1935 int32_t position = length - 1; 1936 1937 for(int32_t i = 0; i < length; i++) { 1938 if (flag[i] == '\'') { 1939 flag[i] = '\"'; 1940 } 1941 } 1942#endif 1943 // Don't really need a return value, just need to stop compiler warnings about 1944 // the unused parameter 'o' on platforms where it is not otherwise used. 1945 return o; 1946} 1947 1948static void loadLists(UPKGOptions *o, UErrorCode *status) 1949{ 1950 CharList *l, *tail = NULL, *tail2 = NULL; 1951 FileStream *in; 1952 char line[16384]; 1953 char *linePtr, *lineNext; 1954 const uint32_t lineMax = 16300; 1955 char *tmp; 1956 int32_t tmpLength = 0; 1957 char *s; 1958 int32_t ln=0; /* line number */ 1959 1960 for(l = o->fileListFiles; l; l = l->next) { 1961 if(o->verbose) { 1962 fprintf(stdout, "# pkgdata: Reading %s..\n", l->str); 1963 } 1964 /* TODO: stdin */ 1965 in = T_FileStream_open(l->str, "r"); /* open files list */ 1966 1967 if(!in) { 1968 fprintf(stderr, "Error opening <%s>.\n", l->str); 1969 *status = U_FILE_ACCESS_ERROR; 1970 return; 1971 } 1972 1973 while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */ 1974 ln++; 1975 if(uprv_strlen(line)>lineMax) { 1976 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax); 1977 exit(1); 1978 } 1979 /* remove spaces at the beginning */ 1980 linePtr = line; 1981 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */ 1982#if U_PLATFORM != U_PF_OS390 1983 while(isspace(*linePtr)) { 1984 linePtr++; 1985 } 1986#endif 1987 s=linePtr; 1988 /* remove trailing newline characters */ 1989 while(*s!=0) { 1990 if(*s=='\r' || *s=='\n') { 1991 *s=0; 1992 break; 1993 } 1994 ++s; 1995 } 1996 if((*linePtr == 0) || (*linePtr == '#')) { 1997 continue; /* comment or empty line */ 1998 } 1999 2000 /* Now, process the line */ 2001 lineNext = NULL; 2002 2003 while(linePtr && *linePtr) { /* process space-separated items */ 2004 while(*linePtr == ' ') { 2005 linePtr++; 2006 } 2007 /* Find the next quote */ 2008 if(linePtr[0] == '"') 2009 { 2010 lineNext = uprv_strchr(linePtr+1, '"'); 2011 if(lineNext == NULL) { 2012 fprintf(stderr, "%s:%d - missing trailing double quote (\")\n", 2013 l->str, (int)ln); 2014 exit(1); 2015 } else { 2016 lineNext++; 2017 if(*lineNext) { 2018 if(*lineNext != ' ') { 2019 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n", 2020 l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0'); 2021 exit(1); 2022 } 2023 *lineNext = 0; 2024 lineNext++; 2025 } 2026 } 2027 } else { 2028 lineNext = uprv_strchr(linePtr, ' '); 2029 if(lineNext) { 2030 *lineNext = 0; /* terminate at space */ 2031 lineNext++; 2032 } 2033 } 2034 2035 /* add the file */ 2036 s = (char*)getLongPathname(linePtr); 2037 2038 /* normal mode.. o->files is just the bare list without package names */ 2039 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr)); 2040 if(uprv_pathIsAbsolute(s) || s[0] == '.') { 2041 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); 2042 exit(U_ILLEGAL_ARGUMENT_ERROR); 2043 } 2044 tmpLength = uprv_strlen(o->srcDir) + 2045 uprv_strlen(s) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */ 2046 if((tmp = (char *)uprv_malloc(tmpLength)) == NULL) { 2047 fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength); 2048 exit(U_MEMORY_ALLOCATION_ERROR); 2049 } 2050 uprv_strcpy(tmp, o->srcDir); 2051 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING); 2052 uprv_strcat(tmp, s); 2053 o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp); 2054 linePtr = lineNext; 2055 } /* for each entry on line */ 2056 } /* for each line */ 2057 T_FileStream_close(in); 2058 } /* for each file list file */ 2059} 2060 2061/* Try calling icu-config directly to get the option file. */ 2062 static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) { 2063#if U_HAVE_POPEN 2064 FILE *p = NULL; 2065 size_t n; 2066 static char buf[512] = ""; 2067 char cmdBuf[1024]; 2068 UErrorCode status = U_ZERO_ERROR; 2069 const char cmd[] = "icu-config --incpkgdatafile"; 2070 2071 /* #1 try the same path where pkgdata was called from. */ 2072 findDirname(progname, cmdBuf, 1024, &status); 2073 if(U_SUCCESS(status)) { 2074 if (cmdBuf[0] != 0) { 2075 uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024); 2076 } 2077 uprv_strncat(cmdBuf, cmd, 1023); 2078 2079 if(verbose) { 2080 fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf); 2081 } 2082 p = popen(cmdBuf, "r"); 2083 } 2084 2085 if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) { 2086 if(verbose) { 2087 fprintf(stdout, "# Calling icu-config: %s\n", cmd); 2088 } 2089 pclose(p); 2090 2091 p = popen(cmd, "r"); 2092 if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) { 2093 fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname); 2094 return -1; 2095 } 2096 } 2097 2098 pclose(p); 2099 2100 for (int32_t length = strlen(buf) - 1; length >= 0; length--) { 2101 if (buf[length] == '\n' || buf[length] == ' ') { 2102 buf[length] = 0; 2103 } else { 2104 break; 2105 } 2106 } 2107 2108 if(buf[strlen(buf)-1]=='\n') 2109 { 2110 buf[strlen(buf)-1]=0; 2111 } 2112 2113 if(buf[0] == 0) 2114 { 2115 fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname); 2116 return -1; 2117 } 2118 2119 if(verbose) { 2120 fprintf(stdout, "# icu-config said: %s\n", buf); 2121 } 2122 2123 option->value = buf; 2124 option->doesOccur = TRUE; 2125 2126 return 0; 2127#else 2128 return -1; 2129#endif 2130} 2131