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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial