| Index: icu46/source/tools/pkgdata/pkgdata.cpp
|
| ===================================================================
|
| --- icu46/source/tools/pkgdata/pkgdata.cpp (revision 0)
|
| +++ icu46/source/tools/pkgdata/pkgdata.cpp (revision 0)
|
| @@ -0,0 +1,1805 @@
|
| +/******************************************************************************
|
| + * Copyright (C) 2000-2010, International Business Machines
|
| + * Corporation and others. All Rights Reserved.
|
| + *******************************************************************************
|
| + * file name: pkgdata.c
|
| + * encoding: ANSI X3.4 (1968)
|
| + * tab size: 8 (not used)
|
| + * indentation:4
|
| + *
|
| + * created on: 2000may15
|
| + * created by: Steven \u24C7 Loomis
|
| + *
|
| + * This program packages the ICU data into different forms
|
| + * (DLL, common data, etc.)
|
| + */
|
| +
|
| +/*
|
| + * We define _XOPEN_SOURCE so that we can get popen and pclose.
|
| + */
|
| +#if !defined(_XOPEN_SOURCE)
|
| +#if __STDC_VERSION__ >= 199901L
|
| +/* It is invalid to compile an XPG3, XPG4, XPG4v2 or XPG5 application using c99 on Solaris */
|
| +#define _XOPEN_SOURCE 600
|
| +#else
|
| +#define _XOPEN_SOURCE 4
|
| +#endif
|
| +#endif
|
| +
|
| +
|
| +#include "unicode/utypes.h"
|
| +
|
| +#if U_HAVE_POPEN
|
| +#if defined(U_CYGWIN) && defined(__STRICT_ANSI__)
|
| +/* popen/pclose aren't defined in strict ANSI on Cygwin */
|
| +#undef __STRICT_ANSI__
|
| +#endif
|
| +#endif
|
| +
|
| +#include "unicode/putil.h"
|
| +#include "cmemory.h"
|
| +#include "cstring.h"
|
| +#include "filestrm.h"
|
| +#include "toolutil.h"
|
| +#include "unicode/uclean.h"
|
| +#include "unewdata.h"
|
| +#include "uoptions.h"
|
| +#include "putilimp.h"
|
| +#include "package.h"
|
| +#include "pkg_icu.h"
|
| +#include "pkg_genc.h"
|
| +#include "pkg_gencmn.h"
|
| +#include "flagparser.h"
|
| +#include "filetools.h"
|
| +
|
| +
|
| +#if U_HAVE_POPEN
|
| +# include <unistd.h>
|
| +#endif
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +
|
| +U_CDECL_BEGIN
|
| +#include "pkgtypes.h"
|
| +U_CDECL_END
|
| +
|
| +#ifdef U_WINDOWS
|
| +#ifdef __GNUC__
|
| +#define WINDOWS_WITH_GNUC
|
| +#else
|
| +#define WINDOWS_WITH_MSVC
|
| +#endif
|
| +#endif
|
| +#if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX)
|
| +#define BUILD_DATA_WITHOUT_ASSEMBLY
|
| +#endif
|
| +#if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
|
| +#define CAN_WRITE_OBJ_CODE
|
| +#endif
|
| +#if defined(U_CYGWIN) || defined(CYGWINMSVC)
|
| +#define USING_CYGWIN
|
| +#endif
|
| +
|
| +/*
|
| + * When building the data library without assembly,
|
| + * some platforms use a single c code file for all of
|
| + * the data to generate the final data library. This can
|
| + * increase the performance of the pkdata tool.
|
| + */
|
| +#if defined(OS400)
|
| +#define USE_SINGLE_CCODE_FILE
|
| +#endif
|
| +
|
| +/* Need to fix the file seperator character when using MinGW. */
|
| +#if defined(WINDOWS_WITH_GNUC) || defined(USING_CYGWIN)
|
| +#define PKGDATA_FILE_SEP_STRING "/"
|
| +#else
|
| +#define PKGDATA_FILE_SEP_STRING U_FILE_SEP_STRING
|
| +#endif
|
| +
|
| +#define LARGE_BUFFER_MAX_SIZE 2048
|
| +#define SMALL_BUFFER_MAX_SIZE 512
|
| +
|
| +static void loadLists(UPKGOptions *o, UErrorCode *status);
|
| +
|
| +static int32_t pkg_executeOptions(UPKGOptions *o);
|
| +
|
| +#ifdef WINDOWS_WITH_MSVC
|
| +static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
|
| +#endif
|
| +static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE);
|
| +static int32_t pkg_installLibrary(const char *installDir, const char *dir);
|
| +static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
|
| +static int32_t pkg_installCommonMode(const char *installDir, const char *fileName);
|
| +
|
| +#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
|
| +static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
|
| +#endif
|
| +
|
| +static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
|
| +static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL);
|
| +static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
|
| +static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt);
|
| +static int32_t initializePkgDataFlags(UPKGOptions *o);
|
| +
|
| +static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option);
|
| +static int runCommand(const char* command, UBool specialHandling=FALSE);
|
| +
|
| +enum {
|
| + NAME,
|
| + BLDOPT,
|
| + MODE,
|
| + HELP,
|
| + HELP_QUESTION_MARK,
|
| + VERBOSE,
|
| + COPYRIGHT,
|
| + COMMENT,
|
| + DESTDIR,
|
| + REBUILD,
|
| + TEMPDIR,
|
| + INSTALL,
|
| + SOURCEDIR,
|
| + ENTRYPOINT,
|
| + REVISION,
|
| + FORCE_PREFIX,
|
| + LIBNAME,
|
| + QUIET
|
| +};
|
| +
|
| +/* This sets the modes that are available */
|
| +static struct {
|
| + const char *name, *alt_name;
|
| + const char *desc;
|
| +} modes[] = {
|
| + { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
|
| +#ifdef U_WINDOWS
|
| + { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
|
| + { "common", "archive", "Generates just the common file, <package>.dat"},
|
| + { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
|
| +#else
|
| +#ifdef UDATA_SO_SUFFIX
|
| + { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX },
|
| +#endif
|
| + { "common", "archive", "Generates one common data file, <package>.dat" },
|
| + { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
|
| +#endif
|
| +};
|
| +
|
| +static UOption options[]={
|
| + /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG),
|
| + /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
|
| + /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG),
|
| + /*03*/ UOPTION_HELP_H, /* -h */
|
| + /*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */
|
| + /*05*/ UOPTION_VERBOSE, /* -v */
|
| + /*06*/ UOPTION_COPYRIGHT, /* -c */
|
| + /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
|
| + /*08*/ UOPTION_DESTDIR, /* -d */
|
| + /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
|
| + /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
|
| + /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
|
| + /*14*/ UOPTION_SOURCEDIR ,
|
| + /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
|
| + /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
|
| + /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
|
| + /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
|
| + /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG)
|
| +};
|
| +
|
| +enum {
|
| + GENCCODE_ASSEMBLY_TYPE,
|
| + SO_EXT,
|
| + SOBJ_EXT,
|
| + A_EXT,
|
| + LIBPREFIX,
|
| + LIB_EXT_ORDER,
|
| + COMPILER,
|
| + LIBFLAGS,
|
| + GENLIB,
|
| + LDICUDTFLAGS,
|
| + LD_SONAME,
|
| + RPATH_FLAGS,
|
| + BIR_FLAGS,
|
| + AR,
|
| + ARFLAGS,
|
| + RANLIB,
|
| + INSTALL_CMD,
|
| + PKGDATA_FLAGS_SIZE
|
| +};
|
| +static char **pkgDataFlags = NULL;
|
| +
|
| +enum {
|
| + LIB_FILE,
|
| + LIB_FILE_VERSION_MAJOR,
|
| + LIB_FILE_VERSION,
|
| + LIB_FILE_VERSION_TMP,
|
| +#ifdef U_CYGWIN
|
| + LIB_FILE_CYGWIN,
|
| + LIB_FILE_CYGWIN_VERSION,
|
| +#endif
|
| + LIB_FILENAMES_SIZE
|
| +};
|
| +static char libFileNames[LIB_FILENAMES_SIZE][256];
|
| +
|
| +static UPKGOptions *pkg_checkFlag(UPKGOptions *o);
|
| +
|
| +const char options_help[][320]={
|
| + "Set the data name",
|
| +#ifdef U_MAKE_IS_NMAKE
|
| + "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
|
| +#else
|
| + "Specify options for the builder.",
|
| +#endif
|
| + "Specify the mode of building (see below; default: common)",
|
| + "This usage text",
|
| + "This usage text",
|
| + "Make the output verbose",
|
| + "Use the standard ICU copyright",
|
| + "Use a custom comment (instead of the copyright)",
|
| + "Specify the destination directory for files",
|
| + "Force rebuilding of all data",
|
| + "Specify temporary dir (default: output dir)",
|
| + "Install the data (specify target)",
|
| + "Specify a custom source directory",
|
| + "Specify a custom entrypoint name (default: short name)",
|
| + "Specify a version when packaging in dll or static mode",
|
| + "Add package to all file names if not present",
|
| + "Library name to build (if different than package name)",
|
| + "Quite mode. (e.g. Do not output a readme file for static libraries)"
|
| +};
|
| +
|
| +const char *progname = "PKGDATA";
|
| +
|
| +int
|
| +main(int argc, char* argv[]) {
|
| + int result = 0;
|
| + /* FileStream *out; */
|
| + UPKGOptions o;
|
| + CharList *tail;
|
| + UBool needsHelp = FALSE;
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + /* char tmp[1024]; */
|
| + uint32_t i;
|
| + int32_t n;
|
| +
|
| + U_MAIN_INIT_ARGS(argc, argv);
|
| +
|
| + progname = argv[0];
|
| +
|
| + options[MODE].value = "common";
|
| +
|
| + /* read command line options */
|
| + argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
|
| +
|
| + /* error handling, printing usage message */
|
| + /* I've decided to simply print an error and quit. This tool has too
|
| + many options to just display them all of the time. */
|
| +
|
| + if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
|
| + needsHelp = TRUE;
|
| + }
|
| + else {
|
| + if(!needsHelp && argc<0) {
|
| + fprintf(stderr,
|
| + "%s: error in command line argument \"%s\"\n",
|
| + progname,
|
| + argv[-argc]);
|
| + fprintf(stderr, "Run '%s --help' for help.\n", progname);
|
| + return 1;
|
| + }
|
| +
|
| +
|
| +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
|
| + if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) {
|
| + if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) {
|
| + fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n");
|
| + fprintf(stderr, "Run '%s --help' for help.\n", progname);
|
| + return 1;
|
| + }
|
| + }
|
| +#else
|
| + if(options[BLDOPT].doesOccur) {
|
| + fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
|
| + }
|
| +#endif
|
| +
|
| + if(!options[NAME].doesOccur) /* -O we already have - don't report it. */
|
| + {
|
| + fprintf(stderr, " required parameter -p is missing \n");
|
| + fprintf(stderr, "Run '%s --help' for help.\n", progname);
|
| + return 1;
|
| + }
|
| +
|
| + if(argc == 1) {
|
| + fprintf(stderr,
|
| + "No input files specified.\n"
|
| + "Run '%s --help' for help.\n", progname);
|
| + return 1;
|
| + }
|
| + } /* end !needsHelp */
|
| +
|
| + if(argc<0 || needsHelp ) {
|
| + fprintf(stderr,
|
| + "usage: %s [-options] [-] [packageFile] \n"
|
| + "\tProduce packaged ICU data from the given list(s) of files.\n"
|
| + "\t'-' by itself means to read from stdin.\n"
|
| + "\tpackageFile is a text file containing the list of files to package.\n",
|
| + progname);
|
| +
|
| + fprintf(stderr, "\n options:\n");
|
| + for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
|
| + fprintf(stderr, "%-5s -%c %s%-10s %s\n",
|
| + (i<1?"[REQ]":""),
|
| + options[i].shortName,
|
| + options[i].longName ? "or --" : " ",
|
| + options[i].longName ? options[i].longName : "",
|
| + options_help[i]);
|
| + }
|
| +
|
| + fprintf(stderr, "modes: (-m option)\n");
|
| + for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
|
| + fprintf(stderr, " %-9s ", modes[i].name);
|
| + if (modes[i].alt_name) {
|
| + fprintf(stderr, "/ %-9s", modes[i].alt_name);
|
| + } else {
|
| + fprintf(stderr, " ");
|
| + }
|
| + fprintf(stderr, " %s\n", modes[i].desc);
|
| + }
|
| + return 1;
|
| + }
|
| +
|
| + /* OK, fill in the options struct */
|
| + uprv_memset(&o, 0, sizeof(o));
|
| +
|
| + o.mode = options[MODE].value;
|
| + o.version = options[REVISION].doesOccur ? options[REVISION].value : 0;
|
| +
|
| + o.shortName = options[NAME].value;
|
| + {
|
| + int32_t len = (int32_t)uprv_strlen(o.shortName);
|
| + char *csname, *cp;
|
| + const char *sp;
|
| +
|
| + cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
|
| + if (*(sp = o.shortName)) {
|
| + *cp++ = isalpha(*sp) ? * sp : '_';
|
| + for (++sp; *sp; ++sp) {
|
| + *cp++ = isalnum(*sp) ? *sp : '_';
|
| + }
|
| + }
|
| + *cp = 0;
|
| +
|
| + o.cShortName = csname;
|
| + }
|
| +
|
| + if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */
|
| + o.libName = options[LIBNAME].value;
|
| + } else {
|
| + o.libName = o.shortName;
|
| + }
|
| +
|
| + if(options[QUIET].doesOccur) {
|
| + o.quiet = TRUE;
|
| + } else {
|
| + o.quiet = FALSE;
|
| + }
|
| +
|
| + o.verbose = options[VERBOSE].doesOccur;
|
| +
|
| +
|
| +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
|
| + if (options[BLDOPT].doesOccur) {
|
| + o.options = options[BLDOPT].value;
|
| + } else {
|
| + o.options = NULL;
|
| + }
|
| +#endif
|
| + if(options[COPYRIGHT].doesOccur) {
|
| + o.comment = U_COPYRIGHT_STRING;
|
| + } else if (options[COMMENT].doesOccur) {
|
| + o.comment = options[COMMENT].value;
|
| + }
|
| +
|
| + if( options[DESTDIR].doesOccur ) {
|
| + o.targetDir = options[DESTDIR].value;
|
| + } else {
|
| + o.targetDir = "."; /* cwd */
|
| + }
|
| +
|
| + o.rebuild = options[REBUILD].doesOccur;
|
| +
|
| + if( options[TEMPDIR].doesOccur ) {
|
| + o.tmpDir = options[TEMPDIR].value;
|
| + } else {
|
| + o.tmpDir = o.targetDir;
|
| + }
|
| +
|
| + if( options[INSTALL].doesOccur ) {
|
| + o.install = options[INSTALL].value;
|
| + } else {
|
| + o.install = NULL;
|
| + }
|
| +
|
| + if( options[SOURCEDIR].doesOccur ) {
|
| + o.srcDir = options[SOURCEDIR].value;
|
| + } else {
|
| + o.srcDir = ".";
|
| + }
|
| +
|
| + if( options[ENTRYPOINT].doesOccur ) {
|
| + o.entryName = options[ENTRYPOINT].value;
|
| + } else {
|
| + o.entryName = o.cShortName;
|
| + }
|
| +
|
| + /* OK options are set up. Now the file lists. */
|
| + tail = NULL;
|
| + for( n=1; n<argc; n++) {
|
| + o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
|
| + }
|
| +
|
| + /* load the files */
|
| + loadLists(&o, &status);
|
| + if( U_FAILURE(status) ) {
|
| + fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
|
| + return 2;
|
| + }
|
| +
|
| + result = pkg_executeOptions(&o);
|
| +
|
| + if (pkgDataFlags != NULL) {
|
| + for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
|
| + if (pkgDataFlags[n] != NULL) {
|
| + uprv_free(pkgDataFlags[n]);
|
| + }
|
| + }
|
| + uprv_free(pkgDataFlags);
|
| + }
|
| +
|
| + if (o.cShortName != NULL) {
|
| + uprv_free((char *)o.cShortName);
|
| + }
|
| + if (o.fileListFiles != NULL) {
|
| + pkg_deleteList(o.fileListFiles);
|
| + }
|
| + if (o.filePaths != NULL) {
|
| + pkg_deleteList(o.filePaths);
|
| + }
|
| + if (o.files != NULL) {
|
| + pkg_deleteList(o.files);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +static int runCommand(const char* command, UBool specialHandling) {
|
| + char *cmd = NULL;
|
| + char cmdBuffer[SMALL_BUFFER_MAX_SIZE];
|
| + int32_t len = strlen(command);
|
| +
|
| + if (len == 0) {
|
| + return 0;
|
| + }
|
| +
|
| + if (!specialHandling) {
|
| +#if defined(USING_CYGWIN) || defined(OS400)
|
| +#define CMD_PADDING_SIZE 20
|
| + if ((len + CMD_PADDING_SIZE) >= SMALL_BUFFER_MAX_SIZE) {
|
| + cmd = (char *)uprv_malloc(len + CMD_PADDING_SIZE);
|
| + } else {
|
| + cmd = cmdBuffer;
|
| + }
|
| +#ifdef USING_CYGWIN
|
| + sprintf(cmd, "bash -c \"%s\"", command);
|
| +
|
| +#elif defined(OS400)
|
| + sprintf(cmd, "QSH CMD('%s')", command);
|
| +#endif
|
| +#else
|
| + goto normal_command_mode;
|
| +#endif
|
| + } else {
|
| +normal_command_mode:
|
| + cmd = (char *)command;
|
| + }
|
| +
|
| + printf("pkgdata: %s\n", cmd);
|
| + int result = system(cmd);
|
| + if (result != 0) {
|
| + printf("-- return status = %d\n", result);
|
| + }
|
| +
|
| + if (cmd != cmdBuffer && cmd != command) {
|
| + uprv_free(cmd);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +#define LN_CMD "ln -s"
|
| +#define RM_CMD "rm -f"
|
| +
|
| +#define MODE_COMMON 'c'
|
| +#define MODE_STATIC 's'
|
| +#define MODE_DLL 'd'
|
| +#define MODE_FILES 'f'
|
| +
|
| +static int32_t pkg_executeOptions(UPKGOptions *o) {
|
| + int32_t result = 0;
|
| +
|
| + const char mode = o->mode[0];
|
| + char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
|
| + char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
|
| +
|
| + initializePkgDataFlags(o);
|
| +
|
| + if (mode == MODE_FILES) {
|
| + /* Copy the raw data to the installation directory. */
|
| + if (o->install != NULL) {
|
| + uprv_strcpy(targetDir, o->install);
|
| + if (o->shortName != NULL) {
|
| + uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
|
| + uprv_strcat(targetDir, o->shortName);
|
| + }
|
| +
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Install: Files mode, copying files to %s..\n", targetDir);
|
| + }
|
| + result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
|
| + }
|
| + return result;
|
| + } else /* if (mode == MODE_COMMON || mode == MODE_STATIC || mode == MODE_DLL) */ {
|
| + uprv_strcpy(targetDir, o->targetDir);
|
| + uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
|
| +
|
| + uprv_strcpy(tmpDir, o->tmpDir);
|
| + uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
|
| +
|
| + uprv_strcpy(datFileNamePath, tmpDir);
|
| +
|
| + uprv_strcpy(datFileName, o->shortName);
|
| + uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
|
| +
|
| + uprv_strcat(datFileNamePath, datFileName);
|
| +
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Writing package file %s ..\n", datFileNamePath);
|
| + }
|
| + result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_CHARSET_FAMILY ? 'e' : U_IS_BIG_ENDIAN ? 'b' : 'l');
|
| + if (result != 0) {
|
| + fprintf(stderr,"Error writing package dat file.\n");
|
| + return result;
|
| + }
|
| +
|
| + if (mode == MODE_COMMON) {
|
| + char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
|
| +
|
| + uprv_strcpy(targetFileNamePath, targetDir);
|
| + uprv_strcat(targetFileNamePath, datFileName);
|
| +
|
| + if (T_FileStream_file_exists(targetFileNamePath)) {
|
| + if ((result = remove(targetFileNamePath)) != 0) {
|
| + fprintf(stderr, "Unable to remove old dat file: %s\n", targetFileNamePath);
|
| + return result;
|
| + }
|
| + }
|
| +
|
| + /* Move the dat file created to the target directory. */
|
| + result = rename(datFileNamePath, targetFileNamePath);
|
| +
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Moving package file to %s ..\n", targetFileNamePath);
|
| + }
|
| + if (result != 0) {
|
| + fprintf(stderr, "Unable to move dat file (%s) to target location (%s).\n", datFileNamePath, targetFileNamePath);
|
| + }
|
| +
|
| + if (o->install != NULL) {
|
| + result = pkg_installCommonMode(o->install, targetFileNamePath);
|
| + }
|
| +
|
| + return result;
|
| + } else /* if (mode[0] == MODE_STATIC || mode[0] == MODE_DLL) */ {
|
| + char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char version_major[10] = "";
|
| + UBool reverseExt = FALSE;
|
| +
|
| +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
|
| + /* Get the version major number. */
|
| + if (o->version != NULL) {
|
| + for (uint32_t i = 0;i < sizeof(version_major);i++) {
|
| + if (o->version[i] == '.') {
|
| + version_major[i] = 0;
|
| + break;
|
| + }
|
| + version_major[i] = o->version[i];
|
| + }
|
| + }
|
| +
|
| +#ifndef OS400
|
| + /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
|
| + * reverseExt is FALSE if the suffix should be the version number.
|
| + */
|
| + if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
|
| + reverseExt = TRUE;
|
| + }
|
| +#endif
|
| + /* Using the base libName and version number, generate the library file names. */
|
| + createFileNames(o, mode, version_major, o->version, o->libName, reverseExt);
|
| +
|
| + if ((o->version!=NULL || (mode==MODE_STATIC)) && o->rebuild == FALSE) {
|
| + /* Check to see if a previous built data library file exists and check if it is the latest. */
|
| + sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]);
|
| + if (T_FileStream_file_exists(checkLibFile)) {
|
| + if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) {
|
| + if (o->install != NULL) {
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Installing already-built library into %s\n", o->install);
|
| + }
|
| + result = pkg_installLibrary(o->install, targetDir);
|
| + } else {
|
| + if(o->verbose) {
|
| + printf("# Not rebuilding %s - up to date.\n", checkLibFile);
|
| + }
|
| + }
|
| + return result;
|
| + } else if (o->verbose && (o->install!=NULL)) {
|
| + fprintf(stdout, "# Not installing up-to-date library %s into %s\n", checkLibFile, o->install);
|
| + }
|
| + } else if(o->verbose && (o->install!=NULL)) {
|
| + fprintf(stdout, "# Not installing missing %s into %s\n", checkLibFile, o->install);
|
| + }
|
| + }
|
| +
|
| + pkg_checkFlag(o);
|
| +#endif
|
| +
|
| + if (pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
|
| + const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
|
| +
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Generating assembly code %s of type %s ..\n", gencFilePath, genccodeAssembly);
|
| + }
|
| +
|
| + /* Offset genccodeAssembly by 3 because "-a " */
|
| + if (genccodeAssembly &&
|
| + (uprv_strlen(genccodeAssembly)>3) &&
|
| + checkAssemblyHeaderName(genccodeAssembly+3)) {
|
| + writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath);
|
| +
|
| + result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Error generating assembly code for data.\n");
|
| + return result;
|
| + } else if (mode == MODE_STATIC) {
|
| + if(o->install != NULL) {
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Installing static library into %s\n", o->install);
|
| + }
|
| + result = pkg_installLibrary(o->install, targetDir);
|
| + }
|
| + return result;
|
| + }
|
| + } else {
|
| + fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
|
| + return -1;
|
| + }
|
| + } else {
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Writing object code to %s ..\n", gencFilePath);
|
| + }
|
| +#ifdef CAN_WRITE_OBJ_CODE
|
| + writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
|
| +#ifdef U_LINUX
|
| + result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
|
| +#elif defined(WINDOWS_WITH_MSVC)
|
| + result = pkg_createWindowsDLL(mode, gencFilePath, o);
|
| +#endif
|
| +#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
|
| + result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
|
| +#endif
|
| + if (result != 0) {
|
| + fprintf(stderr, "Error generating package data.\n");
|
| + return result;
|
| + }
|
| + }
|
| +#ifndef U_WINDOWS
|
| + if(mode != MODE_STATIC) {
|
| + /* Certain platforms uses archive library. (e.g. AIX) */
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Creating data archive library file ..\n");
|
| + }
|
| + result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Error creating data archive library file.\n");
|
| + return result;
|
| + }
|
| +#ifndef OS400
|
| + /* Create symbolic links for the final library file. */
|
| + result = pkg_createSymLinks(targetDir);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Error creating symbolic links of the data library file.\n");
|
| + return result;
|
| + }
|
| +#endif
|
| + } /* !MODE_STATIC */
|
| +#endif
|
| +
|
| +#if !defined(U_WINDOWS) || defined(USING_CYGWIN)
|
| + /* Install the libraries if option was set. */
|
| + if (o->install != NULL) {
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Installing library file to %s ..\n", o->install);
|
| + }
|
| + result = pkg_installLibrary(o->install, targetDir);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Error installing the data library.\n");
|
| + return result;
|
| + }
|
| + }
|
| +#endif
|
| + }
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +/* Initialize the pkgDataFlags with the option file given. */
|
| +static int32_t initializePkgDataFlags(UPKGOptions *o) {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + int32_t result = 0;
|
| + int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE;
|
| + int32_t tmpResult = 0;
|
| +
|
| + /* Initialize pkgdataFlags */
|
| + pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
|
| +
|
| + /* If we run out of space, allocate more */
|
| +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
|
| + do {
|
| +#endif
|
| + if (pkgDataFlags != NULL) {
|
| + for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
|
| + pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize);
|
| + if (pkgDataFlags[i] != NULL) {
|
| + pkgDataFlags[i][0] = 0;
|
| + } else {
|
| + fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
|
| + return -1;
|
| + }
|
| + }
|
| + } else {
|
| + fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
|
| + return -1;
|
| + }
|
| +
|
| + if (o->options == NULL) {
|
| + return result;
|
| + }
|
| +
|
| +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
|
| + /* Read in options file. */
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# Reading options file %s\n", o->options);
|
| + }
|
| + status = U_ZERO_ERROR;
|
| + tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, (int32_t)PKGDATA_FLAGS_SIZE, &status);
|
| + if (status == U_BUFFER_OVERFLOW_ERROR) {
|
| + for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
|
| + uprv_free(pkgDataFlags[i]);
|
| + }
|
| + currentBufferSize = tmpResult;
|
| + } else if (U_FAILURE(status)) {
|
| + fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status));
|
| + return -1;
|
| + }
|
| +#endif
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# pkgDataFlags=");
|
| + for(int32_t i=0;i<PKGDATA_FLAGS_SIZE && pkgDataFlags[i][0];i++) {
|
| + fprintf(stdout, "%c \"%s\"", (i>0)?',':' ',pkgDataFlags[i]);
|
| + }
|
| + fprintf(stdout, "\n");
|
| + }
|
| +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
|
| + } while (status == U_BUFFER_OVERFLOW_ERROR);
|
| +#endif
|
| +
|
| + return result;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
|
| + * Depending on the configuration, the library name may either end with version number or shared object suffix.
|
| + */
|
| +static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt) {
|
| + sprintf(libFileNames[LIB_FILE], "%s%s",
|
| + pkgDataFlags[LIBPREFIX],
|
| + libName);
|
| +
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]);
|
| + }
|
| +
|
| + if (version != NULL) {
|
| +#ifdef U_CYGWIN
|
| + sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s.%s",
|
| + libName,
|
| + pkgDataFlags[SO_EXT]);
|
| + sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s.%s",
|
| + libName,
|
| + version_major,
|
| + pkgDataFlags[SO_EXT]);
|
| +
|
| + uprv_strcat(pkgDataFlags[SO_EXT], ".");
|
| + uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
|
| +
|
| +#elif defined(OS400) || defined(_AIX)
|
| + sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s",
|
| + libFileNames[LIB_FILE],
|
| + pkgDataFlags[SOBJ_EXT]);
|
| +#else
|
| + sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
|
| + libFileNames[LIB_FILE],
|
| + pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
|
| + reverseExt ? version : pkgDataFlags[SOBJ_EXT],
|
| + reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
|
| +#endif
|
| + sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s",
|
| + libFileNames[LIB_FILE],
|
| + pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
|
| + reverseExt ? version_major : pkgDataFlags[SO_EXT],
|
| + reverseExt ? pkgDataFlags[SO_EXT] : version_major);
|
| +
|
| + sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
|
| + libFileNames[LIB_FILE],
|
| + pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
|
| + reverseExt ? version : pkgDataFlags[SO_EXT],
|
| + reverseExt ? pkgDataFlags[SO_EXT] : version);
|
| +
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]);
|
| + }
|
| +
|
| +#ifdef U_CYGWIN
|
| + /* Cygwin only deals with the version major number. */
|
| + uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
|
| +#endif
|
| + }
|
| + if(mode == MODE_STATIC) {
|
| + sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]);
|
| + libFileNames[LIB_FILE_VERSION_MAJOR][0]=0;
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames[LIB_FILE_VERSION]);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/* Create the symbolic links for the final library file. */
|
| +static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) {
|
| + int32_t result = 0;
|
| + char cmd[LARGE_BUFFER_MAX_SIZE];
|
| + char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */
|
| + char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */
|
| +
|
| +#ifndef USING_CYGWIN
|
| + /* No symbolic link to make. */
|
| + if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 ||
|
| + uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
|
| + return result;
|
| + }
|
| +
|
| + sprintf(cmd, "cd %s && %s %s && %s %s %s",
|
| + targetDir,
|
| + RM_CMD,
|
| + libFileNames[LIB_FILE_VERSION_MAJOR],
|
| + LN_CMD,
|
| + libFileNames[LIB_FILE_VERSION],
|
| + libFileNames[LIB_FILE_VERSION_MAJOR]);
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +#endif
|
| +
|
| + if (specialHandling) {
|
| +#ifdef U_CYGWIN
|
| + sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]);
|
| + sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
|
| +#else
|
| + goto normal_symlink_mode;
|
| +#endif
|
| + } else {
|
| +normal_symlink_mode:
|
| + sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]);
|
| + sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
|
| + }
|
| +
|
| + sprintf(cmd, "cd %s && %s %s && %s %s %s",
|
| + targetDir,
|
| + RM_CMD,
|
| + name1,
|
| + LN_CMD,
|
| + name2,
|
| + name1);
|
| +
|
| + result = runCommand(cmd);
|
| +
|
| + return result;
|
| +}
|
| +
|
| +static int32_t pkg_installLibrary(const char *installDir, const char *targetDir) {
|
| + int32_t result = 0;
|
| + char cmd[SMALL_BUFFER_MAX_SIZE];
|
| +
|
| + sprintf(cmd, "cd %s && %s %s %s%s%s",
|
| + targetDir,
|
| + pkgDataFlags[INSTALL_CMD],
|
| + libFileNames[LIB_FILE_VERSION],
|
| + installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
|
| + );
|
| +
|
| + result = runCommand(cmd);
|
| +
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +
|
| +#ifdef CYGWINMSVC
|
| + sprintf(cmd, "cd %s && %s %s.lib %s",
|
| + targetDir,
|
| + pkgDataFlags[INSTALL_CMD],
|
| + libFileNames[LIB_FILE],
|
| + installDir
|
| + );
|
| + result = runCommand(cmd);
|
| +
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +#elif defined (U_CYGWIN)
|
| + sprintf(cmd, "cd %s && %s %s %s",
|
| + targetDir,
|
| + pkgDataFlags[INSTALL_CMD],
|
| + libFileNames[LIB_FILE_CYGWIN_VERSION],
|
| + installDir
|
| + );
|
| + result = runCommand(cmd);
|
| +
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +#endif
|
| +
|
| + return pkg_createSymLinks(installDir, TRUE);
|
| +}
|
| +
|
| +static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) {
|
| + int32_t result = 0;
|
| + char cmd[SMALL_BUFFER_MAX_SIZE] = "";
|
| +
|
| + if (!T_FileStream_file_exists(installDir)) {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| +
|
| + uprv_mkdir(installDir, &status);
|
| + if (U_FAILURE(status)) {
|
| + fprintf(stderr, "Error creating installation directory: %s\n", installDir);
|
| + return -1;
|
| + }
|
| + }
|
| +#ifndef U_WINDOWS_WITH_MSVC
|
| + sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir);
|
| +#else
|
| + sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS);
|
| +#endif
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +#ifdef U_WINDOWS_MSVC
|
| +/* Copy commands for installing the raw data files on Windows. */
|
| +#define WIN_INSTALL_CMD "xcopy"
|
| +#define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
|
| +#endif
|
| +static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
|
| + int32_t result = 0;
|
| + char cmd[SMALL_BUFFER_MAX_SIZE] = "";
|
| +
|
| + if (!T_FileStream_file_exists(installDir)) {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| +
|
| + uprv_mkdir(installDir, &status);
|
| + if (U_FAILURE(status)) {
|
| + fprintf(stderr, "Error creating installation directory: %s\n", installDir);
|
| + return -1;
|
| + }
|
| + }
|
| +#ifndef U_WINDOWS_WITH_MSVC
|
| + char buffer[SMALL_BUFFER_MAX_SIZE] = "";
|
| +
|
| + FileStream *f = T_FileStream_open(fileListName, "r");
|
| + if (f != NULL) {
|
| + for(;;) {
|
| + if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
|
| + /* Remove new line character. */
|
| + buffer[uprv_strlen(buffer)-1] = 0;
|
| +
|
| + sprintf(cmd, "%s %s%s%s %s%s%s",
|
| + pkgDataFlags[INSTALL_CMD],
|
| + srcDir, PKGDATA_FILE_SEP_STRING, buffer,
|
| + installDir, PKGDATA_FILE_SEP_STRING, buffer);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
|
| + break;
|
| + }
|
| + } else {
|
| + if (!T_FileStream_eof(f)) {
|
| + fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
|
| + result = -1;
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + T_FileStream_close(f);
|
| + } else {
|
| + result = -1;
|
| + fprintf(stderr, "Unable to open list file: %s\n", fileListName);
|
| + }
|
| +#else
|
| + sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
|
| + }
|
| +#endif
|
| +
|
| + return result;
|
| +}
|
| +
|
| +/* Archiving of the library file may be needed depending on the platform and options given.
|
| + * If archiving is not needed, copy over the library file name.
|
| + */
|
| +static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
|
| + int32_t result = 0;
|
| + char cmd[LARGE_BUFFER_MAX_SIZE];
|
| +
|
| + /* If the shared object suffix and the final object suffix is different and the final object suffix and the
|
| + * archive file suffix is the same, then the final library needs to be archived.
|
| + */
|
| + if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
|
| + sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
|
| + libFileNames[LIB_FILE],
|
| + pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
|
| + reverseExt ? version : pkgDataFlags[SO_EXT],
|
| + reverseExt ? pkgDataFlags[SO_EXT] : version);
|
| +
|
| + sprintf(cmd, "%s %s %s%s %s%s",
|
| + pkgDataFlags[AR],
|
| + pkgDataFlags[ARFLAGS],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION_TMP]);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +
|
| + sprintf(cmd, "%s %s%s",
|
| + pkgDataFlags[RANLIB],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION]);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +
|
| + /* Remove unneeded library file. */
|
| + sprintf(cmd, "%s %s%s",
|
| + RM_CMD,
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION_TMP]);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +
|
| + } else {
|
| + uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +/*
|
| + * Using the compiler information from the configuration file set by -O option, generate the library file.
|
| + * command may be given to allow for a larger buffer for cmd.
|
| + */
|
| +static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) {
|
| + int32_t result = 0;
|
| + char *cmd = NULL;
|
| + UBool freeCmd = FALSE;
|
| +
|
| + /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
|
| + * containing many object files and so the calling function should supply a command buffer that is large
|
| + * enough to handle this. Otherwise, use the default size.
|
| + */
|
| + if (command != NULL) {
|
| + cmd = command;
|
| + } else {
|
| + if ((cmd = (char *)uprv_malloc(sizeof(char) * LARGE_BUFFER_MAX_SIZE)) == NULL) {
|
| + fprintf(stderr, "Unable to allocate memory for command.\n");
|
| + return -1;
|
| + }
|
| + freeCmd = TRUE;
|
| + }
|
| +
|
| + if (mode == MODE_STATIC) {
|
| + sprintf(cmd, "%s %s %s%s %s",
|
| + pkgDataFlags[AR],
|
| + pkgDataFlags[ARFLAGS],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION],
|
| + objectFile);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result == 0) {
|
| + sprintf(cmd, "%s %s%s",
|
| + pkgDataFlags[RANLIB],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION]);
|
| +
|
| + result = runCommand(cmd);
|
| + }
|
| + } else /* if (mode == MODE_DLL) */ {
|
| +#ifdef U_CYGWIN
|
| + sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
|
| + pkgDataFlags[GENLIB],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION_TMP],
|
| + pkgDataFlags[LDICUDTFLAGS],
|
| + targetDir, libFileNames[LIB_FILE_CYGWIN_VERSION],
|
| +#else
|
| + sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
|
| + pkgDataFlags[GENLIB],
|
| + pkgDataFlags[LDICUDTFLAGS],
|
| + targetDir,
|
| + libFileNames[LIB_FILE_VERSION_TMP],
|
| +#endif
|
| + objectFile,
|
| + pkgDataFlags[LD_SONAME],
|
| + pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
|
| + pkgDataFlags[RPATH_FLAGS],
|
| + pkgDataFlags[BIR_FLAGS]);
|
| +
|
| + /* Generate the library file. */
|
| + result = runCommand(cmd);
|
| + }
|
| +
|
| + if (freeCmd) {
|
| + uprv_free(cmd);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
|
| + char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char *cmd;
|
| + int32_t result = 0;
|
| +
|
| + int32_t length = 0;
|
| +
|
| + /* Remove the ending .s and replace it with .o for the new object file. */
|
| + uprv_strcpy(tempObjectFile, gencFilePath);
|
| + tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
|
| +
|
| + length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
|
| + + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + 10;
|
| +
|
| + cmd = (char *)uprv_malloc(sizeof(char) * length);
|
| + if (cmd == NULL) {
|
| + return -1;
|
| + }
|
| +
|
| + /* Generate the object file. */
|
| + sprintf(cmd, "%s %s -o %s %s",
|
| + pkgDataFlags[COMPILER],
|
| + pkgDataFlags[LIBFLAGS],
|
| + tempObjectFile,
|
| + gencFilePath);
|
| +
|
| + result = runCommand(cmd);
|
| + uprv_free(cmd);
|
| + if (result != 0) {
|
| + return result;
|
| + }
|
| +
|
| + return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
|
| +}
|
| +
|
| +#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
|
| +/*
|
| + * Generation of the data library without assembly code needs to compile each data file
|
| + * individually and then link it all together.
|
| + * Note: Any update to the directory structure of the data needs to be reflected here.
|
| + */
|
| +enum {
|
| + DATA_PREFIX_BRKITR,
|
| + DATA_PREFIX_COLL,
|
| + DATA_PREFIX_CURR,
|
| + DATA_PREFIX_LANG,
|
| + DATA_PREFIX_RBNF,
|
| + DATA_PREFIX_REGION,
|
| + DATA_PREFIX_TRANSLIT,
|
| + DATA_PREFIX_ZONE,
|
| + DATA_PREFIX_LENGTH
|
| +};
|
| +
|
| +const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
|
| + "brkitr",
|
| + "coll",
|
| + "curr",
|
| + "lang",
|
| + "rbnf",
|
| + "region",
|
| + "translit",
|
| + "zone"
|
| +};
|
| +
|
| +static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
|
| + int32_t result = 0;
|
| + CharList *list = o->filePaths;
|
| + CharList *listNames = o->files;
|
| + int32_t listSize = pkg_countCharList(list);
|
| + char *buffer;
|
| + char *cmd;
|
| + char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
|
| +#ifdef USE_SINGLE_CCODE_FILE
|
| + char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
|
| +
|
| + sprintf(icudtAll, "%s%s%sall.c",
|
| + o->tmpDir,
|
| + PKGDATA_FILE_SEP_STRING,
|
| + libFileNames[LIB_FILE]);
|
| + /* Remove previous icudtall.c file. */
|
| + if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
|
| + fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
|
| + return result;
|
| + }
|
| +#endif
|
| +
|
| + if (list == NULL || listNames == NULL) {
|
| + /* list and listNames should never be NULL since we are looping through the CharList with
|
| + * the given size.
|
| + */
|
| + return -1;
|
| + }
|
| +
|
| + if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
|
| + fprintf(stderr, "Unable to allocate memory for cmd.\n");
|
| + return -1;
|
| + } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
|
| + fprintf(stderr, "Unable to allocate memory for buffer.\n");
|
| + uprv_free(cmd);
|
| + return -1;
|
| + }
|
| +
|
| + for (int32_t i = 0; i < (listSize + 1); i++) {
|
| + const char *file ;
|
| + const char *name;
|
| +
|
| + if (i == 0) {
|
| + /* The first iteration calls the gencmn function and initailizes the buffer. */
|
| + createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
|
| + buffer[0] = 0;
|
| +#ifdef USE_SINGLE_CCODE_FILE
|
| + uprv_strcpy(tempObjectFile, gencmnFile);
|
| + tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
|
| +
|
| + sprintf(cmd, "%s %s -o %s %s"
|
| + pkgDataFlags[COMPILER],
|
| + pkgDataFlags[LIBFLAGS],
|
| + tempObjectFile,
|
| + gencmnFile);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + break;
|
| + }
|
| +
|
| + sprintf(buffer, "%s",tempObjectFile);
|
| +#endif
|
| + } else {
|
| + char newName[SMALL_BUFFER_MAX_SIZE];
|
| + char dataName[SMALL_BUFFER_MAX_SIZE];
|
| + char dataDirName[SMALL_BUFFER_MAX_SIZE];
|
| + const char *pSubstring;
|
| + file = list->str;
|
| + name = listNames->str;
|
| +
|
| + newName[0] = dataName[0] = 0;
|
| + for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
|
| + dataDirName[0] = 0;
|
| + sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
|
| + /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
|
| + pSubstring = uprv_strstr(name, dataDirName);
|
| + if (pSubstring != NULL) {
|
| + char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
|
| + const char *p = name + uprv_strlen(dataDirName);
|
| + for (int32_t i = 0;;i++) {
|
| + if (p[i] == '.') {
|
| + newNameTmp[i] = '_';
|
| + continue;
|
| + }
|
| + newNameTmp[i] = p[i];
|
| + if (p[i] == 0) {
|
| + break;
|
| + }
|
| + }
|
| + sprintf(newName, "%s_%s",
|
| + DATA_PREFIX[n],
|
| + newNameTmp);
|
| + sprintf(dataName, "%s_%s",
|
| + o->shortName,
|
| + DATA_PREFIX[n]);
|
| + }
|
| + if (newName[0] != 0) {
|
| + break;
|
| + }
|
| + }
|
| +
|
| + writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
|
| +#ifdef USE_SINGLE_CCODE_FILE
|
| + sprintf(cmd, "cat %s >> %s", gencmnFile, icudtAll);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + break;
|
| + } else {
|
| + /* Remove the c code file after concatenating it to icudtall.c file. */
|
| + if ((result = remove(gencmnFile)) != 0) {
|
| + fprintf(stderr, "Unable to remove c code file: %s\n", gencmnFile);
|
| + return result;
|
| + }
|
| + }
|
| +#endif
|
| + }
|
| +
|
| +#ifndef USE_SINGLE_CCODE_FILE
|
| + uprv_strcpy(tempObjectFile, gencmnFile);
|
| + tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
|
| +
|
| + sprintf(cmd, "%s %s -o %s %s",
|
| + pkgDataFlags[COMPILER],
|
| + pkgDataFlags[LIBFLAGS],
|
| + tempObjectFile,
|
| + gencmnFile);
|
| + result = runCommand(cmd);
|
| + if (result != 0) {
|
| + break;
|
| + }
|
| +
|
| + uprv_strcat(buffer, " ");
|
| + uprv_strcat(buffer, tempObjectFile);
|
| +
|
| +#endif
|
| +
|
| + if (i > 0) {
|
| + list = list->next;
|
| + listNames = listNames->next;
|
| + }
|
| + }
|
| +
|
| +#ifdef USE_SINGLE_CCODE_FILE
|
| + uprv_strcpy(tempObjectFile, icudtAll);
|
| + tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
|
| +
|
| + sprintf(cmd, "%s %s -o %s %s",
|
| + pkgDataFlags[COMPILER],
|
| + pkgDataFlags[LIBFLAGS],
|
| + tempObjectFile,
|
| + icudtAll);
|
| +
|
| + result = runCommand(cmd);
|
| + if (result == 0) {
|
| + uprv_strcat(buffer, " ");
|
| + uprv_strcat(buffer, tempObjectFile);
|
| + }
|
| +#endif
|
| +
|
| + if (result == 0) {
|
| + /* Generate the library file. */
|
| + result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd);
|
| + }
|
| +
|
| + uprv_free(buffer);
|
| + uprv_free(cmd);
|
| +
|
| + return result;
|
| +}
|
| +#endif
|
| +
|
| +#ifdef WINDOWS_WITH_MSVC
|
| +#define LINK_CMD "link.exe /nologo /release /out:"
|
| +#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:"
|
| +#define LIB_CMD "LIB.exe /nologo /out:"
|
| +#define LIB_FILE "icudt.lib"
|
| +#define LIB_EXT UDATA_LIB_SUFFIX
|
| +#define DLL_EXT UDATA_SO_SUFFIX
|
| +
|
| +static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
|
| + char cmd[LARGE_BUFFER_MAX_SIZE];
|
| + if (mode == MODE_STATIC) {
|
| + char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
|
| +
|
| + uprv_strcpy(staticLibFilePath, o->tmpDir);
|
| + uprv_strcat(staticLibFilePath, PKGDATA_FILE_SEP_STRING);
|
| +
|
| + uprv_strcat(staticLibFilePath, o->entryName);
|
| + uprv_strcat(staticLibFilePath, LIB_EXT);
|
| +
|
| + sprintf(cmd, "%s\"%s\" \"%s\"",
|
| + LIB_CMD,
|
| + staticLibFilePath,
|
| + gencFilePath);
|
| + } else if (mode == MODE_DLL) {
|
| + char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
|
| + char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
|
| +
|
| +#ifdef CYGWINMSVC
|
| + uprv_strcpy(dllFilePath, o->targetDir);
|
| +#else
|
| + uprv_strcpy(dllFilePath, o->srcDir);
|
| +#endif
|
| + uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
|
| + uprv_strcpy(libFilePath, dllFilePath);
|
| +
|
| +#ifdef CYGWINMSVC
|
| + uprv_strcat(libFilePath, o->libName);
|
| + uprv_strcat(libFilePath, ".lib");
|
| +
|
| + uprv_strcat(dllFilePath, o->libName);
|
| + uprv_strcat(dllFilePath, o->version);
|
| +#else
|
| + if (strstr(o->libName, "icudt")) {
|
| + uprv_strcat(libFilePath, LIB_FILE);
|
| + } else {
|
| + uprv_strcat(libFilePath, o->libName);
|
| + uprv_strcat(libFilePath, ".lib");
|
| + }
|
| + uprv_strcat(dllFilePath, o->entryName);
|
| +#endif
|
| + uprv_strcat(dllFilePath, DLL_EXT);
|
| +
|
| + uprv_strcpy(tmpResFilePath, o->tmpDir);
|
| + uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
|
| + uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
|
| +
|
| + if (T_FileStream_file_exists(tmpResFilePath)) {
|
| + sprintf(resFilePath, "\"%s\"", tmpResFilePath);
|
| + }
|
| +
|
| + /* Check if dll file and lib file exists and that it is not newer than genc file. */
|
| + if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
|
| + (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
|
| + if(o->verbose) {
|
| + printf("# Not rebuilding %s - up to date.\n", gencFilePath);
|
| + }
|
| + return 0;
|
| + }
|
| +
|
| + sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" %s",
|
| + LINK_CMD,
|
| + dllFilePath,
|
| + LINK_FLAGS,
|
| + libFilePath,
|
| + gencFilePath,
|
| + resFilePath
|
| + );
|
| + }
|
| +
|
| + return runCommand(cmd, TRUE);
|
| +}
|
| +#endif
|
| +
|
| +static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
|
| +#ifdef U_AIX
|
| + /* AIX needs a map file. */
|
| + char *flag = NULL;
|
| + int32_t length = 0;
|
| + char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
|
| + const char MAP_FILE_EXT[] = ".map";
|
| + FileStream *f = NULL;
|
| + char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
|
| + int32_t start = -1;
|
| + int32_t count = 0;
|
| +
|
| + flag = pkgDataFlags[BIR_FLAGS];
|
| + length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
|
| +
|
| + for (int32_t i = 0; i < length; i++) {
|
| + if (flag[i] == MAP_FILE_EXT[count]) {
|
| + if (count == 0) {
|
| + start = i;
|
| + }
|
| + count++;
|
| + } else {
|
| + count = 0;
|
| + }
|
| +
|
| + if (count == uprv_strlen(MAP_FILE_EXT)) {
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (start >= 0) {
|
| + int32_t index = 0;
|
| + for (int32_t i = 0;;i++) {
|
| + if (i == start) {
|
| + for (int32_t n = 0;;n++) {
|
| + if (o->shortName[n] == 0) {
|
| + break;
|
| + }
|
| + tmpbuffer[index++] = o->shortName[n];
|
| + }
|
| + }
|
| +
|
| + tmpbuffer[index++] = flag[i];
|
| +
|
| + if (flag[i] == 0) {
|
| + break;
|
| + }
|
| + }
|
| +
|
| + uprv_memset(flag, 0, length);
|
| + uprv_strcpy(flag, tmpbuffer);
|
| +
|
| + uprv_strcpy(mapFile, o->shortName);
|
| + uprv_strcat(mapFile, MAP_FILE_EXT);
|
| +
|
| + f = T_FileStream_open(mapFile, "w");
|
| + if (f == NULL) {
|
| + fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
|
| + } else {
|
| + sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
|
| +
|
| + T_FileStream_writeLine(f, tmpbuffer);
|
| +
|
| + T_FileStream_close(f);
|
| + }
|
| + }
|
| +#elif defined(U_CYGWIN)
|
| + /* Cygwin needs to change flag options. */
|
| + char *flag = NULL;
|
| + int32_t length = 0;
|
| +
|
| + flag = pkgDataFlags[GENLIB];
|
| + length = uprv_strlen(pkgDataFlags[GENLIB]);
|
| +
|
| + int32_t position = length - 1;
|
| +
|
| + for(;position >= 0;position--) {
|
| + if (flag[position] == '=') {
|
| + position++;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + uprv_memset(flag + position, 0, length - position);
|
| +#elif defined(OS400)
|
| + /* OS400 needs to fix the ld options (swap single quote with double quote) */
|
| + char *flag = NULL;
|
| + int32_t length = 0;
|
| +
|
| + flag = pkgDataFlags[GENLIB];
|
| + length = uprv_strlen(pkgDataFlags[GENLIB]);
|
| +
|
| + int32_t position = length - 1;
|
| +
|
| + for(int32_t i = 0; i < length; i++) {
|
| + if (flag[i] == '\'') {
|
| + flag[i] = '\"';
|
| + }
|
| + }
|
| +#endif
|
| + // Don't really need a return value, just need to stop compiler warnings about
|
| + // the unused parameter 'o' on platforms where it is not otherwise used.
|
| + return o;
|
| +}
|
| +
|
| +static void loadLists(UPKGOptions *o, UErrorCode *status)
|
| +{
|
| + CharList *l, *tail = NULL, *tail2 = NULL;
|
| + FileStream *in;
|
| + char line[16384];
|
| + char *linePtr, *lineNext;
|
| + const uint32_t lineMax = 16300;
|
| + char tmp[1024];
|
| + char *s;
|
| + int32_t ln=0; /* line number */
|
| +
|
| + for(l = o->fileListFiles; l; l = l->next) {
|
| + if(o->verbose) {
|
| + fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
|
| + }
|
| + /* TODO: stdin */
|
| + in = T_FileStream_open(l->str, "r"); /* open files list */
|
| +
|
| + if(!in) {
|
| + fprintf(stderr, "Error opening <%s>.\n", l->str);
|
| + *status = U_FILE_ACCESS_ERROR;
|
| + return;
|
| + }
|
| +
|
| + while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
|
| + ln++;
|
| + if(uprv_strlen(line)>lineMax) {
|
| + fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
|
| + exit(1);
|
| + }
|
| + /* remove spaces at the beginning */
|
| + linePtr = line;
|
| + while(isspace(*linePtr)) {
|
| + linePtr++;
|
| + }
|
| + s=linePtr;
|
| + /* remove trailing newline characters */
|
| + while(*s!=0) {
|
| + if(*s=='\r' || *s=='\n') {
|
| + *s=0;
|
| + break;
|
| + }
|
| + ++s;
|
| + }
|
| + if((*linePtr == 0) || (*linePtr == '#')) {
|
| + continue; /* comment or empty line */
|
| + }
|
| +
|
| + /* Now, process the line */
|
| + lineNext = NULL;
|
| +
|
| + while(linePtr && *linePtr) { /* process space-separated items */
|
| + while(*linePtr == ' ') {
|
| + linePtr++;
|
| + }
|
| + /* Find the next quote */
|
| + if(linePtr[0] == '"')
|
| + {
|
| + lineNext = uprv_strchr(linePtr+1, '"');
|
| + if(lineNext == NULL) {
|
| + fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
|
| + l->str, (int)ln);
|
| + exit(1);
|
| + } else {
|
| + lineNext++;
|
| + if(*lineNext) {
|
| + if(*lineNext != ' ') {
|
| + fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
|
| + l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
|
| + exit(1);
|
| + }
|
| + *lineNext = 0;
|
| + lineNext++;
|
| + }
|
| + }
|
| + } else {
|
| + lineNext = uprv_strchr(linePtr, ' ');
|
| + if(lineNext) {
|
| + *lineNext = 0; /* terminate at space */
|
| + lineNext++;
|
| + }
|
| + }
|
| +
|
| + /* add the file */
|
| + s = (char*)getLongPathname(linePtr);
|
| +
|
| + /* normal mode.. o->files is just the bare list without package names */
|
| + o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
|
| + if(uprv_pathIsAbsolute(s)) {
|
| + 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);
|
| + exit(U_ILLEGAL_ARGUMENT_ERROR);
|
| + }
|
| + uprv_strcpy(tmp, o->srcDir);
|
| + uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" :PKGDATA_FILE_SEP_STRING);
|
| + uprv_strcat(tmp, s);
|
| + o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
|
| + linePtr = lineNext;
|
| + } /* for each entry on line */
|
| + } /* for each line */
|
| + T_FileStream_close(in);
|
| + } /* for each file list file */
|
| +}
|
| +
|
| +/* Try calling icu-config directly to get the option file. */
|
| + static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
|
| +#if U_HAVE_POPEN
|
| + FILE *p = NULL;
|
| + size_t n;
|
| + static char buf[512] = "";
|
| + char cmdBuf[1024];
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + const char cmd[] = "icu-config --incpkgdatafile";
|
| +
|
| + /* #1 try the same path where pkgdata was called from. */
|
| + findDirname(progname, cmdBuf, 1024, &status);
|
| + if(U_SUCCESS(status)) {
|
| + uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024);
|
| + uprv_strncat(cmdBuf, cmd, 1024);
|
| +
|
| + if(verbose) {
|
| + fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf);
|
| + }
|
| + p = popen(cmdBuf, "r");
|
| + }
|
| +
|
| + if(p == NULL) {
|
| + if(verbose) {
|
| + fprintf(stdout, "# Calling icu-config: %s\n", cmd);
|
| + }
|
| + p = popen(cmd, "r");
|
| + }
|
| +
|
| + if(p == NULL)
|
| + {
|
| + fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
|
| + return -1;
|
| + }
|
| +
|
| + n = fread(buf, 1, 511, p);
|
| +
|
| + pclose(p);
|
| +
|
| + if(n<=0)
|
| + {
|
| + fprintf(stderr,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname);
|
| + return -1;
|
| + }
|
| +
|
| + for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
|
| + if (buf[length] == '\n' || buf[length] == ' ') {
|
| + buf[length] = 0;
|
| + } else {
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if(buf[strlen(buf)-1]=='\n')
|
| + {
|
| + buf[strlen(buf)-1]=0;
|
| + }
|
| +
|
| + if(buf[0] == 0)
|
| + {
|
| + fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
|
| + return -1;
|
| + }
|
| +
|
| + if(verbose) {
|
| + fprintf(stdout, "# icu-config said: %s\n", buf);
|
| + }
|
| +
|
| + option->value = buf;
|
| + option->doesOccur = TRUE;
|
| +
|
| + return 0;
|
| +#endif
|
| + return -1;
|
| +}
|
|
|
| Property changes on: icu46/source/tools/pkgdata/pkgdata.cpp
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|