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