1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/icupkg/icupkg.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,554 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 2005-2013, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* file name: icupkg.cpp 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* created on: 2005jul29 1.17 +* created by: Markus W. Scherer 1.18 +* 1.19 +* This tool operates on ICU data (.dat package) files. 1.20 +* It takes one as input, or creates an empty one, and can remove, add, and 1.21 +* extract data pieces according to command-line options. 1.22 +* At the same time, it swaps each piece to a consistent set of platform 1.23 +* properties as desired. 1.24 +* Useful as an install-time tool for shipping only one flavor of ICU data 1.25 +* and preparing data files for the target platform. 1.26 +* Also for customizing ICU data (pruning, augmenting, replacing) and for 1.27 +* taking it apart. 1.28 +* Subsumes functionality and implementation code from 1.29 +* gencmn, decmn, and icuswap tools. 1.30 +* Will not work with data DLLs (shared libraries). 1.31 +*/ 1.32 + 1.33 +#include "unicode/utypes.h" 1.34 +#include "unicode/putil.h" 1.35 +#include "cstring.h" 1.36 +#include "toolutil.h" 1.37 +#include "uoptions.h" 1.38 +#include "uparse.h" 1.39 +#include "filestrm.h" 1.40 +#include "package.h" 1.41 +#include "pkg_icu.h" 1.42 + 1.43 +#include <stdio.h> 1.44 +#include <stdlib.h> 1.45 +#include <string.h> 1.46 + 1.47 +U_NAMESPACE_USE 1.48 + 1.49 +// TODO: add --matchmode=regex for using the ICU regex engine for item name pattern matching? 1.50 + 1.51 +// general definitions ----------------------------------------------------- *** 1.52 + 1.53 +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 1.54 + 1.55 +// main() ------------------------------------------------------------------ *** 1.56 + 1.57 +static void 1.58 +printUsage(const char *pname, UBool isHelp) { 1.59 + FILE *where=isHelp ? stdout : stderr; 1.60 + 1.61 + fprintf(where, 1.62 + "%csage: %s [-h|-?|--help ] [-tl|-tb|-te] [-c] [-C comment]\n" 1.63 + "\t[-a list] [-r list] [-x list] [-l [-o outputListFileName]]\n" 1.64 + "\t[-s path] [-d path] [-w] [-m mode]\n" 1.65 + "\t[--auto_toc_prefix] [--auto_toc_prefix_with_type] [--toc_prefix]\n" 1.66 + "\tinfilename [outfilename]\n", 1.67 + isHelp ? 'U' : 'u', pname); 1.68 + if(isHelp) { 1.69 + fprintf(where, 1.70 + "\n" 1.71 + "Read the input ICU .dat package file, modify it according to the options,\n" 1.72 + "swap it to the desired platform properties (charset & endianness),\n" 1.73 + "and optionally write the resulting ICU .dat package to the output file.\n" 1.74 + "Items are removed, then added, then extracted and listed.\n" 1.75 + "An ICU .dat package is written if items are removed or added,\n" 1.76 + "or if the input and output filenames differ,\n" 1.77 + "or if the --writepkg (-w) option is set.\n"); 1.78 + fprintf(where, 1.79 + "\n" 1.80 + "If the input filename is \"new\" then an empty package is created.\n" 1.81 + "If the output filename is missing, then it is automatically generated\n" 1.82 + "from the input filename: If the input filename ends with an l, b, or e\n" 1.83 + "matching its platform properties, then the output filename will\n" 1.84 + "contain the letter from the -t (--type) option.\n"); 1.85 + fprintf(where, 1.86 + "\n" 1.87 + "This tool can also be used to just swap a single ICU data file, replacing the\n" 1.88 + "former icuswap tool. For this mode, provide the infilename (and optional\n" 1.89 + "outfilename) for a non-package ICU data file.\n" 1.90 + "Allowed options include -t, -w, -s and -d.\n" 1.91 + "The filenames can be absolute, or relative to the source/dest dir paths.\n" 1.92 + "Other options are not allowed in this mode.\n"); 1.93 + fprintf(where, 1.94 + "\n" 1.95 + "Options:\n" 1.96 + "\t(Only the last occurrence of an option is used.)\n" 1.97 + "\n" 1.98 + "\t-h or -? or --help print this message and exit\n"); 1.99 + fprintf(where, 1.100 + "\n" 1.101 + "\t-tl or --type l output for little-endian/ASCII charset family\n" 1.102 + "\t-tb or --type b output for big-endian/ASCII charset family\n" 1.103 + "\t-te or --type e output for big-endian/EBCDIC charset family\n" 1.104 + "\t The output type defaults to the input type.\n" 1.105 + "\n" 1.106 + "\t-c or --copyright include the ICU copyright notice\n" 1.107 + "\t-C comment or --comment comment include a comment string\n"); 1.108 + fprintf(where, 1.109 + "\n" 1.110 + "\t-a list or --add list add items to the package\n" 1.111 + "\t-r list or --remove list remove items from the package\n" 1.112 + "\t-x list or --extract list extract items from the package\n" 1.113 + "\tThe list can be a single item's filename,\n" 1.114 + "\tor a .txt filename with a list of item filenames,\n" 1.115 + "\tor an ICU .dat package filename.\n"); 1.116 + fprintf(where, 1.117 + "\n" 1.118 + "\t-w or --writepkg write the output package even if no items are removed\n" 1.119 + "\t or added (e.g., for only swapping the data)\n"); 1.120 + fprintf(where, 1.121 + "\n" 1.122 + "\t-m mode or --matchmode mode set the matching mode for item names with\n" 1.123 + "\t wildcards\n" 1.124 + "\t noslash: the '*' wildcard does not match the '/' tree separator\n"); 1.125 + fprintf(where, 1.126 + "\n" 1.127 + "\tIn the .dat package, the Table of Contents (ToC) contains an entry\n" 1.128 + "\tfor each item of the form prefix/tree/itemname .\n" 1.129 + "\tThe prefix normally matches the package basename, and icupkg checks that,\n" 1.130 + "\tbut this is not necessary when ICU need not find and load the package by filename.\n" 1.131 + "\tICU package names end with the platform type letter, and thus differ\n" 1.132 + "\tbetween platform types. This is not required for user data packages.\n"); 1.133 + fprintf(where, 1.134 + "\n" 1.135 + "\t--auto_toc_prefix automatic ToC entries prefix\n" 1.136 + "\t Uses the prefix of the first entry of the\n" 1.137 + "\t input package, rather than its basename.\n" 1.138 + "\t Requires a non-empty input package.\n" 1.139 + "\t--auto_toc_prefix_with_type auto_toc_prefix + adjust platform type\n" 1.140 + "\t Same as auto_toc_prefix but also checks that\n" 1.141 + "\t the prefix ends with the input platform\n" 1.142 + "\t type letter, and modifies it to the output\n" 1.143 + "\t platform type letter.\n" 1.144 + "\t At most one of the auto_toc_prefix options\n" 1.145 + "\t can be used at a time.\n" 1.146 + "\t--toc_prefix prefix ToC prefix to be used in the output package\n" 1.147 + "\t Overrides the package basename\n" 1.148 + "\t and --auto_toc_prefix.\n" 1.149 + "\t Cannot be combined with --auto_toc_prefix_with_type.\n"); 1.150 + /* 1.151 + * Usage text columns, starting after the initial TAB. 1.152 + * 1 2 3 4 5 6 7 8 1.153 + * 901234567890123456789012345678901234567890123456789012345678901234567890 1.154 + */ 1.155 + fprintf(where, 1.156 + "\n" 1.157 + "\tList file syntax: Items are listed on one or more lines and separated\n" 1.158 + "\tby whitespace (space+tab).\n" 1.159 + "\tComments begin with # and are ignored. Empty lines are ignored.\n" 1.160 + "\tLines where the first non-whitespace character is one of %s\n" 1.161 + "\tare also ignored, to reserve for future syntax.\n", 1.162 + U_PKG_RESERVED_CHARS); 1.163 + fprintf(where, 1.164 + "\tItems for removal or extraction may contain a single '*' wildcard\n" 1.165 + "\tcharacter. The '*' matches zero or more characters.\n" 1.166 + "\tIf --matchmode noslash (-m noslash) is set, then the '*'\n" 1.167 + "\tdoes not match '/'.\n"); 1.168 + fprintf(where, 1.169 + "\n" 1.170 + "\tItems must be listed relative to the package, and the --sourcedir or\n" 1.171 + "\tthe --destdir path will be prepended.\n" 1.172 + "\tThe paths are only prepended to item filenames while adding or\n" 1.173 + "\textracting items, not to ICU .dat package or list filenames.\n" 1.174 + "\t\n" 1.175 + "\tPaths may contain '/' instead of the platform's\n" 1.176 + "\tfile separator character, and are converted as appropriate.\n"); 1.177 + fprintf(where, 1.178 + "\n" 1.179 + "\t-s path or --sourcedir path directory for the --add items\n" 1.180 + "\t-d path or --destdir path directory for the --extract items\n" 1.181 + "\n" 1.182 + "\t-l or --list list the package items\n" 1.183 + "\t (after modifying the package)\n" 1.184 + "\t to stdout or to output list file\n" 1.185 + "\t-o path or --outlist path path/filename for the --list output\n"); 1.186 + } 1.187 +} 1.188 + 1.189 +static UOption options[]={ 1.190 + UOPTION_HELP_H, 1.191 + UOPTION_HELP_QUESTION_MARK, 1.192 + UOPTION_DEF("type", 't', UOPT_REQUIRES_ARG), 1.193 + 1.194 + UOPTION_COPYRIGHT, 1.195 + UOPTION_DEF("comment", 'C', UOPT_REQUIRES_ARG), 1.196 + 1.197 + UOPTION_SOURCEDIR, 1.198 + UOPTION_DESTDIR, 1.199 + 1.200 + UOPTION_DEF("writepkg", 'w', UOPT_NO_ARG), 1.201 + 1.202 + UOPTION_DEF("matchmode", 'm', UOPT_REQUIRES_ARG), 1.203 + 1.204 + UOPTION_DEF("add", 'a', UOPT_REQUIRES_ARG), 1.205 + UOPTION_DEF("remove", 'r', UOPT_REQUIRES_ARG), 1.206 + UOPTION_DEF("extract", 'x', UOPT_REQUIRES_ARG), 1.207 + 1.208 + UOPTION_DEF("list", 'l', UOPT_NO_ARG), 1.209 + UOPTION_DEF("outlist", 'o', UOPT_REQUIRES_ARG), 1.210 + 1.211 + UOPTION_DEF("auto_toc_prefix", '\1', UOPT_NO_ARG), 1.212 + UOPTION_DEF("auto_toc_prefix_with_type", '\1', UOPT_NO_ARG), 1.213 + UOPTION_DEF("toc_prefix", '\1', UOPT_REQUIRES_ARG) 1.214 +}; 1.215 + 1.216 +enum { 1.217 + OPT_HELP_H, 1.218 + OPT_HELP_QUESTION_MARK, 1.219 + OPT_OUT_TYPE, 1.220 + 1.221 + OPT_COPYRIGHT, 1.222 + OPT_COMMENT, 1.223 + 1.224 + OPT_SOURCEDIR, 1.225 + OPT_DESTDIR, 1.226 + 1.227 + OPT_WRITEPKG, 1.228 + 1.229 + OPT_MATCHMODE, 1.230 + 1.231 + OPT_ADD_LIST, 1.232 + OPT_REMOVE_LIST, 1.233 + OPT_EXTRACT_LIST, 1.234 + 1.235 + OPT_LIST_ITEMS, 1.236 + OPT_LIST_FILE, 1.237 + 1.238 + OPT_AUTO_TOC_PREFIX, 1.239 + OPT_AUTO_TOC_PREFIX_WITH_TYPE, 1.240 + OPT_TOC_PREFIX, 1.241 + 1.242 + OPT_COUNT 1.243 +}; 1.244 + 1.245 +static UBool 1.246 +isPackageName(const char *filename) { 1.247 + int32_t len; 1.248 + 1.249 + len=(int32_t)strlen(filename)-4; /* -4: subtract the length of ".dat" */ 1.250 + return (UBool)(len>0 && 0==strcmp(filename+len, ".dat")); 1.251 +} 1.252 +/* 1.253 +This line is required by MinGW because it incorrectly globs the arguments. 1.254 +So when \* is used, it turns into a list of files instead of a literal "*" 1.255 +*/ 1.256 +int _CRT_glob = 0; 1.257 + 1.258 +extern int 1.259 +main(int argc, char *argv[]) { 1.260 + const char *pname, *sourcePath, *destPath, *inFilename, *outFilename, *outComment; 1.261 + char outType; 1.262 + UBool isHelp, isModified, isPackage; 1.263 + int result = 0; 1.264 + 1.265 + Package *pkg, *listPkg, *addListPkg; 1.266 + 1.267 + U_MAIN_INIT_ARGS(argc, argv); 1.268 + 1.269 + /* get the program basename */ 1.270 + pname=findBasename(argv[0]); 1.271 + 1.272 + argc=u_parseArgs(argc, argv, LENGTHOF(options), options); 1.273 + isHelp=options[OPT_HELP_H].doesOccur || options[OPT_HELP_QUESTION_MARK].doesOccur; 1.274 + if(isHelp) { 1.275 + printUsage(pname, TRUE); 1.276 + return U_ZERO_ERROR; 1.277 + } 1.278 + 1.279 + pkg=new Package; 1.280 + if(pkg==NULL) { 1.281 + fprintf(stderr, "icupkg: not enough memory\n"); 1.282 + return U_MEMORY_ALLOCATION_ERROR; 1.283 + } 1.284 + isModified=FALSE; 1.285 + 1.286 + int autoPrefix=0; 1.287 + if(options[OPT_AUTO_TOC_PREFIX].doesOccur) { 1.288 + pkg->setAutoPrefix(); 1.289 + ++autoPrefix; 1.290 + } 1.291 + if(options[OPT_AUTO_TOC_PREFIX_WITH_TYPE].doesOccur) { 1.292 + if(options[OPT_TOC_PREFIX].doesOccur) { 1.293 + fprintf(stderr, "icupkg: --auto_toc_prefix_with_type and also --toc_prefix\n"); 1.294 + printUsage(pname, FALSE); 1.295 + return U_ILLEGAL_ARGUMENT_ERROR; 1.296 + } 1.297 + pkg->setAutoPrefixWithType(); 1.298 + ++autoPrefix; 1.299 + } 1.300 + if(argc<2 || 3<argc || autoPrefix>1) { 1.301 + printUsage(pname, FALSE); 1.302 + return U_ILLEGAL_ARGUMENT_ERROR; 1.303 + } 1.304 + 1.305 + if(options[OPT_SOURCEDIR].doesOccur) { 1.306 + sourcePath=options[OPT_SOURCEDIR].value; 1.307 + } else { 1.308 + // work relative to the current working directory 1.309 + sourcePath=NULL; 1.310 + } 1.311 + if(options[OPT_DESTDIR].doesOccur) { 1.312 + destPath=options[OPT_DESTDIR].value; 1.313 + } else { 1.314 + // work relative to the current working directory 1.315 + destPath=NULL; 1.316 + } 1.317 + 1.318 + if(0==strcmp(argv[1], "new")) { 1.319 + if(autoPrefix) { 1.320 + fprintf(stderr, "icupkg: --auto_toc_prefix[_with_type] but no input package\n"); 1.321 + printUsage(pname, FALSE); 1.322 + return U_ILLEGAL_ARGUMENT_ERROR; 1.323 + } 1.324 + inFilename=NULL; 1.325 + isPackage=TRUE; 1.326 + } else { 1.327 + inFilename=argv[1]; 1.328 + if(isPackageName(inFilename)) { 1.329 + pkg->readPackage(inFilename); 1.330 + isPackage=TRUE; 1.331 + } else { 1.332 + /* swap a single file (icuswap replacement) rather than work on a package */ 1.333 + pkg->addFile(sourcePath, inFilename); 1.334 + isPackage=FALSE; 1.335 + } 1.336 + } 1.337 + 1.338 + if(argc>=3) { 1.339 + outFilename=argv[2]; 1.340 + if(0!=strcmp(argv[1], argv[2])) { 1.341 + isModified=TRUE; 1.342 + } 1.343 + } else if(isPackage) { 1.344 + outFilename=NULL; 1.345 + } else /* !isPackage */ { 1.346 + outFilename=inFilename; 1.347 + isModified=(UBool)(sourcePath!=destPath); 1.348 + } 1.349 + 1.350 + /* parse the output type option */ 1.351 + if(options[OPT_OUT_TYPE].doesOccur) { 1.352 + const char *type=options[OPT_OUT_TYPE].value; 1.353 + if(type[0]==0 || type[1]!=0) { 1.354 + /* the type must be exactly one letter */ 1.355 + printUsage(pname, FALSE); 1.356 + return U_ILLEGAL_ARGUMENT_ERROR; 1.357 + } 1.358 + outType=type[0]; 1.359 + switch(outType) { 1.360 + case 'l': 1.361 + case 'b': 1.362 + case 'e': 1.363 + break; 1.364 + default: 1.365 + printUsage(pname, FALSE); 1.366 + return U_ILLEGAL_ARGUMENT_ERROR; 1.367 + } 1.368 + 1.369 + /* 1.370 + * Set the isModified flag if the output type differs from the 1.371 + * input package type. 1.372 + * If we swap a single file, just assume that we are modifying it. 1.373 + * The Package class does not give us access to the item and its type. 1.374 + */ 1.375 + isModified|=(UBool)(!isPackage || outType!=pkg->getInType()); 1.376 + } else if(isPackage) { 1.377 + outType=pkg->getInType(); // default to input type 1.378 + } else /* !isPackage: swap single file */ { 1.379 + outType=0; /* tells extractItem() to not swap */ 1.380 + } 1.381 + 1.382 + if(options[OPT_WRITEPKG].doesOccur) { 1.383 + isModified=TRUE; 1.384 + } 1.385 + 1.386 + if(!isPackage) { 1.387 + /* 1.388 + * icuswap tool replacement: Only swap a single file. 1.389 + * Check that irrelevant options are not set. 1.390 + */ 1.391 + if( options[OPT_COMMENT].doesOccur || 1.392 + options[OPT_COPYRIGHT].doesOccur || 1.393 + options[OPT_MATCHMODE].doesOccur || 1.394 + options[OPT_REMOVE_LIST].doesOccur || 1.395 + options[OPT_ADD_LIST].doesOccur || 1.396 + options[OPT_EXTRACT_LIST].doesOccur || 1.397 + options[OPT_LIST_ITEMS].doesOccur 1.398 + ) { 1.399 + printUsage(pname, FALSE); 1.400 + return U_ILLEGAL_ARGUMENT_ERROR; 1.401 + } 1.402 + if(isModified) { 1.403 + pkg->extractItem(destPath, outFilename, 0, outType); 1.404 + } 1.405 + 1.406 + delete pkg; 1.407 + return result; 1.408 + } 1.409 + 1.410 + /* Work with a package. */ 1.411 + 1.412 + if(options[OPT_COMMENT].doesOccur) { 1.413 + outComment=options[OPT_COMMENT].value; 1.414 + } else if(options[OPT_COPYRIGHT].doesOccur) { 1.415 + outComment=U_COPYRIGHT_STRING; 1.416 + } else { 1.417 + outComment=NULL; 1.418 + } 1.419 + 1.420 + if(options[OPT_MATCHMODE].doesOccur) { 1.421 + if(0==strcmp(options[OPT_MATCHMODE].value, "noslash")) { 1.422 + pkg->setMatchMode(Package::MATCH_NOSLASH); 1.423 + } else { 1.424 + printUsage(pname, FALSE); 1.425 + return U_ILLEGAL_ARGUMENT_ERROR; 1.426 + } 1.427 + } 1.428 + 1.429 + /* remove items */ 1.430 + if(options[OPT_REMOVE_LIST].doesOccur) { 1.431 + listPkg=new Package(); 1.432 + if(listPkg==NULL) { 1.433 + fprintf(stderr, "icupkg: not enough memory\n"); 1.434 + exit(U_MEMORY_ALLOCATION_ERROR); 1.435 + } 1.436 + if(readList(NULL, options[OPT_REMOVE_LIST].value, FALSE, listPkg)) { 1.437 + pkg->removeItems(*listPkg); 1.438 + delete listPkg; 1.439 + isModified=TRUE; 1.440 + } else { 1.441 + printUsage(pname, FALSE); 1.442 + return U_ILLEGAL_ARGUMENT_ERROR; 1.443 + } 1.444 + } 1.445 + 1.446 + /* 1.447 + * add items 1.448 + * use a separate Package so that its memory and items stay around 1.449 + * as long as the main Package 1.450 + */ 1.451 + addListPkg=NULL; 1.452 + if(options[OPT_ADD_LIST].doesOccur) { 1.453 + addListPkg=new Package(); 1.454 + if(addListPkg==NULL) { 1.455 + fprintf(stderr, "icupkg: not enough memory\n"); 1.456 + exit(U_MEMORY_ALLOCATION_ERROR); 1.457 + } 1.458 + if(readList(sourcePath, options[OPT_ADD_LIST].value, TRUE, addListPkg)) { 1.459 + pkg->addItems(*addListPkg); 1.460 + // delete addListPkg; deferred until after writePackage() 1.461 + isModified=TRUE; 1.462 + } else { 1.463 + printUsage(pname, FALSE); 1.464 + return U_ILLEGAL_ARGUMENT_ERROR; 1.465 + } 1.466 + } 1.467 + 1.468 + /* extract items */ 1.469 + if(options[OPT_EXTRACT_LIST].doesOccur) { 1.470 + listPkg=new Package(); 1.471 + if(listPkg==NULL) { 1.472 + fprintf(stderr, "icupkg: not enough memory\n"); 1.473 + exit(U_MEMORY_ALLOCATION_ERROR); 1.474 + } 1.475 + if(readList(NULL, options[OPT_EXTRACT_LIST].value, FALSE, listPkg)) { 1.476 + pkg->extractItems(destPath, *listPkg, outType); 1.477 + delete listPkg; 1.478 + } else { 1.479 + printUsage(pname, FALSE); 1.480 + return U_ILLEGAL_ARGUMENT_ERROR; 1.481 + } 1.482 + } 1.483 + 1.484 + /* list items */ 1.485 + if(options[OPT_LIST_ITEMS].doesOccur) { 1.486 + int32_t i; 1.487 + if (options[OPT_LIST_FILE].doesOccur) { 1.488 + FileStream *out; 1.489 + out = T_FileStream_open(options[OPT_LIST_FILE].value, "w"); 1.490 + if (out != NULL) { 1.491 + for(i=0; i<pkg->getItemCount(); ++i) { 1.492 + T_FileStream_writeLine(out, pkg->getItem(i)->name); 1.493 + T_FileStream_writeLine(out, "\n"); 1.494 + } 1.495 + T_FileStream_close(out); 1.496 + } else { 1.497 + return U_ILLEGAL_ARGUMENT_ERROR; 1.498 + } 1.499 + } else { 1.500 + for(i=0; i<pkg->getItemCount(); ++i) { 1.501 + fprintf(stdout, "%s\n", pkg->getItem(i)->name); 1.502 + } 1.503 + } 1.504 + } 1.505 + 1.506 + /* check dependencies between items */ 1.507 + if(!pkg->checkDependencies()) { 1.508 + /* some dependencies are not fulfilled */ 1.509 + return U_MISSING_RESOURCE_ERROR; 1.510 + } 1.511 + 1.512 + /* write the output .dat package if there are any modifications */ 1.513 + if(isModified) { 1.514 + char outFilenameBuffer[1024]; // for auto-generated output filename, if necessary 1.515 + 1.516 + if(outFilename==NULL || outFilename[0]==0) { 1.517 + if(inFilename==NULL || inFilename[0]==0) { 1.518 + fprintf(stderr, "icupkg: unable to auto-generate an output filename if there is no input filename\n"); 1.519 + exit(U_ILLEGAL_ARGUMENT_ERROR); 1.520 + } 1.521 + 1.522 + /* 1.523 + * auto-generate a filename: 1.524 + * copy the inFilename, 1.525 + * and if the last basename character matches the input file's type, 1.526 + * then replace it with the output file's type 1.527 + */ 1.528 + char suffix[6]="?.dat"; 1.529 + char *s; 1.530 + 1.531 + suffix[0]=pkg->getInType(); 1.532 + strcpy(outFilenameBuffer, inFilename); 1.533 + s=strchr(outFilenameBuffer, 0); 1.534 + if((s-outFilenameBuffer)>5 && 0==memcmp(s-5, suffix, 5)) { 1.535 + *(s-5)=outType; 1.536 + } 1.537 + outFilename=outFilenameBuffer; 1.538 + } 1.539 + if(options[OPT_TOC_PREFIX].doesOccur) { 1.540 + pkg->setPrefix(options[OPT_TOC_PREFIX].value); 1.541 + } 1.542 + result = writePackageDatFile(outFilename, outComment, NULL, NULL, pkg, outType); 1.543 + } 1.544 + 1.545 + delete addListPkg; 1.546 + delete pkg; 1.547 + return result; 1.548 +} 1.549 + 1.550 +/* 1.551 + * Hey, Emacs, please set the following: 1.552 + * 1.553 + * Local Variables: 1.554 + * indent-tabs-mode: nil 1.555 + * End: 1.556 + * 1.557 + */