intl/icu/source/tools/pkgdata/pkgdata.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/tools/pkgdata/pkgdata.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2041 @@
     1.4 +/******************************************************************************
     1.5 + *   Copyright (C) 2000-2013, International Business Machines
     1.6 + *   Corporation and others.  All Rights Reserved.
     1.7 + *******************************************************************************
     1.8 + *   file name:  pkgdata.cpp
     1.9 + *   encoding:   ANSI X3.4 (1968)
    1.10 + *   tab size:   8 (not used)
    1.11 + *   indentation:4
    1.12 + *
    1.13 + *   created on: 2000may15
    1.14 + *   created by: Steven \u24C7 Loomis
    1.15 + *
    1.16 + *   This program packages the ICU data into different forms
    1.17 + *   (DLL, common data, etc.)
    1.18 + */
    1.19 +
    1.20 +// Defines _XOPEN_SOURCE for access to POSIX functions.
    1.21 +// Must be before any other #includes.
    1.22 +#include "uposixdefs.h"
    1.23 +
    1.24 +#include "unicode/utypes.h"
    1.25 +
    1.26 +#include "unicode/putil.h"
    1.27 +#include "putilimp.h"
    1.28 +
    1.29 +#if U_HAVE_POPEN
    1.30 +#if (U_PF_MINGW <= U_PLATFORM || U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__)
    1.31 +/* popen/pclose aren't defined in strict ANSI on Cygwin and MinGW */
    1.32 +#undef __STRICT_ANSI__
    1.33 +#endif
    1.34 +#endif
    1.35 +
    1.36 +#include "cmemory.h"
    1.37 +#include "cstring.h"
    1.38 +#include "filestrm.h"
    1.39 +#include "toolutil.h"
    1.40 +#include "unicode/uclean.h"
    1.41 +#include "unewdata.h"
    1.42 +#include "uoptions.h"
    1.43 +#include "package.h"
    1.44 +#include "pkg_icu.h"
    1.45 +#include "pkg_genc.h"
    1.46 +#include "pkg_gencmn.h"
    1.47 +#include "flagparser.h"
    1.48 +#include "filetools.h"
    1.49 +
    1.50 +#if U_HAVE_POPEN
    1.51 +# include <unistd.h>
    1.52 +#endif
    1.53 +
    1.54 +#include <stdio.h>
    1.55 +#include <stdlib.h>
    1.56 +
    1.57 +U_CDECL_BEGIN
    1.58 +#include "pkgtypes.h"
    1.59 +U_CDECL_END
    1.60 +
    1.61 +
    1.62 +static void loadLists(UPKGOptions *o, UErrorCode *status);
    1.63 +
    1.64 +static int32_t pkg_executeOptions(UPKGOptions *o);
    1.65 +
    1.66 +#ifdef WINDOWS_WITH_MSVC
    1.67 +static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
    1.68 +#endif
    1.69 +static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE);
    1.70 +static int32_t pkg_installLibrary(const char *installDir, const char *dir, UBool noVersion);
    1.71 +static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
    1.72 +static int32_t pkg_installCommonMode(const char *installDir, const char *fileName);
    1.73 +
    1.74 +#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
    1.75 +static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
    1.76 +#endif
    1.77 +
    1.78 +static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
    1.79 +static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL);
    1.80 +static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
    1.81 +static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion);
    1.82 +static int32_t initializePkgDataFlags(UPKGOptions *o);
    1.83 +
    1.84 +static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option);
    1.85 +static int runCommand(const char* command, UBool specialHandling=FALSE);
    1.86 +
    1.87 +#define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
    1.88 +#define IN_DLL_MODE(mode)    (mode == 'd' || mode == 'l')
    1.89 +#define IN_STATIC_MODE(mode) (mode == 's')
    1.90 +#define IN_FILES_MODE(mode)  (mode == 'f')
    1.91 +
    1.92 +enum {
    1.93 +    NAME,
    1.94 +    BLDOPT,
    1.95 +    MODE,
    1.96 +    HELP,
    1.97 +    HELP_QUESTION_MARK,
    1.98 +    VERBOSE,
    1.99 +    COPYRIGHT,
   1.100 +    COMMENT,
   1.101 +    DESTDIR,
   1.102 +    REBUILD,
   1.103 +    TEMPDIR,
   1.104 +    INSTALL,
   1.105 +    SOURCEDIR,
   1.106 +    ENTRYPOINT,
   1.107 +    REVISION,
   1.108 +    FORCE_PREFIX,
   1.109 +    LIBNAME,
   1.110 +    QUIET,
   1.111 +    WITHOUT_ASSEMBLY,
   1.112 +    PDS_BUILD
   1.113 +};
   1.114 +
   1.115 +/* This sets the modes that are available */
   1.116 +static struct {
   1.117 +    const char *name, *alt_name;
   1.118 +    const char *desc;
   1.119 +} modes[] = {
   1.120 +        { "files", 0,           "Uses raw data files (no effect). Installation copies all files to the target location." },
   1.121 +#if U_PLATFORM_HAS_WIN32_API
   1.122 +        { "dll",    "library",  "Generates one common data file and one shared library, <package>.dll"},
   1.123 +        { "common", "archive",  "Generates just the common file, <package>.dat"},
   1.124 +        { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
   1.125 +#else
   1.126 +#ifdef UDATA_SO_SUFFIX
   1.127 +        { "dll",    "library",  "Generates one shared library, <package>" UDATA_SO_SUFFIX },
   1.128 +#endif
   1.129 +        { "common", "archive",  "Generates one common data file, <package>.dat" },
   1.130 +        { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
   1.131 +#endif
   1.132 +};
   1.133 +
   1.134 +static UOption options[]={
   1.135 +    /*00*/    UOPTION_DEF( "name",    'p', UOPT_REQUIRES_ARG),
   1.136 +    /*01*/    UOPTION_DEF( "bldopt",  'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
   1.137 +    /*02*/    UOPTION_DEF( "mode",    'm', UOPT_REQUIRES_ARG),
   1.138 +    /*03*/    UOPTION_HELP_H,                                   /* -h */
   1.139 +    /*04*/    UOPTION_HELP_QUESTION_MARK,                       /* -? */
   1.140 +    /*05*/    UOPTION_VERBOSE,                                  /* -v */
   1.141 +    /*06*/    UOPTION_COPYRIGHT,                                /* -c */
   1.142 +    /*07*/    UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
   1.143 +    /*08*/    UOPTION_DESTDIR,                                  /* -d */
   1.144 +    /*11*/    UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
   1.145 +    /*12*/    UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
   1.146 +    /*13*/    UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
   1.147 +    /*14*/    UOPTION_SOURCEDIR ,
   1.148 +    /*15*/    UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
   1.149 +    /*16*/    UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
   1.150 +    /*17*/    UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
   1.151 +    /*18*/    UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
   1.152 +    /*19*/    UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG),
   1.153 +    /*20*/    UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG),
   1.154 +    /*21*/    UOPTION_DEF( "zos-pds-build", 'z', UOPT_NO_ARG)
   1.155 +};
   1.156 +
   1.157 +/* This enum and the following char array should be kept in sync. */
   1.158 +enum {
   1.159 +    GENCCODE_ASSEMBLY_TYPE,
   1.160 +    SO_EXT,
   1.161 +    SOBJ_EXT,
   1.162 +    A_EXT,
   1.163 +    LIBPREFIX,
   1.164 +    LIB_EXT_ORDER,
   1.165 +    COMPILER,
   1.166 +    LIBFLAGS,
   1.167 +    GENLIB,
   1.168 +    LDICUDTFLAGS,
   1.169 +    LD_SONAME,
   1.170 +    RPATH_FLAGS,
   1.171 +    BIR_FLAGS,
   1.172 +    AR,
   1.173 +    ARFLAGS,
   1.174 +    RANLIB,
   1.175 +    INSTALL_CMD,
   1.176 +    PKGDATA_FLAGS_SIZE
   1.177 +};
   1.178 +static const char* FLAG_NAMES[PKGDATA_FLAGS_SIZE] = {
   1.179 +        "GENCCODE_ASSEMBLY_TYPE",
   1.180 +        "SO",
   1.181 +        "SOBJ",
   1.182 +        "A",
   1.183 +        "LIBPREFIX",
   1.184 +        "LIB_EXT_ORDER",
   1.185 +        "COMPILE",
   1.186 +        "LIBFLAGS",
   1.187 +        "GENLIB",
   1.188 +        "LDICUDTFLAGS",
   1.189 +        "LD_SONAME",
   1.190 +        "RPATH_FLAGS",
   1.191 +        "BIR_LDFLAGS",
   1.192 +        "AR",
   1.193 +        "ARFLAGS",
   1.194 +        "RANLIB",
   1.195 +        "INSTALL_CMD"
   1.196 +};
   1.197 +static char **pkgDataFlags = NULL;
   1.198 +
   1.199 +enum {
   1.200 +    LIB_FILE,
   1.201 +    LIB_FILE_VERSION_MAJOR,
   1.202 +    LIB_FILE_VERSION,
   1.203 +    LIB_FILE_VERSION_TMP,
   1.204 +#if U_PLATFORM == U_PF_CYGWIN
   1.205 +    LIB_FILE_CYGWIN,
   1.206 +    LIB_FILE_CYGWIN_VERSION,
   1.207 +#elif U_PLATFORM == U_PF_MINGW
   1.208 +    LIB_FILE_MINGW,
   1.209 +#endif
   1.210 +    LIB_FILENAMES_SIZE
   1.211 +};
   1.212 +static char libFileNames[LIB_FILENAMES_SIZE][256];
   1.213 +
   1.214 +static UPKGOptions  *pkg_checkFlag(UPKGOptions *o);
   1.215 +
   1.216 +const char options_help[][320]={
   1.217 +    "Set the data name",
   1.218 +#ifdef U_MAKE_IS_NMAKE
   1.219 +    "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
   1.220 +#else
   1.221 +    "Specify options for the builder.",
   1.222 +#endif
   1.223 +    "Specify the mode of building (see below; default: common)",
   1.224 +    "This usage text",
   1.225 +    "This usage text",
   1.226 +    "Make the output verbose",
   1.227 +    "Use the standard ICU copyright",
   1.228 +    "Use a custom comment (instead of the copyright)",
   1.229 +    "Specify the destination directory for files",
   1.230 +    "Force rebuilding of all data",
   1.231 +    "Specify temporary dir (default: output dir)",
   1.232 +    "Install the data (specify target)",
   1.233 +    "Specify a custom source directory",
   1.234 +    "Specify a custom entrypoint name (default: short name)",
   1.235 +    "Specify a version when packaging in dll or static mode",
   1.236 +    "Add package to all file names if not present",
   1.237 +    "Library name to build (if different than package name)",
   1.238 +    "Quite mode. (e.g. Do not output a readme file for static libraries)",
   1.239 +    "Build the data without assembly code"
   1.240 +};
   1.241 +
   1.242 +const char  *progname = "PKGDATA";
   1.243 +
   1.244 +int
   1.245 +main(int argc, char* argv[]) {
   1.246 +    int result = 0;
   1.247 +    /* FileStream  *out; */
   1.248 +    UPKGOptions  o;
   1.249 +    CharList    *tail;
   1.250 +    UBool        needsHelp = FALSE;
   1.251 +    UErrorCode   status = U_ZERO_ERROR;
   1.252 +    /* char         tmp[1024]; */
   1.253 +    uint32_t i;
   1.254 +    int32_t n;
   1.255 +
   1.256 +    U_MAIN_INIT_ARGS(argc, argv);
   1.257 +
   1.258 +    progname = argv[0];
   1.259 +
   1.260 +    options[MODE].value = "common";
   1.261 +
   1.262 +    /* read command line options */
   1.263 +    argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
   1.264 +
   1.265 +    /* error handling, printing usage message */
   1.266 +    /* I've decided to simply print an error and quit. This tool has too
   1.267 +    many options to just display them all of the time. */
   1.268 +
   1.269 +    if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
   1.270 +        needsHelp = TRUE;
   1.271 +    }
   1.272 +    else {
   1.273 +        if(!needsHelp && argc<0) {
   1.274 +            fprintf(stderr,
   1.275 +                "%s: error in command line argument \"%s\"\n",
   1.276 +                progname,
   1.277 +                argv[-argc]);
   1.278 +            fprintf(stderr, "Run '%s --help' for help.\n", progname);
   1.279 +            return 1;
   1.280 +        }
   1.281 +
   1.282 +
   1.283 +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
   1.284 +        if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) {
   1.285 +          if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) {
   1.286 +                fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n");
   1.287 +                fprintf(stderr, "Run '%s --help' for help.\n", progname);
   1.288 +                return 1;
   1.289 +            }
   1.290 +        }
   1.291 +#else
   1.292 +        if(options[BLDOPT].doesOccur) {
   1.293 +            fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
   1.294 +        }
   1.295 +#endif
   1.296 +
   1.297 +        if(!options[NAME].doesOccur) /* -O we already have - don't report it. */
   1.298 +        {
   1.299 +            fprintf(stderr, " required parameter -p is missing \n");
   1.300 +            fprintf(stderr, "Run '%s --help' for help.\n", progname);
   1.301 +            return 1;
   1.302 +        }
   1.303 +
   1.304 +        if(argc == 1) {
   1.305 +            fprintf(stderr,
   1.306 +                "No input files specified.\n"
   1.307 +                "Run '%s --help' for help.\n", progname);
   1.308 +            return 1;
   1.309 +        }
   1.310 +    }   /* end !needsHelp */
   1.311 +
   1.312 +    if(argc<0 || needsHelp  ) {
   1.313 +        fprintf(stderr,
   1.314 +            "usage: %s [-options] [-] [packageFile] \n"
   1.315 +            "\tProduce packaged ICU data from the given list(s) of files.\n"
   1.316 +            "\t'-' by itself means to read from stdin.\n"
   1.317 +            "\tpackageFile is a text file containing the list of files to package.\n",
   1.318 +            progname);
   1.319 +
   1.320 +        fprintf(stderr, "\n options:\n");
   1.321 +        for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
   1.322 +            fprintf(stderr, "%-5s -%c %s%-10s  %s\n",
   1.323 +                (i<1?"[REQ]":""),
   1.324 +                options[i].shortName,
   1.325 +                options[i].longName ? "or --" : "     ",
   1.326 +                options[i].longName ? options[i].longName : "",
   1.327 +                options_help[i]);
   1.328 +        }
   1.329 +
   1.330 +        fprintf(stderr, "modes: (-m option)\n");
   1.331 +        for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
   1.332 +            fprintf(stderr, "   %-9s ", modes[i].name);
   1.333 +            if (modes[i].alt_name) {
   1.334 +                fprintf(stderr, "/ %-9s", modes[i].alt_name);
   1.335 +            } else {
   1.336 +                fprintf(stderr, "           ");
   1.337 +            }
   1.338 +            fprintf(stderr, "  %s\n", modes[i].desc);
   1.339 +        }
   1.340 +        return 1;
   1.341 +    }
   1.342 +
   1.343 +    /* OK, fill in the options struct */
   1.344 +    uprv_memset(&o, 0, sizeof(o));
   1.345 +
   1.346 +    o.mode      = options[MODE].value;
   1.347 +    o.version   = options[REVISION].doesOccur ? options[REVISION].value : 0;
   1.348 +
   1.349 +    o.shortName = options[NAME].value;
   1.350 +    {
   1.351 +        int32_t len = (int32_t)uprv_strlen(o.shortName);
   1.352 +        char *csname, *cp;
   1.353 +        const char *sp;
   1.354 +
   1.355 +        cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
   1.356 +        if (*(sp = o.shortName)) {
   1.357 +            *cp++ = isalpha(*sp) ? * sp : '_';
   1.358 +            for (++sp; *sp; ++sp) {
   1.359 +                *cp++ = isalnum(*sp) ? *sp : '_';
   1.360 +            }
   1.361 +        }
   1.362 +        *cp = 0;
   1.363 +
   1.364 +        o.cShortName = csname;
   1.365 +    }
   1.366 +
   1.367 +    if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */
   1.368 +      o.libName = options[LIBNAME].value;
   1.369 +    } else {
   1.370 +      o.libName = o.shortName;
   1.371 +    }
   1.372 +
   1.373 +    if(options[QUIET].doesOccur) {
   1.374 +      o.quiet = TRUE;
   1.375 +    } else {
   1.376 +      o.quiet = FALSE;
   1.377 +    }
   1.378 +
   1.379 +    if(options[PDS_BUILD].doesOccur) {
   1.380 +      o.pdsbuild = TRUE;
   1.381 +    } else {
   1.382 +      o.pdsbuild = FALSE;
   1.383 +    }
   1.384 +
   1.385 +    o.verbose   = options[VERBOSE].doesOccur;
   1.386 +
   1.387 +
   1.388 +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
   1.389 +    if (options[BLDOPT].doesOccur) {
   1.390 +        o.options   = options[BLDOPT].value;
   1.391 +    } else {
   1.392 +        o.options = NULL;
   1.393 +    }
   1.394 +#endif
   1.395 +    if(options[COPYRIGHT].doesOccur) {
   1.396 +        o.comment = U_COPYRIGHT_STRING;
   1.397 +    } else if (options[COMMENT].doesOccur) {
   1.398 +        o.comment = options[COMMENT].value;
   1.399 +    }
   1.400 +
   1.401 +    if( options[DESTDIR].doesOccur ) {
   1.402 +        o.targetDir = options[DESTDIR].value;
   1.403 +    } else {
   1.404 +        o.targetDir = ".";  /* cwd */
   1.405 +    }
   1.406 +
   1.407 +    o.rebuild   = options[REBUILD].doesOccur;
   1.408 +
   1.409 +    if( options[TEMPDIR].doesOccur ) {
   1.410 +        o.tmpDir    = options[TEMPDIR].value;
   1.411 +    } else {
   1.412 +        o.tmpDir    = o.targetDir;
   1.413 +    }
   1.414 +
   1.415 +    if( options[INSTALL].doesOccur ) {
   1.416 +        o.install  = options[INSTALL].value;
   1.417 +    } else {
   1.418 +        o.install = NULL;
   1.419 +    }
   1.420 +
   1.421 +    if( options[SOURCEDIR].doesOccur ) {
   1.422 +        o.srcDir   = options[SOURCEDIR].value;
   1.423 +    } else {
   1.424 +        o.srcDir   = ".";
   1.425 +    }
   1.426 +
   1.427 +    if( options[ENTRYPOINT].doesOccur ) {
   1.428 +        o.entryName = options[ENTRYPOINT].value;
   1.429 +    } else {
   1.430 +        o.entryName = o.cShortName;
   1.431 +    }
   1.432 +
   1.433 +    o.withoutAssembly = FALSE;
   1.434 +    if (options[WITHOUT_ASSEMBLY].doesOccur) {
   1.435 +#ifndef BUILD_DATA_WITHOUT_ASSEMBLY
   1.436 +        fprintf(stdout, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n");
   1.437 +        fprintf(stdout, "Warning: This option will be ignored.\n");
   1.438 +#else
   1.439 +        o.withoutAssembly = TRUE;
   1.440 +#endif
   1.441 +    }
   1.442 +
   1.443 +    /* OK options are set up. Now the file lists. */
   1.444 +    tail = NULL;
   1.445 +    for( n=1; n<argc; n++) {
   1.446 +        o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
   1.447 +    }
   1.448 +
   1.449 +    /* load the files */
   1.450 +    loadLists(&o, &status);
   1.451 +    if( U_FAILURE(status) ) {
   1.452 +        fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
   1.453 +        return 2;
   1.454 +    }
   1.455 +
   1.456 +    result = pkg_executeOptions(&o);
   1.457 +
   1.458 +    if (pkgDataFlags != NULL) {
   1.459 +        for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
   1.460 +            if (pkgDataFlags[n] != NULL) {
   1.461 +                uprv_free(pkgDataFlags[n]);
   1.462 +            }
   1.463 +        }
   1.464 +        uprv_free(pkgDataFlags);
   1.465 +    }
   1.466 +
   1.467 +    if (o.cShortName != NULL) {
   1.468 +        uprv_free((char *)o.cShortName);
   1.469 +    }
   1.470 +    if (o.fileListFiles != NULL) {
   1.471 +        pkg_deleteList(o.fileListFiles);
   1.472 +    }
   1.473 +    if (o.filePaths != NULL) {
   1.474 +        pkg_deleteList(o.filePaths);
   1.475 +    }
   1.476 +    if (o.files != NULL) {
   1.477 +        pkg_deleteList(o.files);
   1.478 +    }
   1.479 +
   1.480 +    return result;
   1.481 +}
   1.482 +
   1.483 +static int runCommand(const char* command, UBool specialHandling) {
   1.484 +    char *cmd = NULL;
   1.485 +    char cmdBuffer[SMALL_BUFFER_MAX_SIZE];
   1.486 +    int32_t len = strlen(command);
   1.487 +
   1.488 +    if (len == 0) {
   1.489 +        return 0;
   1.490 +    }
   1.491 +
   1.492 +    if (!specialHandling) {
   1.493 +#if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400
   1.494 +        if ((len + BUFFER_PADDING_SIZE) >= SMALL_BUFFER_MAX_SIZE) {
   1.495 +            cmd = (char *)uprv_malloc(len + BUFFER_PADDING_SIZE);
   1.496 +        } else {
   1.497 +            cmd = cmdBuffer;
   1.498 +        }
   1.499 +#if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
   1.500 +        sprintf(cmd, "bash -c \"%s\"", command);
   1.501 +
   1.502 +#elif U_PLATFORM == U_PF_OS400
   1.503 +        sprintf(cmd, "QSH CMD('%s')", command);
   1.504 +#endif
   1.505 +#else
   1.506 +        goto normal_command_mode;
   1.507 +#endif
   1.508 +    } else {
   1.509 +#if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
   1.510 +normal_command_mode:
   1.511 +#endif
   1.512 +        cmd = (char *)command;
   1.513 +    }
   1.514 +
   1.515 +    printf("pkgdata: %s\n", cmd);
   1.516 +    int result = system(cmd);
   1.517 +    if (result != 0) {
   1.518 +        fprintf(stderr, "-- return status = %d\n", result);
   1.519 +    }
   1.520 +
   1.521 +    if (cmd != cmdBuffer && cmd != command) {
   1.522 +        uprv_free(cmd);
   1.523 +    }
   1.524 +
   1.525 +    return result;
   1.526 +}
   1.527 +
   1.528 +#define LN_CMD "ln -s"
   1.529 +#define RM_CMD "rm -f"
   1.530 +
   1.531 +static int32_t pkg_executeOptions(UPKGOptions *o) {
   1.532 +    int32_t result = 0;
   1.533 +
   1.534 +    const char mode = o->mode[0];
   1.535 +    char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
   1.536 +    char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
   1.537 +    char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
   1.538 +    char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
   1.539 +    char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
   1.540 +
   1.541 +    initializePkgDataFlags(o);
   1.542 +
   1.543 +    if (IN_FILES_MODE(mode)) {
   1.544 +        /* Copy the raw data to the installation directory. */
   1.545 +        if (o->install != NULL) {
   1.546 +            uprv_strcpy(targetDir, o->install);
   1.547 +            if (o->shortName != NULL) {
   1.548 +                uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
   1.549 +                uprv_strcat(targetDir, o->shortName);
   1.550 +            }
   1.551 +            
   1.552 +            if(o->verbose) {
   1.553 +              fprintf(stdout, "# Install: Files mode, copying files to %s..\n", targetDir);
   1.554 +            }
   1.555 +            result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
   1.556 +        }
   1.557 +        return result;
   1.558 +    } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
   1.559 +        UBool noVersion = FALSE;
   1.560 +
   1.561 +        uprv_strcpy(targetDir, o->targetDir);
   1.562 +        uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
   1.563 +
   1.564 +        uprv_strcpy(tmpDir, o->tmpDir);
   1.565 +        uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
   1.566 +
   1.567 +        uprv_strcpy(datFileNamePath, tmpDir);
   1.568 +
   1.569 +        uprv_strcpy(datFileName, o->shortName);
   1.570 +        uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
   1.571 +
   1.572 +        uprv_strcat(datFileNamePath, datFileName);
   1.573 +
   1.574 +        if(o->verbose) {
   1.575 +          fprintf(stdout, "# Writing package file %s ..\n", datFileNamePath);
   1.576 +        }
   1.577 +        result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_CHARSET_FAMILY ? 'e' :  U_IS_BIG_ENDIAN ? 'b' : 'l');
   1.578 +        if (result != 0) {
   1.579 +            fprintf(stderr,"Error writing package dat file.\n");
   1.580 +            return result;
   1.581 +        }
   1.582 +
   1.583 +        if (IN_COMMON_MODE(mode)) {
   1.584 +            char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
   1.585 +
   1.586 +            uprv_strcpy(targetFileNamePath, targetDir);
   1.587 +            uprv_strcat(targetFileNamePath, datFileName);
   1.588 +
   1.589 +            /* Move the dat file created to the target directory. */
   1.590 +            if (uprv_strcmp(datFileNamePath, targetFileNamePath) != 0) {
   1.591 +                if (T_FileStream_file_exists(targetFileNamePath)) {
   1.592 +                    if ((result = remove(targetFileNamePath)) != 0) {
   1.593 +                        fprintf(stderr, "Unable to remove old dat file: %s\n",
   1.594 +                                targetFileNamePath);
   1.595 +                        return result;
   1.596 +                    }
   1.597 +                }
   1.598 +
   1.599 +                result = rename(datFileNamePath, targetFileNamePath);
   1.600 +
   1.601 +                if (o->verbose) {
   1.602 +                    fprintf(stdout, "# Moving package file to %s ..\n",
   1.603 +                            targetFileNamePath);
   1.604 +                }
   1.605 +                if (result != 0) {
   1.606 +                    fprintf(
   1.607 +                            stderr,
   1.608 +                            "Unable to move dat file (%s) to target location (%s).\n",
   1.609 +                            datFileNamePath, targetFileNamePath);
   1.610 +                    return result;
   1.611 +                }
   1.612 +            }
   1.613 +
   1.614 +            if (o->install != NULL) {
   1.615 +                result = pkg_installCommonMode(o->install, targetFileNamePath);
   1.616 +            }
   1.617 +
   1.618 +            return result;
   1.619 +        } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ {
   1.620 +            char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
   1.621 +            char version_major[10] = "";
   1.622 +            UBool reverseExt = FALSE;
   1.623 +
   1.624 +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
   1.625 +            /* Get the version major number. */
   1.626 +            if (o->version != NULL) {
   1.627 +                for (uint32_t i = 0;i < sizeof(version_major);i++) {
   1.628 +                    if (o->version[i] == '.') {
   1.629 +                        version_major[i] = 0;
   1.630 +                        break;
   1.631 +                    }
   1.632 +                    version_major[i] = o->version[i];
   1.633 +                }
   1.634 +            } else {
   1.635 +                noVersion = TRUE;
   1.636 +                if (IN_DLL_MODE(mode)) {
   1.637 +                    fprintf(stdout, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n");
   1.638 +                }
   1.639 +            }
   1.640 +
   1.641 +#if U_PLATFORM != U_PF_OS400
   1.642 +            /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
   1.643 +             * reverseExt is FALSE if the suffix should be the version number.
   1.644 +             */
   1.645 +            if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
   1.646 +                reverseExt = TRUE;
   1.647 +            }
   1.648 +#endif
   1.649 +            /* Using the base libName and version number, generate the library file names. */
   1.650 +            createFileNames(o, mode, version_major, o->version == NULL ? "" : o->version, o->libName, reverseExt, noVersion);
   1.651 +
   1.652 +            if ((o->version!=NULL || IN_STATIC_MODE(mode)) && o->rebuild == FALSE) {
   1.653 +                /* Check to see if a previous built data library file exists and check if it is the latest. */
   1.654 +                sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]);
   1.655 +                if (T_FileStream_file_exists(checkLibFile)) {
   1.656 +                    if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) {
   1.657 +                        if (o->install != NULL) {
   1.658 +                          if(o->verbose) {
   1.659 +                            fprintf(stdout, "# Installing already-built library into %s\n", o->install);
   1.660 +                          }
   1.661 +                          result = pkg_installLibrary(o->install, targetDir, noVersion);
   1.662 +                        } else {
   1.663 +                          if(o->verbose) {
   1.664 +                            printf("# Not rebuilding %s - up to date.\n", checkLibFile);
   1.665 +                          }
   1.666 +                        }
   1.667 +                        return result;
   1.668 +                    } else if (o->verbose && (o->install!=NULL)) {
   1.669 +                      fprintf(stdout, "# Not installing up-to-date library %s into %s\n", checkLibFile, o->install);
   1.670 +                    }
   1.671 +                } else if(o->verbose && (o->install!=NULL)) {
   1.672 +                  fprintf(stdout, "# Not installing missing %s into %s\n", checkLibFile, o->install);
   1.673 +                }
   1.674 +            }
   1.675 +
   1.676 +            if (pkg_checkFlag(o) == NULL) {
   1.677 +                /* Error occurred. */
   1.678 +                return result;
   1.679 +            }
   1.680 +#endif
   1.681 +
   1.682 +            if (!o->withoutAssembly && pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
   1.683 +                const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
   1.684 +
   1.685 +                if(o->verbose) {
   1.686 +                  fprintf(stdout, "# Generating assembly code %s of type %s ..\n", gencFilePath, genccodeAssembly);
   1.687 +                }
   1.688 +                
   1.689 +                /* Offset genccodeAssembly by 3 because "-a " */
   1.690 +                if (genccodeAssembly &&
   1.691 +                    (uprv_strlen(genccodeAssembly)>3) &&
   1.692 +                    checkAssemblyHeaderName(genccodeAssembly+3)) {
   1.693 +                    writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath);
   1.694 +
   1.695 +                    result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
   1.696 +                    if (result != 0) {
   1.697 +                        fprintf(stderr, "Error generating assembly code for data.\n");
   1.698 +                        return result;
   1.699 +                    } else if (IN_STATIC_MODE(mode)) {
   1.700 +                      if(o->install != NULL) {
   1.701 +                        if(o->verbose) {
   1.702 +                          fprintf(stdout, "# Installing static library into %s\n", o->install);
   1.703 +                        }
   1.704 +                        result = pkg_installLibrary(o->install, targetDir, noVersion);
   1.705 +                      }
   1.706 +                      return result;
   1.707 +                    }
   1.708 +                } else {
   1.709 +                    fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
   1.710 +                    return -1;
   1.711 +                }
   1.712 +            } else {
   1.713 +                if(o->verbose) {
   1.714 +                  fprintf(stdout, "# Writing object code to %s ..\n", gencFilePath);
   1.715 +                }
   1.716 +                if (o->withoutAssembly) {
   1.717 +#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
   1.718 +                    result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
   1.719 +#else
   1.720 +                    /* This error should not occur. */
   1.721 +                    fprintf(stderr, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
   1.722 +#endif
   1.723 +                } else {
   1.724 +#ifdef CAN_WRITE_OBJ_CODE
   1.725 +                    writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
   1.726 +#if U_PLATFORM_IS_LINUX_BASED
   1.727 +                    result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
   1.728 +#elif defined(WINDOWS_WITH_MSVC)
   1.729 +                    result = pkg_createWindowsDLL(mode, gencFilePath, o);
   1.730 +#endif
   1.731 +#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
   1.732 +                    result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
   1.733 +#else
   1.734 +                    fprintf(stderr, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
   1.735 +                    return 1;
   1.736 +#endif
   1.737 +                }
   1.738 +
   1.739 +                if (result != 0) {
   1.740 +                    fprintf(stderr, "Error generating package data.\n");
   1.741 +                    return result;
   1.742 +                }
   1.743 +            }
   1.744 +#if !U_PLATFORM_USES_ONLY_WIN32_API
   1.745 +            if(!IN_STATIC_MODE(mode)) {
   1.746 +                /* Certain platforms uses archive library. (e.g. AIX) */
   1.747 +                if(o->verbose) {
   1.748 +                  fprintf(stdout, "# Creating data archive library file ..\n");
   1.749 +                }
   1.750 +                result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
   1.751 +                if (result != 0) {
   1.752 +                    fprintf(stderr, "Error creating data archive library file.\n");
   1.753 +                   return result;
   1.754 +                }
   1.755 +#if U_PLATFORM != U_PF_OS400
   1.756 +                if (!noVersion) {
   1.757 +                    /* Create symbolic links for the final library file. */
   1.758 +#if U_PLATFORM == U_PF_OS390
   1.759 +                    if (!o->pdsbuild) {
   1.760 +                        result = pkg_createSymLinks(targetDir, noVersion);
   1.761 +                    }
   1.762 +#else
   1.763 +                    result = pkg_createSymLinks(targetDir, noVersion);
   1.764 +#endif
   1.765 +                    if (result != 0) {
   1.766 +                        fprintf(stderr, "Error creating symbolic links of the data library file.\n");
   1.767 +                        return result;
   1.768 +                    }
   1.769 +                }
   1.770 +#endif
   1.771 +            } /* !IN_STATIC_MODE */
   1.772 +#endif
   1.773 +
   1.774 +#if !U_PLATFORM_USES_ONLY_WIN32_API
   1.775 +            /* Install the libraries if option was set. */
   1.776 +            if (o->install != NULL) {
   1.777 +                if(o->verbose) {
   1.778 +                  fprintf(stdout, "# Installing library file to %s ..\n", o->install);
   1.779 +                }
   1.780 +                result = pkg_installLibrary(o->install, targetDir, noVersion);
   1.781 +                if (result != 0) {
   1.782 +                    fprintf(stderr, "Error installing the data library.\n");
   1.783 +                    return result;
   1.784 +                }
   1.785 +            }
   1.786 +#endif
   1.787 +        }
   1.788 +    }
   1.789 +    return result;
   1.790 +}
   1.791 +
   1.792 +/* Initialize the pkgDataFlags with the option file given. */
   1.793 +static int32_t initializePkgDataFlags(UPKGOptions *o) {
   1.794 +    UErrorCode status = U_ZERO_ERROR;
   1.795 +    int32_t result = 0;
   1.796 +    int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE;
   1.797 +    int32_t tmpResult = 0;
   1.798 +
   1.799 +    /* Initialize pkgdataFlags */
   1.800 +    pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
   1.801 +
   1.802 +    /* If we run out of space, allocate more */
   1.803 +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
   1.804 +    do {
   1.805 +#endif
   1.806 +        if (pkgDataFlags != NULL) {
   1.807 +            for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
   1.808 +                pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize);
   1.809 +                if (pkgDataFlags[i] != NULL) {
   1.810 +                    pkgDataFlags[i][0] = 0;
   1.811 +                } else {
   1.812 +                    fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
   1.813 +                    return -1;
   1.814 +                }
   1.815 +            }
   1.816 +        } else {
   1.817 +            fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
   1.818 +            return -1;
   1.819 +        }
   1.820 +
   1.821 +        if (o->options == NULL) {
   1.822 +            return result;
   1.823 +        }
   1.824 +
   1.825 +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
   1.826 +        /* Read in options file. */
   1.827 +        if(o->verbose) {
   1.828 +          fprintf(stdout, "# Reading options file %s\n", o->options);
   1.829 +        }
   1.830 +        status = U_ZERO_ERROR;
   1.831 +        tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, FLAG_NAMES, (int32_t)PKGDATA_FLAGS_SIZE, &status);
   1.832 +        if (status == U_BUFFER_OVERFLOW_ERROR) {
   1.833 +            for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
   1.834 +                uprv_free(pkgDataFlags[i]);
   1.835 +            }
   1.836 +            currentBufferSize = tmpResult;
   1.837 +        } else if (U_FAILURE(status)) {
   1.838 +            fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status));
   1.839 +            return -1;
   1.840 +        }
   1.841 +#endif
   1.842 +        if(o->verbose) {
   1.843 +            fprintf(stdout, "# pkgDataFlags=\n");
   1.844 +            for(int32_t i=0;i<PKGDATA_FLAGS_SIZE;i++) {
   1.845 +                fprintf(stdout, "  [%d] %s:  %s\n", i, FLAG_NAMES[i], pkgDataFlags[i]);
   1.846 +            }
   1.847 +            fprintf(stdout, "\n");
   1.848 +        }
   1.849 +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
   1.850 +    } while (status == U_BUFFER_OVERFLOW_ERROR);
   1.851 +#endif
   1.852 +
   1.853 +    return result;
   1.854 +}
   1.855 +
   1.856 +
   1.857 +/*
   1.858 + * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
   1.859 + * Depending on the configuration, the library name may either end with version number or shared object suffix.
   1.860 + */
   1.861 +static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt, UBool noVersion) {
   1.862 +#if U_PLATFORM == U_PF_MINGW
   1.863 +        /* MinGW does not need the library prefix when building in dll mode. */
   1.864 +        if (IN_DLL_MODE(mode)) {
   1.865 +            sprintf(libFileNames[LIB_FILE], "%s", libName);
   1.866 +        } else {
   1.867 +            sprintf(libFileNames[LIB_FILE], "%s%s",
   1.868 +                    pkgDataFlags[LIBPREFIX],
   1.869 +                    libName);
   1.870 +        }
   1.871 +#else
   1.872 +        sprintf(libFileNames[LIB_FILE], "%s%s",
   1.873 +                pkgDataFlags[LIBPREFIX],
   1.874 +                libName);
   1.875 +#endif
   1.876 +
   1.877 +        if(o->verbose) {
   1.878 +          fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]);
   1.879 +        }
   1.880 +
   1.881 +#if U_PLATFORM == U_PF_MINGW
   1.882 +        sprintf(libFileNames[LIB_FILE_MINGW], "%s%s.lib", pkgDataFlags[LIBPREFIX], libName);
   1.883 +#elif U_PLATFORM == U_PF_CYGWIN
   1.884 +        sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s.%s",
   1.885 +                libName,
   1.886 +                pkgDataFlags[SO_EXT]);
   1.887 +        sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s.%s",
   1.888 +                libName,
   1.889 +                version_major,
   1.890 +                pkgDataFlags[SO_EXT]);
   1.891 +
   1.892 +        uprv_strcat(pkgDataFlags[SO_EXT], ".");
   1.893 +        uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
   1.894 +#elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
   1.895 +        sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s",
   1.896 +                libFileNames[LIB_FILE],
   1.897 +                pkgDataFlags[SOBJ_EXT]);
   1.898 +#elif U_PLATFROM == U_PF_OS390
   1.899 +            if (o->pdsbuild) {
   1.900 +                sprintf(libFileNames[LIB_FILE], "%s",
   1.901 +                    libName);
   1.902 +                sprintf(libFileNames[LIB_FILE_VERSION_TMP], "\"%s\"",
   1.903 +                        libFileNames[LIB_FILE]);
   1.904 +            } else {
   1.905 +                sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
   1.906 +                        libFileNames[LIB_FILE],
   1.907 +                        pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.908 +                        reverseExt ? version : pkgDataFlags[SOBJ_EXT],
   1.909 +                        reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
   1.910 +            }
   1.911 +#else
   1.912 +        if (noVersion && !reverseExt) {
   1.913 +            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
   1.914 +                    libFileNames[LIB_FILE],
   1.915 +                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.916 +                    pkgDataFlags[SOBJ_EXT]);
   1.917 +        } else {
   1.918 +            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
   1.919 +                    libFileNames[LIB_FILE],
   1.920 +                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.921 +                    reverseExt ? version : pkgDataFlags[SOBJ_EXT],
   1.922 +                    reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
   1.923 +        }
   1.924 +#endif
   1.925 +        if (noVersion && !reverseExt) {
   1.926 +            sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s",
   1.927 +                    libFileNames[LIB_FILE],
   1.928 +                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.929 +                    pkgDataFlags[SO_EXT]);
   1.930 +
   1.931 +            sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s",
   1.932 +                    libFileNames[LIB_FILE],
   1.933 +                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.934 +                    pkgDataFlags[SO_EXT]);
   1.935 +        } else {
   1.936 +            sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s",
   1.937 +                    libFileNames[LIB_FILE],
   1.938 +                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.939 +                    reverseExt ? version_major : pkgDataFlags[SO_EXT],
   1.940 +                    reverseExt ? pkgDataFlags[SO_EXT] : version_major);
   1.941 +
   1.942 +            sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
   1.943 +                    libFileNames[LIB_FILE],
   1.944 +                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
   1.945 +                    reverseExt ? version : pkgDataFlags[SO_EXT],
   1.946 +                    reverseExt ? pkgDataFlags[SO_EXT] : version);
   1.947 +        }
   1.948 +
   1.949 +        if(o->verbose) {
   1.950 +          fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]);
   1.951 +        }
   1.952 +
   1.953 +#if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
   1.954 +        /* Cygwin and MinGW only deals with the version major number. */
   1.955 +        uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
   1.956 +#endif
   1.957 +
   1.958 +        if(IN_STATIC_MODE(mode)) {
   1.959 +            sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]);
   1.960 +            libFileNames[LIB_FILE_VERSION_MAJOR][0]=0;
   1.961 +            if(o->verbose) {
   1.962 +              fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s  (static)\n", libFileNames[LIB_FILE_VERSION]);
   1.963 +            }
   1.964 +        }
   1.965 +}
   1.966 +
   1.967 +/* Create the symbolic links for the final library file. */
   1.968 +static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) {
   1.969 +    int32_t result = 0;
   1.970 +    char cmd[LARGE_BUFFER_MAX_SIZE];
   1.971 +    char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */
   1.972 +    char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */
   1.973 +
   1.974 +#if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW
   1.975 +    /* No symbolic link to make. */
   1.976 +    if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 ||
   1.977 +        uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
   1.978 +        return result;
   1.979 +    }
   1.980 +    
   1.981 +    sprintf(cmd, "cd %s && %s %s && %s %s %s",
   1.982 +            targetDir,
   1.983 +            RM_CMD,
   1.984 +            libFileNames[LIB_FILE_VERSION_MAJOR],
   1.985 +            LN_CMD,
   1.986 +            libFileNames[LIB_FILE_VERSION],
   1.987 +            libFileNames[LIB_FILE_VERSION_MAJOR]);
   1.988 +    result = runCommand(cmd);
   1.989 +    if (result != 0) {
   1.990 +        fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
   1.991 +        return result;
   1.992 +    }
   1.993 +#endif
   1.994 +
   1.995 +    if (specialHandling) {
   1.996 +#if U_PLATFORM == U_PF_CYGWIN
   1.997 +        sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]);
   1.998 +        sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
   1.999 +#else
  1.1000 +        goto normal_symlink_mode;
  1.1001 +#endif
  1.1002 +    } else {
  1.1003 +#if U_PLATFORM != U_PF_CYGWIN
  1.1004 +normal_symlink_mode:
  1.1005 +#endif
  1.1006 +        sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]);
  1.1007 +        sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
  1.1008 +    }
  1.1009 +
  1.1010 +    sprintf(cmd, "cd %s && %s %s && %s %s %s",
  1.1011 +            targetDir,
  1.1012 +            RM_CMD,
  1.1013 +            name1,
  1.1014 +            LN_CMD,
  1.1015 +            name2,
  1.1016 +            name1);
  1.1017 +
  1.1018 +     result = runCommand(cmd);
  1.1019 +
  1.1020 +    return result;
  1.1021 +}
  1.1022 +
  1.1023 +static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, UBool noVersion) {
  1.1024 +    int32_t result = 0;
  1.1025 +    char cmd[SMALL_BUFFER_MAX_SIZE];
  1.1026 +
  1.1027 +    sprintf(cmd, "cd %s && %s %s %s%s%s",
  1.1028 +            targetDir,
  1.1029 +            pkgDataFlags[INSTALL_CMD],
  1.1030 +            libFileNames[LIB_FILE_VERSION],
  1.1031 +            installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
  1.1032 +            );
  1.1033 +
  1.1034 +    result = runCommand(cmd);
  1.1035 +
  1.1036 +    if (result != 0) {
  1.1037 +        fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
  1.1038 +        return result;
  1.1039 +    }
  1.1040 +
  1.1041 +#ifdef CYGWINMSVC
  1.1042 +    sprintf(cmd, "cd %s && %s %s.lib %s",
  1.1043 +            targetDir,
  1.1044 +            pkgDataFlags[INSTALL_CMD],
  1.1045 +            libFileNames[LIB_FILE],
  1.1046 +            installDir
  1.1047 +            );
  1.1048 +    result = runCommand(cmd);
  1.1049 +
  1.1050 +    if (result != 0) {
  1.1051 +        fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
  1.1052 +        return result;
  1.1053 +    }
  1.1054 +#elif U_PLATFORM == U_PF_CYGWIN
  1.1055 +    sprintf(cmd, "cd %s && %s %s %s",
  1.1056 +            targetDir,
  1.1057 +            pkgDataFlags[INSTALL_CMD],
  1.1058 +            libFileNames[LIB_FILE_CYGWIN_VERSION],
  1.1059 +            installDir
  1.1060 +            );
  1.1061 +    result = runCommand(cmd);
  1.1062 +
  1.1063 +    if (result != 0) {
  1.1064 +        fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
  1.1065 +        return result;
  1.1066 +    }
  1.1067 +#endif
  1.1068 +
  1.1069 +    if (noVersion) {
  1.1070 +        return result;
  1.1071 +    } else {
  1.1072 +        return pkg_createSymLinks(installDir, TRUE);
  1.1073 +    }
  1.1074 +}
  1.1075 +
  1.1076 +static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) {
  1.1077 +    int32_t result = 0;
  1.1078 +    char cmd[SMALL_BUFFER_MAX_SIZE] = "";
  1.1079 +
  1.1080 +    if (!T_FileStream_file_exists(installDir)) {
  1.1081 +        UErrorCode status = U_ZERO_ERROR;
  1.1082 +
  1.1083 +        uprv_mkdir(installDir, &status);
  1.1084 +        if (U_FAILURE(status)) {
  1.1085 +            fprintf(stderr, "Error creating installation directory: %s\n", installDir);
  1.1086 +            return -1;
  1.1087 +        }
  1.1088 +    }
  1.1089 +#ifndef U_WINDOWS_WITH_MSVC
  1.1090 +    sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir);
  1.1091 +#else
  1.1092 +    sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS);
  1.1093 +#endif
  1.1094 +
  1.1095 +    result = runCommand(cmd);
  1.1096 +    if (result != 0) {
  1.1097 +        fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
  1.1098 +    }
  1.1099 +
  1.1100 +    return result;
  1.1101 +}
  1.1102 +
  1.1103 +#ifdef U_WINDOWS_MSVC
  1.1104 +/* Copy commands for installing the raw data files on Windows. */
  1.1105 +#define WIN_INSTALL_CMD "xcopy"
  1.1106 +#define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
  1.1107 +#endif
  1.1108 +static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
  1.1109 +    int32_t result = 0;
  1.1110 +    char cmd[SMALL_BUFFER_MAX_SIZE] = "";
  1.1111 +
  1.1112 +    if (!T_FileStream_file_exists(installDir)) {
  1.1113 +        UErrorCode status = U_ZERO_ERROR;
  1.1114 +
  1.1115 +        uprv_mkdir(installDir, &status);
  1.1116 +        if (U_FAILURE(status)) {
  1.1117 +            fprintf(stderr, "Error creating installation directory: %s\n", installDir);
  1.1118 +            return -1;
  1.1119 +        }
  1.1120 +    }
  1.1121 +#ifndef U_WINDOWS_WITH_MSVC
  1.1122 +    char buffer[SMALL_BUFFER_MAX_SIZE] = "";
  1.1123 +    int32_t bufferLength = 0;
  1.1124 +
  1.1125 +    FileStream *f = T_FileStream_open(fileListName, "r");
  1.1126 +    if (f != NULL) {
  1.1127 +        for(;;) {
  1.1128 +            if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
  1.1129 +                bufferLength = uprv_strlen(buffer);
  1.1130 +                /* Remove new line character. */
  1.1131 +                if (bufferLength > 0) {
  1.1132 +                    buffer[bufferLength-1] = 0;
  1.1133 +                }
  1.1134 +
  1.1135 +                sprintf(cmd, "%s %s%s%s %s%s%s",
  1.1136 +                        pkgDataFlags[INSTALL_CMD],
  1.1137 +                        srcDir, PKGDATA_FILE_SEP_STRING, buffer,
  1.1138 +                        installDir, PKGDATA_FILE_SEP_STRING, buffer);
  1.1139 +
  1.1140 +                result = runCommand(cmd);
  1.1141 +                if (result != 0) {
  1.1142 +                    fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
  1.1143 +                    break;
  1.1144 +                }
  1.1145 +            } else {
  1.1146 +                if (!T_FileStream_eof(f)) {
  1.1147 +                    fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
  1.1148 +                    result = -1;
  1.1149 +                }
  1.1150 +                break;
  1.1151 +            }
  1.1152 +        }
  1.1153 +        T_FileStream_close(f);
  1.1154 +    } else {
  1.1155 +        result = -1;
  1.1156 +        fprintf(stderr, "Unable to open list file: %s\n", fileListName);
  1.1157 +    }
  1.1158 +#else
  1.1159 +    sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
  1.1160 +    result = runCommand(cmd);
  1.1161 +    if (result != 0) {
  1.1162 +        fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
  1.1163 +    }
  1.1164 +#endif
  1.1165 +
  1.1166 +    return result;
  1.1167 +}
  1.1168 +
  1.1169 +/* Archiving of the library file may be needed depending on the platform and options given.
  1.1170 + * If archiving is not needed, copy over the library file name.
  1.1171 + */
  1.1172 +static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
  1.1173 +    int32_t result = 0;
  1.1174 +    char cmd[LARGE_BUFFER_MAX_SIZE];
  1.1175 +
  1.1176 +    /* If the shared object suffix and the final object suffix is different and the final object suffix and the
  1.1177 +     * archive file suffix is the same, then the final library needs to be archived.
  1.1178 +     */
  1.1179 +    if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
  1.1180 +        sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
  1.1181 +                libFileNames[LIB_FILE],
  1.1182 +                pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
  1.1183 +                reverseExt ? version : pkgDataFlags[SO_EXT],
  1.1184 +                reverseExt ? pkgDataFlags[SO_EXT] : version);
  1.1185 +
  1.1186 +        sprintf(cmd, "%s %s %s%s %s%s",
  1.1187 +                pkgDataFlags[AR],
  1.1188 +                pkgDataFlags[ARFLAGS],
  1.1189 +                targetDir,
  1.1190 +                libFileNames[LIB_FILE_VERSION],
  1.1191 +                targetDir,
  1.1192 +                libFileNames[LIB_FILE_VERSION_TMP]);
  1.1193 +
  1.1194 +        result = runCommand(cmd); 
  1.1195 +        if (result != 0) { 
  1.1196 +            fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
  1.1197 +            return result; 
  1.1198 +        } 
  1.1199 +        
  1.1200 +        sprintf(cmd, "%s %s%s", 
  1.1201 +            pkgDataFlags[RANLIB], 
  1.1202 +            targetDir, 
  1.1203 +            libFileNames[LIB_FILE_VERSION]);
  1.1204 +        
  1.1205 +        result = runCommand(cmd); 
  1.1206 +        if (result != 0) {
  1.1207 +            fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
  1.1208 +            return result;
  1.1209 +        }
  1.1210 +
  1.1211 +        /* Remove unneeded library file. */
  1.1212 +        sprintf(cmd, "%s %s%s",
  1.1213 +                RM_CMD,
  1.1214 +                targetDir,
  1.1215 +                libFileNames[LIB_FILE_VERSION_TMP]);
  1.1216 +
  1.1217 +        result = runCommand(cmd);
  1.1218 +        if (result != 0) {
  1.1219 +            fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
  1.1220 +            return result;
  1.1221 +        }
  1.1222 +
  1.1223 +    } else {
  1.1224 +        uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
  1.1225 +    }
  1.1226 +
  1.1227 +    return result;
  1.1228 +}
  1.1229 +
  1.1230 +/*
  1.1231 + * Using the compiler information from the configuration file set by -O option, generate the library file.
  1.1232 + * command may be given to allow for a larger buffer for cmd.
  1.1233 + */
  1.1234 +static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) {
  1.1235 +    int32_t result = 0;
  1.1236 +    char *cmd = NULL;
  1.1237 +    UBool freeCmd = FALSE;
  1.1238 +    int32_t length = 0;
  1.1239 +
  1.1240 +    /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
  1.1241 +     * containing many object files and so the calling function should supply a command buffer that is large
  1.1242 +     * enough to handle this. Otherwise, use the default size.
  1.1243 +     */
  1.1244 +    if (command != NULL) {
  1.1245 +        cmd = command;
  1.1246 +    }
  1.1247 +
  1.1248 +    if (IN_STATIC_MODE(mode)) {
  1.1249 +        if (cmd == NULL) {
  1.1250 +            length = uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) +
  1.1251 +                     uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE;
  1.1252 +            if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
  1.1253 +                fprintf(stderr, "Unable to allocate memory for command.\n");
  1.1254 +                return -1;
  1.1255 +            }
  1.1256 +            freeCmd = TRUE;
  1.1257 +        }
  1.1258 +        sprintf(cmd, "%s %s %s%s %s",
  1.1259 +                pkgDataFlags[AR],
  1.1260 +                pkgDataFlags[ARFLAGS],
  1.1261 +                targetDir,
  1.1262 +                libFileNames[LIB_FILE_VERSION],
  1.1263 +                objectFile);
  1.1264 +
  1.1265 +        result = runCommand(cmd);
  1.1266 +        if (result == 0) {
  1.1267 +            sprintf(cmd, "%s %s%s", 
  1.1268 +                    pkgDataFlags[RANLIB], 
  1.1269 +                    targetDir, 
  1.1270 +                    libFileNames[LIB_FILE_VERSION]); 
  1.1271 +        
  1.1272 +            result = runCommand(cmd);
  1.1273 +        }
  1.1274 +    } else /* if (IN_DLL_MODE(mode)) */ {
  1.1275 +        if (cmd == NULL) {
  1.1276 +            length = uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) +
  1.1277 +                     ((uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP])) * 2) +
  1.1278 +                     uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) +
  1.1279 +                     uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) +
  1.1280 +                     uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE;
  1.1281 +#if U_PLATFORM == U_PF_CYGWIN
  1.1282 +            length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]);
  1.1283 +#elif U_PLATFORM == U_PF_MINGW
  1.1284 +            length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_MINGW]);
  1.1285 +#endif
  1.1286 +            if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
  1.1287 +                fprintf(stderr, "Unable to allocate memory for command.\n");
  1.1288 +                return -1;
  1.1289 +            }
  1.1290 +            freeCmd = TRUE;
  1.1291 +        }
  1.1292 +#if U_PLATFORM == U_PF_MINGW
  1.1293 +        sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
  1.1294 +                pkgDataFlags[GENLIB],
  1.1295 +                targetDir,
  1.1296 +                libFileNames[LIB_FILE_MINGW],
  1.1297 +                pkgDataFlags[LDICUDTFLAGS],
  1.1298 +                targetDir,
  1.1299 +                libFileNames[LIB_FILE_VERSION_TMP],
  1.1300 +#elif U_PLATFORM == U_PF_CYGWIN
  1.1301 +        sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
  1.1302 +                pkgDataFlags[GENLIB],
  1.1303 +                targetDir,
  1.1304 +                libFileNames[LIB_FILE_VERSION_TMP],
  1.1305 +                pkgDataFlags[LDICUDTFLAGS],
  1.1306 +                targetDir,
  1.1307 +                libFileNames[LIB_FILE_CYGWIN_VERSION],
  1.1308 +#elif U_PLATFORM == U_PF_AIX
  1.1309 +        sprintf(cmd, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
  1.1310 +                RM_CMD,
  1.1311 +                targetDir,
  1.1312 +                libFileNames[LIB_FILE_VERSION_TMP],
  1.1313 +                pkgDataFlags[GENLIB],
  1.1314 +                pkgDataFlags[LDICUDTFLAGS],
  1.1315 +                targetDir,
  1.1316 +                libFileNames[LIB_FILE_VERSION_TMP],
  1.1317 +#else
  1.1318 +        sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
  1.1319 +                pkgDataFlags[GENLIB],
  1.1320 +                pkgDataFlags[LDICUDTFLAGS],
  1.1321 +                targetDir,
  1.1322 +                libFileNames[LIB_FILE_VERSION_TMP],
  1.1323 +#endif
  1.1324 +                objectFile,
  1.1325 +                pkgDataFlags[LD_SONAME],
  1.1326 +                pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
  1.1327 +                pkgDataFlags[RPATH_FLAGS],
  1.1328 +                pkgDataFlags[BIR_FLAGS]);
  1.1329 +
  1.1330 +        /* Generate the library file. */
  1.1331 +        result = runCommand(cmd);
  1.1332 +
  1.1333 +#if U_PLATFORM == U_PF_OS390 && defined(OS390BATCH)
  1.1334 +        char PDS_LibName[512];
  1.1335 +        if (uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) {
  1.1336 +            sprintf(PDS_LibName,"%s%s%s",
  1.1337 +                    "\"//'",
  1.1338 +                    getenv("LOADMOD"),
  1.1339 +                    "(IXMI" U_ICU_VERSION_SHORT "DA)'\"");
  1.1340 +        } else if (uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) {
  1.1341 +           sprintf(PDS_LibName,"%s%s%s",
  1.1342 +                   "\"//'",
  1.1343 +                   getenv("LOADMOD"),
  1.1344 +                   "(IXMI" U_ICU_VERSION_SHORT "D1)'\"");
  1.1345 +           sprintf(cmd, "%s %s -o %s %s %s%s %s %s",
  1.1346 +                   pkgDataFlags[GENLIB],
  1.1347 +                   pkgDataFlags[LDICUDTFLAGS],
  1.1348 +                   PDS_LibName,
  1.1349 +                   objectFile,
  1.1350 +                   pkgDataFlags[LD_SONAME],
  1.1351 +                   pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
  1.1352 +                   pkgDataFlags[RPATH_FLAGS],
  1.1353 +                   pkgDataFlags[BIR_FLAGS]);
  1.1354 +        }
  1.1355 +        result = runCommand(cmd);
  1.1356 +#endif
  1.1357 +    }
  1.1358 +
  1.1359 +    if (result != 0) {
  1.1360 +        fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd);
  1.1361 +    }
  1.1362 +
  1.1363 +    if (freeCmd) {
  1.1364 +        uprv_free(cmd);
  1.1365 +    }
  1.1366 +
  1.1367 +    return result;
  1.1368 +}
  1.1369 +
  1.1370 +static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
  1.1371 +    char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
  1.1372 +    char *cmd;
  1.1373 +    int32_t result = 0;
  1.1374 +
  1.1375 +    int32_t length = 0;
  1.1376 +
  1.1377 +    /* Remove the ending .s and replace it with .o for the new object file. */
  1.1378 +    uprv_strcpy(tempObjectFile, gencFilePath);
  1.1379 +    tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
  1.1380 +
  1.1381 +    length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
  1.1382 +                    + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE;
  1.1383 +
  1.1384 +    cmd = (char *)uprv_malloc(sizeof(char) * length);
  1.1385 +    if (cmd == NULL) {
  1.1386 +        return -1;
  1.1387 +    }
  1.1388 +
  1.1389 +    /* Generate the object file. */
  1.1390 +    sprintf(cmd, "%s %s -o %s %s",
  1.1391 +            pkgDataFlags[COMPILER],
  1.1392 +            pkgDataFlags[LIBFLAGS],
  1.1393 +            tempObjectFile,
  1.1394 +            gencFilePath);
  1.1395 +
  1.1396 +    result = runCommand(cmd);
  1.1397 +    uprv_free(cmd);
  1.1398 +    if (result != 0) {
  1.1399 +        fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd);
  1.1400 +        return result;
  1.1401 +    }
  1.1402 +
  1.1403 +    return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
  1.1404 +}
  1.1405 +
  1.1406 +#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
  1.1407 +/*
  1.1408 + * Generation of the data library without assembly code needs to compile each data file
  1.1409 + * individually and then link it all together.
  1.1410 + * Note: Any update to the directory structure of the data needs to be reflected here.
  1.1411 + */
  1.1412 +enum {
  1.1413 +    DATA_PREFIX_BRKITR,
  1.1414 +    DATA_PREFIX_COLL,
  1.1415 +    DATA_PREFIX_CURR,
  1.1416 +    DATA_PREFIX_LANG,
  1.1417 +    DATA_PREFIX_RBNF,
  1.1418 +    DATA_PREFIX_REGION,
  1.1419 +    DATA_PREFIX_TRANSLIT,
  1.1420 +    DATA_PREFIX_ZONE,
  1.1421 +    DATA_PREFIX_LENGTH
  1.1422 +};
  1.1423 +
  1.1424 +const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
  1.1425 +        "brkitr",
  1.1426 +        "coll",
  1.1427 +        "curr",
  1.1428 +        "lang",
  1.1429 +        "rbnf",
  1.1430 +        "region",
  1.1431 +        "translit",
  1.1432 +        "zone"
  1.1433 +};
  1.1434 +
  1.1435 +static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
  1.1436 +    int32_t result = 0;
  1.1437 +    CharList *list = o->filePaths;
  1.1438 +    CharList *listNames = o->files;
  1.1439 +    int32_t listSize = pkg_countCharList(list);
  1.1440 +    char *buffer;
  1.1441 +    char *cmd;
  1.1442 +    char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
  1.1443 +    char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
  1.1444 +#ifdef USE_SINGLE_CCODE_FILE
  1.1445 +    char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
  1.1446 +    FileStream *icudtAllFile = NULL;
  1.1447 +    
  1.1448 +    sprintf(icudtAll, "%s%s%sall.c",
  1.1449 +            o->tmpDir,
  1.1450 +            PKGDATA_FILE_SEP_STRING, 
  1.1451 +            libFileNames[LIB_FILE]);
  1.1452 +    /* Remove previous icudtall.c file. */
  1.1453 +    if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
  1.1454 +        fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
  1.1455 +        return result;
  1.1456 +    }
  1.1457 +
  1.1458 +    if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==NULL) {
  1.1459 +        fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll);
  1.1460 +        return result;
  1.1461 +    }
  1.1462 +#endif
  1.1463 +
  1.1464 +    if (list == NULL || listNames == NULL) {
  1.1465 +        /* list and listNames should never be NULL since we are looping through the CharList with
  1.1466 +         * the given size.
  1.1467 +         */
  1.1468 +        return -1;
  1.1469 +    }
  1.1470 +
  1.1471 +    if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
  1.1472 +        fprintf(stderr, "Unable to allocate memory for cmd.\n");
  1.1473 +        return -1;
  1.1474 +    } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
  1.1475 +        fprintf(stderr, "Unable to allocate memory for buffer.\n");
  1.1476 +        uprv_free(cmd);
  1.1477 +        return -1;
  1.1478 +    }
  1.1479 +
  1.1480 +    for (int32_t i = 0; i < (listSize + 1); i++) {
  1.1481 +        const char *file ;
  1.1482 +        const char *name;
  1.1483 +
  1.1484 +        if (i == 0) {
  1.1485 +            /* The first iteration calls the gencmn function and initailizes the buffer. */
  1.1486 +            createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
  1.1487 +            buffer[0] = 0;
  1.1488 +#ifdef USE_SINGLE_CCODE_FILE
  1.1489 +            uprv_strcpy(tempObjectFile, gencmnFile);
  1.1490 +            tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
  1.1491 +            
  1.1492 +            sprintf(cmd, "%s %s -o %s %s",
  1.1493 +                        pkgDataFlags[COMPILER],
  1.1494 +                        pkgDataFlags[LIBFLAGS],
  1.1495 +                        tempObjectFile,
  1.1496 +                        gencmnFile);
  1.1497 +            
  1.1498 +            result = runCommand(cmd);
  1.1499 +            if (result != 0) {
  1.1500 +                break;
  1.1501 +            }
  1.1502 +            
  1.1503 +            sprintf(buffer, "%s",tempObjectFile);
  1.1504 +#endif
  1.1505 +        } else {
  1.1506 +            char newName[SMALL_BUFFER_MAX_SIZE];
  1.1507 +            char dataName[SMALL_BUFFER_MAX_SIZE];
  1.1508 +            char dataDirName[SMALL_BUFFER_MAX_SIZE];
  1.1509 +            const char *pSubstring;
  1.1510 +            file = list->str;
  1.1511 +            name = listNames->str;
  1.1512 +
  1.1513 +            newName[0] = dataName[0] = 0;
  1.1514 +            for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
  1.1515 +                dataDirName[0] = 0;
  1.1516 +                sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
  1.1517 +                /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
  1.1518 +                pSubstring = uprv_strstr(name, dataDirName);
  1.1519 +                if (pSubstring != NULL) {
  1.1520 +                    char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
  1.1521 +                    const char *p = name + uprv_strlen(dataDirName);
  1.1522 +                    for (int32_t i = 0;;i++) {
  1.1523 +                        if (p[i] == '.') {
  1.1524 +                            newNameTmp[i] = '_';
  1.1525 +                            continue;
  1.1526 +                        }
  1.1527 +                        newNameTmp[i] = p[i];
  1.1528 +                        if (p[i] == 0) {
  1.1529 +                            break;
  1.1530 +                        }
  1.1531 +                    }
  1.1532 +                    sprintf(newName, "%s_%s",
  1.1533 +                            DATA_PREFIX[n],
  1.1534 +                            newNameTmp);
  1.1535 +                    sprintf(dataName, "%s_%s",
  1.1536 +                            o->shortName,
  1.1537 +                            DATA_PREFIX[n]);
  1.1538 +                }
  1.1539 +                if (newName[0] != 0) {
  1.1540 +                    break;
  1.1541 +                }
  1.1542 +            }
  1.1543 +
  1.1544 +            if(o->verbose) {
  1.1545 +              printf("# Generating %s \n", gencmnFile);
  1.1546 +            }
  1.1547 +
  1.1548 +            writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
  1.1549 +
  1.1550 +#ifdef USE_SINGLE_CCODE_FILE
  1.1551 +            sprintf(cmd, "#include \"%s\"\n", gencmnFile);
  1.1552 +            T_FileStream_writeLine(icudtAllFile, cmd);
  1.1553 +            /* don't delete the file */
  1.1554 +#endif
  1.1555 +        }
  1.1556 +
  1.1557 +#ifndef USE_SINGLE_CCODE_FILE
  1.1558 +        uprv_strcpy(tempObjectFile, gencmnFile);
  1.1559 +        tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
  1.1560 +        
  1.1561 +        sprintf(cmd, "%s %s -o %s %s",
  1.1562 +                    pkgDataFlags[COMPILER],
  1.1563 +                    pkgDataFlags[LIBFLAGS],
  1.1564 +                    tempObjectFile,
  1.1565 +                    gencmnFile);
  1.1566 +        result = runCommand(cmd);
  1.1567 +        if (result != 0) {
  1.1568 +            fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
  1.1569 +            break;
  1.1570 +        }
  1.1571 +
  1.1572 +        uprv_strcat(buffer, " ");
  1.1573 +        uprv_strcat(buffer, tempObjectFile);
  1.1574 +
  1.1575 +#endif
  1.1576 +        
  1.1577 +        if (i > 0) {
  1.1578 +            list = list->next;
  1.1579 +            listNames = listNames->next;
  1.1580 +        }
  1.1581 +    }
  1.1582 +
  1.1583 +#ifdef USE_SINGLE_CCODE_FILE
  1.1584 +    T_FileStream_close(icudtAllFile);
  1.1585 +    uprv_strcpy(tempObjectFile, icudtAll);
  1.1586 +    tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
  1.1587 +
  1.1588 +    sprintf(cmd, "%s %s -I. -o %s %s",
  1.1589 +        pkgDataFlags[COMPILER],
  1.1590 +        pkgDataFlags[LIBFLAGS],
  1.1591 +        tempObjectFile,
  1.1592 +        icudtAll);
  1.1593 +    
  1.1594 +    result = runCommand(cmd);
  1.1595 +    if (result == 0) {
  1.1596 +        uprv_strcat(buffer, " ");
  1.1597 +        uprv_strcat(buffer, tempObjectFile);
  1.1598 +    } else {
  1.1599 +        fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
  1.1600 +    }
  1.1601 +#endif
  1.1602 +
  1.1603 +    if (result == 0) {
  1.1604 +        /* Generate the library file. */
  1.1605 +#if U_PLATFORM == U_PF_OS390
  1.1606 +        if (o->pdsbuild && IN_DLL_MODE(mode)) {
  1.1607 +            result = pkg_generateLibraryFile("",mode, buffer, cmd);
  1.1608 +        } else {
  1.1609 +            result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
  1.1610 +        }
  1.1611 +#else
  1.1612 +        result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
  1.1613 +#endif
  1.1614 +    }
  1.1615 +
  1.1616 +    uprv_free(buffer);
  1.1617 +    uprv_free(cmd);
  1.1618 +
  1.1619 +    return result;
  1.1620 +}
  1.1621 +#endif
  1.1622 +
  1.1623 +#ifdef WINDOWS_WITH_MSVC
  1.1624 +#define LINK_CMD "link.exe /nologo /release /out:"
  1.1625 +#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO  /base:0x4ad00000 /implib:"
  1.1626 +#define LIB_CMD "LIB.exe /nologo /out:"
  1.1627 +#define LIB_FILE "icudt.lib"
  1.1628 +#define LIB_EXT UDATA_LIB_SUFFIX
  1.1629 +#define DLL_EXT UDATA_SO_SUFFIX
  1.1630 +
  1.1631 +static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
  1.1632 +    int32_t result = 0;
  1.1633 +    char cmd[LARGE_BUFFER_MAX_SIZE];
  1.1634 +    if (IN_STATIC_MODE(mode)) {
  1.1635 +        char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
  1.1636 +
  1.1637 +#ifdef CYGWINMSVC
  1.1638 +        sprintf(staticLibFilePath, "%s%s%s%s%s",
  1.1639 +                o->targetDir,
  1.1640 +                PKGDATA_FILE_SEP_STRING,
  1.1641 +                pkgDataFlags[LIBPREFIX],
  1.1642 +                o->libName,
  1.1643 +                LIB_EXT);
  1.1644 +#else
  1.1645 +        sprintf(staticLibFilePath, "%s%s%s%s%s",
  1.1646 +                o->targetDir,
  1.1647 +                PKGDATA_FILE_SEP_STRING,
  1.1648 +                (strstr(o->libName, "icudt") ? "s" : ""),
  1.1649 +                o->libName,
  1.1650 +                LIB_EXT);
  1.1651 +#endif
  1.1652 +
  1.1653 +        sprintf(cmd, "%s\"%s\" \"%s\"",
  1.1654 +                LIB_CMD,
  1.1655 +                staticLibFilePath,
  1.1656 +                gencFilePath);
  1.1657 +    } else if (IN_DLL_MODE(mode)) {
  1.1658 +        char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
  1.1659 +        char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
  1.1660 +        char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
  1.1661 +        char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
  1.1662 +
  1.1663 +#ifdef CYGWINMSVC
  1.1664 +        uprv_strcpy(dllFilePath, o->targetDir);
  1.1665 +#else
  1.1666 +        uprv_strcpy(dllFilePath, o->srcDir);
  1.1667 +#endif
  1.1668 +        uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
  1.1669 +        uprv_strcpy(libFilePath, dllFilePath);
  1.1670 +
  1.1671 +#ifdef CYGWINMSVC
  1.1672 +        uprv_strcat(libFilePath, o->libName);
  1.1673 +        uprv_strcat(libFilePath, ".lib");
  1.1674 +        
  1.1675 +        uprv_strcat(dllFilePath, o->libName);
  1.1676 +        uprv_strcat(dllFilePath, o->version);
  1.1677 +#else
  1.1678 +        if (strstr(o->libName, "icudt")) {
  1.1679 +            uprv_strcat(libFilePath, LIB_FILE);
  1.1680 +        } else {
  1.1681 +            uprv_strcat(libFilePath, o->libName);
  1.1682 +            uprv_strcat(libFilePath, ".lib");
  1.1683 +        }
  1.1684 +        uprv_strcat(dllFilePath, o->entryName);
  1.1685 +#endif
  1.1686 +        uprv_strcat(dllFilePath, DLL_EXT);
  1.1687 +        
  1.1688 +        uprv_strcpy(tmpResFilePath, o->tmpDir);
  1.1689 +        uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
  1.1690 +        uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
  1.1691 +
  1.1692 +        if (T_FileStream_file_exists(tmpResFilePath)) {
  1.1693 +            sprintf(resFilePath, "\"%s\"", tmpResFilePath);
  1.1694 +        }
  1.1695 +
  1.1696 +        /* Check if dll file and lib file exists and that it is not newer than genc file. */
  1.1697 +        if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
  1.1698 +            (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
  1.1699 +          if(o->verbose) {
  1.1700 +            printf("# Not rebuilding %s - up to date.\n", gencFilePath);
  1.1701 +          }
  1.1702 +          return 0;
  1.1703 +        }
  1.1704 +
  1.1705 +        sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" %s",
  1.1706 +                LINK_CMD,
  1.1707 +                dllFilePath,
  1.1708 +                LINK_FLAGS,
  1.1709 +                libFilePath,
  1.1710 +                gencFilePath,
  1.1711 +                resFilePath
  1.1712 +                );
  1.1713 +    }
  1.1714 +
  1.1715 +    result = runCommand(cmd, TRUE);
  1.1716 +    if (result != 0) {
  1.1717 +        fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd);
  1.1718 +    }
  1.1719 +
  1.1720 +    return result;
  1.1721 +}
  1.1722 +#endif
  1.1723 +
  1.1724 +static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
  1.1725 +#if U_PLATFORM == U_PF_AIX
  1.1726 +    /* AIX needs a map file. */
  1.1727 +    char *flag = NULL;
  1.1728 +    int32_t length = 0;
  1.1729 +    char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
  1.1730 +    const char MAP_FILE_EXT[] = ".map";
  1.1731 +    FileStream *f = NULL;
  1.1732 +    char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
  1.1733 +    int32_t start = -1;
  1.1734 +    uint32_t count = 0;
  1.1735 +    const char rm_cmd[] = "rm -f all ;";
  1.1736 +
  1.1737 +    flag = pkgDataFlags[GENLIB];
  1.1738 +
  1.1739 +    /* This portion of the code removes 'rm -f all' in the GENLIB.
  1.1740 +     * Only occurs in AIX.
  1.1741 +     */
  1.1742 +    if (uprv_strstr(flag, rm_cmd) != NULL) {
  1.1743 +        char *tmpGenlibFlagBuffer = NULL;
  1.1744 +        int32_t i, offset;
  1.1745 +
  1.1746 +        length = uprv_strlen(flag) + 1;
  1.1747 +        tmpGenlibFlagBuffer = (char *)uprv_malloc(length);
  1.1748 +        if (tmpGenlibFlagBuffer == NULL) {
  1.1749 +            /* Memory allocation error */
  1.1750 +            fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length);
  1.1751 +            return NULL;
  1.1752 +        }
  1.1753 +
  1.1754 +        uprv_strcpy(tmpGenlibFlagBuffer, flag);
  1.1755 +
  1.1756 +        offset = uprv_strlen(rm_cmd);
  1.1757 +
  1.1758 +        for (i = 0; i < (length - offset); i++) {
  1.1759 +            flag[i] = tmpGenlibFlagBuffer[offset + i];
  1.1760 +        }
  1.1761 +
  1.1762 +        /* Zero terminate the string */
  1.1763 +        flag[i] = 0;
  1.1764 +
  1.1765 +        uprv_free(tmpGenlibFlagBuffer);
  1.1766 +    }
  1.1767 +
  1.1768 +    flag = pkgDataFlags[BIR_FLAGS];
  1.1769 +    length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
  1.1770 +
  1.1771 +    for (int32_t i = 0; i < length; i++) {
  1.1772 +        if (flag[i] == MAP_FILE_EXT[count]) {
  1.1773 +            if (count == 0) {
  1.1774 +                start = i;
  1.1775 +            }
  1.1776 +            count++;
  1.1777 +        } else {
  1.1778 +            count = 0;
  1.1779 +        }
  1.1780 +
  1.1781 +        if (count == uprv_strlen(MAP_FILE_EXT)) {
  1.1782 +            break;
  1.1783 +        }
  1.1784 +    }
  1.1785 +
  1.1786 +    if (start >= 0) {
  1.1787 +        int32_t index = 0;
  1.1788 +        for (int32_t i = 0;;i++) {
  1.1789 +            if (i == start) {
  1.1790 +                for (int32_t n = 0;;n++) {
  1.1791 +                    if (o->shortName[n] == 0) {
  1.1792 +                        break;
  1.1793 +                    }
  1.1794 +                    tmpbuffer[index++] = o->shortName[n];
  1.1795 +                }
  1.1796 +            }
  1.1797 +
  1.1798 +            tmpbuffer[index++] = flag[i];
  1.1799 +
  1.1800 +            if (flag[i] == 0) {
  1.1801 +                break;
  1.1802 +            }
  1.1803 +        }
  1.1804 +
  1.1805 +        uprv_memset(flag, 0, length);
  1.1806 +        uprv_strcpy(flag, tmpbuffer);
  1.1807 +
  1.1808 +        uprv_strcpy(mapFile, o->shortName);
  1.1809 +        uprv_strcat(mapFile, MAP_FILE_EXT);
  1.1810 +
  1.1811 +        f = T_FileStream_open(mapFile, "w");
  1.1812 +        if (f == NULL) {
  1.1813 +            fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
  1.1814 +            return NULL;
  1.1815 +        } else {
  1.1816 +            sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
  1.1817 +    
  1.1818 +            T_FileStream_writeLine(f, tmpbuffer);
  1.1819 +    
  1.1820 +            T_FileStream_close(f);
  1.1821 +        }
  1.1822 +    }
  1.1823 +#elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
  1.1824 +    /* Cygwin needs to change flag options. */
  1.1825 +    char *flag = NULL;
  1.1826 +    int32_t length = 0;
  1.1827 +
  1.1828 +    flag = pkgDataFlags[GENLIB];
  1.1829 +    length = uprv_strlen(pkgDataFlags[GENLIB]);
  1.1830 +
  1.1831 +    int32_t position = length - 1;
  1.1832 +
  1.1833 +    for(;position >= 0;position--) {
  1.1834 +        if (flag[position] == '=') {
  1.1835 +            position++;
  1.1836 +            break;
  1.1837 +        }
  1.1838 +    }
  1.1839 +
  1.1840 +    uprv_memset(flag + position, 0, length - position);
  1.1841 +#elif U_PLATFORM == U_PF_OS400
  1.1842 +    /* OS/400 needs to fix the ld options (swap single quote with double quote) */
  1.1843 +    char *flag = NULL;
  1.1844 +    int32_t length = 0;
  1.1845 +
  1.1846 +    flag = pkgDataFlags[GENLIB];
  1.1847 +    length = uprv_strlen(pkgDataFlags[GENLIB]);
  1.1848 +
  1.1849 +    int32_t position = length - 1;
  1.1850 +
  1.1851 +    for(int32_t i = 0; i < length; i++) {
  1.1852 +        if (flag[i] == '\'') {
  1.1853 +            flag[i] = '\"';
  1.1854 +        }
  1.1855 +    }
  1.1856 +#endif
  1.1857 +    // Don't really need a return value, just need to stop compiler warnings about
  1.1858 +    // the unused parameter 'o' on platforms where it is not otherwise used.
  1.1859 +    return o;   
  1.1860 +}
  1.1861 +
  1.1862 +static void loadLists(UPKGOptions *o, UErrorCode *status)
  1.1863 +{
  1.1864 +    CharList   *l, *tail = NULL, *tail2 = NULL;
  1.1865 +    FileStream *in;
  1.1866 +    char        line[16384];
  1.1867 +    char       *linePtr, *lineNext;
  1.1868 +    const uint32_t   lineMax = 16300;
  1.1869 +    char       *tmp;
  1.1870 +    int32_t     tmpLength = 0;
  1.1871 +    char       *s;
  1.1872 +    int32_t     ln=0; /* line number */
  1.1873 +
  1.1874 +    for(l = o->fileListFiles; l; l = l->next) {
  1.1875 +        if(o->verbose) {
  1.1876 +            fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
  1.1877 +        }
  1.1878 +        /* TODO: stdin */
  1.1879 +        in = T_FileStream_open(l->str, "r"); /* open files list */
  1.1880 +
  1.1881 +        if(!in) {
  1.1882 +            fprintf(stderr, "Error opening <%s>.\n", l->str);
  1.1883 +            *status = U_FILE_ACCESS_ERROR;
  1.1884 +            return;
  1.1885 +        }
  1.1886 +
  1.1887 +        while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
  1.1888 +            ln++;
  1.1889 +            if(uprv_strlen(line)>lineMax) {
  1.1890 +                fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
  1.1891 +                exit(1);
  1.1892 +            }
  1.1893 +            /* remove spaces at the beginning */
  1.1894 +            linePtr = line;
  1.1895 +            /* On z/OS, disable call to isspace (#9996).  Investigate using uprv_isspace instead (#9999) */
  1.1896 +#if U_PLATFORM != U_PF_OS390
  1.1897 +            while(isspace(*linePtr)) {
  1.1898 +                linePtr++;
  1.1899 +            }
  1.1900 +#endif
  1.1901 +            s=linePtr;
  1.1902 +            /* remove trailing newline characters */
  1.1903 +            while(*s!=0) {
  1.1904 +                if(*s=='\r' || *s=='\n') {
  1.1905 +                    *s=0;
  1.1906 +                    break;
  1.1907 +                }
  1.1908 +                ++s;
  1.1909 +            }
  1.1910 +            if((*linePtr == 0) || (*linePtr == '#')) {
  1.1911 +                continue; /* comment or empty line */
  1.1912 +            }
  1.1913 +
  1.1914 +            /* Now, process the line */
  1.1915 +            lineNext = NULL;
  1.1916 +
  1.1917 +            while(linePtr && *linePtr) { /* process space-separated items */
  1.1918 +                while(*linePtr == ' ') {
  1.1919 +                    linePtr++;
  1.1920 +                }
  1.1921 +                /* Find the next quote */
  1.1922 +                if(linePtr[0] == '"')
  1.1923 +                {
  1.1924 +                    lineNext = uprv_strchr(linePtr+1, '"');
  1.1925 +                    if(lineNext == NULL) {
  1.1926 +                        fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
  1.1927 +                            l->str, (int)ln);
  1.1928 +                        exit(1);
  1.1929 +                    } else {
  1.1930 +                        lineNext++;
  1.1931 +                        if(*lineNext) {
  1.1932 +                            if(*lineNext != ' ') {
  1.1933 +                                fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
  1.1934 +                                    l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
  1.1935 +                                exit(1);
  1.1936 +                            }
  1.1937 +                            *lineNext = 0;
  1.1938 +                            lineNext++;
  1.1939 +                        }
  1.1940 +                    }
  1.1941 +                } else {
  1.1942 +                    lineNext = uprv_strchr(linePtr, ' ');
  1.1943 +                    if(lineNext) {
  1.1944 +                        *lineNext = 0; /* terminate at space */
  1.1945 +                        lineNext++;
  1.1946 +                    }
  1.1947 +                }
  1.1948 +
  1.1949 +                /* add the file */
  1.1950 +                s = (char*)getLongPathname(linePtr);
  1.1951 +
  1.1952 +                /* normal mode.. o->files is just the bare list without package names */
  1.1953 +                o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
  1.1954 +                if(uprv_pathIsAbsolute(s) || s[0] == '.') {
  1.1955 +                    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);
  1.1956 +                    exit(U_ILLEGAL_ARGUMENT_ERROR);
  1.1957 +                }
  1.1958 +                tmpLength = uprv_strlen(o->srcDir) + 
  1.1959 +                            uprv_strlen(s) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
  1.1960 +                if((tmp = (char *)uprv_malloc(tmpLength)) == NULL) {
  1.1961 +                    fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength);
  1.1962 +                    exit(U_MEMORY_ALLOCATION_ERROR);
  1.1963 +                }
  1.1964 +                uprv_strcpy(tmp, o->srcDir);
  1.1965 +                uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING);
  1.1966 +                uprv_strcat(tmp, s);
  1.1967 +                o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp);
  1.1968 +                linePtr = lineNext;
  1.1969 +            } /* for each entry on line */
  1.1970 +        } /* for each line */
  1.1971 +        T_FileStream_close(in);
  1.1972 +    } /* for each file list file */
  1.1973 +}
  1.1974 +
  1.1975 +/* Try calling icu-config directly to get the option file. */
  1.1976 + static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
  1.1977 +#if U_HAVE_POPEN
  1.1978 +    FILE *p = NULL;
  1.1979 +    size_t n;
  1.1980 +    static char buf[512] = "";
  1.1981 +    char cmdBuf[1024];
  1.1982 +    UErrorCode status = U_ZERO_ERROR;
  1.1983 +    const char cmd[] = "icu-config --incpkgdatafile";
  1.1984 +
  1.1985 +    /* #1 try the same path where pkgdata was called from. */
  1.1986 +    findDirname(progname, cmdBuf, 1024, &status);
  1.1987 +    if(U_SUCCESS(status)) {
  1.1988 +      if (cmdBuf[0] != 0) {
  1.1989 +          uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024);
  1.1990 +      }
  1.1991 +      uprv_strncat(cmdBuf, cmd, 1024);
  1.1992 +      
  1.1993 +      if(verbose) {
  1.1994 +        fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf);
  1.1995 +      }
  1.1996 +      p = popen(cmdBuf, "r");
  1.1997 +    }
  1.1998 +
  1.1999 +    if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) {
  1.2000 +      if(verbose) {
  1.2001 +        fprintf(stdout, "# Calling icu-config: %s\n", cmd);
  1.2002 +      }
  1.2003 +      pclose(p);
  1.2004 +
  1.2005 +      p = popen(cmd, "r");
  1.2006 +      if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) {
  1.2007 +          fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
  1.2008 +          return -1;
  1.2009 +      }
  1.2010 +    }
  1.2011 +
  1.2012 +    pclose(p);
  1.2013 +
  1.2014 +    for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
  1.2015 +        if (buf[length] == '\n' || buf[length] == ' ') {
  1.2016 +            buf[length] = 0;
  1.2017 +        } else {
  1.2018 +            break;
  1.2019 +        }
  1.2020 +    }
  1.2021 +
  1.2022 +    if(buf[strlen(buf)-1]=='\n')
  1.2023 +    {
  1.2024 +        buf[strlen(buf)-1]=0;
  1.2025 +    }
  1.2026 +
  1.2027 +    if(buf[0] == 0)
  1.2028 +    {
  1.2029 +        fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
  1.2030 +        return -1;
  1.2031 +    }
  1.2032 +
  1.2033 +    if(verbose) {
  1.2034 +      fprintf(stdout, "# icu-config said: %s\n", buf);
  1.2035 +    }
  1.2036 +
  1.2037 +    option->value = buf;
  1.2038 +    option->doesOccur = TRUE;
  1.2039 +
  1.2040 +    return 0;
  1.2041 +#else
  1.2042 +    return -1;
  1.2043 +#endif
  1.2044 +}

mercurial