1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
48393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius*   Copyright (C) 2005-2013, International Business Machines
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   file name:  icupkg.cpp
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   encoding:   US-ASCII
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   tab size:   8 (not used)
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   indentation:4
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created on: 2005jul29
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created by: Markus W. Scherer
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   This tool operates on ICU data (.dat package) files.
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   It takes one as input, or creates an empty one, and can remove, add, and
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   extract data pieces according to command-line options.
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   At the same time, it swaps each piece to a consistent set of platform
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   properties as desired.
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Useful as an install-time tool for shipping only one flavor of ICU data
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   and preparing data files for the target platform.
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Also for customizing ICU data (pruning, augmenting, replacing) and for
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   taking it apart.
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Subsumes functionality and implementation code from
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   gencmn, decmn, and icuswap tools.
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Will not work with data DLLs (shared libraries).
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "toolutil.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uoptions.h"
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uparse.h"
366d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru#include "filestrm.h"
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "package.h"
38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "pkg_icu.h"
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdlib.h>
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <string.h>
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_USE
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TODO: add --matchmode=regex for using the ICU regex engine for item name pattern matching?
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// general definitions ----------------------------------------------------- ***
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// main() ------------------------------------------------------------------ ***
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruprintUsage(const char *pname, UBool isHelp) {
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FILE *where=isHelp ? stdout : stderr;
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fprintf(where,
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "%csage: %s [-h|-?|--help ] [-tl|-tb|-te] [-c] [-C comment]\n"
606d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            "\t[-a list] [-r list] [-x list] [-l [-o outputListFileName]]\n"
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t[-s path] [-d path] [-w] [-m mode]\n"
6259d709d503bab6e2b61931737e662dd293b40578ccornelius            "\t[--auto_toc_prefix] [--auto_toc_prefix_with_type] [--toc_prefix]\n"
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tinfilename [outfilename]\n",
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isHelp ? 'U' : 'u', pname);
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isHelp) {
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "Read the input ICU .dat package file, modify it according to the options,\n"
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "swap it to the desired platform properties (charset & endianness),\n"
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "and optionally write the resulting ICU .dat package to the output file.\n"
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "Items are removed, then added, then extracted and listed.\n"
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "An ICU .dat package is written if items are removed or added,\n"
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "or if the input and output filenames differ,\n"
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "or if the --writepkg (-w) option is set.\n");
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "If the input filename is \"new\" then an empty package is created.\n"
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "If the output filename is missing, then it is automatically generated\n"
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "from the input filename: If the input filename ends with an l, b, or e\n"
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "matching its platform properties, then the output filename will\n"
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "contain the letter from the -t (--type) option.\n");
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "This tool can also be used to just swap a single ICU data file, replacing the\n"
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "former icuswap tool. For this mode, provide the infilename (and optional\n"
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "outfilename) for a non-package ICU data file.\n"
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "Allowed options include -t, -w, -s and -d.\n"
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "The filenames can be absolute, or relative to the source/dest dir paths.\n"
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "Other options are not allowed in this mode.\n");
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "Options:\n"
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t(Only the last occurrence of an option is used.)\n"
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-h or -? or --help    print this message and exit\n");
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-tl or --type l   output for little-endian/ASCII charset family\n"
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-tb or --type b   output for big-endian/ASCII charset family\n"
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-te or --type e   output for big-endian/EBCDIC charset family\n"
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t                  The output type defaults to the input type.\n"
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-c or --copyright include the ICU copyright notice\n"
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-C comment or --comment comment   include a comment string\n");
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-a list or --add list      add items to the package\n"
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-r list or --remove list   remove items from the package\n"
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-x list or --extract list  extract items from the package\n"
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tThe list can be a single item's filename,\n"
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tor a .txt filename with a list of item filenames,\n"
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tor an ICU .dat package filename.\n");
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-w or --writepkg  write the output package even if no items are removed\n"
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t                  or added (e.g., for only swapping the data)\n");
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-m mode or --matchmode mode  set the matching mode for item names with\n"
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t                             wildcards\n"
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t        noslash: the '*' wildcard does not match the '/' tree separator\n");
1228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        fprintf(where,
1238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\n"
1248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\tIn the .dat package, the Table of Contents (ToC) contains an entry\n"
1258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\tfor each item of the form prefix/tree/itemname .\n"
1268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\tThe prefix normally matches the package basename, and icupkg checks that,\n"
1278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\tbut this is not necessary when ICU need not find and load the package by filename.\n"
1288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\tICU package names end with the platform type letter, and thus differ\n"
1298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\tbetween platform types. This is not required for user data packages.\n");
1308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        fprintf(where,
1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\n"
1328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t--auto_toc_prefix            automatic ToC entries prefix\n"
1338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             Uses the prefix of the first entry of the\n"
1348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             input package, rather than its basename.\n"
1358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             Requires a non-empty input package.\n"
1368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t--auto_toc_prefix_with_type  auto_toc_prefix + adjust platform type\n"
1378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             Same as auto_toc_prefix but also checks that\n"
1388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             the prefix ends with the input platform\n"
1398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             type letter, and modifies it to the output\n"
1408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             platform type letter.\n"
1418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                At most one of the auto_toc_prefix options\n"
1428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                can be used at a time.\n"
1438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t--toc_prefix prefix          ToC prefix to be used in the output package\n"
1448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             Overrides the package basename\n"
14559d709d503bab6e2b61931737e662dd293b40578ccornelius            "\t                             and --auto_toc_prefix.\n"
14659d709d503bab6e2b61931737e662dd293b40578ccornelius            "\t                             Cannot be combined with --auto_toc_prefix_with_type.\n");
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Usage text columns, starting after the initial TAB.
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         *      1         2         3         4         5         6         7         8
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         *     901234567890123456789012345678901234567890123456789012345678901234567890
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tList file syntax: Items are listed on one or more lines and separated\n"
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tby whitespace (space+tab).\n"
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tComments begin with # and are ignored. Empty lines are ignored.\n"
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tLines where the first non-whitespace character is one of %s\n"
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tare also ignored, to reserve for future syntax.\n",
159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            U_PKG_RESERVED_CHARS);
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tItems for removal or extraction may contain a single '*' wildcard\n"
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tcharacter. The '*' matches zero or more characters.\n"
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tIf --matchmode noslash (-m noslash) is set, then the '*'\n"
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tdoes not match '/'.\n");
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tItems must be listed relative to the package, and the --sourcedir or\n"
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tthe --destdir path will be prepended.\n"
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tThe paths are only prepended to item filenames while adding or\n"
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\textracting items, not to ICU .dat package or list filenames.\n"
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t\n"
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tPaths may contain '/' instead of the platform's\n"
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\tfile separator character, and are converted as appropriate.\n");
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(where,
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-s path or --sourcedir path  directory for the --add items\n"
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\t-d path or --destdir path    directory for the --extract items\n"
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\n"
1798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t-l or --list                 list the package items\n"
1808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             (after modifying the package)\n"
1818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t                             to stdout or to output list file\n"
1828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "\t-o path or --outlist path    path/filename for the --list output\n");
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UOption options[]={
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_HELP_H,
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_HELP_QUESTION_MARK,
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("type", 't', UOPT_REQUIRES_ARG),
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_COPYRIGHT,
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("comment", 'C', UOPT_REQUIRES_ARG),
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_SOURCEDIR,
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DESTDIR,
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("writepkg", 'w', UOPT_NO_ARG),
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("matchmode", 'm', UOPT_REQUIRES_ARG),
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("add", 'a', UOPT_REQUIRES_ARG),
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("remove", 'r', UOPT_REQUIRES_ARG),
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UOPTION_DEF("extract", 'x', UOPT_REQUIRES_ARG),
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2056d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    UOPTION_DEF("list", 'l', UOPT_NO_ARG),
2068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UOPTION_DEF("outlist", 'o', UOPT_REQUIRES_ARG),
2078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
2088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UOPTION_DEF("auto_toc_prefix", '\1', UOPT_NO_ARG),
2098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UOPTION_DEF("auto_toc_prefix_with_type", '\1', UOPT_NO_ARG),
2108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UOPTION_DEF("toc_prefix", '\1', UOPT_REQUIRES_ARG)
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruenum {
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_HELP_H,
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_HELP_QUESTION_MARK,
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_OUT_TYPE,
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_COPYRIGHT,
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_COMMENT,
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_SOURCEDIR,
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_DESTDIR,
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_WRITEPKG,
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_MATCHMODE,
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_ADD_LIST,
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_REMOVE_LIST,
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_EXTRACT_LIST,
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_LIST_ITEMS,
2336d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    OPT_LIST_FILE,
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    OPT_AUTO_TOC_PREFIX,
2368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    OPT_AUTO_TOC_PREFIX_WITH_TYPE,
2378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    OPT_TOC_PREFIX,
2388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    OPT_COUNT
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruisPackageName(const char *filename) {
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    len=(int32_t)strlen(filename)-4; /* -4: subtract the length of ".dat" */
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(len>0 && 0==strcmp(filename+len, ".dat"));
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis line is required by MinGW because it incorrectly globs the arguments.
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSo when \* is used, it turns into a list of files instead of a literal "*"
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint _CRT_glob = 0;
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruextern int
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumain(int argc, char *argv[]) {
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *pname, *sourcePath, *destPath, *inFilename, *outFilename, *outComment;
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char outType;
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isHelp, isModified, isPackage;
260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int result = 0;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Package *pkg, *listPkg, *addListPkg;
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_MAIN_INIT_ARGS(argc, argv);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* get the program basename */
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pname=findBasename(argv[0]);
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    argc=u_parseArgs(argc, argv, LENGTHOF(options), options);
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    isHelp=options[OPT_HELP_H].doesOccur || options[OPT_HELP_QUESTION_MARK].doesOccur;
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isHelp) {
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printUsage(pname, TRUE);
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_ZERO_ERROR;
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pkg=new Package;
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pkg==NULL) {
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr, "icupkg: not enough memory\n");
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_MEMORY_ALLOCATION_ERROR;
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    isModified=FALSE;
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int autoPrefix=0;
2848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if(options[OPT_AUTO_TOC_PREFIX].doesOccur) {
2858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        pkg->setAutoPrefix();
2868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        ++autoPrefix;
2878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
2888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if(options[OPT_AUTO_TOC_PREFIX_WITH_TYPE].doesOccur) {
2898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if(options[OPT_TOC_PREFIX].doesOccur) {
2908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            fprintf(stderr, "icupkg: --auto_toc_prefix_with_type and also --toc_prefix\n");
2918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            printUsage(pname, FALSE);
2928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return U_ILLEGAL_ARGUMENT_ERROR;
2938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
2948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        pkg->setAutoPrefixWithType();
2958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        ++autoPrefix;
2968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
2978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if(argc<2 || 3<argc || autoPrefix>1) {
2988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        printUsage(pname, FALSE);
2998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return U_ILLEGAL_ARGUMENT_ERROR;
3008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
3018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_SOURCEDIR].doesOccur) {
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sourcePath=options[OPT_SOURCEDIR].value;
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // work relative to the current working directory
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        sourcePath=NULL;
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_DESTDIR].doesOccur) {
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        destPath=options[OPT_DESTDIR].value;
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // work relative to the current working directory
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        destPath=NULL;
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(0==strcmp(argv[1], "new")) {
3168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if(autoPrefix) {
3178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            fprintf(stderr, "icupkg: --auto_toc_prefix[_with_type] but no input package\n");
3188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            printUsage(pname, FALSE);
3198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return U_ILLEGAL_ARGUMENT_ERROR;
3208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        inFilename=NULL;
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isPackage=TRUE;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        inFilename=argv[1];
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isPackageName(inFilename)) {
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->readPackage(inFilename);
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isPackage=TRUE;
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* swap a single file (icuswap replacement) rather than work on a package */
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->addFile(sourcePath, inFilename);
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isPackage=FALSE;
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(argc>=3) {
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outFilename=argv[2];
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(0!=strcmp(argv[1], argv[2])) {
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isModified=TRUE;
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(isPackage) {
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outFilename=NULL;
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else /* !isPackage */ {
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outFilename=inFilename;
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isModified=(UBool)(sourcePath!=destPath);
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* parse the output type option */
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_OUT_TYPE].doesOccur) {
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const char *type=options[OPT_OUT_TYPE].value;
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(type[0]==0 || type[1]!=0) {
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* the type must be exactly one letter */
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outType=type[0];
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        switch(outType) {
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case 'l':
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case 'b':
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case 'e':
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Set the isModified flag if the output type differs from the
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * input package type.
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * If we swap a single file, just assume that we are modifying it.
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * The Package class does not give us access to the item and its type.
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        isModified|=(UBool)(!isPackage || outType!=pkg->getInType());
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(isPackage) {
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outType=pkg->getInType(); // default to input type
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else /* !isPackage: swap single file */ {
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outType=0; /* tells extractItem() to not swap */
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_WRITEPKG].doesOccur) {
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isModified=TRUE;
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!isPackage) {
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * icuswap tool replacement: Only swap a single file.
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Check that irrelevant options are not set.
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( options[OPT_COMMENT].doesOccur ||
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            options[OPT_COPYRIGHT].doesOccur ||
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            options[OPT_MATCHMODE].doesOccur ||
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            options[OPT_REMOVE_LIST].doesOccur ||
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            options[OPT_ADD_LIST].doesOccur ||
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            options[OPT_EXTRACT_LIST].doesOccur ||
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            options[OPT_LIST_ITEMS].doesOccur
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ) {
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isModified) {
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->extractItem(destPath, outFilename, 0, outType);
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete pkg;
404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return result;
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Work with a package. */
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_COMMENT].doesOccur) {
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outComment=options[OPT_COMMENT].value;
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(options[OPT_COPYRIGHT].doesOccur) {
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outComment=U_COPYRIGHT_STRING;
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        outComment=NULL;
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_MATCHMODE].doesOccur) {
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(0==strcmp(options[OPT_MATCHMODE].value, "noslash")) {
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->setMatchMode(Package::MATCH_NOSLASH);
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* remove items */
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_REMOVE_LIST].doesOccur) {
42854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        listPkg=new Package();
42954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(listPkg==NULL) {
43054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            fprintf(stderr, "icupkg: not enough memory\n");
43154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            exit(U_MEMORY_ALLOCATION_ERROR);
43254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
43354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(readList(NULL, options[OPT_REMOVE_LIST].value, FALSE, listPkg)) {
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->removeItems(*listPkg);
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete listPkg;
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isModified=TRUE;
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * add items
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * use a separate Package so that its memory and items stay around
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * as long as the main Package
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    addListPkg=NULL;
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_ADD_LIST].doesOccur) {
45054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        addListPkg=new Package();
45154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(addListPkg==NULL) {
45254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            fprintf(stderr, "icupkg: not enough memory\n");
45354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            exit(U_MEMORY_ALLOCATION_ERROR);
45454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
45554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(readList(sourcePath, options[OPT_ADD_LIST].value, TRUE, addListPkg)) {
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->addItems(*addListPkg);
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // delete addListPkg; deferred until after writePackage()
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isModified=TRUE;
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* extract items */
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_EXTRACT_LIST].doesOccur) {
46754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        listPkg=new Package();
46854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(listPkg==NULL) {
46954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            fprintf(stderr, "icupkg: not enough memory\n");
47054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            exit(U_MEMORY_ALLOCATION_ERROR);
47154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
47254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(readList(NULL, options[OPT_EXTRACT_LIST].value, FALSE, listPkg)) {
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pkg->extractItems(destPath, *listPkg, outType);
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete listPkg;
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            printUsage(pname, FALSE);
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return U_ILLEGAL_ARGUMENT_ERROR;
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* list items */
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(options[OPT_LIST_ITEMS].doesOccur) {
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i;
4846d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        if (options[OPT_LIST_FILE].doesOccur) {
4856d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            FileStream *out;
4866d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            out = T_FileStream_open(options[OPT_LIST_FILE].value, "w");
4876d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            if (out != NULL) {
4886d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                for(i=0; i<pkg->getItemCount(); ++i) {
4896d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                    T_FileStream_writeLine(out, pkg->getItem(i)->name);
4906d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                    T_FileStream_writeLine(out, "\n");
4916d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                }
4926d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                T_FileStream_close(out);
4936d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            } else {
4946d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                return U_ILLEGAL_ARGUMENT_ERROR;
4956d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            }
4966d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        } else {
4976d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            for(i=0; i<pkg->getItemCount(); ++i) {
4986d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                fprintf(stdout, "%s\n", pkg->getItem(i)->name);
4996d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            }
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check dependencies between items */
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!pkg->checkDependencies()) {
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* some dependencies are not fulfilled */
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_MISSING_RESOURCE_ERROR;
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* write the output .dat package if there are any modifications */
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isModified) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char outFilenameBuffer[1024]; // for auto-generated output filename, if necessary
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(outFilename==NULL || outFilename[0]==0) {
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(inFilename==NULL || inFilename[0]==0) {
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr, "icupkg: unable to auto-generate an output filename if there is no input filename\n");
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                exit(U_ILLEGAL_ARGUMENT_ERROR);
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * auto-generate a filename:
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * copy the inFilename,
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * and if the last basename character matches the input file's type,
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * then replace it with the output file's type
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char suffix[6]="?.dat";
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char *s;
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            suffix[0]=pkg->getInType();
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            strcpy(outFilenameBuffer, inFilename);
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s=strchr(outFilenameBuffer, 0);
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if((s-outFilenameBuffer)>5 && 0==memcmp(s-5, suffix, 5)) {
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *(s-5)=outType;
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            outFilename=outFilenameBuffer;
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
5368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if(options[OPT_TOC_PREFIX].doesOccur) {
5378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            pkg->setPrefix(options[OPT_TOC_PREFIX].value);
5388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        result = writePackageDatFile(outFilename, outComment, NULL, NULL, pkg, outType);
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete addListPkg;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete pkg;
544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return result;
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Hey, Emacs, please set the following:
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Local Variables:
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * indent-tabs-mode: nil
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * End:
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
555