]>
Commit | Line | Data |
---|---|---|
1 | /****************************************************************************** | |
2 | * | |
3 | * Copyright (C) 2000-2004, International Business Machines | |
4 | * Corporation and others. All Rights Reserved. | |
5 | * | |
6 | ******************************************************************************* | |
7 | * file name: pkgdata.c | |
8 | * encoding: ANSI X3.4 (1968) | |
9 | * tab size: 8 (not used) | |
10 | * indentation:4 | |
11 | * | |
12 | * created on: 2000may15 | |
13 | * created by: Steven \u24C7 Loomis | |
14 | * | |
15 | * This program packages the ICU data into different forms | |
16 | * (DLL, common data, etc.) | |
17 | */ | |
18 | ||
19 | #include "unicode/utypes.h" | |
20 | #include "unicode/putil.h" | |
21 | #include "cmemory.h" | |
22 | #include "cstring.h" | |
23 | #include "filestrm.h" | |
24 | #include "toolutil.h" | |
25 | #include "unicode/uclean.h" | |
26 | #include "unewdata.h" | |
27 | #include "uoptions.h" | |
28 | ||
29 | #if U_HAVE_POPEN | |
30 | /* | |
31 | We define __USE_POSIX2 so that we can get popen and pclose when | |
32 | --enable-strict is used | |
33 | */ | |
34 | # ifndef __USE_POSIX2 | |
35 | # define __USE_POSIX2 1 | |
36 | # endif | |
37 | # include <unistd.h> | |
38 | #endif | |
39 | #include <stdio.h> | |
40 | #include <stdlib.h> | |
41 | ||
42 | U_CDECL_BEGIN | |
43 | #include "pkgtypes.h" | |
44 | #include "makefile.h" | |
45 | U_CDECL_END | |
46 | ||
47 | static int executeMakefile(const UPKGOptions *o); | |
48 | static void loadLists(UPKGOptions *o, UErrorCode *status); | |
49 | ||
50 | /* always have this fcn, just might not do anything */ | |
51 | static void fillInMakefileFromICUConfig(UOption *option); | |
52 | ||
53 | /* This sets the modes that are available */ | |
54 | static struct | |
55 | { | |
56 | const char *name, *alt_name; | |
57 | UPKGMODE *fcn; | |
58 | const char *desc; | |
59 | } modes[] = | |
60 | { | |
61 | { "files", 0, pkg_mode_files, "Uses raw data files (no effect). Installation copies all files to the target location." }, | |
62 | #ifdef U_MAKE_IS_NMAKE | |
63 | { "dll", "library", pkg_mode_windows, "Generates one common data file and one shared library, <package>.dll"}, | |
64 | { "common", "archive", pkg_mode_windows, "Generates just the common file, <package>.dat"}, | |
65 | { "static", "static", pkg_mode_windows, "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX } | |
66 | #else /*#ifdef U_MAKE_IS_NMAKE*/ | |
67 | #ifdef UDATA_SO_SUFFIX | |
68 | { "dll", "library", pkg_mode_dll, "Generates one shared library, <package>" UDATA_SO_SUFFIX }, | |
69 | #endif | |
70 | { "common", "archive", pkg_mode_common, "Generates one common data file, <package>.dat" }, | |
71 | { "static", "static", pkg_mode_static, "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX } | |
72 | #endif /*#ifdef U_MAKE_IS_NMAKE*/ | |
73 | }; | |
74 | ||
75 | static UOption options[]={ | |
76 | /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG), | |
77 | /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */ | |
78 | /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG), | |
79 | /*03*/ UOPTION_HELP_H, /* -h */ | |
80 | /*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */ | |
81 | /*05*/ UOPTION_VERBOSE, /* -v */ | |
82 | /*06*/ UOPTION_COPYRIGHT, /* -c */ | |
83 | /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG), | |
84 | /*08*/ UOPTION_DESTDIR, /* -d */ | |
85 | /*09*/ UOPTION_DEF( "clean", 'k', UOPT_NO_ARG), | |
86 | /*10*/ UOPTION_DEF( "nooutput",'n', UOPT_NO_ARG), | |
87 | /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG), | |
88 | /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG), | |
89 | /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG), | |
90 | /*14*/ UOPTION_SOURCEDIR , | |
91 | /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG), | |
92 | /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG), | |
93 | /*17*/ UOPTION_DEF( 0, 'M', UOPT_REQUIRES_ARG), | |
94 | /*18*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG), | |
95 | /*19*/ UOPTION_DEF( "numerictmp", 'N', UOPT_NO_ARG), | |
96 | /*20*/ UOPTION_DEF( "embed", 'E', UOPT_NO_ARG), | |
97 | /*21*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG), | |
98 | /*22*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG) | |
99 | }; | |
100 | ||
101 | const char options_help[][320]={ | |
102 | "Set the data name", | |
103 | #ifdef U_MAKE_IS_NMAKE | |
104 | "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)", | |
105 | #else | |
106 | "Specify options for the builder. (Autdetected if icu-config is available)", | |
107 | #endif | |
108 | "Specify the mode of building (see below; default: common)", | |
109 | "This usage text", | |
110 | "This usage text", | |
111 | "Make the output verbose", | |
112 | "Use the standard ICU copyright", | |
113 | "Use a custom comment (instead of the copyright)", | |
114 | "Specify the destination directory for files", | |
115 | "Clean out generated & temporary files", | |
116 | "Suppress output of data, just list files to be created", | |
117 | "Force rebuilding of all data", | |
118 | "Specify temporary dir (default: output dir)", | |
119 | "Install the data (specify target)", | |
120 | "Specify a custom source directory", | |
121 | "Specify a custom entrypoint name (default: short name)", | |
122 | "Specify a version when packaging in DLL or static mode", | |
123 | "Pass the next argument to make(1)", | |
124 | "Add package to all file names if not present", | |
125 | "Use short numeric temporary file names such as t1234.c", | |
126 | "Use Embedded paths (such as 'mypackage_') - for compatibility.", | |
127 | "Library name to build (if different than package name)", | |
128 | "Quite mode. (e.g. Do not output a readme file for static libraries)" | |
129 | }; | |
130 | ||
131 | const char *progname = "PKGDATA"; | |
132 | ||
133 | int | |
134 | main(int argc, char* argv[]) { | |
135 | FileStream *out; | |
136 | UPKGOptions o; | |
137 | CharList *tail; | |
138 | UBool needsHelp = FALSE; | |
139 | UErrorCode status = U_ZERO_ERROR; | |
140 | char tmp[1024]; | |
141 | int32_t i; | |
142 | ||
143 | U_MAIN_INIT_ARGS(argc, argv); | |
144 | ||
145 | progname = argv[0]; | |
146 | ||
147 | options[2].value = "common"; | |
148 | options[17].value = ""; | |
149 | ||
150 | /* read command line options */ | |
151 | argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); | |
152 | ||
153 | /* error handling, printing usage message */ | |
154 | /* I've decided to simply print an error and quit. This tool has too | |
155 | many options to just display them all of the time. */ | |
156 | ||
157 | if(options[3].doesOccur || options[4].doesOccur) { | |
158 | needsHelp = TRUE; | |
159 | } | |
160 | else { | |
161 | if(!needsHelp && argc<0) { | |
162 | fprintf(stderr, | |
163 | "%s: error in command line argument \"%s\"\n", | |
164 | progname, | |
165 | argv[-argc]); | |
166 | fprintf(stderr, "Run '%s --help' for help.\n", progname); | |
167 | return 1; | |
168 | } | |
169 | ||
170 | if(!options[1].doesOccur) { | |
171 | /* Try to fill in from icu-config or equivalent */ | |
172 | fillInMakefileFromICUConfig(&options[1]); | |
173 | } | |
174 | #ifdef U_MAKE_IS_NMAKE | |
175 | else { | |
176 | fprintf(stderr, "Warning: You are using the deprecated -O option\n" | |
177 | "\tYou can fix this warning by installing pkgdata, gencmn and genccode\n" | |
178 | "\tinto the same directory and not specifying the -O option to pkgdata.\n"); | |
179 | } | |
180 | #endif | |
181 | ||
182 | if(!options[1].doesOccur) { | |
183 | fprintf(stderr, " required parameter is missing: -O is required \n"); | |
184 | fprintf(stderr, "Run '%s --help' for help.\n", progname); | |
185 | return 1; | |
186 | } | |
187 | ||
188 | if(!options[0].doesOccur) /* -O we already have - don't report it. */ | |
189 | { | |
190 | fprintf(stderr, " required parameter -p is missing \n"); | |
191 | fprintf(stderr, "Run '%s --help' for help.\n", progname); | |
192 | return 1; | |
193 | } | |
194 | ||
195 | if(argc == 1) { | |
196 | fprintf(stderr, | |
197 | "No input files specified.\n" | |
198 | "Run '%s --help' for help.\n", progname); | |
199 | return 1; | |
200 | } | |
201 | } /* end !needsHelp */ | |
202 | ||
203 | if(argc<0 || needsHelp ) { | |
204 | fprintf(stderr, | |
205 | "usage: %s [-options] [-] [packageFile] \n" | |
206 | "\tProduce packaged ICU data from the given list(s) of files.\n" | |
207 | "\t'-' by itself means to read from stdin.\n" | |
208 | "\tpackageFile is a text file containing the list of files to package.\n", | |
209 | progname); | |
210 | ||
211 | fprintf(stderr, "\n options:\n"); | |
212 | for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) { | |
213 | fprintf(stderr, "%-5s -%c %s%-10s %s\n", | |
214 | (i<1?"[REQ]":""), | |
215 | options[i].shortName, | |
216 | options[i].longName ? "or --" : " ", | |
217 | options[i].longName ? options[i].longName : "", | |
218 | options_help[i]); | |
219 | } | |
220 | ||
221 | fprintf(stderr, "modes: (-m option)\n"); | |
222 | for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) { | |
223 | fprintf(stderr, " %-9s ", modes[i].name); | |
224 | if (modes[i].alt_name) { | |
225 | fprintf(stderr, "/ %-9s", modes[i].alt_name); | |
226 | } else { | |
227 | fprintf(stderr, " "); | |
228 | } | |
229 | fprintf(stderr, " %s\n", modes[i].desc); | |
230 | } | |
231 | return 1; | |
232 | } | |
233 | ||
234 | /* OK, fill in the options struct */ | |
235 | uprv_memset(&o, 0, sizeof(o)); | |
236 | ||
237 | o.mode = options[2].value; | |
238 | o.version = options[16].doesOccur ? options[16].value : 0; | |
239 | o.makeArgs = options[17].value; | |
240 | ||
241 | o.fcn = NULL; | |
242 | ||
243 | for(i=0;i<sizeof(modes)/sizeof(modes[0]);i++) { | |
244 | if(!uprv_strcmp(modes[i].name, o.mode)) { | |
245 | o.fcn = modes[i].fcn; | |
246 | break; | |
247 | } else if (modes[i].alt_name && !uprv_strcmp(modes[i].alt_name, o.mode)) { | |
248 | o.mode = modes[i].name; | |
249 | o.fcn = modes[i].fcn; | |
250 | break; | |
251 | } | |
252 | } | |
253 | ||
254 | if(o.fcn == NULL) { | |
255 | fprintf(stderr, "Error: invalid mode '%s' specified. Run '%s --help' to list valid modes.\n", o.mode, progname); | |
256 | return 1; | |
257 | } | |
258 | ||
259 | o.shortName = options[0].value; | |
260 | { | |
261 | int32_t len = (int32_t)uprv_strlen(o.shortName); | |
262 | char *csname, *cp; | |
263 | const char *sp; | |
264 | ||
265 | cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName)); | |
266 | if (*(sp = o.shortName)) { | |
267 | *cp++ = isalpha(*sp) ? * sp : '_'; | |
268 | for (++sp; *sp; ++sp) { | |
269 | *cp++ = isalnum(*sp) ? *sp : '_'; | |
270 | } | |
271 | } | |
272 | *cp = 0; | |
273 | ||
274 | o.cShortName = csname; | |
275 | } | |
276 | ||
277 | if(options[21].doesOccur) { /* get libname from shortname, or explicit -L parameter */ | |
278 | o.libName = options[21].value; | |
279 | } else { | |
280 | o.libName = o.shortName; | |
281 | } | |
282 | ||
283 | if(options[22].doesOccur) { | |
284 | o.quiet = TRUE; | |
285 | } else { | |
286 | o.quiet = FALSE; | |
287 | } | |
288 | ||
289 | o.verbose = options[5].doesOccur; | |
290 | #ifdef U_MAKE_IS_NMAKE /* format is R:pathtoICU or D:pathtoICU */ | |
291 | { | |
292 | char *pathstuff = (char *)options[1].value; | |
293 | if(options[1].value[uprv_strlen(options[1].value)-1] == '\\') { | |
294 | pathstuff[uprv_strlen(options[1].value)-1] = '\0'; | |
295 | } | |
296 | if(*pathstuff == PKGDATA_DERIVED_PATH || *pathstuff == 'R' || *pathstuff == 'D') { | |
297 | o.options = pathstuff; | |
298 | pathstuff++; | |
299 | if(*pathstuff == ':') { | |
300 | *pathstuff = '\0'; | |
301 | pathstuff++; | |
302 | } | |
303 | else { | |
304 | fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n"); | |
305 | return 1; | |
306 | } | |
307 | } else { | |
308 | fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n"); | |
309 | return 1; | |
310 | } | |
311 | o.icuroot = pathstuff; | |
312 | if (o.verbose) { | |
313 | fprintf(stdout, "# ICUROOT is %s\n", o.icuroot); | |
314 | } | |
315 | } | |
316 | #else /* on UNIX, we'll just include the file... */ | |
317 | o.options = options[1].value; | |
318 | #endif | |
319 | if(options[6].doesOccur) { | |
320 | o.comment = U_COPYRIGHT_STRING; | |
321 | } else if (options[7].doesOccur) { | |
322 | o.comment = options[7].value; | |
323 | } | |
324 | ||
325 | if( options[8].doesOccur ) { | |
326 | o.targetDir = options[8].value; | |
327 | } else { | |
328 | o.targetDir = "."; /* cwd */ | |
329 | } | |
330 | ||
331 | o.clean = options[9].doesOccur; | |
332 | o.nooutput = options[10].doesOccur; | |
333 | o.rebuild = options[11].doesOccur; | |
334 | o.numeric = options[19].doesOccur; | |
335 | if(o.numeric) { | |
336 | o.rebuild = TRUE; /* force rebuild if numeric */ | |
337 | } | |
338 | ||
339 | o.embed = options[20].doesOccur; | |
340 | ||
341 | if( options[12].doesOccur ) { | |
342 | o.tmpDir = options[12].value; | |
343 | } else { | |
344 | o.tmpDir = o.targetDir; | |
345 | } | |
346 | ||
347 | if( options[13].doesOccur ) { | |
348 | o.install = options[13].value; | |
349 | } | |
350 | ||
351 | if( options[14].doesOccur ) { | |
352 | o.srcDir = options[14].value; | |
353 | } else { | |
354 | o.srcDir = "."; | |
355 | } | |
356 | ||
357 | if( options[15].doesOccur ) { | |
358 | o.entryName = options[15].value; | |
359 | } else { | |
360 | o.entryName = o.cShortName; | |
361 | } | |
362 | ||
363 | /* OK options are set up. Now the file lists. */ | |
364 | tail = NULL; | |
365 | for( i=1; i<argc; i++) { | |
366 | if ( !uprv_strcmp(argv[i] , "-") ) { | |
367 | /* stdin */ | |
368 | if( o.hadStdin == TRUE ) { | |
369 | fprintf(stderr, "Error: can't specify '-' twice!\n" | |
370 | "Run '%s --help' for help.\n", progname); | |
371 | return 1; | |
372 | } | |
373 | o.hadStdin = TRUE; | |
374 | } | |
375 | ||
376 | o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[i])); | |
377 | } | |
378 | ||
379 | /* load the files */ | |
380 | loadLists(&o, &status); | |
381 | if( U_FAILURE(status) ) { | |
382 | fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status)); | |
383 | return 2; | |
384 | } | |
385 | ||
386 | /* Makefile pathname */ | |
387 | uprv_strcpy(tmp, o.tmpDir); | |
388 | uprv_strcat(tmp, U_FILE_SEP_STRING); | |
389 | uprv_strcat(tmp, o.shortName); | |
390 | uprv_strcat(tmp, "_"); | |
391 | uprv_strcat(tmp, o.mode); | |
392 | uprv_strcat(tmp, ".mak"); /* MAY NEED TO CHANGE PER PLATFORM */ | |
393 | ||
394 | o.makeFile = uprv_strdup(tmp); | |
395 | ||
396 | out = T_FileStream_open(o.makeFile, "w"); | |
397 | if (out) { | |
398 | pkg_mak_writeHeader(out, &o); /* need to take status */ | |
399 | o.fcn(&o, out, &status); | |
400 | pkg_mak_writeFooter(out, &o); | |
401 | T_FileStream_close(out); | |
402 | } else { | |
403 | fprintf(stderr, "warning: couldn't create %s, will use existing file if any\n", o.makeFile); | |
404 | /*status = U_FILE_ACCESS_ERROR;*/ | |
405 | } | |
406 | ||
407 | if(U_FAILURE(status)) { | |
408 | fprintf(stderr, "Error creating makefile [%s]: %s\n", o.mode, | |
409 | u_errorName(status)); | |
410 | return 1; | |
411 | } | |
412 | ||
413 | if(o.nooutput == TRUE) { | |
414 | return 0; /* nothing to do. */ | |
415 | } | |
416 | ||
417 | return executeMakefile(&o); | |
418 | } | |
419 | ||
420 | /* POSIX - execute makefile */ | |
421 | static int executeMakefile(const UPKGOptions *o) | |
422 | { | |
423 | char cmd[1024]; | |
424 | /*char pwd[1024];*/ | |
425 | const char *make; | |
426 | int rc; | |
427 | ||
428 | make = getenv("MAKE"); | |
429 | ||
430 | if(!make || !make[0]) { | |
431 | make = U_MAKE; | |
432 | } | |
433 | ||
434 | /*getcwd(pwd, 1024);*/ | |
435 | #ifdef WIN32 | |
436 | sprintf(cmd, "%s %s%s -f \"%s\" %s %s %s %s", | |
437 | make, | |
438 | o->install ? "INSTALLTO=" : "", | |
439 | o->install ? o->install : "", | |
440 | o->makeFile, | |
441 | o->clean ? "clean" : "", | |
442 | o->rebuild ? "rebuild" : "", | |
443 | o->install ? "install" : "", | |
444 | o->makeArgs); | |
445 | #elif OS400 | |
446 | sprintf(cmd, "CALL GNU/GMAKE PARM(%s%s%s '-f' '%s' %s %s %s %s)", | |
447 | o->install ? "'INSTALLTO=" : "", | |
448 | o->install ? o->install : "", | |
449 | o->install ? "'" : "", | |
450 | o->makeFile, | |
451 | o->clean ? "'clean'" : "", | |
452 | o->rebuild ? "'rebuild'" : "", | |
453 | o->install ? "'install'" : "", | |
454 | o->makeArgs); | |
455 | #else | |
456 | sprintf(cmd, "%s %s%s -f %s %s %s %s %s", | |
457 | make, | |
458 | o->install ? "INSTALLTO=" : "", | |
459 | o->install ? o->install : "", | |
460 | o->makeFile, | |
461 | o->clean ? "clean" : "", | |
462 | o->rebuild ? "rebuild" : "", | |
463 | o->install ? "install" : "", | |
464 | o->makeArgs); | |
465 | #endif | |
466 | if(o->verbose) { | |
467 | puts(cmd); | |
468 | } | |
469 | ||
470 | rc = system(cmd); | |
471 | ||
472 | if(rc < 0) { | |
473 | fprintf(stderr, "# Failed, rc=%d\n", rc); | |
474 | } | |
475 | ||
476 | return rc < 128 ? rc : (rc >> 8); | |
477 | } | |
478 | ||
479 | ||
480 | static void loadLists(UPKGOptions *o, UErrorCode *status) | |
481 | { | |
482 | CharList *l, *tail = NULL, *tail2 = NULL; | |
483 | FileStream *in; | |
484 | char line[16384]; | |
485 | char *linePtr, *lineNext; | |
486 | const uint32_t lineMax = 16300; | |
487 | char tmp[1024]; | |
488 | char pkgPrefix[1024]; | |
489 | int32_t pkgPrefixLen; | |
490 | const char *baseName; | |
491 | char *s; | |
492 | int32_t ln=0; /* line number */ | |
493 | UBool fixPrefix; | |
494 | ||
495 | ||
496 | fixPrefix = options[18].doesOccur; | |
497 | ||
498 | strcpy(pkgPrefix, o->shortName); | |
499 | strcat(pkgPrefix, "_"); | |
500 | pkgPrefixLen=(int32_t)uprv_strlen(pkgPrefix); | |
501 | for(l = o->fileListFiles; l; l = l->next) { | |
502 | if(o->verbose) { | |
503 | fprintf(stdout, "# Reading %s..\n", l->str); | |
504 | } | |
505 | /* TODO: stdin */ | |
506 | in = T_FileStream_open(l->str, "r"); /* open files list */ | |
507 | ||
508 | if(!in) { | |
509 | fprintf(stderr, "Error opening <%s>.\n", l->str); | |
510 | *status = U_FILE_ACCESS_ERROR; | |
511 | return; | |
512 | } | |
513 | ||
514 | while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */ | |
515 | if((ln == 0) && (!o->embed)) { | |
516 | /* determine if we need to run in 'embed' (compatibility) mode */ | |
517 | if(!strncmp(findBasename(line), pkgPrefix, pkgPrefixLen)) { | |
518 | fprintf(stderr, "Warning: Found path '%s' in file name. Assuming compatibility (-E) mode.\n", pkgPrefix); | |
519 | o->embed = 1; | |
520 | } | |
521 | } | |
522 | ln++; | |
523 | if(uprv_strlen(line)>lineMax) { | |
524 | fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax); | |
525 | exit(1); | |
526 | } | |
527 | /* remove spaces at the beginning */ | |
528 | linePtr = line; | |
529 | while(isspace(*linePtr)) { | |
530 | linePtr++; | |
531 | } | |
532 | s=linePtr; | |
533 | /* remove trailing newline characters */ | |
534 | while(*s!=0) { | |
535 | if(*s=='\r' || *s=='\n') { | |
536 | *s=0; | |
537 | break; | |
538 | } | |
539 | ++s; | |
540 | } | |
541 | if((*linePtr == 0) || (*linePtr == '#')) { | |
542 | continue; /* comment or empty line */ | |
543 | } | |
544 | ||
545 | /* Now, process the line */ | |
546 | lineNext = NULL; | |
547 | ||
548 | while(linePtr && *linePtr) { /* process space-separated items */ | |
549 | while(*linePtr == ' ') { | |
550 | linePtr++; | |
551 | } | |
552 | /* Find the next quote */ | |
553 | if(linePtr[0] == '"') | |
554 | { | |
555 | lineNext = uprv_strchr(linePtr+1, '"'); | |
556 | if(lineNext == NULL) { | |
557 | fprintf(stderr, "%s:%d - missing trailing double quote (\")\n", | |
558 | l->str, (int)ln); | |
559 | exit(1); | |
560 | } else { | |
561 | lineNext++; | |
562 | if(*lineNext) { | |
563 | if(*lineNext != ' ') { | |
564 | fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n", | |
565 | l->str, (int)ln, lineNext-line, (*lineNext)?*lineNext:'0'); | |
566 | exit(1); | |
567 | } | |
568 | *lineNext = 0; | |
569 | lineNext++; | |
570 | } | |
571 | } | |
572 | } else { | |
573 | lineNext = uprv_strchr(linePtr, ' '); | |
574 | if(lineNext) { | |
575 | *lineNext = 0; /* terminate at space */ | |
576 | lineNext++; | |
577 | } | |
578 | } | |
579 | ||
580 | /* add the file */ | |
581 | s = (char*)getLongPathname(linePtr); | |
582 | ||
583 | if(o->embed == 0) { | |
584 | /* normal mode.. o->files is just the bare list without package names */ | |
585 | o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr)); | |
586 | uprv_strcpy(tmp, o->srcDir); | |
587 | uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING); | |
588 | uprv_strcat(tmp, s); | |
589 | o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp)); | |
590 | } else {/* embedded package_ mode */ | |
591 | baseName = findBasename(s); | |
592 | ||
593 | if(s != baseName) { | |
594 | /* s was something 'long' with a path */ | |
595 | /* paths already have the prefix */ | |
596 | o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName)); | |
597 | o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(s)); | |
598 | } else { /* s was just a basename, we want to prepend source dir*/ | |
599 | /* check for prefix of package */ | |
600 | uprv_strcpy(tmp, o->srcDir); | |
601 | uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING); | |
602 | o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName)); | |
603 | uprv_strcat(tmp, s); | |
604 | o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp)); | |
605 | } | |
606 | } /* end compatibility mode */ | |
607 | linePtr = lineNext; | |
608 | } /* for each entry on line */ | |
609 | } /* for each line */ | |
610 | T_FileStream_close(in); | |
611 | } /* for each file list file */ | |
612 | } | |
613 | ||
614 | /* Try calling icu-config directly to get information */ | |
615 | static void fillInMakefileFromICUConfig(UOption *option) | |
616 | { | |
617 | #if U_HAVE_POPEN | |
618 | FILE *p; | |
619 | size_t n; | |
620 | static char buf[512] = ""; | |
621 | static const char cmd[] = "icu-config --incfile"; | |
622 | ||
623 | if(options[5].doesOccur) | |
624 | { | |
625 | /* informational */ | |
626 | fprintf(stderr, "%s: No -O option found, trying '%s'.\n", progname, cmd); | |
627 | } | |
628 | ||
629 | p = popen(cmd, "r"); | |
630 | ||
631 | if(p == NULL) | |
632 | { | |
633 | fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname); | |
634 | return; | |
635 | } | |
636 | ||
637 | n = fread(buf, 1, 511, p); | |
638 | ||
639 | pclose(p); | |
640 | ||
641 | if(n<=0) | |
642 | { | |
643 | fprintf(stderr,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname); | |
644 | return; | |
645 | } | |
646 | ||
647 | if(buf[strlen(buf)-1]=='\n') | |
648 | { | |
649 | buf[strlen(buf)-1]=0; | |
650 | } | |
651 | ||
652 | if(buf[0] == 0) | |
653 | { | |
654 | fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname); | |
655 | return; | |
656 | } | |
657 | ||
658 | if(options[5].doesOccur) | |
659 | { | |
660 | /* informational */ | |
661 | fprintf(stderr, "%s: icu-config: using '-O %s'\n", progname, buf); | |
662 | } | |
663 | option->value = buf; | |
664 | option->doesOccur = TRUE; | |
665 | #else /* ! U_HAVE_POPEN */ | |
666 | ||
667 | #ifdef WIN32 | |
668 | char pathbuffer[_MAX_PATH] = {0}; | |
669 | char *fullEXEpath = NULL; | |
670 | char *pathstuff = NULL; | |
671 | ||
672 | if (strchr(progname, U_FILE_SEP_CHAR) != NULL || strchr(progname, U_FILE_ALT_SEP_CHAR) != NULL) { | |
673 | /* pkgdata was executed with relative path */ | |
674 | fullEXEpath = _fullpath(pathbuffer, progname, sizeof(pathbuffer)); | |
675 | pathstuff = (char *)options[1].value; | |
676 | ||
677 | if (fullEXEpath) { | |
678 | pathstuff = strrchr(fullEXEpath, U_FILE_SEP_CHAR); | |
679 | if (pathstuff) { | |
680 | pathstuff[1] = 0; | |
681 | uprv_memmove(fullEXEpath + 2, fullEXEpath, uprv_strlen(fullEXEpath)+1); | |
682 | fullEXEpath[0] = PKGDATA_DERIVED_PATH; | |
683 | fullEXEpath[1] = ':'; | |
684 | option->value = uprv_strdup(fullEXEpath); | |
685 | option->doesOccur = TRUE; | |
686 | } | |
687 | } | |
688 | } | |
689 | else { | |
690 | /* pkgdata was executed from the path */ | |
691 | /* Search for file in PATH environment variable: */ | |
692 | _searchenv("pkgdata.exe", "PATH", pathbuffer ); | |
693 | if( *pathbuffer != '\0' ) { | |
694 | fullEXEpath = pathbuffer; | |
695 | pathstuff = strrchr(pathbuffer, U_FILE_SEP_CHAR); | |
696 | if (pathstuff) { | |
697 | pathstuff[1] = 0; | |
698 | uprv_memmove(fullEXEpath + 2, fullEXEpath, uprv_strlen(fullEXEpath)+1); | |
699 | fullEXEpath[0] = PKGDATA_DERIVED_PATH; | |
700 | fullEXEpath[1] = ':'; | |
701 | option->value = uprv_strdup(fullEXEpath); | |
702 | option->doesOccur = TRUE; | |
703 | } | |
704 | } | |
705 | } | |
706 | /* else can't determine the path */ | |
707 | #endif | |
708 | ||
709 | /* no popen available */ | |
710 | /* Put other OS specific ways to search for the Makefile.inc type | |
711 | information or else fail.. */ | |
712 | ||
713 | #endif | |
714 | } |