]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/pkgdata/pkgdata.cpp
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / tools / pkgdata / pkgdata.cpp
index f33a639fb16ddaf2d45d17d80a137c3f564989e3..8b99f75b0203b0c8b902785f54e5034c57f64a19 100644 (file)
@@ -1,5 +1,5 @@
 /******************************************************************************
- *   Copyright (C) 2000-2013, International Business Machines
+ *   Copyright (C) 2000-2016, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  *******************************************************************************
  *   file name:  pkgdata.cpp
@@ -43,6 +43,7 @@
 #include "pkg_gencmn.h"
 #include "flagparser.h"
 #include "filetools.h"
+#include "charstr.h"
 
 #if U_HAVE_POPEN
 # include <unistd.h>
@@ -55,6 +56,13 @@ U_CDECL_BEGIN
 #include "pkgtypes.h"
 U_CDECL_END
 
+#if U_HAVE_POPEN
+
+using icu::LocalPointerBase;
+
+U_DEFINE_LOCAL_OPEN_POINTER(LocalPipeFilePointer, FILE, pclose);
+
+#endif
 
 static void loadLists(UPKGOptions *o, UErrorCode *status);
 
@@ -72,8 +80,13 @@ static int32_t pkg_installCommonMode(const char *installDir, const char *fileNam
 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
 #endif
 
+#ifdef CAN_WRITE_OBJ_CODE
+static void pkg_createOptMatchArch(char *optMatchArch);
+static void pkg_destroyOptMatchArch(char *optMatchArch);
+#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_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL, UBool specialHandling=FALSE);
 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, UBool noVersion);
 static int32_t initializePkgDataFlags(UPKGOptions *o);
@@ -203,6 +216,9 @@ enum {
     LIB_FILE_CYGWIN_VERSION,
 #elif U_PLATFORM == U_PF_MINGW
     LIB_FILE_MINGW,
+#elif U_PLATFORM == U_PF_OS390
+    LIB_FILE_OS390BATCH_MAJOR,
+    LIB_FILE_OS390BATCH_VERSION,
 #endif
     LIB_FILENAMES_SIZE
 };
@@ -233,7 +249,8 @@ const char options_help[][320]={
     "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)",
-    "Build the data without assembly code"
+    "Build the data without assembly code",
+    "Build PDS dataset (zOS build only)"
 };
 
 const char  *progname = "PKGDATA";
@@ -257,7 +274,7 @@ main(int argc, char* argv[]) {
     options[MODE].value = "common";
 
     /* read command line options */
-    argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
+    argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options);
 
     /* error handling, printing usage message */
     /* I've decided to simply print an error and quit. This tool has too
@@ -315,7 +332,7 @@ main(int argc, char* argv[]) {
             progname);
 
         fprintf(stderr, "\n options:\n");
-        for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
+        for(i=0;i<UPRV_LENGTHOF(options);i++) {
             fprintf(stderr, "%-5s -%c %s%-10s  %s\n",
                 (i<1?"[REQ]":""),
                 options[i].shortName,
@@ -325,7 +342,7 @@ main(int argc, char* argv[]) {
         }
 
         fprintf(stderr, "modes: (-m option)\n");
-        for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
+        for(i=0;i<UPRV_LENGTHOF(modes);i++) {
             fprintf(stderr, "   %-9s ", modes[i].name);
             if (modes[i].alt_name) {
                 fprintf(stderr, "/ %-9s", modes[i].alt_name);
@@ -374,7 +391,13 @@ main(int argc, char* argv[]) {
     }
 
     if(options[PDS_BUILD].doesOccur) {
+#if U_PLATFORM == U_PF_OS390
       o.pdsbuild = TRUE;
+#else
+      o.pdsbuild = FALSE;
+      fprintf(stdout, "Warning: You are using the -z option which only works on z/OS.\n");
+
+#endif
     } else {
       o.pdsbuild = FALSE;
     }
@@ -646,7 +669,7 @@ static int32_t pkg_executeOptions(UPKGOptions *o) {
             /* Using the base libName and version number, generate the library file names. */
             createFileNames(o, mode, version_major, o->version == NULL ? "" : o->version, o->libName, reverseExt, noVersion);
 
-            if ((o->version!=NULL || IN_STATIC_MODE(mode)) && o->rebuild == FALSE) {
+            if ((o->version!=NULL || IN_STATIC_MODE(mode)) && o->rebuild == FALSE && o->pdsbuild == FALSE) {
                 /* Check to see if a previous built data library file exists and check if it is the latest. */
                 sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]);
                 if (T_FileStream_file_exists(checkLibFile)) {
@@ -719,7 +742,11 @@ static int32_t pkg_executeOptions(UPKGOptions *o) {
 #endif
                 } else {
 #ifdef CAN_WRITE_OBJ_CODE
-                    writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
+                    /* Try to detect the arch type, use NULL if unsuccessful */
+                    char optMatchArch[10] = { 0 };
+                    pkg_createOptMatchArch(optMatchArch);
+                    writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, (optMatchArch[0] == 0 ? NULL : optMatchArch), NULL, gencFilePath);
+                    pkg_destroyOptMatchArch(optMatchArch);
 #if U_PLATFORM_IS_LINUX_BASED
                     result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
 #elif defined(WINDOWS_WITH_MSVC)
@@ -753,9 +780,7 @@ static int32_t pkg_executeOptions(UPKGOptions *o) {
                 if (!noVersion) {
                     /* Create symbolic links for the final library file. */
 #if U_PLATFORM == U_PF_OS390
-                    if (!o->pdsbuild) {
-                        result = pkg_createSymLinks(targetDir, noVersion);
-                    }
+                    result = pkg_createSymLinks(targetDir, o->pdsbuild);
 #else
                     result = pkg_createSymLinks(targetDir, noVersion);
 #endif
@@ -807,6 +832,10 @@ static int32_t initializePkgDataFlags(UPKGOptions *o) {
                     pkgDataFlags[i][0] = 0;
                 } else {
                     fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
+                    /* If an error occurs, ensure that the rest of the array is NULL */
+                    for (int32_t n = i + 1; n < PKGDATA_FLAGS_SIZE; n++) {
+                        pkgDataFlags[n] = NULL;
+                    }
                     return -1;
                 }
             }
@@ -828,7 +857,10 @@ static int32_t initializePkgDataFlags(UPKGOptions *o) {
         tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, FLAG_NAMES, (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]);
+                if (pkgDataFlags[i]) {
+                    uprv_free(pkgDataFlags[i]);
+                    pkgDataFlags[i] = NULL;
+                }
             }
             currentBufferSize = tmpResult;
         } else if (U_FAILURE(status)) {
@@ -856,6 +888,9 @@ static int32_t initializePkgDataFlags(UPKGOptions *o) {
  * Depending on the configuration, the library name may either end with version number or shared object suffix.
  */
 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt, UBool noVersion) {
+    const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
+    const char* FILE_SUFFIX = pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "";
+
 #if U_PLATFORM == U_PF_MINGW
         /* MinGW does not need the library prefix when building in dll mode. */
         if (IN_DLL_MODE(mode)) {
@@ -876,70 +911,78 @@ static void createFileNames(UPKGOptions *o, const char mode, const char *version
         }
 
 #if U_PLATFORM == U_PF_MINGW
-        sprintf(libFileNames[LIB_FILE_MINGW], "%s%s.lib", pkgDataFlags[LIBPREFIX], libName);
+        // Name the import library lib*.dll.a
+        sprintf(libFileNames[LIB_FILE_MINGW], "lib%s.dll.a", libName);
 #elif U_PLATFORM == U_PF_CYGWIN
-        sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s.%s",
+        sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s%s%s",
                 libName,
+                FILE_EXTENSION_SEP,
                 pkgDataFlags[SO_EXT]);
-        sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s.%s",
+        sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s%s%s",
                 libName,
                 version_major,
+                FILE_EXTENSION_SEP,
                 pkgDataFlags[SO_EXT]);
 
         uprv_strcat(pkgDataFlags[SO_EXT], ".");
         uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
-        sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s",
+        sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
                 libFileNames[LIB_FILE],
+                FILE_EXTENSION_SEP,
                 pkgDataFlags[SOBJ_EXT]);
-#elif U_PLATFROM == U_PF_OS390
-            if (o->pdsbuild) {
-                sprintf(libFileNames[LIB_FILE], "%s",
-                    libName);
-                sprintf(libFileNames[LIB_FILE_VERSION_TMP], "\"%s\"",
-                        libFileNames[LIB_FILE]);
-            } 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);
-            }
+#elif U_PLATFORM == U_PF_OS390
+        sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s%s%s",
+                    libFileNames[LIB_FILE],
+                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    reverseExt ? version : pkgDataFlags[SOBJ_EXT],
+                    FILE_EXTENSION_SEP,
+                    reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
+
+        sprintf(libFileNames[LIB_FILE_OS390BATCH_VERSION], "%s%s.x",
+                    libFileNames[LIB_FILE],
+                    version);
+        sprintf(libFileNames[LIB_FILE_OS390BATCH_MAJOR], "%s%s.x",
+                    libFileNames[LIB_FILE],
+                    version_major);
 #else
         if (noVersion && !reverseExt) {
             sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
                     libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    FILE_SUFFIX,
                     pkgDataFlags[SOBJ_EXT]);
         } else {
-            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
+            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s%s%s",
                     libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    FILE_SUFFIX,
                     reverseExt ? version : pkgDataFlags[SOBJ_EXT],
+                    FILE_EXTENSION_SEP,
                     reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
         }
 #endif
         if (noVersion && !reverseExt) {
             sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s",
                     libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    FILE_SUFFIX,
                     pkgDataFlags[SO_EXT]);
 
             sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s",
                     libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    FILE_SUFFIX,
                     pkgDataFlags[SO_EXT]);
         } else {
-            sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s",
+            sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s%s%s",
                     libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    FILE_SUFFIX,
                     reverseExt ? version_major : pkgDataFlags[SO_EXT],
+                    FILE_EXTENSION_SEP,
                     reverseExt ? pkgDataFlags[SO_EXT] : version_major);
 
-            sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
+            sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s%s%s",
                     libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    FILE_SUFFIX,
                     reverseExt ? version : pkgDataFlags[SO_EXT],
+                    FILE_EXTENSION_SEP,
                     reverseExt ? pkgDataFlags[SO_EXT] : version);
         }
 
@@ -967,6 +1010,7 @@ static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling)
     char cmd[LARGE_BUFFER_MAX_SIZE];
     char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */
     char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */
+    const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
 
 #if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW
     /* No symbolic link to make. */
@@ -993,6 +1037,41 @@ static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling)
 #if U_PLATFORM == U_PF_CYGWIN
         sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]);
         sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
+#elif U_PLATFORM == U_PF_OS390
+        /* Create the symbolic links for the import data */
+        /* Use the cmd buffer to store path to import data file to check its existence */
+        sprintf(cmd, "%s/%s", targetDir, libFileNames[LIB_FILE_OS390BATCH_VERSION]);
+        if (T_FileStream_file_exists(cmd)) {
+            sprintf(cmd, "cd %s && %s %s && %s %s %s",
+                    targetDir,
+                    RM_CMD,
+                    libFileNames[LIB_FILE_OS390BATCH_MAJOR],
+                    LN_CMD,
+                    libFileNames[LIB_FILE_OS390BATCH_VERSION],
+                    libFileNames[LIB_FILE_OS390BATCH_MAJOR]);
+            result = runCommand(cmd);
+            if (result != 0) {
+                fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
+                return result;
+            }
+
+            sprintf(cmd, "cd %s && %s %s.x && %s %s %s.x",
+                    targetDir,
+                    RM_CMD,
+                    libFileNames[LIB_FILE],
+                    LN_CMD,
+                    libFileNames[LIB_FILE_OS390BATCH_VERSION],
+                    libFileNames[LIB_FILE]);
+            result = runCommand(cmd);
+            if (result != 0) {
+                fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
+                return result;
+            }
+        }
+
+        /* Needs to be set here because special handling skips it */
+        sprintf(name1, "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
+        sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
 #else
         goto normal_symlink_mode;
 #endif
@@ -1000,7 +1079,7 @@ static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling)
 #if U_PLATFORM != U_PF_CYGWIN
 normal_symlink_mode:
 #endif
