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