tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkgdata.cpp (80915B)


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