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