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 = 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",
    908                     pkgDataFlags[LIBPREFIX],
    909                     libName);
    910         }
    911 #else
    912         sprintf(libFileNames[LIB_FILE], "%s%s",
    913                 pkgDataFlags[LIBPREFIX],
    914                 libName);
    915 #endif
    916 
    917         if(o->verbose) {
    918           fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]);
    919         }
    920 
    921 #if U_PLATFORM == U_PF_MINGW
    922         // Name the import library lib*.dll.a
    923         sprintf(libFileNames[LIB_FILE_MINGW], "lib%s.dll.a", libName);
    924 #elif U_PLATFORM == U_PF_CYGWIN
    925         sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s%s%s",
    926                 libName,
    927                 FILE_EXTENSION_SEP,
    928                 pkgDataFlags[SO_EXT]);
    929         sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s%s%s",
    930                 libName,
    931                 version_major,
    932                 FILE_EXTENSION_SEP,
    933                 pkgDataFlags[SO_EXT]);
    934 
    935         uprv_strcat(pkgDataFlags[SO_EXT], ".");
    936         uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
    937 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
    938         sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
    939                 libFileNames[LIB_FILE],
    940                 FILE_EXTENSION_SEP,
    941                 pkgDataFlags[SOBJ_EXT]);
    942 #elif U_PLATFORM == U_PF_OS390
    943         sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s%s%s",
    944                     libFileNames[LIB_FILE],
    945                     pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
    946                     reverseExt ? version : pkgDataFlags[SOBJ_EXT],
    947                     FILE_EXTENSION_SEP,
    948                     reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
    949 
    950         sprintf(libFileNames[LIB_FILE_OS390BATCH_VERSION], "%s%s.x",
    951                     libFileNames[LIB_FILE],
    952                     version);
    953         sprintf(libFileNames[LIB_FILE_OS390BATCH_MAJOR], "%s%s.x",
    954                     libFileNames[LIB_FILE],
    955                     version_major);
    956 #else
    957         if (noVersion && !reverseExt) {
    958             sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
    959                     libFileNames[LIB_FILE],
    960                     FILE_SUFFIX,
    961                     pkgDataFlags[SOBJ_EXT]);
    962         } else {
    963             sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s%s%s",
    964                     libFileNames[LIB_FILE],
    965                     FILE_SUFFIX,
    966                     reverseExt ? version : pkgDataFlags[SOBJ_EXT],
    967                     FILE_EXTENSION_SEP,
    968                     reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
    969         }
    970 #endif
    971         if (noVersion && !reverseExt) {
    972             sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s",
    973                     libFileNames[LIB_FILE],
    974                     FILE_SUFFIX,
    975                     pkgDataFlags[SO_EXT]);
    976 
    977             sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s",
    978                     libFileNames[LIB_FILE],
    979                     FILE_SUFFIX,
    980                     pkgDataFlags[SO_EXT]);
    981         } else {
    982             sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s%s%s",
    983                     libFileNames[LIB_FILE],
    984                     FILE_SUFFIX,
    985                     reverseExt ? version_major : pkgDataFlags[SO_EXT],
    986                     FILE_EXTENSION_SEP,
    987                     reverseExt ? pkgDataFlags[SO_EXT] : version_major);
    988 
    989             sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s%s%s",
    990                     libFileNames[LIB_FILE],
    991                     FILE_SUFFIX,
    992                     reverseExt ? version : pkgDataFlags[SO_EXT],
    993                     FILE_EXTENSION_SEP,
    994                     reverseExt ? pkgDataFlags[SO_EXT] : version);
    995         }
    996 
    997         if(o->verbose) {
    998           fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]);
    999         }
   1000 
   1001 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
   1002         /* Cygwin and MinGW only deals with the version major number. */
   1003         uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
   1004 #endif
   1005 
   1006         if(IN_STATIC_MODE(mode)) {
   1007             sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]);
   1008             libFileNames[LIB_FILE_VERSION_MAJOR][0]=0;
   1009             if(o->verbose) {
   1010               fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s  (static)\n", libFileNames[LIB_FILE_VERSION]);
   1011             }
   1012         }
   1013 }
   1014 
   1015 /* Create the symbolic links for the final library file. */
   1016 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) {
   1017     int32_t result = 0;
   1018     char cmd[LARGE_BUFFER_MAX_SIZE];
   1019     char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */
   1020     char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */
   1021     const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
   1022 
   1023 #if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW
   1024     /* No symbolic link to make. */
   1025     if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 ||
   1026         uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
   1027         return result;
   1028     }
   1029 
   1030     sprintf(cmd, "cd %s && %s %s && %s %s %s",
   1031             targetDir,
   1032             RM_CMD,
   1033             libFileNames[LIB_FILE_VERSION_MAJOR],
   1034             LN_CMD,
   1035             libFileNames[LIB_FILE_VERSION],
   1036             libFileNames[LIB_FILE_VERSION_MAJOR]);
   1037     result = runCommand(cmd);
   1038     if (result != 0) {
   1039         fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
   1040         return result;
   1041     }
   1042 #endif
   1043 
   1044     if (specialHandling) {
   1045 #if U_PLATFORM == U_PF_CYGWIN
   1046         sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]);
   1047         sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
   1048 #elif U_PLATFORM == U_PF_OS390
   1049         /* Create the symbolic links for the import data */
   1050         /* Use the cmd buffer to store path to import data file to check its existence */
   1051         sprintf(cmd, "%s/%s", targetDir, libFileNames[LIB_FILE_OS390BATCH_VERSION]);
   1052         if (T_FileStream_file_exists(cmd)) {
   1053             sprintf(cmd, "cd %s && %s %s && %s %s %s",
   1054                     targetDir,
   1055                     RM_CMD,
   1056                     libFileNames[LIB_FILE_OS390BATCH_MAJOR],
   1057                     LN_CMD,
   1058                     libFileNames[LIB_FILE_OS390BATCH_VERSION],
   1059                     libFileNames[LIB_FILE_OS390BATCH_MAJOR]);
   1060             result = runCommand(cmd);
   1061             if (result != 0) {
   1062                 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
   1063                 return result;
   1064             }
   1065 
   1066             sprintf(cmd, "cd %s && %s %s.x && %s %s %s.x",
   1067                     targetDir,
   1068                     RM_CMD,
   1069                     libFileNames[LIB_FILE],
   1070                     LN_CMD,
   1071                     libFileNames[LIB_FILE_OS390BATCH_VERSION],
   1072                     libFileNames[LIB_FILE]);
   1073             result = runCommand(cmd);
   1074             if (result != 0) {
   1075                 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
   1076                 return result;
   1077             }
   1078         }
   1079 
   1080         /* Needs to be set here because special handling skips it */
   1081         sprintf(name1, "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
   1082         sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
   1083 #else
   1084         goto normal_symlink_mode;
   1085 #endif
   1086     } else {
   1087 #if U_PLATFORM != U_PF_CYGWIN
   1088 normal_symlink_mode:
   1089 #endif
   1090         sprintf(name1, "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
   1091         sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
   1092     }
   1093 
   1094     sprintf(cmd, "cd %s && %s %s && %s %s %s",
   1095             targetDir,
   1096             RM_CMD,
   1097             name1,
   1098             LN_CMD,
   1099             name2,
   1100             name1);
   1101 
   1102      result = runCommand(cmd);
   1103 
   1104     return result;
   1105 }
   1106 
   1107 static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, UBool noVersion) {
   1108     int32_t result = 0;
   1109     char cmd[SMALL_BUFFER_MAX_SIZE];
   1110 
   1111     sprintf(cmd, "cd %s && %s %s %s%s%s",
   1112             targetDir,
   1113             pkgDataFlags[INSTALL_CMD],
   1114             libFileNames[LIB_FILE_VERSION],
   1115             installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
   1116             );
   1117 
   1118     result = runCommand(cmd);
   1119 
   1120     if (result != 0) {
   1121         fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
   1122         return result;
   1123     }
   1124 
   1125 #ifdef CYGWINMSVC
   1126     sprintf(cmd, "cd %s && %s %s.lib %s",
   1127             targetDir,
   1128             pkgDataFlags[INSTALL_CMD],
   1129             libFileNames[LIB_FILE],
   1130             installDir
   1131             );
   1132     result = runCommand(cmd);
   1133 
   1134     if (result != 0) {
   1135         fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
   1136         return result;
   1137     }
   1138 #elif U_PLATFORM == U_PF_CYGWIN
   1139     sprintf(cmd, "cd %s && %s %s %s",
   1140             targetDir,
   1141             pkgDataFlags[INSTALL_CMD],
   1142             libFileNames[LIB_FILE_CYGWIN_VERSION],
   1143             installDir
   1144             );
   1145     result = runCommand(cmd);
   1146 
   1147     if (result != 0) {
   1148         fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
   1149         return result;
   1150     }
   1151 
   1152 #elif U_PLATFORM == U_PF_OS390
   1153     if (T_FileStream_file_exists(libFileNames[LIB_FILE_OS390BATCH_VERSION])) {
   1154         sprintf(cmd, "%s %s %s",
   1155                 pkgDataFlags[INSTALL_CMD],
   1156                 libFileNames[LIB_FILE_OS390BATCH_VERSION],
   1157                 installDir
   1158                 );
   1159         result = runCommand(cmd);
   1160 
   1161         if (result != 0) {
   1162             fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
   1163             return result;
   1164         }
   1165     }
   1166 #endif
   1167 
   1168     if (noVersion) {
   1169         return result;
   1170     } else {
   1171         return pkg_createSymLinks(installDir, TRUE);
   1172     }
   1173 }
   1174 
   1175 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) {
   1176     int32_t result = 0;
   1177     char cmd[SMALL_BUFFER_MAX_SIZE] = "";
   1178 
   1179     if (!T_FileStream_file_exists(installDir)) {
   1180         UErrorCode status = U_ZERO_ERROR;
   1181 
   1182         uprv_mkdir(installDir, &status);
   1183         if (U_FAILURE(status)) {
   1184             fprintf(stderr, "Error creating installation directory: %s\n", installDir);
   1185             return -1;
   1186         }
   1187     }
   1188 #ifndef U_WINDOWS_WITH_MSVC
   1189     sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir);
   1190 #else
   1191     sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS);
   1192 #endif
   1193 
   1194     result = runCommand(cmd);
   1195     if (result != 0) {
   1196         fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
   1197     }
   1198 
   1199     return result;
   1200 }
   1201 
   1202 #ifdef U_WINDOWS_MSVC
   1203 /* Copy commands for installing the raw data files on Windows. */
   1204 #define WIN_INSTALL_CMD "xcopy"
   1205 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
   1206 #endif
   1207 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
   1208     int32_t result = 0;
   1209     char cmd[SMALL_BUFFER_MAX_SIZE] = "";
   1210 
   1211     if (!T_FileStream_file_exists(installDir)) {
   1212         UErrorCode status = U_ZERO_ERROR;
   1213 
   1214         uprv_mkdir(installDir, &status);
   1215         if (U_FAILURE(status)) {
   1216             fprintf(stderr, "Error creating installation directory: %s\n", installDir);
   1217             return -1;
   1218         }
   1219     }
   1220 #ifndef U_WINDOWS_WITH_MSVC
   1221     char buffer[SMALL_BUFFER_MAX_SIZE] = "";
   1222     int32_t bufferLength = 0;
   1223 
   1224     FileStream *f = T_FileStream_open(fileListName, "r");
   1225     if (f != NULL) {
   1226         for(;;) {
   1227             if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
   1228                 bufferLength = uprv_strlen(buffer);
   1229                 /* Remove new line character. */
   1230                 if (bufferLength > 0) {
   1231                     buffer[bufferLength-1] = 0;
   1232                 }
   1233 
   1234                 sprintf(cmd, "%s %s%s%s %s%s%s",
   1235                         pkgDataFlags[INSTALL_CMD],
   1236                         srcDir, PKGDATA_FILE_SEP_STRING, buffer,
   1237                         installDir, PKGDATA_FILE_SEP_STRING, buffer);
   1238 
   1239                 result = runCommand(cmd);
   1240                 if (result != 0) {
   1241                     fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
   1242                     break;
   1243                 }
   1244             } else {
   1245                 if (!T_FileStream_eof(f)) {
   1246                     fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
   1247                     result = -1;
   1248                 }
   1249                 break;
   1250             }
   1251         }
   1252         T_FileStream_close(f);
   1253     } else {
   1254         result = -1;
   1255         fprintf(stderr, "Unable to open list file: %s\n", fileListName);
   1256     }
   1257 #else
   1258     sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
   1259     result = runCommand(cmd);
   1260     if (result != 0) {
   1261         fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
   1262     }
   1263 #endif
   1264 
   1265     return result;
   1266 }
   1267 
   1268 /* Archiving of the library file may be needed depending on the platform and options given.
   1269  * If archiving is not needed, copy over the library file name.
   1270  */
   1271 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
   1272     int32_t result = 0;
   1273     char cmd[LARGE_BUFFER_MAX_SIZE];
   1274 
   1275     /* If the shared object suffix and the final object suffix is different and the final object suffix and the
   1276      * archive file suffix is the same, then the final library needs to be archived.
   1277      */
   1278     if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
   1279         sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
   1280                 libFileNames[LIB_FILE],
   1281                 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1282                 reverseExt ? version : pkgDataFlags[SO_EXT],
   1283                 reverseExt ? pkgDataFlags[SO_EXT] : version);
   1284 
   1285         sprintf(cmd, "%s %s %s%s %s%s",
   1286                 pkgDataFlags[AR],
   1287                 pkgDataFlags[ARFLAGS],
   1288                 targetDir,
   1289                 libFileNames[LIB_FILE_VERSION],
   1290                 targetDir,
   1291                 libFileNames[LIB_FILE_VERSION_TMP]);
   1292 
   1293         result = runCommand(cmd);
   1294         if (result != 0) {
   1295             fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
   1296             return result;
   1297         }
   1298 
   1299         sprintf(cmd, "%s %s%s",
   1300             pkgDataFlags[RANLIB],
   1301             targetDir,
   1302             libFileNames[LIB_FILE_VERSION]);
   1303 
   1304         result = runCommand(cmd);
   1305         if (result != 0) {
   1306             fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
   1307             return result;
   1308         }
   1309 
   1310         /* Remove unneeded library file. */
   1311         sprintf(cmd, "%s %s%s",
   1312                 RM_CMD,
   1313                 targetDir,
   1314                 libFileNames[LIB_FILE_VERSION_TMP]);
   1315 
   1316         result = runCommand(cmd);
   1317         if (result != 0) {
   1318             fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
   1319             return result;
   1320         }
   1321 
   1322     } else {
   1323         uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
   1324     }
   1325 
   1326     return result;
   1327 }
   1328 
   1329 /*
   1330  * Using the compiler information from the configuration file set by -O option, generate the library file.
   1331  * command may be given to allow for a larger buffer for cmd.
   1332  */
   1333 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command, UBool specialHandling) {
   1334     int32_t result = 0;
   1335     char *cmd = NULL;
   1336     UBool freeCmd = FALSE;
   1337     int32_t length = 0;
   1338 
   1339     (void)specialHandling;  // Suppress unused variable compiler warnings on platforms where all usage
   1340                             // of this parameter is #ifdefed out.
   1341 
   1342     /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
   1343      * containing many object files and so the calling function should supply a command buffer that is large
   1344      * enough to handle this. Otherwise, use the default size.
   1345      */
   1346     if (command != NULL) {
   1347         cmd = command;
   1348     }
   1349 
   1350     if (IN_STATIC_MODE(mode)) {
   1351         if (cmd == NULL) {
   1352             length = uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) +
   1353                      uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE;
   1354             if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
   1355                 fprintf(stderr, "Unable to allocate memory for command.\n");
   1356                 return -1;
   1357             }
   1358             freeCmd = TRUE;
   1359         }
   1360         sprintf(cmd, "%s %s %s%s %s",
   1361                 pkgDataFlags[AR],
   1362                 pkgDataFlags[ARFLAGS],
   1363                 targetDir,
   1364                 libFileNames[LIB_FILE_VERSION],
   1365                 objectFile);
   1366 
   1367         result = runCommand(cmd);
   1368         if (result == 0) {
   1369             sprintf(cmd, "%s %s%s",
   1370                     pkgDataFlags[RANLIB],
   1371                     targetDir,
   1372                     libFileNames[LIB_FILE_VERSION]);
   1373 
   1374             result = runCommand(cmd);
   1375         }
   1376     } else /* if (IN_DLL_MODE(mode)) */ {
   1377         if (cmd == NULL) {
   1378             length = uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) +
   1379                      ((uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP])) * 2) +
   1380                      uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) +
   1381                      uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) +
   1382                      uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE;
   1383 #if U_PLATFORM == U_PF_CYGWIN
   1384             length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]);
   1385 #elif U_PLATFORM == U_PF_MINGW
   1386             length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_MINGW]);
   1387 #endif
   1388             if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
   1389                 fprintf(stderr, "Unable to allocate memory for command.\n");
   1390                 return -1;
   1391             }
   1392             freeCmd = TRUE;
   1393         }
   1394 #if U_PLATFORM == U_PF_MINGW
   1395         sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
   1396                 pkgDataFlags[GENLIB],
   1397                 targetDir,
   1398                 libFileNames[LIB_FILE_MINGW],
   1399                 pkgDataFlags[LDICUDTFLAGS],
   1400                 targetDir,
   1401                 libFileNames[LIB_FILE_VERSION_TMP],
   1402 #elif U_PLATFORM == U_PF_CYGWIN
   1403         sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
   1404                 pkgDataFlags[GENLIB],
   1405                 targetDir,
   1406                 libFileNames[LIB_FILE_VERSION_TMP],
   1407                 pkgDataFlags[LDICUDTFLAGS],
   1408                 targetDir,
   1409                 libFileNames[LIB_FILE_CYGWIN_VERSION],
   1410 #elif U_PLATFORM == U_PF_AIX
   1411         sprintf(cmd, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
   1412                 RM_CMD,
   1413                 targetDir,
   1414                 libFileNames[LIB_FILE_VERSION_TMP],
   1415                 pkgDataFlags[GENLIB],
   1416                 pkgDataFlags[LDICUDTFLAGS],
   1417                 targetDir,
   1418                 libFileNames[LIB_FILE_VERSION_TMP],
   1419 #else
   1420         sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
   1421                 pkgDataFlags[GENLIB],
   1422                 pkgDataFlags[LDICUDTFLAGS],
   1423                 targetDir,
   1424                 libFileNames[LIB_FILE_VERSION_TMP],
   1425 #endif
   1426                 objectFile,
   1427                 pkgDataFlags[LD_SONAME],
   1428                 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
   1429                 pkgDataFlags[RPATH_FLAGS],
   1430                 pkgDataFlags[BIR_FLAGS]);
   1431 
   1432         /* Generate the library file. */
   1433         result = runCommand(cmd);
   1434 
   1435 #if U_PLATFORM == U_PF_OS390
   1436         char *env_tmp;
   1437         char PDS_LibName[512];
   1438         char PDS_Name[512];
   1439 
   1440         PDS_Name[0] = 0;
   1441         PDS_LibName[0] = 0;
   1442         if (specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) {
   1443             if (env_tmp = getenv("ICU_PDS_NAME")) {
   1444                 sprintf(PDS_Name, "%s%s",
   1445                         env_tmp,
   1446                         "DA");
   1447                 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
   1448             } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
   1449                 sprintf(PDS_Name, "%s%s",
   1450                         env_tmp,
   1451                         U_ICU_VERSION_SHORT "DA");
   1452             } else {
   1453                 sprintf(PDS_Name, "%s%s",
   1454                         "IXMI",
   1455                         U_ICU_VERSION_SHORT "DA");
   1456             }
   1457         } else if (!specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) {
   1458             if (env_tmp = getenv("ICU_PDS_NAME")) {
   1459                 sprintf(PDS_Name, "%s%s",
   1460                         env_tmp,
   1461                         "D1");
   1462                 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
   1463             } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
   1464                 sprintf(PDS_Name, "%s%s",
   1465                         env_tmp,
   1466                         U_ICU_VERSION_SHORT "D1");
   1467             } else {
   1468                 sprintf(PDS_Name, "%s%s",
   1469                         "IXMI",
   1470                         U_ICU_VERSION_SHORT "D1");
   1471             }
   1472         }
   1473 
   1474         if (PDS_Name[0]) {
   1475             sprintf(PDS_LibName,"%s%s%s%s%s",
   1476                     "\"//'",
   1477                     getenv("LOADMOD"),
   1478                     "(",
   1479                     PDS_Name,
   1480                     ")'\"");
   1481             sprintf(cmd, "%s %s -o %s %s %s%s %s %s",
   1482                    pkgDataFlags[GENLIB],
   1483                    pkgDataFlags[LDICUDTFLAGS],
   1484                    PDS_LibName,
   1485                    objectFile,
   1486                    pkgDataFlags[LD_SONAME],
   1487                    pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
   1488                    pkgDataFlags[RPATH_FLAGS],
   1489                    pkgDataFlags[BIR_FLAGS]);
   1490 
   1491             result = runCommand(cmd);
   1492         }
   1493 #endif
   1494     }
   1495 
   1496     if (result != 0) {
   1497         fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd);
   1498     }
   1499 
   1500     if (freeCmd) {
   1501         uprv_free(cmd);
   1502     }
   1503 
   1504     return result;
   1505 }
   1506 
   1507 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
   1508     char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
   1509     char *cmd;
   1510     int32_t result = 0;
   1511 
   1512     int32_t length = 0;
   1513 
   1514     /* Remove the ending .s and replace it with .o for the new object file. */
   1515     uprv_strcpy(tempObjectFile, gencFilePath);
   1516     tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
   1517 
   1518     length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
   1519                     + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE;
   1520 
   1521     cmd = (char *)uprv_malloc(sizeof(char) * length);
   1522     if (cmd == NULL) {
   1523         return -1;
   1524     }
   1525 
   1526     /* Generate the object file. */
   1527     sprintf(cmd, "%s %s -o %s %s",
   1528             pkgDataFlags[COMPILER],
   1529             pkgDataFlags[LIBFLAGS],
   1530             tempObjectFile,
   1531             gencFilePath);
   1532 
   1533     result = runCommand(cmd);
   1534     uprv_free(cmd);
   1535     if (result != 0) {
   1536         fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd);
   1537         return result;
   1538     }
   1539 
   1540     return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
   1541 }
   1542 
   1543 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
   1544 /*
   1545  * Generation of the data library without assembly code needs to compile each data file
   1546  * individually and then link it all together.
   1547  * Note: Any update to the directory structure of the data needs to be reflected here.
   1548  */
   1549 enum {
   1550     DATA_PREFIX_BRKITR,
   1551     DATA_PREFIX_COLL,
   1552     DATA_PREFIX_CURR,
   1553     DATA_PREFIX_LANG,
   1554     DATA_PREFIX_RBNF,
   1555     DATA_PREFIX_REGION,
   1556     DATA_PREFIX_TRANSLIT,
   1557     DATA_PREFIX_ZONE,
   1558     DATA_PREFIX_UNIT,
   1559     DATA_PREFIX_LENGTH
   1560 };
   1561 
   1562 const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
   1563         "brkitr",
   1564         "coll",
   1565         "curr",
   1566         "lang",
   1567         "rbnf",
   1568         "region",
   1569         "translit",
   1570         "zone",
   1571         "unit"
   1572 };
   1573 
   1574 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
   1575     int32_t result = 0;
   1576     CharList *list = o->filePaths;
   1577     CharList *listNames = o->files;
   1578     int32_t listSize = pkg_countCharList(list);
   1579     char *buffer;
   1580     char *cmd;
   1581     char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
   1582     char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
   1583 #ifdef USE_SINGLE_CCODE_FILE
   1584     char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
   1585     FileStream *icudtAllFile = NULL;
   1586 
   1587     sprintf(icudtAll, "%s%s%sall.c",
   1588             o->tmpDir,
   1589             PKGDATA_FILE_SEP_STRING,
   1590             libFileNames[LIB_FILE]);
   1591     /* Remove previous icudtall.c file. */
   1592     if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
   1593         fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
   1594         return result;
   1595     }
   1596 
   1597     if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==NULL) {
   1598         fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll);
   1599         return result;
   1600     }
   1601 #endif
   1602 
   1603     if (list == NULL || listNames == NULL) {
   1604         /* list and listNames should never be NULL since we are looping through the CharList with
   1605          * the given size.
   1606          */
   1607         return -1;
   1608     }
   1609 
   1610     if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
   1611         fprintf(stderr, "Unable to allocate memory for cmd.\n");
   1612         return -1;
   1613     } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
   1614         fprintf(stderr, "Unable to allocate memory for buffer.\n");
   1615         uprv_free(cmd);
   1616         return -1;
   1617     }
   1618 
   1619     for (int32_t i = 0; i < (listSize + 1); i++) {
   1620         const char *file ;
   1621         const char *name;
   1622 
   1623         if (i == 0) {
   1624             /* The first iteration calls the gencmn function and initailizes the buffer. */
   1625             createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
   1626             buffer[0] = 0;
   1627 #ifdef USE_SINGLE_CCODE_FILE
   1628             uprv_strcpy(tempObjectFile, gencmnFile);
   1629             tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
   1630 
   1631             sprintf(cmd, "%s %s -o %s %s",
   1632                         pkgDataFlags[COMPILER],
   1633                         pkgDataFlags[LIBFLAGS],
   1634                         tempObjectFile,
   1635                         gencmnFile);
   1636 
   1637             result = runCommand(cmd);
   1638             if (result != 0) {
   1639                 break;
   1640             }
   1641 
   1642             sprintf(buffer, "%s",tempObjectFile);
   1643 #endif
   1644         } else {
   1645             char newName[SMALL_BUFFER_MAX_SIZE];
   1646             char dataName[SMALL_BUFFER_MAX_SIZE];
   1647             char dataDirName[SMALL_BUFFER_MAX_SIZE];
   1648             const char *pSubstring;
   1649             file = list->str;
   1650             name = listNames->str;
   1651 
   1652             newName[0] = dataName[0] = 0;
   1653             for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
   1654                 dataDirName[0] = 0;
   1655                 sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
   1656                 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
   1657                 pSubstring = uprv_strstr(name, dataDirName);
   1658                 if (pSubstring != NULL) {
   1659                     char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
   1660                     const char *p = name + uprv_strlen(dataDirName);
   1661                     for (int32_t i = 0;;i++) {
   1662                         if (p[i] == '.') {
   1663                             newNameTmp[i] = '_';
   1664                             continue;
   1665                         }
   1666                         newNameTmp[i] = p[i];
   1667                         if (p[i] == 0) {
   1668                             break;
   1669                         }
   1670                     }
   1671                     sprintf(newName, "%s_%s",
   1672                             DATA_PREFIX[n],
   1673                             newNameTmp);
   1674                     sprintf(dataName, "%s_%s",
   1675                             o->shortName,
   1676                             DATA_PREFIX[n]);
   1677                 }
   1678                 if (newName[0] != 0) {
   1679                     break;
   1680                 }
   1681             }
   1682 
   1683             if(o->verbose) {
   1684               printf("# Generating %s \n", gencmnFile);
   1685             }
   1686 
   1687             writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
   1688 
   1689 #ifdef USE_SINGLE_CCODE_FILE
   1690             sprintf(cmd, "#include \"%s\"\n", gencmnFile);
   1691             T_FileStream_writeLine(icudtAllFile, cmd);
   1692             /* don't delete the file */
   1693 #endif
   1694         }
   1695 
   1696 #ifndef USE_SINGLE_CCODE_FILE
   1697         uprv_strcpy(tempObjectFile, gencmnFile);
   1698         tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
   1699 
   1700         sprintf(cmd, "%s %s -o %s %s",
   1701                     pkgDataFlags[COMPILER],
   1702                     pkgDataFlags[LIBFLAGS],
   1703                     tempObjectFile,
   1704                     gencmnFile);
   1705         result = runCommand(cmd);
   1706         if (result != 0) {
   1707             fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
   1708             break;
   1709         }
   1710 
   1711         uprv_strcat(buffer, " ");
   1712         uprv_strcat(buffer, tempObjectFile);
   1713 
   1714 #endif
   1715 
   1716         if (i > 0) {
   1717             list = list->next;
   1718             listNames = listNames->next;
   1719         }
   1720     }
   1721 
   1722 #ifdef USE_SINGLE_CCODE_FILE
   1723     T_FileStream_close(icudtAllFile);
   1724     uprv_strcpy(tempObjectFile, icudtAll);
   1725     tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
   1726 
   1727     sprintf(cmd, "%s %s -I. -o %s %s",
   1728         pkgDataFlags[COMPILER],
   1729         pkgDataFlags[LIBFLAGS],
   1730         tempObjectFile,
   1731         icudtAll);
   1732 
   1733     result = runCommand(cmd);
   1734     if (result == 0) {
   1735         uprv_strcat(buffer, " ");
   1736         uprv_strcat(buffer, tempObjectFile);
   1737     } else {
   1738         fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
   1739     }
   1740 #endif
   1741 
   1742     if (result == 0) {
   1743         /* Generate the library file. */
   1744 #if U_PLATFORM == U_PF_OS390
   1745         result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd, (o->pdsbuild && IN_DLL_MODE(mode)));
   1746 #else
   1747         result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
   1748 #endif
   1749     }
   1750 
   1751     uprv_free(buffer);
   1752     uprv_free(cmd);
   1753 
   1754     return result;
   1755 }
   1756 #endif
   1757 
   1758 #ifdef WINDOWS_WITH_MSVC
   1759 #define LINK_CMD "link.exe /nologo /release /out:"
   1760 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /implib:"
   1761 #ifdef _WIN64
   1762 #define LINK_EXTRA_UWP_FLAGS "/NXCOMPAT /DYNAMICBASE /APPCONTAINER "
   1763 #else
   1764 #define LINK_EXTRA_UWP_FLAGS "/NXCOMPAT /SAFESEH /DYNAMICBASE /APPCONTAINER /MACHINE:X86"
   1765 #endif
   1766 #define LINK_EXTRA_UWP_FLAGS_ARM "/NXCOMPAT /DYNAMICBASE /APPCONTAINER /MACHINE:ARM"
   1767 #define LINK_EXTRA_NO_UWP_FLAGS "/base:0x4ad00000 "
   1768 #define LIB_CMD "LIB.exe /nologo /out:"
   1769 #define LIB_FILE "icudt.lib"
   1770 #define LIB_EXT UDATA_LIB_SUFFIX
   1771 #define DLL_EXT UDATA_SO_SUFFIX
   1772 
   1773 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
   1774     int32_t result = 0;
   1775     char cmd[LARGE_BUFFER_MAX_SIZE];
   1776     if (IN_STATIC_MODE(mode)) {
   1777         char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1778 
   1779 #ifdef CYGWINMSVC
   1780         sprintf(staticLibFilePath, "%s%s%s%s%s",
   1781                 o->targetDir,
   1782                 PKGDATA_FILE_SEP_STRING,
   1783                 pkgDataFlags[LIBPREFIX],
   1784                 o->libName,
   1785                 LIB_EXT);
   1786 #else
   1787         sprintf(staticLibFilePath, "%s%s%s%s%s",
   1788                 o->targetDir,
   1789                 PKGDATA_FILE_SEP_STRING,
   1790                 (strstr(o->libName, "icudt") ? "s" : ""),
   1791                 o->libName,
   1792                 LIB_EXT);
   1793 #endif
   1794 
   1795         sprintf(cmd, "%s\"%s\" \"%s\"",
   1796                 LIB_CMD,
   1797                 staticLibFilePath,
   1798                 gencFilePath);
   1799     } else if (IN_DLL_MODE(mode)) {
   1800         char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1801         char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1802         char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1803         char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1804 
   1805 #ifdef CYGWINMSVC
   1806         uprv_strcpy(dllFilePath, o->targetDir);
   1807 #else
   1808         uprv_strcpy(dllFilePath, o->srcDir);
   1809 #endif
   1810         uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
   1811         uprv_strcpy(libFilePath, dllFilePath);
   1812 
   1813 #ifdef CYGWINMSVC
   1814         uprv_strcat(libFilePath, o->libName);
   1815         uprv_strcat(libFilePath, ".lib");
   1816 
   1817         uprv_strcat(dllFilePath, o->libName);
   1818         uprv_strcat(dllFilePath, o->version);
   1819 #else
   1820         if (strstr(o->libName, "icudt")) {
   1821             uprv_strcat(libFilePath, LIB_FILE);
   1822         } else {
   1823             uprv_strcat(libFilePath, o->libName);
   1824             uprv_strcat(libFilePath, ".lib");
   1825         }
   1826         uprv_strcat(dllFilePath, o->entryName);
   1827 #endif
   1828         uprv_strcat(dllFilePath, DLL_EXT);
   1829 
   1830         uprv_strcpy(tmpResFilePath, o->tmpDir);
   1831         uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
   1832         uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
   1833 
   1834         if (T_FileStream_file_exists(tmpResFilePath)) {
   1835             sprintf(resFilePath, "\"%s\"", tmpResFilePath);
   1836         }
   1837 
   1838         /* Check if dll file and lib file exists and that it is not newer than genc file. */
   1839         if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
   1840             (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
   1841           if(o->verbose) {
   1842             printf("# Not rebuilding %s - up to date.\n", gencFilePath);
   1843           }
   1844           return 0;
   1845         }
   1846 
   1847         char *extraFlags = "";
   1848 #ifdef WINDOWS_WITH_MSVC
   1849         if (options[UWP_BUILD].doesOccur)
   1850         {
   1851             if (options[UWP_ARM_BUILD].doesOccur)
   1852             {
   1853                 extraFlags = LINK_EXTRA_UWP_FLAGS_ARM;
   1854             }
   1855             else
   1856             {
   1857                 extraFlags = LINK_EXTRA_UWP_FLAGS;
   1858             }
   1859         }
   1860         else
   1861         {
   1862             extraFlags = LINK_EXTRA_NO_UWP_FLAGS;
   1863         }
   1864 #endif
   1865         sprintf(cmd, "%s\"%s\" %s %s\"%s\" \"%s\" %s",
   1866             LINK_CMD,
   1867             dllFilePath,
   1868             extraFlags,
   1869             LINK_FLAGS,
   1870             libFilePath,
   1871             gencFilePath,
   1872             resFilePath
   1873         );
   1874     }
   1875 
   1876     result = runCommand(cmd, TRUE);
   1877     if (result != 0) {
   1878         fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd);
   1879     }
   1880 
   1881     return result;
   1882 }
   1883 #endif
   1884 
   1885 static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
   1886 #if U_PLATFORM == U_PF_AIX
   1887     /* AIX needs a map file. */
   1888     char *flag = NULL;
   1889     int32_t length = 0;
   1890     char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
   1891     const char MAP_FILE_EXT[] = ".map";
   1892     FileStream *f = NULL;
   1893     char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
   1894     int32_t start = -1;
   1895     uint32_t count = 0;
   1896     const char rm_cmd[] = "rm -f all ;";
   1897 
   1898     flag = pkgDataFlags[GENLIB];
   1899 
   1900     /* This portion of the code removes 'rm -f all' in the GENLIB.
   1901      * Only occurs in AIX.
   1902      */
   1903     if (uprv_strstr(flag, rm_cmd) != NULL) {
   1904         char *tmpGenlibFlagBuffer = NULL;
   1905         int32_t i, offset;
   1906 
   1907         length = uprv_strlen(flag) + 1;
   1908         tmpGenlibFlagBuffer = (char *)uprv_malloc(length);
   1909         if (tmpGenlibFlagBuffer == NULL) {
   1910             /* Memory allocation error */
   1911             fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length);
   1912             return NULL;
   1913         }
   1914 
   1915         uprv_strcpy(tmpGenlibFlagBuffer, flag);
   1916 
   1917         offset = uprv_strlen(rm_cmd);
   1918 
   1919         for (i = 0; i < (length - offset); i++) {
   1920             flag[i] = tmpGenlibFlagBuffer[offset + i];
   1921         }
   1922 
   1923         /* Zero terminate the string */
   1924         flag[i] = 0;
   1925 
   1926         uprv_free(tmpGenlibFlagBuffer);
   1927     }
   1928 
   1929     flag = pkgDataFlags[BIR_FLAGS];
   1930     length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
   1931 
   1932     for (int32_t i = 0; i < length; i++) {
   1933         if (flag[i] == MAP_FILE_EXT[count]) {
   1934             if (count == 0) {
   1935                 start = i;
   1936             }
   1937             count++;
   1938         } else {
   1939             count = 0;
   1940         }
   1941 
   1942         if (count == uprv_strlen(MAP_FILE_EXT)) {
   1943             break;
   1944         }
   1945     }
   1946 
   1947     if (start >= 0) {
   1948         int32_t index = 0;
   1949         for (int32_t i = 0;;i++) {
   1950             if (i == start) {
   1951                 for (int32_t n = 0;;n++) {
   1952                     if (o->shortName[n] == 0) {
   1953                         break;
   1954                     }
   1955                     tmpbuffer[index++] = o->shortName[n];
   1956                 }
   1957             }
   1958 
   1959             tmpbuffer[index++] = flag[i];
   1960 
   1961             if (flag[i] == 0) {
   1962                 break;
   1963             }
   1964         }
   1965 
   1966         uprv_memset(flag, 0, length);
   1967         uprv_strcpy(flag, tmpbuffer);
   1968 
   1969         uprv_strcpy(mapFile, o->shortName);
   1970         uprv_strcat(mapFile, MAP_FILE_EXT);
   1971 
   1972         f = T_FileStream_open(mapFile, "w");
   1973         if (f == NULL) {
   1974             fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
   1975             return NULL;
   1976         } else {
   1977             sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
   1978 
   1979             T_FileStream_writeLine(f, tmpbuffer);
   1980 
   1981             T_FileStream_close(f);
   1982         }
   1983     }
   1984 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
   1985     /* Cygwin needs to change flag options. */
   1986     char *flag = NULL;
   1987     int32_t length = 0;
   1988 
   1989     flag = pkgDataFlags[GENLIB];
   1990     length = uprv_strlen(pkgDataFlags[GENLIB]);
   1991 
   1992     int32_t position = length - 1;
   1993 
   1994     for(;position >= 0;position--) {
   1995         if (flag[position] == '=') {
   1996             position++;
   1997             break;
   1998         }
   1999     }
   2000 
   2001     uprv_memset(flag + position, 0, length - position);
   2002 #elif U_PLATFORM == U_PF_OS400
   2003     /* OS/400 needs to fix the ld options (swap single quote with double quote) */
   2004     char *flag = NULL;
   2005     int32_t length = 0;
   2006 
   2007     flag = pkgDataFlags[GENLIB];
   2008     length = uprv_strlen(pkgDataFlags[GENLIB]);
   2009 
   2010     int32_t position = length - 1;
   2011 
   2012     for(int32_t i = 0; i < length; i++) {
   2013         if (flag[i] == '\'') {
   2014             flag[i] = '\"';
   2015         }
   2016     }
   2017 #endif
   2018     // Don't really need a return value, just need to stop compiler warnings about
   2019     // the unused parameter 'o' on platforms where it is not otherwise used.
   2020     return o;
   2021 }
   2022 
   2023 static void loadLists(UPKGOptions *o, UErrorCode *status)
   2024 {
   2025     CharList   *l, *tail = NULL, *tail2 = NULL;
   2026     FileStream *in;
   2027     char        line[16384];
   2028     char       *linePtr, *lineNext;
   2029     const uint32_t   lineMax = 16300;
   2030     char       *tmp;
   2031     int32_t     tmpLength = 0;
   2032     char       *s;
   2033     int32_t     ln=0; /* line number */
   2034 
   2035     for(l = o->fileListFiles; l; l = l->next) {
   2036         if(o->verbose) {
   2037             fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
   2038         }
   2039         /* TODO: stdin */
   2040         in = T_FileStream_open(l->str, "r"); /* open files list */
   2041 
   2042         if(!in) {
   2043             fprintf(stderr, "Error opening <%s>.\n", l->str);
   2044             *status = U_FILE_ACCESS_ERROR;
   2045             return;
   2046         }
   2047 
   2048         while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
   2049             ln++;
   2050             if(uprv_strlen(line)>lineMax) {
   2051                 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
   2052                 exit(1);
   2053             }
   2054             /* remove spaces at the beginning */
   2055             linePtr = line;
   2056             /* On z/OS, disable call to isspace (#9996).  Investigate using uprv_isspace instead (#9999) */
   2057 #if U_PLATFORM != U_PF_OS390
   2058             while(isspace(*linePtr)) {
   2059                 linePtr++;
   2060             }
   2061 #endif
   2062             s=linePtr;
   2063             /* remove trailing newline characters */
   2064             while(*s!=0) {
   2065                 if(*s=='\r' || *s=='\n') {
   2066                     *s=0;
   2067                     break;
   2068                 }
   2069                 ++s;
   2070             }
   2071             if((*linePtr == 0) || (*linePtr == '#')) {
   2072                 continue; /* comment or empty line */
   2073             }
   2074 
   2075             /* Now, process the line */
   2076             lineNext = NULL;
   2077 
   2078             while(linePtr && *linePtr) { /* process space-separated items */
   2079                 while(*linePtr == ' ') {
   2080                     linePtr++;
   2081                 }
   2082                 /* Find the next quote */
   2083                 if(linePtr[0] == '"')
   2084                 {
   2085                     lineNext = uprv_strchr(linePtr+1, '"');
   2086                     if(lineNext == NULL) {
   2087                         fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
   2088                             l->str, (int)ln);
   2089                         exit(1);
   2090                     } else {
   2091                         lineNext++;
   2092                         if(*lineNext) {
   2093                             if(*lineNext != ' ') {
   2094                                 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
   2095                                     l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
   2096                                 exit(1);
   2097                             }
   2098                             *lineNext = 0;
   2099                             lineNext++;
   2100                         }
   2101                     }
   2102                 } else {
   2103                     lineNext = uprv_strchr(linePtr, ' ');
   2104                     if(lineNext) {
   2105                         *lineNext = 0; /* terminate at space */
   2106                         lineNext++;
   2107                     }
   2108                 }
   2109 
   2110                 /* add the file */
   2111                 s = (char*)getLongPathname(linePtr);
   2112 
   2113                 /* normal mode.. o->files is just the bare list without package names */
   2114                 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
   2115                 if(uprv_pathIsAbsolute(s) || s[0] == '.') {
   2116                     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);
   2117                     exit(U_ILLEGAL_ARGUMENT_ERROR);
   2118                 }
   2119                 tmpLength = uprv_strlen(o->srcDir) +
   2120                             uprv_strlen(s) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
   2121                 if((tmp = (char *)uprv_malloc(tmpLength)) == NULL) {
   2122                     fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength);
   2123                     exit(U_MEMORY_ALLOCATION_ERROR);
   2124                 }
   2125                 uprv_strcpy(tmp, o->srcDir);
   2126                 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING);
   2127                 uprv_strcat(tmp, s);
   2128                 o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp);
   2129                 linePtr = lineNext;
   2130             } /* for each entry on line */
   2131         } /* for each line */
   2132         T_FileStream_close(in);
   2133     } /* for each file list file */
   2134 }
   2135 
   2136 /* Try calling icu-config directly to get the option file. */
   2137  static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
   2138 #if U_HAVE_POPEN
   2139     LocalPipeFilePointer p;
   2140     size_t n;
   2141     static char buf[512] = "";
   2142     icu::CharString cmdBuf;
   2143     UErrorCode status = U_ZERO_ERROR;
   2144     const char cmd[] = "icu-config --incpkgdatafile";
   2145     char dirBuf[1024] = "";
   2146     /* #1 try the same path where pkgdata was called from. */
   2147     findDirname(progname, dirBuf, UPRV_LENGTHOF(dirBuf), &status);
   2148     if(U_SUCCESS(status)) {
   2149       cmdBuf.append(dirBuf, status);
   2150       if (cmdBuf[0] != 0) {
   2151         cmdBuf.append( U_FILE_SEP_STRING, status );
   2152       }
   2153       cmdBuf.append( cmd, status );
   2154 
   2155       if(verbose) {
   2156         fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf.data());
   2157       }
   2158       p.adoptInstead(popen(cmdBuf.data(), "r"));
   2159     }
   2160 
   2161     if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) {
   2162         if(verbose) {
   2163             fprintf(stdout, "# Calling icu-config: %s\n", cmd);
   2164         }
   2165 
   2166         p.adoptInstead(popen(cmd, "r"));
   2167         if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) {
   2168             fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
   2169             return -1;
   2170         }
   2171     }
   2172 
   2173     for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
   2174         if (buf[length] == '\n' || buf[length] == ' ') {
   2175             buf[length] = 0;
   2176         } else {
   2177             break;
   2178         }
   2179     }
   2180 
   2181     if(buf[strlen(buf)-1]=='\n')
   2182     {
   2183         buf[strlen(buf)-1]=0;
   2184     }
   2185 
   2186     if(buf[0] == 0)
   2187     {
   2188         fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
   2189         return -1;
   2190     }
   2191 
   2192     if(verbose) {
   2193       fprintf(stdout, "# icu-config said: %s\n", buf);
   2194     }
   2195 
   2196     option->value = buf;
   2197     option->doesOccur = TRUE;
   2198 
   2199     return 0;
   2200 #else
   2201     return -1;
   2202 #endif
   2203 }
   2204 
   2205 #ifdef CAN_WRITE_OBJ_CODE
   2206  /* Create optMatchArch for genccode architecture detection */
   2207 static void pkg_createOptMatchArch(char *optMatchArch) {
   2208 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
   2209     const char* code = "void oma(){}";
   2210     const char* source = "oma.c";
   2211     const char* obj = "oma.obj";
   2212     FileStream* stream = NULL;
   2213 
   2214     stream = T_FileStream_open(source,"w");
   2215     if (stream != NULL) {
   2216         T_FileStream_writeLine(stream, code);
   2217         T_FileStream_close(stream);
   2218 
   2219         char cmd[LARGE_BUFFER_MAX_SIZE];
   2220         sprintf(cmd, "%s %s -o %s",
   2221             pkgDataFlags[COMPILER],
   2222             source,
   2223             obj);
   2224 
   2225         if (runCommand(cmd) == 0){
   2226             sprintf(optMatchArch, "%s", obj);
   2227         }
   2228         else {
   2229             fprintf(stderr, "Failed to compile %s\n", source);
   2230         }
   2231         if(!T_FileStream_remove(source)){
   2232             fprintf(stderr, "T_FileStream_remove failed to delete %s\n", source);
   2233         }
   2234     }
   2235     else {
   2236         fprintf(stderr, "T_FileStream_open failed to open %s for writing\n", source);
   2237     }
   2238 #endif
   2239 }
   2240 static void pkg_destroyOptMatchArch(char *optMatchArch) {
   2241     if(T_FileStream_file_exists(optMatchArch) && !T_FileStream_remove(optMatchArch)){
   2242         fprintf(stderr, "T_FileStream_remove failed to delete %s\n", optMatchArch);
   2243     }
   2244 }
   2245 #endif
   2246