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