-        sprintf(name1, "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]);
+        sprintf(name1, "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
         sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
     }
 
@@ -1061,6 +1140,21 @@ static int32_t pkg_installLibrary(const char *installDir, const char *targetDir,
         fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
         return result;
     }
+
+#elif U_PLATFORM == U_PF_OS390
+    if (T_FileStream_file_exists(libFileNames[LIB_FILE_OS390BATCH_VERSION])) {
+        sprintf(cmd, "%s %s %s",
+                pkgDataFlags[INSTALL_CMD],
+                libFileNames[LIB_FILE_OS390BATCH_VERSION],
+                installDir
+                );
+        result = runCommand(cmd);
+
+        if (result != 0) {
+            fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
+            return result;
+        }
+    }
 #endif
 
     if (noVersion) {
@@ -1228,12 +1322,15 @@ static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UB
  * Using the compiler information from the configuration file set by -O option, generate the library file.
  * command may be given to allow for a larger buffer for cmd.
  */
-static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) {
+static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command, UBool specialHandling) {
     int32_t result = 0;
     char *cmd = NULL;
     UBool freeCmd = FALSE;
     int32_t length = 0;
 
+    (void)specialHandling;  // Suppress unused variable compiler warnings on platforms where all usage
+                            // of this parameter is #ifdefed out.
+
     /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
      * containing many object files and so the calling function should supply a command buffer that is large
      * enough to handle this. Otherwise, use the default size.
@@ -1326,6 +1423,66 @@ static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, c
 
         /* Generate the library file. */
         result = runCommand(cmd);
+
+#if U_PLATFORM == U_PF_OS390
+        char *env_tmp;
+        char PDS_LibName[512];
+        char PDS_Name[512];
+
+        PDS_Name[0] = 0;
+        PDS_LibName[0] = 0;
+        if (specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) {
+            if (env_tmp = getenv("ICU_PDS_NAME")) {
+                sprintf(PDS_Name, "%s%s",
+                        env_tmp,
+                        "DA");
+                strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
+            } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
+                sprintf(PDS_Name, "%s%s",
+                        env_tmp,
+                        U_ICU_VERSION_SHORT "DA");
+            } else {
+                sprintf(PDS_Name, "%s%s",
+                        "IXMI",
+                        U_ICU_VERSION_SHORT "DA");
+            }
+        } else if (!specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) {
+            if (env_tmp = getenv("ICU_PDS_NAME")) {
+                sprintf(PDS_Name, "%s%s",
+                        env_tmp,
+                        "D1");
+                strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
+            } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
+                sprintf(PDS_Name, "%s%s",
+                        env_tmp,
+                        U_ICU_VERSION_SHORT "D1");
+            } else {
+                sprintf(PDS_Name, "%s%s",
+                        "IXMI",
+                        U_ICU_VERSION_SHORT "D1");
+            }
+        }
+
+        if (PDS_Name[0]) {
+            sprintf(PDS_LibName,"%s%s%s%s%s",
+                    "\"//'",
+                    getenv("LOADMOD"),
+                    "(",
+                    PDS_Name,
+                    ")'\"");
+            sprintf(cmd, "%s %s -o %s %s %s%s %s %s",
+                   pkgDataFlags[GENLIB],
+                   pkgDataFlags[LDICUDTFLAGS],
+                   PDS_LibName,
+                   objectFile,
+                   pkgDataFlags[LD_SONAME],
+                   pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
+                   pkgDataFlags[RPATH_FLAGS],
+                   pkgDataFlags[BIR_FLAGS]);
+
+            result = runCommand(cmd);
+        }
+#endif
     }
 
     if (result != 0) {
@@ -1390,6 +1547,7 @@ enum {
     DATA_PREFIX_REGION,
     DATA_PREFIX_TRANSLIT,
     DATA_PREFIX_ZONE,
+    DATA_PREFIX_UNIT,
     DATA_PREFIX_LENGTH
 };
 
@@ -1401,7 +1559,8 @@ const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
         "rbnf",
         "region",
         "translit",
-        "zone"
+        "zone",
+        "unit"
 };
 
 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
