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