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