File: | out/../deps/icu-small/source/tools/icupkg/icupkg.cpp |
Warning: | line 307, column 9 Potential leak of memory pointed to by 'pkg' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // © 2016 and later: Unicode, Inc. and others. | |||
2 | // License & terms of use: http://www.unicode.org/copyright.html | |||
3 | /* | |||
4 | ******************************************************************************* | |||
5 | * | |||
6 | * Copyright (C) 2005-2014, International Business Machines | |||
7 | * Corporation and others. All Rights Reserved. | |||
8 | * | |||
9 | ******************************************************************************* | |||
10 | * file name: icupkg.cpp | |||
11 | * encoding: UTF-8 | |||
12 | * tab size: 8 (not used) | |||
13 | * indentation:4 | |||
14 | * | |||
15 | * created on: 2005jul29 | |||
16 | * created by: Markus W. Scherer | |||
17 | * | |||
18 | * This tool operates on ICU data (.dat package) files. | |||
19 | * It takes one as input, or creates an empty one, and can remove, add, and | |||
20 | * extract data pieces according to command-line options. | |||
21 | * At the same time, it swaps each piece to a consistent set of platform | |||
22 | * properties as desired. | |||
23 | * Useful as an install-time tool for shipping only one flavor of ICU data | |||
24 | * and preparing data files for the target platform. | |||
25 | * Also for customizing ICU data (pruning, augmenting, replacing) and for | |||
26 | * taking it apart. | |||
27 | * Subsumes functionality and implementation code from | |||
28 | * gencmn, decmn, and icuswap tools. | |||
29 | * Will not work with data DLLs (shared libraries). | |||
30 | */ | |||
31 | ||||
32 | #include "unicode/utypes.h" | |||
33 | #include "unicode/putil.h" | |||
34 | #include "cstring.h" | |||
35 | #include "toolutil.h" | |||
36 | #include "uoptions.h" | |||
37 | #include "uparse.h" | |||
38 | #include "filestrm.h" | |||
39 | #include "package.h" | |||
40 | #include "pkg_icu.h" | |||
41 | ||||
42 | #include <stdio.h> | |||
43 | #include <stdlib.h> | |||
44 | #include <string.h> | |||
45 | ||||
46 | U_NAMESPACE_USEusing namespace icu_71; | |||
47 | ||||
48 | // TODO: add --matchmode=regex for using the ICU regex engine for item name pattern matching? | |||
49 | ||||
50 | // general definitions ----------------------------------------------------- *** | |||
51 | ||||
52 | // main() ------------------------------------------------------------------ *** | |||
53 | ||||
54 | static void | |||
55 | printUsage(const char *pname, UBool isHelp) { | |||
56 | FILE *where=isHelp ? stdoutstdout : stderrstderr; | |||
57 | ||||
58 | fprintf(where, | |||
59 | "%csage: %s [-h|-?|--help ] [-tl|-tb|-te] [-c] [-C comment]\n" | |||
60 | "\t[-a list] [-r list] [-x list] [-l [-o outputListFileName]]\n" | |||
61 | "\t[-s path] [-d path] [-w] [-m mode]\n" | |||
62 | "\t[--ignore-deps]\n" | |||
63 | "\t[--auto_toc_prefix] [--auto_toc_prefix_with_type] [--toc_prefix]\n" | |||
64 | "\tinfilename [outfilename]\n", | |||
65 | isHelp ? 'U' : 'u', pname); | |||
66 | if(isHelp) { | |||
67 | fprintf(where, | |||
68 | "\n" | |||
69 | "Read the input ICU .dat package file, modify it according to the options,\n" | |||
70 | "swap it to the desired platform properties (charset & endianness),\n" | |||
71 | "and optionally write the resulting ICU .dat package to the output file.\n" | |||
72 | "Items are removed, then added, then extracted and listed.\n" | |||
73 | "An ICU .dat package is written if items are removed or added,\n" | |||
74 | "or if the input and output filenames differ,\n" | |||
75 | "or if the --writepkg (-w) option is set.\n"); | |||
76 | fprintf(where, | |||
77 | "\n" | |||
78 | "If the input filename is \"new\" then an empty package is created.\n" | |||
79 | "If the output filename is missing, then it is automatically generated\n" | |||
80 | "from the input filename: If the input filename ends with an l, b, or e\n" | |||
81 | "matching its platform properties, then the output filename will\n" | |||
82 | "contain the letter from the -t (--type) option.\n"); | |||
83 | fprintf(where, | |||
84 | "\n" | |||
85 | "This tool can also be used to just swap a single ICU data file, replacing the\n" | |||
86 | "former icuswap tool. For this mode, provide the infilename (and optional\n" | |||
87 | "outfilename) for a non-package ICU data file.\n" | |||
88 | "Allowed options include -t, -w, -s and -d.\n" | |||
89 | "The filenames can be absolute, or relative to the source/dest dir paths.\n" | |||
90 | "Other options are not allowed in this mode.\n"); | |||
91 | fprintf(where, | |||
92 | "\n" | |||
93 | "Options:\n" | |||
94 | "\t(Only the last occurrence of an option is used.)\n" | |||
95 | "\n" | |||
96 | "\t-h or -? or --help print this message and exit\n"); | |||
97 | fprintf(where, | |||
98 | "\n" | |||
99 | "\t-tl or --type l output for little-endian/ASCII charset family\n" | |||
100 | "\t-tb or --type b output for big-endian/ASCII charset family\n" | |||
101 | "\t-te or --type e output for big-endian/EBCDIC charset family\n" | |||
102 | "\t The output type defaults to the input type.\n" | |||
103 | "\n" | |||
104 | "\t-c or --copyright include the ICU copyright notice\n" | |||
105 | "\t-C comment or --comment comment include a comment string\n"); | |||
106 | fprintf(where, | |||
107 | "\n" | |||
108 | "\t-a list or --add list add items to the package\n" | |||
109 | "\t-r list or --remove list remove items from the package\n" | |||
110 | "\t-x list or --extract list extract items from the package\n" | |||
111 | "\tThe list can be a single item's filename,\n" | |||
112 | "\tor a .txt filename with a list of item filenames,\n" | |||
113 | "\tor an ICU .dat package filename.\n"); | |||
114 | fprintf(where, | |||
115 | "\n" | |||
116 | "\t-w or --writepkg write the output package even if no items are removed\n" | |||
117 | "\t or added (e.g., for only swapping the data)\n"); | |||
118 | fprintf(where, | |||
119 | "\n" | |||
120 | "\t-m mode or --matchmode mode set the matching mode for item names with\n" | |||
121 | "\t wildcards\n" | |||
122 | "\t noslash: the '*' wildcard does not match the '/' tree separator\n"); | |||
123 | fprintf(where, | |||
124 | "\n" | |||
125 | "\t--ignore-deps Do not fail if not all resource dependencies are met. Use this\n" | |||
126 | "\t option if the missing resources come from another source."); | |||
127 | fprintf(where, | |||
128 | "\n" | |||
129 | "\tIn the .dat package, the Table of Contents (ToC) contains an entry\n" | |||
130 | "\tfor each item of the form prefix/tree/itemname .\n" | |||
131 | "\tThe prefix normally matches the package basename, and icupkg checks that,\n" | |||
132 | "\tbut this is not necessary when ICU need not find and load the package by filename.\n" | |||
133 | "\tICU package names end with the platform type letter, and thus differ\n" | |||
134 | "\tbetween platform types. This is not required for user data packages.\n"); | |||
135 | fprintf(where, | |||
136 | "\n" | |||
137 | "\t--auto_toc_prefix automatic ToC entries prefix\n" | |||
138 | "\t Uses the prefix of the first entry of the\n" | |||
139 | "\t input package, rather than its basename.\n" | |||
140 | "\t Requires a non-empty input package.\n" | |||
141 | "\t--auto_toc_prefix_with_type auto_toc_prefix + adjust platform type\n" | |||
142 | "\t Same as auto_toc_prefix but also checks that\n" | |||
143 | "\t the prefix ends with the input platform\n" | |||
144 | "\t type letter, and modifies it to the output\n" | |||
145 | "\t platform type letter.\n" | |||
146 | "\t At most one of the auto_toc_prefix options\n" | |||
147 | "\t can be used at a time.\n" | |||
148 | "\t--toc_prefix prefix ToC prefix to be used in the output package\n" | |||
149 | "\t Overrides the package basename\n" | |||
150 | "\t and --auto_toc_prefix.\n" | |||
151 | "\t Cannot be combined with --auto_toc_prefix_with_type.\n"); | |||
152 | /* | |||
153 | * Usage text columns, starting after the initial TAB. | |||
154 | * 1 2 3 4 5 6 7 8 | |||
155 | * 901234567890123456789012345678901234567890123456789012345678901234567890 | |||
156 | */ | |||
157 | fprintf(where, | |||
158 | "\n" | |||
159 | "\tList file syntax: Items are listed on one or more lines and separated\n" | |||
160 | "\tby whitespace (space+tab).\n" | |||
161 | "\tComments begin with # and are ignored. Empty lines are ignored.\n" | |||
162 | "\tLines where the first non-whitespace character is one of %s\n" | |||
163 | "\tare also ignored, to reserve for future syntax.\n", | |||
164 | U_PKG_RESERVED_CHARS"\"%&'()*+,-./:;<=>?_"); | |||
165 | fprintf(where, | |||
166 | "\tItems for removal or extraction may contain a single '*' wildcard\n" | |||
167 | "\tcharacter. The '*' matches zero or more characters.\n" | |||
168 | "\tIf --matchmode noslash (-m noslash) is set, then the '*'\n" | |||
169 | "\tdoes not match '/'.\n"); | |||
170 | fprintf(where, | |||
171 | "\n" | |||
172 | "\tItems must be listed relative to the package, and the --sourcedir or\n" | |||
173 | "\tthe --destdir path will be prepended.\n" | |||
174 | "\tThe paths are only prepended to item filenames while adding or\n" | |||
175 | "\textracting items, not to ICU .dat package or list filenames.\n" | |||
176 | "\t\n" | |||
177 | "\tPaths may contain '/' instead of the platform's\n" | |||
178 | "\tfile separator character, and are converted as appropriate.\n"); | |||
179 | fprintf(where, | |||
180 | "\n" | |||
181 | "\t-s path or --sourcedir path directory for the --add items\n" | |||
182 | "\t-d path or --destdir path directory for the --extract items\n" | |||
183 | "\n" | |||
184 | "\t-l or --list list the package items\n" | |||
185 | "\t (after modifying the package)\n" | |||
186 | "\t to stdout or to output list file\n" | |||
187 | "\t-o path or --outlist path path/filename for the --list output\n"); | |||
188 | } | |||
189 | } | |||
190 | ||||
191 | static UOption options[]={ | |||
192 | UOPTION_HELP_H{ "help", __null, __null, __null, 'h', UOPT_NO_ARG, 0 }, | |||
193 | UOPTION_HELP_QUESTION_MARK{ "help", __null, __null, __null, '?', UOPT_NO_ARG, 0 }, | |||
194 | UOPTION_DEF("type", 't', UOPT_REQUIRES_ARG){ "type", __null, __null, __null, 't', UOPT_REQUIRES_ARG, 0 }, | |||
195 | ||||
196 | UOPTION_COPYRIGHT{ "copyright", __null, __null, __null, 'c', UOPT_NO_ARG, 0 }, | |||
197 | UOPTION_DEF("comment", 'C', UOPT_REQUIRES_ARG){ "comment", __null, __null, __null, 'C', UOPT_REQUIRES_ARG, 0 }, | |||
198 | ||||
199 | UOPTION_SOURCEDIR{ "sourcedir", __null, __null, __null, 's', UOPT_REQUIRES_ARG , 0 }, | |||
200 | UOPTION_DESTDIR{ "destdir", __null, __null, __null, 'd', UOPT_REQUIRES_ARG, 0 }, | |||
201 | ||||
202 | UOPTION_DEF("writepkg", 'w', UOPT_NO_ARG){ "writepkg", __null, __null, __null, 'w', UOPT_NO_ARG, 0 }, | |||
203 | ||||
204 | UOPTION_DEF("matchmode", 'm', UOPT_REQUIRES_ARG){ "matchmode", __null, __null, __null, 'm', UOPT_REQUIRES_ARG , 0 }, | |||
205 | ||||
206 | UOPTION_DEF("ignore-deps", '\1', UOPT_NO_ARG){ "ignore-deps", __null, __null, __null, '\1', UOPT_NO_ARG, 0 }, | |||
207 | ||||
208 | UOPTION_DEF("add", 'a', UOPT_REQUIRES_ARG){ "add", __null, __null, __null, 'a', UOPT_REQUIRES_ARG, 0 }, | |||
209 | UOPTION_DEF("remove", 'r', UOPT_REQUIRES_ARG){ "remove", __null, __null, __null, 'r', UOPT_REQUIRES_ARG, 0 }, | |||
210 | UOPTION_DEF("extract", 'x', UOPT_REQUIRES_ARG){ "extract", __null, __null, __null, 'x', UOPT_REQUIRES_ARG, 0 }, | |||
211 | ||||
212 | UOPTION_DEF("list", 'l', UOPT_NO_ARG){ "list", __null, __null, __null, 'l', UOPT_NO_ARG, 0 }, | |||
213 | UOPTION_DEF("outlist", 'o', UOPT_REQUIRES_ARG){ "outlist", __null, __null, __null, 'o', UOPT_REQUIRES_ARG, 0 }, | |||
214 | ||||
215 | UOPTION_DEF("auto_toc_prefix", '\1', UOPT_NO_ARG){ "auto_toc_prefix", __null, __null, __null, '\1', UOPT_NO_ARG , 0 }, | |||
216 | UOPTION_DEF("auto_toc_prefix_with_type", '\1', UOPT_NO_ARG){ "auto_toc_prefix_with_type", __null, __null, __null, '\1', UOPT_NO_ARG , 0 }, | |||
217 | UOPTION_DEF("toc_prefix", '\1', UOPT_REQUIRES_ARG){ "toc_prefix", __null, __null, __null, '\1', UOPT_REQUIRES_ARG , 0 } | |||
218 | }; | |||
219 | ||||
220 | enum { | |||
221 | OPT_HELP_H, | |||
222 | OPT_HELP_QUESTION_MARK, | |||
223 | OPT_OUT_TYPE, | |||
224 | ||||
225 | OPT_COPYRIGHT, | |||
226 | OPT_COMMENT, | |||
227 | ||||
228 | OPT_SOURCEDIR, | |||
229 | OPT_DESTDIR, | |||
230 | ||||
231 | OPT_WRITEPKG, | |||
232 | ||||
233 | OPT_MATCHMODE, | |||
234 | ||||
235 | OPT_IGNORE_DEPS, | |||
236 | ||||
237 | OPT_ADD_LIST, | |||
238 | OPT_REMOVE_LIST, | |||
239 | OPT_EXTRACT_LIST, | |||
240 | ||||
241 | OPT_LIST_ITEMS, | |||
242 | OPT_LIST_FILE, | |||
243 | ||||
244 | OPT_AUTO_TOC_PREFIX, | |||
245 | OPT_AUTO_TOC_PREFIX_WITH_TYPE, | |||
246 | OPT_TOC_PREFIX, | |||
247 | ||||
248 | OPT_COUNT | |||
249 | }; | |||
250 | ||||
251 | static UBool | |||
252 | isPackageName(const char *filename) { | |||
253 | int32_t len; | |||
254 | ||||
255 | len=(int32_t)strlen(filename)-4; /* -4: subtract the length of ".dat" */ | |||
256 | return (UBool)(len>0 && 0==strcmp(filename+len, ".dat")); | |||
257 | } | |||
258 | /* | |||
259 | This line is required by MinGW because it incorrectly globs the arguments. | |||
260 | So when \* is used, it turns into a list of files instead of a literal "*" | |||
261 | */ | |||
262 | int _CRT_glob = 0; | |||
263 | ||||
264 | extern int | |||
265 | main(int argc, char *argv[]) { | |||
266 | const char *pname, *sourcePath, *destPath, *inFilename, *outFilename, *outComment; | |||
267 | char outType; | |||
268 | UBool isHelp, isModified, isPackage; | |||
269 | int result = 0; | |||
270 | ||||
271 | Package *pkg, *listPkg, *addListPkg; | |||
272 | ||||
273 | U_MAIN_INIT_ARGS(argc, argv); | |||
274 | ||||
275 | /* get the program basename */ | |||
276 | pname=findBasename(argv[0]); | |||
277 | ||||
278 | argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options)(int32_t)(sizeof(options)/sizeof((options)[0])), options); | |||
279 | isHelp=options[OPT_HELP_H].doesOccur || options[OPT_HELP_QUESTION_MARK].doesOccur; | |||
| ||||
280 | if(isHelp) { | |||
281 | printUsage(pname, TRUE1); | |||
282 | return U_ZERO_ERROR; | |||
283 | } | |||
284 | ||||
285 | pkg=new Package; | |||
286 | if(pkg
| |||
287 | fprintf(stderrstderr, "icupkg: not enough memory\n"); | |||
288 | return U_MEMORY_ALLOCATION_ERROR; | |||
289 | } | |||
290 | isModified=FALSE0; | |||
291 | ||||
292 | int autoPrefix=0; | |||
293 | if(options[OPT_AUTO_TOC_PREFIX].doesOccur) { | |||
294 | pkg->setAutoPrefix(); | |||
295 | ++autoPrefix; | |||
296 | } | |||
297 | if(options[OPT_AUTO_TOC_PREFIX_WITH_TYPE].doesOccur) { | |||
298 | if(options[OPT_TOC_PREFIX].doesOccur) { | |||
299 | fprintf(stderrstderr, "icupkg: --auto_toc_prefix_with_type and also --toc_prefix\n"); | |||
300 | printUsage(pname, FALSE0); | |||
301 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
302 | } | |||
303 | pkg->setAutoPrefixWithType(); | |||
304 | ++autoPrefix; | |||
305 | } | |||
306 | if(argc<2 || 3<argc || autoPrefix>1) { | |||
307 | printUsage(pname, FALSE0); | |||
| ||||
308 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
309 | } | |||
310 | ||||
311 | if(options[OPT_SOURCEDIR].doesOccur) { | |||
312 | sourcePath=options[OPT_SOURCEDIR].value; | |||
313 | } else { | |||
314 | // work relative to the current working directory | |||
315 | sourcePath=NULL__null; | |||
316 | } | |||
317 | if(options[OPT_DESTDIR].doesOccur) { | |||
318 | destPath=options[OPT_DESTDIR].value; | |||
319 | } else { | |||
320 | // work relative to the current working directory | |||
321 | destPath=NULL__null; | |||
322 | } | |||
323 | ||||
324 | if(0==strcmp(argv[1], "new")) { | |||
325 | if(autoPrefix) { | |||
326 | fprintf(stderrstderr, "icupkg: --auto_toc_prefix[_with_type] but no input package\n"); | |||
327 | printUsage(pname, FALSE0); | |||
328 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
329 | } | |||
330 | inFilename=NULL__null; | |||
331 | isPackage=TRUE1; | |||
332 | } else { | |||
333 | inFilename=argv[1]; | |||
334 | if(isPackageName(inFilename)) { | |||
335 | pkg->readPackage(inFilename); | |||
336 | isPackage=TRUE1; | |||
337 | } else { | |||
338 | /* swap a single file (icuswap replacement) rather than work on a package */ | |||
339 | pkg->addFile(sourcePath, inFilename); | |||
340 | isPackage=FALSE0; | |||
341 | } | |||
342 | } | |||
343 | ||||
344 | if(argc>=3) { | |||
345 | outFilename=argv[2]; | |||
346 | if(0!=strcmp(argv[1], argv[2])) { | |||
347 | isModified=TRUE1; | |||
348 | } | |||
349 | } else if(isPackage) { | |||
350 | outFilename=NULL__null; | |||
351 | } else /* !isPackage */ { | |||
352 | outFilename=inFilename; | |||
353 | isModified=(UBool)(sourcePath!=destPath); | |||
354 | } | |||
355 | ||||
356 | /* parse the output type option */ | |||
357 | if(options[OPT_OUT_TYPE].doesOccur) { | |||
358 | const char *type=options[OPT_OUT_TYPE].value; | |||
359 | if(type[0]==0 || type[1]!=0) { | |||
360 | /* the type must be exactly one letter */ | |||
361 | printUsage(pname, FALSE0); | |||
362 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
363 | } | |||
364 | outType=type[0]; | |||
365 | switch(outType) { | |||
366 | case 'l': | |||
367 | case 'b': | |||
368 | case 'e': | |||
369 | break; | |||
370 | default: | |||
371 | printUsage(pname, FALSE0); | |||
372 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
373 | } | |||
374 | ||||
375 | /* | |||
376 | * Set the isModified flag if the output type differs from the | |||
377 | * input package type. | |||
378 | * If we swap a single file, just assume that we are modifying it. | |||
379 | * The Package class does not give us access to the item and its type. | |||
380 | */ | |||
381 | isModified|=(UBool)(!isPackage || outType!=pkg->getInType()); | |||
382 | } else if(isPackage) { | |||
383 | outType=pkg->getInType(); // default to input type | |||
384 | } else /* !isPackage: swap single file */ { | |||
385 | outType=0; /* tells extractItem() to not swap */ | |||
386 | } | |||
387 | ||||
388 | if(options[OPT_WRITEPKG].doesOccur) { | |||
389 | isModified=TRUE1; | |||
390 | } | |||
391 | ||||
392 | if(!isPackage) { | |||
393 | /* | |||
394 | * icuswap tool replacement: Only swap a single file. | |||
395 | * Check that irrelevant options are not set. | |||
396 | */ | |||
397 | if( options[OPT_COMMENT].doesOccur || | |||
398 | options[OPT_COPYRIGHT].doesOccur || | |||
399 | options[OPT_MATCHMODE].doesOccur || | |||
400 | options[OPT_REMOVE_LIST].doesOccur || | |||
401 | options[OPT_ADD_LIST].doesOccur || | |||
402 | options[OPT_EXTRACT_LIST].doesOccur || | |||
403 | options[OPT_LIST_ITEMS].doesOccur | |||
404 | ) { | |||
405 | printUsage(pname, FALSE0); | |||
406 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
407 | } | |||
408 | if(isModified) { | |||
409 | pkg->extractItem(destPath, outFilename, 0, outType); | |||
410 | } | |||
411 | ||||
412 | delete pkg; | |||
413 | return result; | |||
414 | } | |||
415 | ||||
416 | /* Work with a package. */ | |||
417 | ||||
418 | if(options[OPT_COMMENT].doesOccur) { | |||
419 | outComment=options[OPT_COMMENT].value; | |||
420 | } else if(options[OPT_COPYRIGHT].doesOccur) { | |||
421 | outComment=U_COPYRIGHT_STRING" Copyright (C) 2016 and later: Unicode, Inc. and others. License & terms of use: http://www.unicode.org/copyright.html "; | |||
422 | } else { | |||
423 | outComment=NULL__null; | |||
424 | } | |||
425 | ||||
426 | if(options[OPT_MATCHMODE].doesOccur) { | |||
427 | if(0==strcmp(options[OPT_MATCHMODE].value, "noslash")) { | |||
428 | pkg->setMatchMode(Package::MATCH_NOSLASH); | |||
429 | } else { | |||
430 | printUsage(pname, FALSE0); | |||
431 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
432 | } | |||
433 | } | |||
434 | ||||
435 | /* remove items */ | |||
436 | if(options[OPT_REMOVE_LIST].doesOccur) { | |||
437 | listPkg=new Package(); | |||
438 | if(listPkg==NULL__null) { | |||
439 | fprintf(stderrstderr, "icupkg: not enough memory\n"); | |||
440 | exit(U_MEMORY_ALLOCATION_ERROR); | |||
441 | } | |||
442 | if(readList(NULL__null, options[OPT_REMOVE_LIST].value, FALSE0, listPkg)) { | |||
443 | pkg->removeItems(*listPkg); | |||
444 | delete listPkg; | |||
445 | isModified=TRUE1; | |||
446 | } else { | |||
447 | printUsage(pname, FALSE0); | |||
448 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
449 | } | |||
450 | } | |||
451 | ||||
452 | /* | |||
453 | * add items | |||
454 | * use a separate Package so that its memory and items stay around | |||
455 | * as long as the main Package | |||
456 | */ | |||
457 | addListPkg=NULL__null; | |||
458 | if(options[OPT_ADD_LIST].doesOccur) { | |||
459 | addListPkg=new Package(); | |||
460 | if(addListPkg==NULL__null) { | |||
461 | fprintf(stderrstderr, "icupkg: not enough memory\n"); | |||
462 | exit(U_MEMORY_ALLOCATION_ERROR); | |||
463 | } | |||
464 | if(readList(sourcePath, options[OPT_ADD_LIST].value, TRUE1, addListPkg)) { | |||
465 | pkg->addItems(*addListPkg); | |||
466 | // delete addListPkg; deferred until after writePackage() | |||
467 | isModified=TRUE1; | |||
468 | } else { | |||
469 | printUsage(pname, FALSE0); | |||
470 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
471 | } | |||
472 | } | |||
473 | ||||
474 | /* extract items */ | |||
475 | if(options[OPT_EXTRACT_LIST].doesOccur) { | |||
476 | listPkg=new Package(); | |||
477 | if(listPkg==NULL__null) { | |||
478 | fprintf(stderrstderr, "icupkg: not enough memory\n"); | |||
479 | exit(U_MEMORY_ALLOCATION_ERROR); | |||
480 | } | |||
481 | if(readList(NULL__null, options[OPT_EXTRACT_LIST].value, FALSE0, listPkg)) { | |||
482 | pkg->extractItems(destPath, *listPkg, outType); | |||
483 | delete listPkg; | |||
484 | } else { | |||
485 | printUsage(pname, FALSE0); | |||
486 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
487 | } | |||
488 | } | |||
489 | ||||
490 | /* list items */ | |||
491 | if(options[OPT_LIST_ITEMS].doesOccur) { | |||
492 | int32_t i; | |||
493 | if (options[OPT_LIST_FILE].doesOccur) { | |||
494 | FileStream *out; | |||
495 | out = T_FileStream_open(options[OPT_LIST_FILE].value, "w"); | |||
496 | if (out != NULL__null) { | |||
497 | for(i=0; i<pkg->getItemCount(); ++i) { | |||
498 | T_FileStream_writeLine(out, pkg->getItem(i)->name); | |||
499 | T_FileStream_writeLine(out, "\n"); | |||
500 | } | |||
501 | T_FileStream_close(out); | |||
502 | } else { | |||
503 | return U_ILLEGAL_ARGUMENT_ERROR; | |||
504 | } | |||
505 | } else { | |||
506 | for(i=0; i<pkg->getItemCount(); ++i) { | |||
507 | fprintf(stdoutstdout, "%s\n", pkg->getItem(i)->name); | |||
508 | } | |||
509 | } | |||
510 | } | |||
511 | ||||
512 | /* check dependencies between items */ | |||
513 | if(!options[OPT_IGNORE_DEPS].doesOccur && !pkg->checkDependencies()) { | |||
514 | /* some dependencies are not fulfilled */ | |||
515 | return U_MISSING_RESOURCE_ERROR; | |||
516 | } | |||
517 | ||||
518 | /* write the output .dat package if there are any modifications */ | |||
519 | if(isModified) { | |||
520 | char outFilenameBuffer[1024]; // for auto-generated output filename, if necessary | |||
521 | ||||
522 | if(outFilename==NULL__null || outFilename[0]==0) { | |||
523 | if(inFilename==NULL__null || inFilename[0]==0) { | |||
524 | fprintf(stderrstderr, "icupkg: unable to auto-generate an output filename if there is no input filename\n"); | |||
525 | exit(U_ILLEGAL_ARGUMENT_ERROR); | |||
526 | } | |||
527 | ||||
528 | /* | |||
529 | * auto-generate a filename: | |||
530 | * copy the inFilename, | |||
531 | * and if the last basename character matches the input file's type, | |||
532 | * then replace it with the output file's type | |||
533 | */ | |||
534 | char suffix[6]="?.dat"; | |||
535 | char *s; | |||
536 | ||||
537 | suffix[0]=pkg->getInType(); | |||
538 | strcpy(outFilenameBuffer, inFilename); | |||
539 | s=strchr(outFilenameBuffer, 0); | |||
540 | if((s-outFilenameBuffer)>5 && 0==memcmp(s-5, suffix, 5)) { | |||
541 | *(s-5)=outType; | |||
542 | } | |||
543 | outFilename=outFilenameBuffer; | |||
544 | } | |||
545 | if(options[OPT_TOC_PREFIX].doesOccur) { | |||
546 | pkg->setPrefix(options[OPT_TOC_PREFIX].value); | |||
547 | } | |||
548 | result = writePackageDatFile(outFilename, outComment, NULL__null, NULL__null, pkg, outType); | |||
549 | } | |||
550 | ||||
551 | delete addListPkg; | |||
552 | delete pkg; | |||
553 | return result; | |||
554 | } | |||
555 | ||||
556 | /* | |||
557 | * Hey, Emacs, please set the following: | |||
558 | * | |||
559 | * Local Variables: | |||
560 | * indent-tabs-mode: nil | |||
561 | * End: | |||
562 | * | |||
563 | */ |