Home | History | Annotate | Download | only in pkgdata
      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 
     54 U_CDECL_BEGIN
     55 #include "pkgtypes.h"
     56 U_CDECL_END
     57 
     58 
     59 static void loadLists(UPKGOptions *o, UErrorCode *status);
     60 
     61 static int32_t pkg_executeOptions(UPKGOptions *o);
     62 
     63 #ifdef WINDOWS_WITH_MSVC
     64 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
     65 #endif
     66 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE);
     67 static int32_t pkg_installLibrary(const char *installDir, const char *dir, UBool noVersion);
     68 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
     69 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName);
     70 
     71 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
     72 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
     73 #endif
     74 
     75 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
     76 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL);
     77 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
     78 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion);
     79 static int32_t initializePkgDataFlags(UPKGOptions *o);
     80 
     81 static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option);
     82 static int runCommand(const char* command, UBool specialHandling=FALSE);
     83 
     84 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
     85 #define IN_DLL_MODE(mode)    (mode == 'd' || mode == 'l')
     86 #define IN_STATIC_MODE(mode) (mode == 's')
     87 #define IN_FILES_MODE(mode)  (mode == 'f')
     88 
     89 enum {
     90     NAME,
     91     BLDOPT,
     92     MODE,
     93     HELP,
     94     HELP_QUESTION_MARK,
     95     VERBOSE,
     96     COPYRIGHT,
     97     COMMENT,
     98     DESTDIR,
     99     REBUILD,
    100     TEMPDIR,
    101     INSTALL,
    102     SOURCEDIR,
    103     ENTRYPOINT,
    104     REVISION,
    105     FORCE_PREFIX,
    106     LIBNAME,
    107     QUIET,
    108     WITHOUT_ASSEMBLY,
    109     PDS_BUILD
    110 };
    111 
    112 /* This sets the modes that are available */
    113 static struct {
    114     const char *name, *alt_name;
    115     const char *desc;
    116 } modes[] = {
    117         { "files", 0,           "Uses raw data files (no effect). Installation copies all files to the target location." },
    118 #if U_PLATFORM_HAS_WIN32_API
    119         { "dll",    "library",  "Generates one common data file and one shared library, <package>.dll"},
    120         { "common", "archive",  "Generates just the common file, <package>.dat"},
    121         { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
    122 #else
    123 #ifdef UDATA_SO_SUFFIX
    124         { "dll",    "library",  "Generates one shared library, <package>" UDATA_SO_SUFFIX },
    125 #endif
    126         { "common", "archive",  "Generates one common data file, <package>.dat" },
    127         { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
    128 #endif
    129 };
    130 
    131 static UOption options[]={
    132     /*00*/    UOPTION_DEF( "name",    'p', UOPT_REQUIRES_ARG),
    133     /*01*/    UOPTION_DEF( "bldopt",  'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
    134     /*02*/    UOPTION_DEF( "mode",    'm', UOPT_REQUIRES_ARG),
    135     /*03*/    UOPTION_HELP_H,                                   /* -h */
    136     /*04*/    UOPTION_HELP_QUESTION_MARK,                       /* -? */
    137     /*05*/    UOPTION_VERBOSE,                                  /* -v */
    138     /*06*/    UOPTION_COPYRIGHT,                                /* -c */
    139     /*07*/    UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
    140     /*08*/    UOPTION_DESTDIR,                                  /* -d */
    141     /*11*/    UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
    142     /*12*/    UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
    143     /*13*/    UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
    144     /*14*/    UOPTION_SOURCEDIR ,
    145     /*15*/    UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
    146     /*16*/    UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
    147     /*17*/    UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
    148     /*18*/    UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
    149     /*19*/    UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG),
    150     /*20*/    UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG),
    151     /*21*/    UOPTION_DEF( "zos-pds-build", 'z', UOPT_NO_ARG)
    152 };
    153 
    154 /* This enum and the following char array should be kept in sync. */
    155 enum {
    156     GENCCODE_ASSEMBLY_TYPE,
    157     SO_EXT,
    158     SOBJ_EXT,
    159     A_EXT,
    160     LIBPREFIX,
    161     LIB_EXT_ORDER,
    162     COMPILER,
    163     LIBFLAGS,
    164     GENLIB,
    165     LDICUDTFLAGS,
    166     LD_SONAME,
    167     RPATH_FLAGS,
    168     BIR_FLAGS,
    169     AR,
    170     ARFLAGS,
    171     RANLIB,
    172     INSTALL_CMD,
    173     PKGDATA_FLAGS_SIZE
    174 };
    175 static const char* FLAG_NAMES[PKGDATA_FLAGS_SIZE] = {
    176         "GENCCODE_ASSEMBLY_TYPE",
    177         "SO",
    178         "SOBJ",
    179         "A",
    180         "LIBPREFIX",
    181         "LIB_EXT_ORDER",
    182         "COMPILE",
    183         "LIBFLAGS",
    184         "GENLIB",
    185         "LDICUDTFLAGS",
    186         "LD_SONAME",
    187         "RPATH_FLAGS",
    188         "BIR_LDFLAGS",
    189         "AR",
    190         "ARFLAGS",
    191         "RANLIB",
    192         "INSTALL_CMD"
    193 };
    194 static char **pkgDataFlags = NULL;
    195 
    196 enum {
    197     LIB_FILE,
    198     LIB_FILE_VERSION_MAJOR,
    199     LIB_FILE_VERSION,
    200     LIB_FILE_VERSION_TMP,
    201 #if U_PLATFORM == U_PF_CYGWIN
    202     LIB_FILE_CYGWIN,
    203     LIB_FILE_CYGWIN_VERSION,
    204 #elif U_PLATFORM == U_PF_MINGW
    205     LIB_FILE_MINGW,
    206 #endif
    207     LIB_FILENAMES_SIZE
    208 };
    209 static char libFileNames[LIB_FILENAMES_SIZE][256];
    210 
    211 static UPKGOptions  *pkg_checkFlag(UPKGOptions *o);
    212 
    213 const 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 
    239 const char  *progname = "PKGDATA";
    240 
    241 int
    242 main(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 
    480 static 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)
    507 normal_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 
    528 static 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. */
    790 static 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  */
    858 static 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. */
    965 static 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
   1001 normal_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 
   1020 static 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 
   1073 static 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
   1105 static 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  */
   1169 static 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  */
   1231 static 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 
   1331     if (result != 0) {
   1332         fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd);
   1333     }
   1334 
   1335     if (freeCmd) {
   1336         uprv_free(cmd);
   1337     }
   1338 
   1339     return result;
   1340 }
   1341 
   1342 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
   1343     char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
   1344     char *cmd;
   1345     int32_t result = 0;
   1346 
   1347     int32_t length = 0;
   1348 
   1349     /* Remove the ending .s and replace it with .o for the new object file. */
   1350     uprv_strcpy(tempObjectFile, gencFilePath);
   1351     tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
   1352 
   1353     length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
   1354                     + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE;
   1355 
   1356     cmd = (char *)uprv_malloc(sizeof(char) * length);
   1357     if (cmd == NULL) {
   1358         return -1;
   1359     }
   1360 
   1361     /* Generate the object file. */
   1362     sprintf(cmd, "%s %s -o %s %s",
   1363             pkgDataFlags[COMPILER],
   1364             pkgDataFlags[LIBFLAGS],
   1365             tempObjectFile,
   1366             gencFilePath);
   1367 
   1368     result = runCommand(cmd);
   1369     uprv_free(cmd);
   1370     if (result != 0) {
   1371         fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd);
   1372         return result;
   1373     }
   1374 
   1375     return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
   1376 }
   1377 
   1378 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
   1379 /*
   1380  * Generation of the data library without assembly code needs to compile each data file
   1381  * individually and then link it all together.
   1382  * Note: Any update to the directory structure of the data needs to be reflected here.
   1383  */
   1384 enum {
   1385     DATA_PREFIX_BRKITR,
   1386     DATA_PREFIX_COLL,
   1387     DATA_PREFIX_CURR,
   1388     DATA_PREFIX_LANG,
   1389     DATA_PREFIX_RBNF,
   1390     DATA_PREFIX_REGION,
   1391     DATA_PREFIX_TRANSLIT,
   1392     DATA_PREFIX_ZONE,
   1393     DATA_PREFIX_LENGTH
   1394 };
   1395 
   1396 const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
   1397         "brkitr",
   1398         "coll",
   1399         "curr",
   1400         "lang",
   1401         "rbnf",
   1402         "region",
   1403         "translit",
   1404         "zone"
   1405 };
   1406 
   1407 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
   1408     int32_t result = 0;
   1409     CharList *list = o->filePaths;
   1410     CharList *listNames = o->files;
   1411     int32_t listSize = pkg_countCharList(list);
   1412     char *buffer;
   1413     char *cmd;
   1414     char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
   1415     char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
   1416 #ifdef USE_SINGLE_CCODE_FILE
   1417     char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
   1418     FileStream *icudtAllFile = NULL;
   1419 
   1420     sprintf(icudtAll, "%s%s%sall.c",
   1421             o->tmpDir,
   1422             PKGDATA_FILE_SEP_STRING,
   1423             libFileNames[LIB_FILE]);
   1424     /* Remove previous icudtall.c file. */
   1425     if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
   1426         fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
   1427         return result;
   1428     }
   1429 
   1430     if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==NULL) {
   1431         fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll);
   1432         return result;
   1433     }
   1434 #endif
   1435 
   1436     if (list == NULL || listNames == NULL) {
   1437         /* list and listNames should never be NULL since we are looping through the CharList with
   1438          * the given size.
   1439          */
   1440         return -1;
   1441     }
   1442 
   1443     if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
   1444         fprintf(stderr, "Unable to allocate memory for cmd.\n");
   1445         return -1;
   1446     } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
   1447         fprintf(stderr, "Unable to allocate memory for buffer.\n");
   1448         uprv_free(cmd);
   1449         return -1;
   1450     }
   1451 
   1452     for (int32_t i = 0; i < (listSize + 1); i++) {
   1453         const char *file ;
   1454         const char *name;
   1455 
   1456         if (i == 0) {
   1457             /* The first iteration calls the gencmn function and initailizes the buffer. */
   1458             createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
   1459             buffer[0] = 0;
   1460 #ifdef USE_SINGLE_CCODE_FILE
   1461             uprv_strcpy(tempObjectFile, gencmnFile);
   1462             tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
   1463 
   1464             sprintf(cmd, "%s %s -o %s %s",
   1465                         pkgDataFlags[COMPILER],
   1466                         pkgDataFlags[LIBFLAGS],
   1467                         tempObjectFile,
   1468                         gencmnFile);
   1469 
   1470             result = runCommand(cmd);
   1471             if (result != 0) {
   1472                 break;
   1473             }
   1474 
   1475             sprintf(buffer, "%s",tempObjectFile);
   1476 #endif
   1477         } else {
   1478             char newName[SMALL_BUFFER_MAX_SIZE];
   1479             char dataName[SMALL_BUFFER_MAX_SIZE];
   1480             char dataDirName[SMALL_BUFFER_MAX_SIZE];
   1481             const char *pSubstring;
   1482             file = list->str;
   1483             name = listNames->str;
   1484 
   1485             newName[0] = dataName[0] = 0;
   1486             for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
   1487                 dataDirName[0] = 0;
   1488                 sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
   1489                 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
   1490                 pSubstring = uprv_strstr(name, dataDirName);
   1491                 if (pSubstring != NULL) {
   1492                     char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
   1493                     const char *p = name + uprv_strlen(dataDirName);
   1494                     for (int32_t i = 0;;i++) {
   1495                         if (p[i] == '.') {
   1496                             newNameTmp[i] = '_';
   1497                             continue;
   1498                         }
   1499                         newNameTmp[i] = p[i];
   1500                         if (p[i] == 0) {
   1501                             break;
   1502                         }
   1503                     }
   1504                     sprintf(newName, "%s_%s",
   1505                             DATA_PREFIX[n],
   1506                             newNameTmp);
   1507                     sprintf(dataName, "%s_%s",
   1508                             o->shortName,
   1509                             DATA_PREFIX[n]);
   1510                 }
   1511                 if (newName[0] != 0) {
   1512                     break;
   1513                 }
   1514             }
   1515 
   1516             if(o->verbose) {
   1517               printf("# Generating %s \n", gencmnFile);
   1518             }
   1519 
   1520             writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
   1521 
   1522 #ifdef USE_SINGLE_CCODE_FILE
   1523             sprintf(cmd, "#include \"%s\"\n", gencmnFile);
   1524             T_FileStream_writeLine(icudtAllFile, cmd);
   1525             /* don't delete the file */
   1526 #endif
   1527         }
   1528 
   1529 #ifndef USE_SINGLE_CCODE_FILE
   1530         uprv_strcpy(tempObjectFile, gencmnFile);
   1531         tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
   1532 
   1533         sprintf(cmd, "%s %s -o %s %s",
   1534                     pkgDataFlags[COMPILER],
   1535                     pkgDataFlags[LIBFLAGS],
   1536                     tempObjectFile,
   1537                     gencmnFile);
   1538         result = runCommand(cmd);
   1539         if (result != 0) {
   1540             fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
   1541             break;
   1542         }
   1543 
   1544         uprv_strcat(buffer, " ");
   1545         uprv_strcat(buffer, tempObjectFile);
   1546 
   1547 #endif
   1548 
   1549         if (i > 0) {
   1550             list = list->next;
   1551             listNames = listNames->next;
   1552         }
   1553     }
   1554 
   1555 #ifdef USE_SINGLE_CCODE_FILE
   1556     T_FileStream_close(icudtAllFile);
   1557     uprv_strcpy(tempObjectFile, icudtAll);
   1558     tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
   1559 
   1560     sprintf(cmd, "%s %s -I. -o %s %s",
   1561         pkgDataFlags[COMPILER],
   1562         pkgDataFlags[LIBFLAGS],
   1563         tempObjectFile,
   1564         icudtAll);
   1565 
   1566     result = runCommand(cmd);
   1567     if (result == 0) {
   1568         uprv_strcat(buffer, " ");
   1569         uprv_strcat(buffer, tempObjectFile);
   1570     } else {
   1571         fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
   1572     }
   1573 #endif
   1574 
   1575     if (result == 0) {
   1576         /* Generate the library file. */
   1577 #if U_PLATFORM == U_PF_OS390
   1578         if (o->pdsbuild && IN_DLL_MODE(mode)) {
   1579             result = pkg_generateLibraryFile("",mode, buffer, cmd);
   1580         } else {
   1581             result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
   1582         }
   1583 #else
   1584         result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
   1585 #endif
   1586     }
   1587 
   1588     uprv_free(buffer);
   1589     uprv_free(cmd);
   1590 
   1591     return result;
   1592 }
   1593 #endif
   1594 
   1595 #ifdef WINDOWS_WITH_MSVC
   1596 #define LINK_CMD "link.exe /nologo /release /out:"
   1597 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO  /base:0x4ad00000 /implib:"
   1598 #define LIB_CMD "LIB.exe /nologo /out:"
   1599 #define LIB_FILE "icudt.lib"
   1600 #define LIB_EXT UDATA_LIB_SUFFIX
   1601 #define DLL_EXT UDATA_SO_SUFFIX
   1602 
   1603 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
   1604     int32_t result = 0;
   1605     char cmd[LARGE_BUFFER_MAX_SIZE];
   1606     if (IN_STATIC_MODE(mode)) {
   1607         char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1608 
   1609 #ifdef CYGWINMSVC
   1610         sprintf(staticLibFilePath, "%s%s%s%s%s",
   1611                 o->targetDir,
   1612                 PKGDATA_FILE_SEP_STRING,
   1613                 pkgDataFlags[LIBPREFIX],
   1614                 o->libName,
   1615                 LIB_EXT);
   1616 #else
   1617         sprintf(staticLibFilePath, "%s%s%s%s%s",
   1618                 o->targetDir,
   1619                 PKGDATA_FILE_SEP_STRING,
   1620                 (strstr(o->libName, "icudt") ? "s" : ""),
   1621                 o->libName,
   1622                 LIB_EXT);
   1623 #endif
   1624 
   1625         sprintf(cmd, "%s\"%s\" \"%s\"",
   1626                 LIB_CMD,
   1627                 staticLibFilePath,
   1628                 gencFilePath);
   1629     } else if (IN_DLL_MODE(mode)) {
   1630         char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1631         char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1632         char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1633         char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1634 
   1635 #ifdef CYGWINMSVC
   1636         uprv_strcpy(dllFilePath, o->targetDir);
   1637 #else
   1638         uprv_strcpy(dllFilePath, o->srcDir);
   1639 #endif
   1640         uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
   1641         uprv_strcpy(libFilePath, dllFilePath);
   1642 
   1643 #ifdef CYGWINMSVC
   1644         uprv_strcat(libFilePath, o->libName);
   1645         uprv_strcat(libFilePath, ".lib");
   1646 
   1647         uprv_strcat(dllFilePath, o->libName);
   1648         uprv_strcat(dllFilePath, o->version);
   1649 #else
   1650         if (strstr(o->libName, "icudt")) {
   1651             uprv_strcat(libFilePath, LIB_FILE);
   1652         } else {
   1653             uprv_strcat(libFilePath, o->libName);
   1654             uprv_strcat(libFilePath, ".lib");
   1655         }
   1656         uprv_strcat(dllFilePath, o->entryName);
   1657 #endif
   1658         uprv_strcat(dllFilePath, DLL_EXT);
   1659 
   1660         uprv_strcpy(tmpResFilePath, o->tmpDir);
   1661         uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
   1662         uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
   1663 
   1664         if (T_FileStream_file_exists(tmpResFilePath)) {
   1665             sprintf(resFilePath, "\"%s\"", tmpResFilePath);
   1666         }
   1667 
   1668         /* Check if dll file and lib file exists and that it is not newer than genc file. */
   1669         if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
   1670             (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
   1671           if(o->verbose) {
   1672             printf("# Not rebuilding %s - up to date.\n", gencFilePath);
   1673           }
   1674           return 0;
   1675         }
   1676 
   1677         sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" %s",
   1678                 LINK_CMD,
   1679                 dllFilePath,
   1680                 LINK_FLAGS,
   1681                 libFilePath,
   1682                 gencFilePath,
   1683                 resFilePath
   1684                 );
   1685     }
   1686 
   1687     result = runCommand(cmd, TRUE);
   1688     if (result != 0) {
   1689         fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd);
   1690     }
   1691 
   1692     return result;
   1693 }
   1694 #endif
   1695 
   1696 static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
   1697 #if U_PLATFORM == U_PF_AIX
   1698     /* AIX needs a map file. */
   1699     char *flag = NULL;
   1700     int32_t length = 0;
   1701     char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
   1702     const char MAP_FILE_EXT[] = ".map";
   1703     FileStream *f = NULL;
   1704     char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
   1705     int32_t start = -1;
   1706     uint32_t count = 0;
   1707     const char rm_cmd[] = "rm -f all ;";
   1708 
   1709     flag = pkgDataFlags[GENLIB];
   1710 
   1711     /* This portion of the code removes 'rm -f all' in the GENLIB.
   1712      * Only occurs in AIX.
   1713      */
   1714     if (uprv_strstr(flag, rm_cmd) != NULL) {
   1715         char *tmpGenlibFlagBuffer = NULL;
   1716         int32_t i, offset;
   1717 
   1718         length = uprv_strlen(flag) + 1;
   1719         tmpGenlibFlagBuffer = (char *)uprv_malloc(length);
   1720         if (tmpGenlibFlagBuffer == NULL) {
   1721             /* Memory allocation error */
   1722             fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length);
   1723             return NULL;
   1724         }
   1725 
   1726         uprv_strcpy(tmpGenlibFlagBuffer, flag);
   1727 
   1728         offset = uprv_strlen(rm_cmd);
   1729 
   1730         for (i = 0; i < (length - offset); i++) {
   1731             flag[i] = tmpGenlibFlagBuffer[offset + i];
   1732         }
   1733 
   1734         /* Zero terminate the string */
   1735         flag[i] = 0;
   1736 
   1737         uprv_free(tmpGenlibFlagBuffer);
   1738     }
   1739 
   1740     flag = pkgDataFlags[BIR_FLAGS];
   1741     length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
   1742 
   1743     for (int32_t i = 0; i < length; i++) {
   1744         if (flag[i] == MAP_FILE_EXT[count]) {
   1745             if (count == 0) {
   1746                 start = i;
   1747             }
   1748             count++;
   1749         } else {
   1750             count = 0;
   1751         }
   1752 
   1753         if (count == uprv_strlen(MAP_FILE_EXT)) {
   1754             break;
   1755         }
   1756     }
   1757 
   1758     if (start >= 0) {
   1759         int32_t index = 0;
   1760         for (int32_t i = 0;;i++) {
   1761             if (i == start) {
   1762                 for (int32_t n = 0;;n++) {
   1763                     if (o->shortName[n] == 0) {
   1764                         break;
   1765                     }
   1766                     tmpbuffer[index++] = o->shortName[n];
   1767                 }
   1768             }
   1769 
   1770             tmpbuffer[index++] = flag[i];
   1771 
   1772             if (flag[i] == 0) {
   1773                 break;
   1774             }
   1775         }
   1776 
   1777         uprv_memset(flag, 0, length);
   1778         uprv_strcpy(flag, tmpbuffer);
   1779 
   1780         uprv_strcpy(mapFile, o->shortName);
   1781         uprv_strcat(mapFile, MAP_FILE_EXT);
   1782 
   1783         f = T_FileStream_open(mapFile, "w");
   1784         if (f == NULL) {
   1785             fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
   1786             return NULL;
   1787         } else {
   1788             sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
   1789 
   1790             T_FileStream_writeLine(f, tmpbuffer);
   1791 
   1792             T_FileStream_close(f);
   1793         }
   1794     }
   1795 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
   1796     /* Cygwin needs to change flag options. */
   1797     char *flag = NULL;
   1798     int32_t length = 0;
   1799 
   1800     flag = pkgDataFlags[GENLIB];
   1801     length = uprv_strlen(pkgDataFlags[GENLIB]);
   1802 
   1803     int32_t position = length - 1;
   1804 
   1805     for(;position >= 0;position--) {
   1806         if (flag[position] == '=') {
   1807             position++;
   1808             break;
   1809         }
   1810     }
   1811 
   1812     uprv_memset(flag + position, 0, length - position);
   1813 #elif U_PLATFORM == U_PF_OS400
   1814     /* OS/400 needs to fix the ld options (swap single quote with double quote) */
   1815     char *flag = NULL;
   1816     int32_t length = 0;
   1817 
   1818     flag = pkgDataFlags[GENLIB];
   1819     length = uprv_strlen(pkgDataFlags[GENLIB]);
   1820 
   1821     int32_t position = length - 1;
   1822 
   1823     for(int32_t i = 0; i < length; i++) {
   1824         if (flag[i] == '\'') {
   1825             flag[i] = '\"';
   1826         }
   1827     }
   1828 #endif
   1829     // Don't really need a return value, just need to stop compiler warnings about
   1830     // the unused parameter 'o' on platforms where it is not otherwise used.
   1831     return o;
   1832 }
   1833 
   1834 static void loadLists(UPKGOptions *o, UErrorCode *status)
   1835 {
   1836     CharList   *l, *tail = NULL, *tail2 = NULL;
   1837     FileStream *in;
   1838     char        line[16384];
   1839     char       *linePtr, *lineNext;
   1840     const uint32_t   lineMax = 16300;
   1841     char       *tmp;
   1842     int32_t     tmpLength = 0;
   1843     char       *s;
   1844     int32_t     ln=0; /* line number */
   1845 
   1846     for(l = o->fileListFiles; l; l = l->next) {
   1847         if(o->verbose) {
   1848             fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
   1849         }
   1850         /* TODO: stdin */
   1851         in = T_FileStream_open(l->str, "r"); /* open files list */
   1852 
   1853         if(!in) {
   1854             fprintf(stderr, "Error opening <%s>.\n", l->str);
   1855             *status = U_FILE_ACCESS_ERROR;
   1856             return;
   1857         }
   1858 
   1859         while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
   1860             ln++;
   1861             if(uprv_strlen(line)>lineMax) {
   1862                 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
   1863                 exit(1);
   1864             }
   1865             /* remove spaces at the beginning */
   1866             linePtr = line;
   1867             /* On z/OS, disable call to isspace (#9996).  Investigate using uprv_isspace instead (#9999) */
   1868 #if U_PLATFORM != U_PF_OS390
   1869             while(isspace(*linePtr)) {
   1870                 linePtr++;
   1871             }
   1872 #endif
   1873             s=linePtr;
   1874             /* remove trailing newline characters */
   1875             while(*s!=0) {
   1876                 if(*s=='\r' || *s=='\n') {
   1877                     *s=0;
   1878                     break;
   1879                 }
   1880                 ++s;
   1881             }
   1882             if((*linePtr == 0) || (*linePtr == '#')) {
   1883                 continue; /* comment or empty line */
   1884             }
   1885 
   1886             /* Now, process the line */
   1887             lineNext = NULL;
   1888 
   1889             while(linePtr && *linePtr) { /* process space-separated items */
   1890                 while(*linePtr == ' ') {
   1891                     linePtr++;
   1892                 }
   1893                 /* Find the next quote */
   1894                 if(linePtr[0] == '"')
   1895                 {
   1896                     lineNext = uprv_strchr(linePtr+1, '"');
   1897                     if(lineNext == NULL) {
   1898                         fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
   1899                             l->str, (int)ln);
   1900                         exit(1);
   1901                     } else {
   1902                         lineNext++;
   1903                         if(*lineNext) {
   1904                             if(*lineNext != ' ') {
   1905                                 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
   1906                                     l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
   1907                                 exit(1);
   1908                             }
   1909                             *lineNext = 0;
   1910                             lineNext++;
   1911                         }
   1912                     }
   1913                 } else {
   1914                     lineNext = uprv_strchr(linePtr, ' ');
   1915                     if(lineNext) {
   1916                         *lineNext = 0; /* terminate at space */
   1917                         lineNext++;
   1918                     }
   1919                 }
   1920 
   1921                 /* add the file */
   1922                 s = (char*)getLongPathname(linePtr);
   1923 
   1924                 /* normal mode.. o->files is just the bare list without package names */
   1925                 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
   1926                 if(uprv_pathIsAbsolute(s) || s[0] == '.') {
   1927                     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);
   1928                     exit(U_ILLEGAL_ARGUMENT_ERROR);
   1929                 }
   1930                 tmpLength = uprv_strlen(o->srcDir) +
   1931                             uprv_strlen(s) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
   1932                 if((tmp = (char *)uprv_malloc(tmpLength)) == NULL) {
   1933                     fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength);
   1934                     exit(U_MEMORY_ALLOCATION_ERROR);
   1935                 }
   1936                 uprv_strcpy(tmp, o->srcDir);
   1937                 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING);
   1938                 uprv_strcat(tmp, s);
   1939                 o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp);
   1940                 linePtr = lineNext;
   1941             } /* for each entry on line */
   1942         } /* for each line */
   1943         T_FileStream_close(in);
   1944     } /* for each file list file */
   1945 }
   1946 
   1947 /* Try calling icu-config directly to get the option file. */
   1948  static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
   1949 #if U_HAVE_POPEN
   1950     FILE *p = NULL;
   1951     size_t n;
   1952     static char buf[512] = "";
   1953     char cmdBuf[1024];
   1954     UErrorCode status = U_ZERO_ERROR;
   1955     const char cmd[] = "icu-config --incpkgdatafile";
   1956 
   1957     /* #1 try the same path where pkgdata was called from. */
   1958     findDirname(progname, cmdBuf, 1024, &status);
   1959     if(U_SUCCESS(status)) {
   1960       if (cmdBuf[0] != 0) {
   1961           uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024);
   1962       }
   1963       uprv_strncat(cmdBuf, cmd, 1024);
   1964 
   1965       if(verbose) {
   1966         fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf);
   1967       }
   1968       p = popen(cmdBuf, "r");
   1969     }
   1970 
   1971     if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) {
   1972       if(verbose) {
   1973         fprintf(stdout, "# Calling icu-config: %s\n", cmd);
   1974       }
   1975       pclose(p);
   1976 
   1977       p = popen(cmd, "r");
   1978       if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) {
   1979           fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
   1980           return -1;
   1981       }
   1982     }
   1983 
   1984     pclose(p);
   1985 
   1986     for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
   1987         if (buf[length] == '\n' || buf[length] == ' ') {
   1988             buf[length] = 0;
   1989         } else {
   1990             break;
   1991         }
   1992     }
   1993 
   1994     if(buf[strlen(buf)-1]=='\n')
   1995     {
   1996         buf[strlen(buf)-1]=0;
   1997     }
   1998 
   1999     if(buf[0] == 0)
   2000     {
   2001         fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
   2002         return -1;
   2003     }
   2004 
   2005     if(verbose) {
   2006       fprintf(stdout, "# icu-config said: %s\n", buf);
   2007     }
   2008 
   2009     option->value = buf;
   2010     option->doesOccur = TRUE;
   2011 
   2012     return 0;
   2013 #else
   2014     return -1;
   2015 #endif
   2016 }
   2017