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 #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 
   1367 static 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  */
   1409 enum {
   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 
   1421 const 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 
   1432 static 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 
   1628 static 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 
   1721 static 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 
   1859 static 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