Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(969)

Side by Side Diff: icu46/source/tools/pkgdata/pkgdata.cpp

Issue 5516007: Check in the pristine copy of ICU 4.6... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « icu46/source/tools/pkgdata/Makefile.in ('k') | icu46/source/tools/pkgdata/pkgdata.vcxproj » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « icu46/source/tools/pkgdata/Makefile.in ('k') | icu46/source/tools/pkgdata/pkgdata.vcxproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698