@@ -1575,11 +1734,7 @@ static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetD
     if (result == 0) {
         /* Generate the library file. */
 #if U_PLATFORM == U_PF_OS390
-        if (o->pdsbuild && IN_DLL_MODE(mode)) {
-            result = pkg_generateLibraryFile("",mode, buffer, cmd);
-        } else {
-            result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
-        }
+        result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd, (o->pdsbuild && IN_DLL_MODE(mode)));
 #else
         result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
 #endif
@@ -1947,42 +2102,40 @@ static void loadLists(UPKGOptions *o, UErrorCode *status)
 /* Try calling icu-config directly to get the option file. */
  static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
 #if U_HAVE_POPEN
-    FILE *p = NULL;
+    LocalPipeFilePointer p;
     size_t n;
     static char buf[512] = "";
-    char cmdBuf[1024];
+    icu::CharString cmdBuf;
     UErrorCode status = U_ZERO_ERROR;
     const char cmd[] = "icu-config --incpkgdatafile";
-
+    char dirBuf[1024] = "";
     /* #1 try the same path where pkgdata was called from. */
-    findDirname(progname, cmdBuf, 1024, &status);
+    findDirname(progname, dirBuf, UPRV_LENGTHOF(dirBuf), &status);
     if(U_SUCCESS(status)) {
+      cmdBuf.append(dirBuf, status);
       if (cmdBuf[0] != 0) {
-          uprv_strncat(cmdBuf, U_FILE_SEP_STRING, 1024);
+        cmdBuf.append( U_FILE_SEP_STRING, status );
       }
-      uprv_strncat(cmdBuf, cmd, 1024);
+      cmdBuf.append( cmd, status );
       
       if(verbose) {
-        fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf);
+        fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf.data());
       }
-      p = popen(cmdBuf, "r");
+      p.adoptInstead(popen(cmdBuf.data(), "r"));
     }
 
-    if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) {
-      if(verbose) {
-        fprintf(stdout, "# Calling icu-config: %s\n", cmd);
-      }
-      pclose(p);
+    if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) {
+        if(verbose) {
+            fprintf(stdout, "# Calling icu-config: %s\n", cmd);
+        }
 
-      p = popen(cmd, "r");
-      if(p == NULL || (n = fread(buf, 1, 511, p)) <= 0) {
-          fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
-          return -1;
-      }
+        p.adoptInstead(popen(cmd, "r"));
+        if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) {
+            fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
+            return -1;
+        }
     }
 
-    pclose(p);
-
     for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
         if (buf[length] == '\n' || buf[length] == ' ') {
             buf[length] = 0;
@@ -2014,3 +2167,45 @@ static void loadLists(UPKGOptions *o, UErrorCode *status)
     return -1;
 #endif
 }
+
+#ifdef CAN_WRITE_OBJ_CODE
+ /* Create optMatchArch for genccode architecture detection */
+static void pkg_createOptMatchArch(char *optMatchArch) {
+#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
+    const char* code = "void oma(){}";
+    const char* source = "oma.c";
+    const char* obj = "oma.obj";
+    FileStream* stream = NULL;
+
+    stream = T_FileStream_open(source,"w");
+    if (stream != NULL) {
+        T_FileStream_writeLine(stream, code);
+        T_FileStream_close(stream);
+
+        char cmd[LARGE_BUFFER_MAX_SIZE];
+        sprintf(cmd, "%s %s -o %s",
+            pkgDataFlags[COMPILER],
+            source,
+            obj);
+
+        if (runCommand(cmd) == 0){
+            sprintf(optMatchArch, "%s", obj);
+        }
+        else {
+            fprintf(stderr, "Failed to compile %s\n", source);
+        }
+        if(!T_FileStream_remove(source)){
+            fprintf(stderr, "T_FileStream_remove failed to delete %s\n", source);
+        }
+    }
+    else {
+        fprintf(stderr, "T_FileStream_open failed to open %s for writing\n", source);
+    }
+#endif
+}
+static void pkg_destroyOptMatchArch(char *optMatchArch) {
+    if(T_FileStream_file_exists(optMatchArch) && !T_FileStream_remove(optMatchArch)){
+        fprintf(stderr, "T_FileStream_remove failed to delete %s\n", optMatchArch);
+    }
+}
+#endif