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