#if !defined(_XOPEN_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 4
#endif
#endif
#include "unicode/utypes.h"
#if U_HAVE_POPEN
#if defined(U_CYGWIN) && defined(__STRICT_ANSI__)
#undef __STRICT_ANSI__
#endif
#endif
#include "unicode/putil.h"
#include "cmemory.h"
#include "cstring.h"
#include "filestrm.h"
#include "toolutil.h"
#include "unicode/uclean.h"
#include "unewdata.h"
#include "uoptions.h"
#include "putilimp.h"
#include "package.h"
#include "pkg_icu.h"
#include "pkg_genc.h"
#include "pkg_gencmn.h"
#include "flagparser.h"
#include "filetools.h"
#if U_HAVE_POPEN
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
U_CDECL_BEGIN
#include "pkgtypes.h"
U_CDECL_END
#ifdef U_WINDOWS
#ifdef __GNUC__
#define WINDOWS_WITH_GNUC
#else
#define WINDOWS_WITH_MSVC
#endif
#endif
#if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX)
#define BUILD_DATA_WITHOUT_ASSEMBLY
#endif
#if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
#define CAN_WRITE_OBJ_CODE
#endif
#if defined(U_CYGWIN) || defined(CYGWINMSVC)
#define USING_CYGWIN
#endif
#if defined(OS400)
#define USE_SINGLE_CCODE_FILE
#endif
#if defined(WINDOWS_WITH_GNUC) || defined(USING_CYGWIN)
#define PKGDATA_FILE_SEP_STRING "/"
#else
#define PKGDATA_FILE_SEP_STRING U_FILE_SEP_STRING
#endif
#define LARGE_BUFFER_MAX_SIZE 2048
#define SMALL_BUFFER_MAX_SIZE 512
#define BUFFER_PADDING_SIZE 20
static void loadLists(UPKGOptions *o, UErrorCode *status);
static int32_t pkg_executeOptions(UPKGOptions *o);
#ifdef WINDOWS_WITH_MSVC
static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
#endif
static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE);
static int32_t pkg_installLibrary(const char *installDir, const char *dir);
static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
static int32_t pkg_installCommonMode(const char *installDir, const char *fileName);
#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
#endif
static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL);
static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt);
static int32_t initializePkgDataFlags(UPKGOptions *o);
static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option);
static int runCommand(const char* command, UBool specialHandling=FALSE);
enum {
NAME,
BLDOPT,
MODE,
HELP,
HELP_QUESTION_MARK,
VERBOSE,
COPYRIGHT,
COMMENT,
DESTDIR,
REBUILD,
TEMPDIR,
INSTALL,
SOURCEDIR,
ENTRYPOINT,
REVISION,
FORCE_PREFIX,
LIBNAME,
QUIET
};
static struct {
const char *name, *alt_name;
const char *desc;
} modes[] = {
{ "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
#ifdef U_WINDOWS
{ "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
{ "common", "archive", "Generates just the common file, <package>.dat"},
{ "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
#else
#ifdef UDATA_SO_SUFFIX
{ "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX },
#endif
{ "common", "archive", "Generates one common data file, <package>.dat" },
{ "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
#endif
};
static UOption options[]={
UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG),
UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG),
UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG),
UOPTION_HELP_H,
UOPTION_HELP_QUESTION_MARK,
UOPTION_VERBOSE,
UOPTION_COPYRIGHT,
UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
UOPTION_DESTDIR,
UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
UOPTION_SOURCEDIR ,
UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG)
};
enum {
GENCCODE_ASSEMBLY_TYPE,
SO_EXT,
SOBJ_EXT,
A_EXT,
LIBPREFIX,
LIB_EXT_ORDER,
COMPILER,
LIBFLAGS,
GENLIB,
LDICUDTFLAGS,
LD_SONAME,
RPATH_FLAGS,
BIR_FLAGS,
AR,
ARFLAGS,
RANLIB,
INSTALL_CMD,
PKGDATA_FLAGS_SIZE
};
static char **pkgDataFlags = NULL;
enum {
LIB_FILE,
LIB_FILE_VERSION_MAJOR,
LIB_FILE_VERSION,
LIB_FILE_VERSION_TMP,
#ifdef U_CYGWIN
LIB_FILE_CYGWIN,
LIB_FILE_CYGWIN_VERSION,
#endif
LIB_FILENAMES_SIZE
};
static char libFileNames[LIB_FILENAMES_SIZE][256];
static UPKGOptions *pkg_checkFlag(UPKGOptions *o);
const char options_help[][320]={
"Set the data name",
#ifdef U_MAKE_IS_NMAKE
"The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
#else
"Specify options for the builder.",
#endif
"Specify the mode of building (see below; default: common)",
"This usage text",
"This usage text",
"Make the output verbose",
"Use the standard ICU copyright",
"Use a custom comment (instead of the copyright)",
"Specify the destination directory for files",
"Force rebuilding of all data",
"Specify temporary dir (default: output dir)",
"Install the data (specify target)",
"Specify a custom source directory",
"Specify a custom entrypoint name (default: short name)",
"Specify a version when packaging in dll or static mode",
"Add package to all file names if not present",
"Library name to build (if different than package name)",
"Quite mode. (e.g. Do not output a readme file for static libraries)"
};
const char *progname = "PKGDATA";
int
main(int argc, char* argv[]) {
int result = 0;
UPKGOptions o;
CharList *tail;
UBool needsHelp = FALSE;
UErrorCode status = U_ZERO_ERROR;
uint32_t i;
int32_t n;
U_MAIN_INIT_ARGS(argc, argv);
progname = argv[0];
options[MODE].value = "common";
argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
needsHelp = TRUE;
}
else {
if(!needsHelp && argc<0) {
fprintf(stderr,
"%s: error in command line argument \"%s\"\n",
progname,
argv[-argc]);
fprintf(stderr, "Run '%s --help' for help.\n", progname);
return 1;
}
#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) {
if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) {
fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n");
fprintf(stderr, "Run '%s --help' for help.\n", progname);
return 1;
}
}
#else
if(options[BLDOPT].doesOccur) {
fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
}
#endif
if(!options[NAME].doesOccur)
{
fprintf(stderr, " required parameter -p is missing \n");
fprintf(stderr, "Run '%s --help' for help.\n", progname);
return 1;
}
if(argc == 1) {
fprintf(stderr,
"No input files specified.\n"
"Run '%s --help' for help.\n", progname);
return 1;
}
}
if(argc<0 || needsHelp ) {
fprintf(stderr,
"usage: %s [-options] [-] [packageFile] \n"
"\tProduce packaged ICU data from the given list(s) of files.\n"
"\t'-' by itself means to read from stdin.\n"
"\tpackageFile is a text file containing the list of files to package.\n",
progname);
fprintf(stderr, "\n options:\n");
for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
fprintf(stderr, "%-5s -%c %s%-10s %s\n",
(i<1?"[REQ]":""),
options[i].shortName,
options[i].longName ? "or --" : " ",
options[i].longName ? options[i].longName : "",
options_help[i]);
}
fprintf(stderr, "modes: (-m option)\n");
for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
fprintf(stderr, " %-9s ", modes[i].name);
if (modes[i].alt_name) {
fprintf(stderr, "/ %-9s", modes[i].alt_name);
} else {
fprintf(stderr, " ");
}
fprintf(stderr, " %s\n", modes[i].desc);
}
return 1;
}
uprv_memset(&o, 0, sizeof(o));
o.mode = options[MODE].value;
o.version = options[REVISION].doesOccur ? options[REVISION].value : 0;
o.shortName = options[NAME].value;
{
int32_t len = (int32_t)uprv_strlen(o.shortName);
char *csname, *cp;
const char *sp;
cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
if (*(sp = o.shortName)) {
*cp++ = isalpha(*sp) ? * sp : '_';
for (++sp; *sp; ++sp) {
*cp++ = isalnum(*sp) ? *sp : '_';
}
}
*cp = 0;
o.cShortName = csname;
}
if(options[LIBNAME].doesOccur) {
o.libName = options[LIBNAME].value;
} else {
o.libName = o.shortName;
}
if(options[QUIET].doesOccur) {
o.quiet = TRUE;
} else {
o.quiet = FALSE;
}
o.verbose = options[VERBOSE].doesOccur;
#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
if (options[BLDOPT].doesOccur) {
o.options = options[BLDOPT].value;
} else {
o.options = NULL;
}
#endif
if(options[COPYRIGHT].doesOccur) {
o.comment = U_COPYRIGHT_STRING;
} else if (options[COMMENT].doesOccur) {
o.comment = options[COMMENT].value;
}
if( options[DESTDIR].doesOccur ) {
o.targetDir = options[DESTDIR].value;
} else {
o.targetDir = ".";
}
o.rebuild = options[REBUILD].doesOccur;
if( options[TEMPDIR].doesOccur ) {
o.tmpDir = options[TEMPDIR].value;
} else {
o.tmpDir = o.targetDir;
}
if( options[INSTALL].doesOccur ) {
o.install = options[INSTALL].value;
} else {
o.install = NULL;
}
if( options[SOURCEDIR].doesOccur ) {
o.srcDir = options[SOURCEDIR].value;
} else {
o.srcDir = ".";
}
if( options[ENTRYPOINT].doesOccur ) {
o.entryName = options[ENTRYPOINT].value;
} else {
o.entryName = o.cShortName;
}
tail = NULL;
for( n=1; n<argc; n++) {
o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
}
loadLists(&o, &status);
if( U_FAILURE(status) ) {
fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
return 2;
}
result = pkg_executeOptions(&o);
if (pkgDataFlags != NULL) {
for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
if (pkgDataFlags[n] != NULL) {
uprv_free(pkgDataFlags[n]);
}
}
uprv_free(pkgDataFlags);
}
if (o.cShortName != NULL) {
uprv_free((char *)o.cShortName);
}
if (o.fileListFiles != NULL) {
pkg_deleteList(o.fileListFiles);
}
if (o.filePaths != NULL) {
pkg_deleteList(o.filePaths);
}
if (o.files != NULL) {
pkg_deleteList(o.files);
}
return result;
}
static int runCommand(const char* command, UBool specialHandling) {
char *cmd = NULL;
char cmdBuffer[SMALL_BUFFER_MAX_SIZE];
int32_t len = strlen(command);
if (len == 0) {
return 0;
}
if (!specialHandling) {
#if defined(USING_CYGWIN) || defined(OS400)
if ((len + BUFFER_PADDING_SIZE) >= SMALL_BUFFER_MAX_SIZE) {
cmd = (char *)uprv_malloc(len + BUFFER_PADDING_SIZE);
} else {
cmd = cmdBuffer;
}
#ifdef USING_CYGWIN
sprintf(cmd, "bash -c \"%s\"", command);
#elif defined(OS400)
sprintf(cmd, "QSH CMD('%s')", command);
#endif
#else
goto normal_command_mode;
#endif
} else {
normal_command_mode:
cmd = (char *)command;
}
printf("pkgdata: %s\n", cmd);
int result = system(cmd);
if (result != 0) {
printf("-- return status = %d\n", result);
}
if (cmd != cmdBuffer && cmd != command) {
uprv_free(cmd);
}
return result;
}
#define LN_CMD "ln -s"
#define RM_CMD "rm -f"
#define MODE_COMMON 'c'
#define MODE_STATIC 's'
#define MODE_DLL 'd'
#define MODE_FILES 'f'
static int32_t pkg_executeOptions(UPKGOptions *o) {
int32_t result = 0;
const char mode = o->mode[0];
char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
initializePkgDataFlags(o);
if (mode == MODE_FILES) {
if (o->install != NULL) {
uprv_strcpy(targetDir, o->install);
if (o->shortName != NULL) {
uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
uprv_strcat(targetDir, o->shortName);
}
if(o->verbose) {
fprintf(stdout, "# Install: Files mode, copying files to %s..\n", targetDir);
}
result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
}
return result;
} else {
uprv_strcpy(targetDir, o->targetDir);
uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
uprv_strcpy(tmpDir, o->tmpDir);
uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
uprv_strcpy(datFileNamePath, tmpDir);
uprv_strcpy(datFileName, o->shortName);
uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
uprv_strcat(datFileNamePath, datFileName);
if(o->verbose) {
fprintf(stdout, "# Writing package file %s ..\n", datFileNamePath);
}
result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_CHARSET_FAMILY ? 'e' : U_IS_BIG_ENDIAN ? 'b' : 'l');
if (result != 0) {
fprintf(stderr,"Error writing package dat file.\n");
return result;
}
if (mode == MODE_COMMON) {
char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
uprv_strcpy(targetFileNamePath, targetDir);
uprv_strcat(targetFileNamePath, datFileName);
if (T_FileStream_file_exists(targetFileNamePath)) {
if ((result = remove(targetFileNamePath)) != 0) {
fprintf(stderr, "Unable to remove old dat file: %s\n", targetFileNamePath);
return result;
}
}
result = rename(datFileNamePath, targetFileNamePath);
if(o->verbose) {
fprintf(stdout, "# Moving package file to %s ..\n", targetFileNamePath);
}
if (result != 0) {
fprintf(stderr, "Unable to move dat file (%s) to target location (%s).\n", datFileNamePath, targetFileNamePath);
}
if (o->install != NULL) {
result = pkg_installCommonMode(o->install, targetFileNamePath);
}
return result;
} else {
char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
char version_major[10] = "";
UBool reverseExt = FALSE;
#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
if (o->version != NULL) {
for (uint32_t i = 0;i < sizeof(version_major);i++) {
if (o->version[i] == '.') {
version_major[i] = 0;
break;
}
version_major[i] = o->version[i];
}
}
#ifndef OS400
if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
reverseExt = TRUE;
}
#endif
createFileNames(o, mode, version_major, o->version, o->libName, reverseExt);
if ((o->version!=NULL || (mode==MODE_STATIC)) && o->rebuild == FALSE) {
sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]);
if (T_FileStream_file_exists(checkLibFile)) {
if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) {
if (o->install != NULL) {
if(o->verbose) {
fprintf(stdout, "# Installing already-built library into %s\n", o->install);
}
result = pkg_installLibrary(o->install, targetDir);
} else {
if(o->verbose) {
printf("# Not rebuilding %s - up to date.\n", checkLibFile);
}
}
return result;
} else if (o->verbose && (o->install!=NULL)) {
fprintf(stdout, "# Not installing up-to-date library %s into %s\n", checkLibFile, o->install);
}
} else if(o->verbose && (o->install!=NULL)) {
fprintf(stdout, "# Not installing missing %s into %s\n", checkLibFile, o->install);
}
}
pkg_checkFlag(o);
#endif
if (pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
if(o->verbose) {
fprintf(stdout, "# Generating assembly code %s of type %s ..\n", gencFilePath, genccodeAssembly);
}
if (genccodeAssembly &&
(uprv_strlen(genccodeAssembly)>3) &&
checkAssemblyHeaderName(genccodeAssembly+3)) {
writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath);
result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
if (result != 0) {
fprintf(stderr, "Error generating assembly code for data.\n");
return result;
} else if (mode == MODE_STATIC) {
if(o->install != NULL) {
if(o->verbose) {
fprintf(stdout, "# Installing static library into %s\n", o->install);
}
result = pkg_installLibrary(o->install, targetDir);
}
return result;
}
} else {
fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
return -1;
}
} else {
if(o->verbose) {
fprintf(stdout, "# Writing object code to %s ..\n", gencFilePath);
}
#ifdef CAN_WRITE_OBJ_CODE
writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
#ifdef U_LINUX
result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
#elif defined(WINDOWS_WITH_MSVC)
result = pkg_createWindowsDLL(mode, gencFilePath, o);
#endif
#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
#endif
if (result != 0) {
fprintf(stderr, "Error generating package data.\n");
return result;
}
}
#ifndef U_WINDOWS
if(mode != MODE_STATIC) {
if(o->verbose) {
fprintf(stdout, "# Creating data archive library file ..\n");
}
result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
if (result != 0) {
fprintf(stderr, "Error creating data archive library file.\n");
return result;
}
#ifndef OS400
result = pkg_createSymLinks(targetDir);
if (result != 0) {
fprintf(stderr, "Error creating symbolic links of the data library file.\n");
return result;
}
#endif
}
#endif
#if !defined(U_WINDOWS) || defined(USING_CYGWIN)
if (o->install != NULL) {
if(o->verbose) {
fprintf(stdout, "# Installing library file to %s ..\n", o->install);
}
result = pkg_installLibrary(o->install, targetDir);
if (result != 0) {
fprintf(stderr, "Error installing the data library.\n");
return result;
}
}
#endif
}
}
return result;
}
static int32_t initializePkgDataFlags(UPKGOptions *o) {
UErrorCode status = U_ZERO_ERROR;
int32_t result = 0;
int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE;
int32_t tmpResult = 0;
pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
do {
#endif
if (pkgDataFlags != NULL) {
for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize);
if (pkgDataFlags[i] != NULL) {
pkgDataFlags[i][0] = 0;
} else {
fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
return -1;
}
}
} else {
fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
return -1;
}
if (o->options == NULL) {
return result;
}
#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
if(o->verbose) {
fprintf(stdout, "# Reading options file %s\n", o->options);
}
status = U_ZERO_ERROR;
tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, (int32_t)PKGDATA_FLAGS_SIZE, &status);
if (status == U_BUFFER_OVERFLOW_ERROR) {
for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
uprv_free(pkgDataFlags[i]);
}
currentBufferSize = tmpResult;
} else if (U_FAILURE(status)) {
fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status));
return -1;
}
#endif
if(o->verbose) {
fprintf(stdout, "# pkgDataFlags=");
for(int32_t i=0;i<PKGDATA_FLAGS_SIZE && pkgDataFlags[i][0];i++) {
fprintf(stdout, "%c \"%s\"", (i>0)?',':' ',pkgDataFlags[i]);
}
fprintf(stdout, "\n");
}
#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
} while (status == U_BUFFER_OVERFLOW_ERROR);
#endif
return result;
}
static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt) {
sprintf(libFileNames[LIB_FILE], "%s%s",
pkgDataFlags[LIBPREFIX],
libName);
if(o->verbose) {
fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]);
}
if (version != NULL) {
#ifdef U_CYGWIN
sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s.%s",
libName,
pkgDataFlags[SO_EXT]);
sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s.%s",
libName,
version_major,
pkgDataFlags[SO_EXT]);
uprv_strcat(pkgDataFlags[SO_EXT], ".");
uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
#elif defined(OS400) || defined(_AIX)
sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s",
libFileNames[LIB_FILE],
pkgDataFlags[SOBJ_EXT]);
#else
sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
libFileNames[LIB_FILE],
pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
reverseExt ? version : pkgDataFlags[SOBJ_EXT],
reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
#endif
sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s",
libFileNames[LIB_FILE],
pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
reverseExt ? version_major : pkgDataFlags[SO_EXT],
reverseExt ? pkgDataFlags[SO_EXT] : version_major);
sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
libFileNames[LIB_FILE],
pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
reverseExt ? version : pkgDataFlags[SO_EXT],
reverseExt ? pkgDataFlags[SO_EXT] : version);
if(o->verbose) {
fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]);
}
#ifdef U_CYGWIN
uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
#endif
}
if(mode == MODE_STATIC) {
sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]);
libFileNames[LIB_FILE_VERSION_MAJOR][0]=0;
if(o->verbose) {
fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames[LIB_FILE_VERSION]);
}
}
}
static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) {
int32_t result = 0;
char cmd[LARGE_BUFFER_MAX_SIZE];
char name1[SMALL_BUFFER_MAX_SIZE];
char name2[SMALL_BUFFER_MAX_SIZE];
#ifndef USING_CYGWIN
if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 ||
uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
return result;
}
sprintf(cmd, "cd %s && %s %s && %s %s %s",
targetDir,
RM_CMD,
libFileNames[LIB_FILE_VERSION_MAJOR],
LN_CMD,
libFileNames[LIB_FILE_VERSION],
libFileNames[LIB_FILE_VERSION_MAJOR]);
result = runCommand(cmd);
if (result != 0) {
return result;
}
#endif
if (specialHandling) {
#ifdef U_CYGWIN
sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]);
sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
#else
goto normal_symlink_mode;
#endif
} else {
normal_symlink_mode:
sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]);
sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
}
sprintf(cmd, "cd %s && %s %s && %s %s %s",
targetDir,
RM_CMD,
name1,
LN_CMD,
name2,
name1);
result = runCommand(cmd);
return result;
}
static int32_t pkg_installLibrary(const char *installDir, const char *targetDir) {
int32_t result = 0;
char cmd[SMALL_BUFFER_MAX_SIZE];
sprintf(cmd, "cd %s && %s %s %s%s%s",
targetDir,
pkgDataFlags[INSTALL_CMD],
libFileNames[LIB_FILE_VERSION],
installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
);
result = runCommand(cmd);
if (result != 0) {
return result;
}
#ifdef CYGWINMSVC
sprintf(cmd, "cd %s && %s %s.lib %s",
targetDir,
pkgDataFlags[INSTALL_CMD],
libFileNames[LIB_FILE],
installDir
);
result = runCommand(cmd);
if (result != 0) {
return result;
}
#elif defined (U_CYGWIN)
sprintf(cmd, "cd %s && %s %s %s",
targetDir,
pkgDataFlags[INSTALL_CMD],
libFileNames[LIB_FILE_CYGWIN_VERSION],
installDir
);
result = runCommand(cmd);
if (result != 0) {
return result;
}
#endif
return pkg_createSymLinks(installDir, TRUE);
}
static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) {
int32_t result = 0;
char cmd[SMALL_BUFFER_MAX_SIZE] = "";
if (!T_FileStream_file_exists(installDir)) {
UErrorCode status = U_ZERO_ERROR;
uprv_mkdir(installDir, &status);
if (U_FAILURE(status)) {
fprintf(stderr, "Error creating installation directory: %s\n", installDir);
return -1;
}
}
#ifndef U_WINDOWS_WITH_MSVC
sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir);
#else
sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS);
#endif
result = runCommand(cmd);
if (result != 0) {
fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
}
return result;
}
#ifdef U_WINDOWS_MSVC
#define WIN_INSTALL_CMD "xcopy"
#define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
#endif
static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
int32_t result = 0;
char cmd[SMALL_BUFFER_MAX_SIZE] = "";
if (!T_FileStream_file_exists(installDir)) {
UErrorCode status = U_ZERO_ERROR;
uprv_mkdir(installDir, &status);
if (U_FAILURE(status)) {
fprintf(stderr, "Error creating installation directory: %s\n", installDir);
return -1;
}
}
#ifndef U_WINDOWS_WITH_MSVC
char buffer[SMALL_BUFFER_MAX_SIZE] = "";
FileStream *f = T_FileStream_open(fileListName, "r");
if (f != NULL) {
for(;;) {
if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
buffer[uprv_strlen(buffer)-1] = 0;
sprintf(cmd, "%s %s%s%s %s%s%s",
pkgDataFlags[INSTALL_CMD],
srcDir, PKGDATA_FILE_SEP_STRING, buffer,
installDir, PKGDATA_FILE_SEP_STRING, buffer);
result = runCommand(cmd);
if (result != 0) {
fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
break;
}
} else {
if (!T_FileStream_eof(f)) {
fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
result = -1;
}
break;
}
}
T_FileStream_close(f);
} else {
result = -1;
fprintf(stderr, "Unable to open list file: %s\n", fileListName);
}
#else
sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
result = runCommand(cmd);
if (result != 0) {
fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
}
#endif
return result;
}
static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
int32_t result = 0;
char cmd[LARGE_BUFFER_MAX_SIZE];
if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
libFileNames[LIB_FILE],
pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
reverseExt ? version : pkgDataFlags[SO_EXT],
reverseExt ? pkgDataFlags[SO_EXT] : version);
sprintf(cmd, "%s %s %s%s %s%s",
pkgDataFlags[AR],
pkgDataFlags[ARFLAGS],
targetDir,
libFileNames[LIB_FILE_VERSION],
targetDir,
libFileNames[LIB_FILE_VERSION_TMP]);
result = runCommand(cmd);
if (result != 0) {
return result;
}
sprintf(cmd, "%s %s%s",
pkgDataFlags[RANLIB],
targetDir,
libFileNames[LIB_FILE_VERSION]);
result = runCommand(cmd);
if (result != 0) {
return result;
}
sprintf(cmd, "%s %s%s",
RM_CMD,
targetDir,
libFileNames[LIB_FILE_VERSION_TMP]);
result = runCommand(cmd);
if (result != 0) {
return result;
}
} else {
uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
}
return result;
}
static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) {
int32_t result = 0;
char *cmd = NULL;
UBool freeCmd = FALSE;
int32_t length = 0;
if (command != NULL) {
cmd = command;
}
if (mode == MODE_STATIC) {
if (cmd == NULL) {
length = uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) +
uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE;
if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
fprintf(stderr, "Unable to allocate memory for command.\n");
return -1;
}
freeCmd = TRUE;
}
sprintf(cmd, "%s %s %s%s %s",
pkgDataFlags[AR],
pkgDataFlags[ARFLAGS],
targetDir,
libFileNames[LIB_FILE_VERSION],
objectFile);
result = runCommand(cmd);
if (result == 0) {
sprintf(cmd, "%s %s%s",
pkgDataFlags[RANLIB],
targetDir,
libFileNames[LIB_FILE_VERSION]);
result = runCommand(cmd);
}
} else {
if (cmd == NULL) {
length = uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) +
uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP]) +
uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) +
uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) +
uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE;
#ifdef U_CYGWIN
length += uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]);
#endif
if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
fprintf(stderr, "Unable to allocate memory for command.\n");
return -1;
}
freeCmd = TRUE;
}
#ifdef U_CYGWIN
sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
pkgDataFlags[GENLIB],
targetDir,
libFileNames[LIB_FILE_VERSION_TMP],
pkgDataFlags[LDICUDTFLAGS],
targetDir, libFileNames[LIB_FILE_CYGWIN_VERSION],
#else
sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
pkgDataFlags[GENLIB],
pkgDataFlags[LDICUDTFLAGS],
targetDir,
libFileNames[LIB_FILE_VERSION_TMP],
#endif
objectFile,
pkgDataFlags[LD_SONAME],
pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
pkgDataFlags[RPATH_FLAGS],
pkgDataFlags[BIR_FLAGS]);
result = runCommand(cmd);
}
if (freeCmd) {
uprv_free(cmd);
}
return result;
}
static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
char *cmd;
int32_t result = 0;
int32_t length = 0;
uprv_strcpy(tempObjectFile, gencFilePath);
tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
+ uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE;
cmd = (char *)uprv_malloc(sizeof(char) * length);
if (cmd == NULL) {
return -1;
}
sprintf(cmd, "%s %s -o %s %s",
pkgDataFlags[COMPILER],
pkgDataFlags[LIBFLAGS],
tempObjectFile,
gencFilePath);
result = runCommand(cmd);
uprv_free(cmd);
if (result != 0) {
return result;
}
return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
}
#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
enum {
DATA_PREFIX_BRKITR,
DATA_PREFIX_COLL,
DATA_PREFIX_CURR,
DATA_PREFIX_LANG,
DATA_PREFIX_RBNF,
DATA_PREFIX_REGION,
DATA_PREFIX_TRANSLIT,
DATA_PREFIX_ZONE,
DATA_PREFIX_LENGTH
};
const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
"brkitr",
"coll",
"curr",
"lang",
"rbnf",
"region",
"translit",
"zone"
};
static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
int32_t result = 0;
CharList *list = o->filePaths;
CharList *listNames = o->files;
int32_t listSize = pkg_countCharList(list);
char *buffer;
char *cmd;
char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
#ifdef USE_SINGLE_CCODE_FILE
char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
sprintf(icudtAll, "%s%s%sall.c",
o->tmpDir,
PKGDATA_FILE_SEP_STRING,
libFileNames[LIB_FILE]);
if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
return result;
}
#endif
if (list == NULL || listNames == NULL) {
return -1;
}
if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
fprintf(stderr, "Unable to allocate memory for cmd.\n");
return -1;
} else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
fprintf(stderr, "Unable to allocate memory for buffer.\n");
uprv_free(cmd);
return -1;
}
for (int32_t i = 0; i < (listSize + 1); i++) {
const char *file ;
const char *name;
if (i == 0) {
createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
buffer[0] = 0;
#ifdef USE_SINGLE_CCODE_FILE
uprv_strcpy(tempObjectFile, gencmnFile);
tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
sprintf(cmd, "%s %s -o %s %s"
pkgDataFlags[COMPILER],
pkgDataFlags[LIBFLAGS],
tempObjectFile,
gencmnFile);
result = runCommand(cmd);
if (result != 0) {
break;
}
sprintf(buffer, "%s",tempObjectFile);
#endif
} else {
char newName[SMALL_BUFFER_MAX_SIZE];
char dataName[SMALL_BUFFER_MAX_SIZE];
char dataDirName[SMALL_BUFFER_MAX_SIZE];
const char *pSubstring;
file = list->str;
name = listNames->str;
newName[0] = dataName[0] = 0;
for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
dataDirName[0] = 0;
sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
pSubstring = uprv_strstr(name, dataDirName);
if (pSubstring != NULL) {
char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
const char *p = name + uprv_strlen(dataDirName);
for (int32_t i = 0;;i++) {
if (p[i] == '.') {
newNameTmp[i] = '_';
continue;
}
newNameTmp[i] = p[i];
if (p[i] == 0) {
break;
}
}
sprintf(newName, "%s_%s",
DATA_PREFIX[n],
newNameTmp);
sprintf(dataName, "%s_%s",
o->shortName,
DATA_PREFIX[n]);
}
if (newName[0] != 0) {
break;
}
}
writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
#ifdef USE_SINGLE_CCODE_FILE
sprintf(cmd, "cat %s >> %s", gencmnFile, icudtAll);
result = runCommand(cmd);
if (result != 0) {
break;
} else {
if ((result = remove(gencmnFile)) != 0) {
fprintf(stderr, "Unable to remove c code file: %s\n", gencmnFile);
return result;
}
}
#endif
}
#ifndef USE_SINGLE_CCODE_FILE
uprv_strcpy(tempObjectFile, gencmnFile);
tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
sprintf(cmd, "%s %s -o %s %s",
pkgDataFlags[COMPILER],
pkgDataFlags[LIBFLAGS],
tempObjectFile,
gencmnFile);
result = runCommand(cmd);
if (result != 0) {
break;
}
uprv_strcat(buffer, " ");
uprv_strcat(buffer, tempObjectFile);
#endif
if (i > 0) {
list = list->next;
listNames = listNames->next;
}
}
#ifdef USE_SINGLE_CCODE_FILE
uprv_strcpy(tempObjectFile, icudtAll);
tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
sprintf(cmd, "%s %s -o %s %s",
pkgDataFlags[COMPILER],
pkgDataFlags[LIBFLAGS],
tempObjectFile,
icudtAll);
result = runCommand(cmd);
if (result == 0) {
uprv_strcat(buffer, " ");
uprv_strcat(buffer, tempObjectFile);
}
#endif
if (result == 0) {
result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd);
}
uprv_free(buffer);
uprv_free(cmd);
return result;
}
#endif
#ifdef WINDOWS_WITH_MSVC
#define LINK_CMD "link.exe /nologo /release /out:"
#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:"
#define LIB_CMD "LIB.exe /nologo /out:"
#define LIB_FILE "icudt.lib"
#define LIB_EXT UDATA_LIB_SUFFIX
#define DLL_EXT UDATA_SO_SUFFIX
static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
char cmd[LARGE_BUFFER_MAX_SIZE];
if (mode == MODE_STATIC) {
char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
uprv_strcpy(staticLibFilePath, o->tmpDir);
uprv_strcat(staticLibFilePath, PKGDATA_FILE_SEP_STRING);
uprv_strcat(staticLibFilePath, o->entryName);
uprv_strcat(staticLibFilePath, LIB_EXT);
sprintf(cmd, "%s\"%s\" \"%s\"",
LIB_CMD,
staticLibFilePath,
gencFilePath);
} else if (mode == MODE_DLL) {
char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
#ifdef CYGWINMSVC
uprv_strcpy(dllFilePath, o->targetDir);
#else
uprv_strcpy(dllFilePath, o->srcDir);
#endif
uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
uprv_strcpy(libFilePath, dllFilePath);
#ifdef CYGWINMSVC
uprv_strcat(libFilePath, o->libName);
uprv_strcat(libFilePath, ".lib");
uprv_strcat(dllFilePath, o->libName);
uprv_strcat(dllFilePath, o->version);
#else
if (strstr(o->libName, "icudt")) {
uprv_strcat(libFilePath, LIB_FILE);
} else {
uprv_strcat(libFilePath, o->libName);
uprv_strcat(libFilePath, ".lib");
}
uprv_strcat(dllFilePath, o->entryName);
#endif
uprv_strcat(dllFilePath, DLL_EXT);
uprv_strcpy(tmpResFilePath, o->tmpDir);
uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
if (T_FileStream_file_exists(tmpResFilePath)) {
sprintf(resFilePath, "\"%s\"", tmpResFilePath);
}
if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
(T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
if(o->verbose) {
printf("# Not rebuilding %s - up to date.\n", gencFilePath);
}
return 0;
}
sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" %s",
LINK_CMD,
dllFilePath,
LINK_FLAGS,
libFilePath,
gencFilePath,
resFilePath
);
}
return runCommand(cmd, TRUE);
}
#endif
static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
#ifdef U_AIX
char *flag = NULL;
int32_t length = 0;
char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
const char MAP_FILE_EXT[] = ".map";
FileStream *f = NULL;
char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
int32_t start = -1;
int32_t count = 0;
flag = pkgDataFlags[BIR_FLAGS];
length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
for (int32_t i = 0; i < length; i++) {
if (flag[i] == MAP_FILE_EXT[count]) {
if (count == 0) {
start = i;
}
count++;
} else {
count = 0;
}
if (count == uprv_strlen(MAP_FILE_EXT)) {
break;
}
}
if (start >= 0) {
int32_t index = 0;
for (int32_t i = 0;;i++) {
if (i == start) {
for (int32_t n = 0;;n++) {
if (o->shortName[n] == 0) {
break;
}
tmpbuffer[index++] = o->shortName[n];
}
}
tmpbuffer[index++] = flag[i];
if (flag[i] == 0) {
break;
}
}
uprv_memset(flag, 0, length);
uprv_strcpy(flag, tmpbuffer);
uprv_strcpy(mapFile, o->shortName);
uprv_strcat(mapFile, MAP_FILE_EXT);
f = T_FileStream_open(mapFile, "w");
if (f == NULL) {
fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
} else {
sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
T_FileStream_writeLine(f, tmpbuffer);
T_FileStream_close(f);
}
}
#elif defined(U_CYGWIN)
char *flag = NULL;
int32_t length = 0;
flag = pkgDataFlags[GENLIB];
length = uprv_strlen(pkgDataFlags[GENLIB]);
int32_t position = length - 1;
for(;position >= 0;position--) {
if (flag[position] == '=') {
position++;
break;
}
}
uprv_memset(flag + position, 0, length - position);
#elif defined(OS400)
char *flag = NULL;
int32_t length = 0;
flag = pkgDataFlags[GENLIB];
length = uprv_strlen(pkgDataFlags[GENLIB]);
int32_t position = length - 1;
for(int32_t i = 0; i < length; i++) {
if (flag[i] == '\'') {
flag[i] = '\"';
}
}
#endif
return o;
}
static void loadLists(UPKGOptions *o, UErrorCode *status)
{
CharList *l, *tail = NULL, *tail2 = NULL;
FileStream *in;
char line[16384];
char *linePtr, *lineNext;
const uint32_t lineMax = 16300;
char tmp[1024];
char *s;
int32_t ln=0;
for(l = o->fileListFiles; l; l = l->next) {
if(o->verbose) {
fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
}
in = T_FileStream_open(l->str, "r");
if(!in) {
fprintf(stderr, "Error opening <%s>.\n", l->str);
*status = U_FILE_ACCESS_ERROR;
return;
}
while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) {
ln++;
if(uprv_strlen(line)>lineMax) {
fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
exit(1);
}
linePtr = line;
while(isspace(*linePtr)) {
linePtr++;
}
s=linePtr;
while(*s!=0) {
if(*s=='\r' || *s=='\n') {
*s=0;
break;
}
++s;
}
if((*linePtr == 0) || (*linePtr == '#')) {
continue;
}
lineNext = NULL;
while(linePtr && *linePtr) {
while(*linePtr == ' ') {
linePtr++;
}
if(linePtr[0] == '"')
{
lineNext = uprv_strchr(linePtr+1, '"');
if(lineNext == NULL) {
fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
l->str, (int)ln);
exit(1);
} else {
lineNext++;
if(*lineNext) {
if(*lineNext != ' ') {
fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
exit(1);
}
*lineNext = 0;
lineNext++;
}
}
} else {
lineNext = uprv_strchr(linePtr, ' ');
if(lineNext) {
*lineNext = 0;
lineNext++;
}
}
s = (char*)getLongPathname(linePtr);
o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
if(uprv_pathIsAbsolute(s)) {
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);
exit(U_ILLEGAL_ARGUMENT_ERROR);
}
uprv_strcpy(tmp, o->srcDir);
uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" :PKGDATA_FILE_SEP_STRING);
uprv_strcat(tmp, s);
o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
linePtr = lineNext;
}
}
T_FileStream_close(in);
}
}
static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
#if U_HAVE_POPEN
FILE *p = NULL;
size_t n;
static char buf[512] = "";
char cmdBuf[1024];
UErrorCode status = U_ZERO_ERROR;
const char cmd[] = "icu-config --incpkgdatafile";
findDirname(progname, cmdBuf, 1024, &status);
if(U_SUCCESS(status)) {
uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024);
uprv_strncat(cmdBuf, cmd, 1024);
if(verbose) {
fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf);
}
p = popen(cmdBuf, "r");
}
if(p == NULL) {
if(verbose) {
fprintf(stdout, "# Calling icu-config: %s\n", cmd);
}
p = popen(cmd, "r");
}
if(p == NULL)
{
fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
return -1;
}
n = fread(buf, 1, 511, p);
pclose(p);
if(n<=0)
{
fprintf(stderr,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname);
return -1;
}
for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
if (buf[length] == '\n' || buf[length] == ' ') {
buf[length] = 0;
} else {
break;
}
}
if(buf[strlen(buf)-1]=='\n')
{
buf[strlen(buf)-1]=0;
}
if(buf[0] == 0)
{
fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
return -1;
}
if(verbose) {
fprintf(stdout, "# icu-config said: %s\n", buf);
}
option->value = buf;
option->doesOccur = TRUE;
return 0;
#endif
return -1;
}