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

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

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

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

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 }

mercurial