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