]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/pkgdata/pkgdata.c
ICU-6.2.10.tar.gz
[apple/icu.git] / icuSources / tools / pkgdata / pkgdata.c
index 2427c4fc08cda00f4f052259e03e48ea7a8b8a42..041ebdbf7e65a2cd8a77786305c81f6eebbba782 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 *
-*   Copyright (C) 2000-2003, International Business Machines
+*   Copyright (C) 2000-2004, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   (DLL, common data, etc.)
 */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include "unicode/utypes.h"
 #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"
 
 #if U_HAVE_POPEN
+/*
+  We define __USE_POSIX2 so that we can get popen and pclose when
+  --enable-strict is used
+*/
+# ifndef __USE_POSIX2
+#  define __USE_POSIX2 1
+# endif
 # include <unistd.h>
 #endif
+#include <stdio.h>
+#include <stdlib.h>
 
 U_CDECL_BEGIN
 #include "pkgtypes.h"
@@ -51,17 +59,17 @@ static struct
 } modes[] =
 {
     { "files", 0, pkg_mode_files, "Uses raw data files (no effect). Installation copies all files to the target location." },
-#ifdef WIN32
+#ifdef U_MAKE_IS_NMAKE
     { "dll",    "library", pkg_mode_windows,    "Generates one common data file and one shared library, <package>.dll"},
     { "common", "archive", pkg_mode_windows,    "Generates just the common file, <package>.dat"},
     { "static", "static",  pkg_mode_windows,    "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
-#else /*#ifdef WIN32*/
+#else /*#ifdef U_MAKE_IS_NMAKE*/
 #ifdef UDATA_SO_SUFFIX
     { "dll",    "library", pkg_mode_dll,    "Generates one shared library, <package>" UDATA_SO_SUFFIX },
 #endif
     { "common", "archive", pkg_mode_common, "Generates one common data file, <package>.dat" },
     { "static", "static",  pkg_mode_static, "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
-#endif /*#ifdef WIN32*/
+#endif /*#ifdef U_MAKE_IS_NMAKE*/
 };
 
 static UOption options[]={
@@ -83,13 +91,17 @@ static UOption options[]={
     /*15*/    UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
     /*16*/    UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
     /*17*/    UOPTION_DEF( 0, 'M', UOPT_REQUIRES_ARG),
-    /*18*/    UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG)
+    /*18*/    UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
+    /*19*/    UOPTION_DEF( "numerictmp", 'N', UOPT_NO_ARG),
+    /*20*/    UOPTION_DEF( "embed", 'E', UOPT_NO_ARG),
+    /*21*/    UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
+    /*22*/    UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG)
 };
 
-const char options_help[][160]={
+const char options_help[][320]={
     "Set the data name",
-#ifdef WIN32
-    "R:icupath for release version or D:icupath for debug version, where icupath is the directory where ICU is located",
+#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. (Autdetected if icu-config is available)",
 #endif
@@ -109,7 +121,11 @@ const char options_help[][160]={
     "Specify a custom entrypoint name (default: short name)",
     "Specify a version when packaging in DLL or static mode",
     "Pass the next argument to make(1)",
-    "Add package to all file names if not present"
+    "Add package to all file names if not present",
+    "Use short numeric temporary file names such as t1234.c",
+    "Use Embedded paths (such as 'mypackage_') - for compatibility.",
+    "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";
@@ -152,21 +168,28 @@ main(int argc, char* argv[]) {
         }
 
         if(!options[1].doesOccur) {
-          /* Try to fill in from icu-config or equivalent */
-          fillInMakefileFromICUConfig(&options[1]);
+            /* Try to fill in from icu-config or equivalent */
+            fillInMakefileFromICUConfig(&options[1]);
+        }
+#ifdef U_MAKE_IS_NMAKE
+        else {
+            fprintf(stderr, "Warning: You are using the deprecated -O option\n"
+                            "\tYou can fix this warning by installing pkgdata, gencmn and genccode\n"
+                            "\tinto the same directory and not specifying the -O option to pkgdata.\n");
         }
+#endif
         
         if(!options[1].doesOccur) {
-          fprintf(stderr, " required parameter is missing: -O is required \n");
-          fprintf(stderr, "Run '%s --help' for help.\n", progname);
-          return 1;
+            fprintf(stderr, " required parameter is missing: -O is required \n");
+            fprintf(stderr, "Run '%s --help' for help.\n", progname);
+            return 1;
         }
-
+        
         if(!options[0].doesOccur) /* -O we already have - don't report it. */
         {
-          fprintf(stderr, " required parameter -p is missing \n");
-          fprintf(stderr, "Run '%s --help' for help.\n", progname);
-          return 1;
+            fprintf(stderr, " required parameter -p is missing \n");
+            fprintf(stderr, "Run '%s --help' for help.\n", progname);
+            return 1;
         }
 
         if(argc == 1) {
@@ -188,7 +211,7 @@ main(int argc, char* argv[]) {
         fprintf(stderr, "\n options:\n");
         for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
             fprintf(stderr, "%-5s -%c %s%-10s  %s\n",
-                (i<2?"[REQ]":""),
+                (i<1?"[REQ]":""),
                 options[i].shortName,
                 options[i].longName ? "or --" : "     ",
                 options[i].longName ? options[i].longName : "",
@@ -234,8 +257,8 @@ main(int argc, char* argv[]) {
     }
 
     o.shortName = options[0].value;
-    /**/ {
-        int len = uprv_strlen(o.shortName);
+    {
+        int32_t len = (int32_t)uprv_strlen(o.shortName);
         char *csname, *cp;
         const char *sp;
 
@@ -251,32 +274,48 @@ main(int argc, char* argv[]) {
         o.cShortName = csname;
     }
 
-#ifdef WIN32 /* format is R:pathtoICU or D:pathtoICU */
+    if(options[21].doesOccur) { /* get libname from shortname, or explicit -L parameter */
+      o.libName = options[21].value;
+    } else {
+      o.libName = o.shortName;
+    }
+    
+    if(options[22].doesOccur) {
+      o.quiet = TRUE;
+    } else {
+      o.quiet = FALSE;
+    }
+
+    o.verbose   = options[5].doesOccur;
+#ifdef U_MAKE_IS_NMAKE /* format is R:pathtoICU or D:pathtoICU */
     {
         char *pathstuff = (char *)options[1].value;
         if(options[1].value[uprv_strlen(options[1].value)-1] == '\\') {
             pathstuff[uprv_strlen(options[1].value)-1] = '\0';
         }
-        if(*pathstuff == 'R' || *pathstuff == 'D') {
+        if(*pathstuff == PKGDATA_DERIVED_PATH || *pathstuff == 'R' || *pathstuff == 'D') {
             o.options = pathstuff;
             pathstuff++;
             if(*pathstuff == ':') {
                 *pathstuff = '\0';
                 pathstuff++;
-            } else {
-                fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n", o.mode, progname);
+            }
+            else {
+                fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n");
                 return 1;
             }
         } else {
-            fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n", o.mode, progname);
+            fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n");
             return 1;
         }
         o.icuroot = pathstuff;
+        if (o.verbose) {
+            fprintf(stdout, "# ICUROOT is %s\n", o.icuroot);
+        }
     }
 #else /* on UNIX, we'll just include the file... */
     o.options   = options[1].value;
 #endif
-    o.verbose   = options[5].doesOccur;
     if(options[6].doesOccur) {
         o.comment = U_COPYRIGHT_STRING;
     } else if (options[7].doesOccur) {
@@ -292,6 +331,12 @@ main(int argc, char* argv[]) {
     o.clean     = options[9].doesOccur;
     o.nooutput  = options[10].doesOccur;
     o.rebuild   = options[11].doesOccur;
+    o.numeric   = options[19].doesOccur;
+    if(o.numeric) { 
+      o.rebuild = TRUE; /* force rebuild if numeric */
+    }
+
+    o.embed = options[20].doesOccur;
 
     if( options[12].doesOccur ) {
         o.tmpDir    = options[12].value;
@@ -439,12 +484,12 @@ static void loadLists(UPKGOptions *o, UErrorCode *status)
     char        line[16384];
     char       *linePtr, *lineNext;
     const uint32_t   lineMax = 16300;
-    char        tmp[1024], tmp2[1024];
+    char        tmp[1024];
     char        pkgPrefix[1024];
     int32_t     pkgPrefixLen;
     const char *baseName;
     char       *s;
-    int32_t     ln;
+    int32_t     ln=0; /* line number */
     UBool       fixPrefix;
     
     
@@ -452,187 +497,218 @@ static void loadLists(UPKGOptions *o, UErrorCode *status)
     
     strcpy(pkgPrefix, o->shortName);
     strcat(pkgPrefix, "_");
-    pkgPrefixLen=uprv_strlen(pkgPrefix);
+    pkgPrefixLen=(int32_t)uprv_strlen(pkgPrefix);
     for(l = o->fileListFiles; l; l = l->next) {
         if(o->verbose) {
             fprintf(stdout, "# Reading %s..\n", l->str);
         }
         /* TODO: stdin */
-        in = T_FileStream_open(l->str, "r");
+        in = T_FileStream_open(l->str, "r"); /* open files list */
         
         if(!in) {
             fprintf(stderr, "Error opening <%s>.\n", l->str);
             *status = U_FILE_ACCESS_ERROR;
             return;
         }
-        
-        ln = 0;
-        
-        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, ln, lineMax);
-                exit(1);
+                
+        while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
+          if((ln == 0) && (!o->embed)) { 
+            /* determine if we need to run in 'embed' (compatibility) mode */
+            if(!strncmp(findBasename(line), pkgPrefix, pkgPrefixLen)) {
+              fprintf(stderr, "Warning: Found path '%s' in file name. Assuming compatibility (-E) mode.\n", pkgPrefix);
+              o->embed = 1;
             }
-            /* remove spaces at the beginning */
-            linePtr = line;
-            while(isspace(*linePtr)) {
-                linePtr++;
+          }
+          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);
+          }
+          /* remove spaces at the beginning */
+          linePtr = line;
+          while(isspace(*linePtr)) {
+            linePtr++;
+          }
+          s=linePtr;
+          /* remove trailing newline characters */
+          while(*s!=0) {
+            if(*s=='\r' || *s=='\n') {
+              *s=0;
+              break;
             }
-            s=linePtr;
-            /* remove trailing newline characters */
-            while(*s!=0) {
-                if(*s=='\r' || *s=='\n') {
-                    *s=0;
-                    break;
-                }
                 ++s;
+          }
+          if((*linePtr == 0) || (*linePtr == '#')) {
+            continue; /* comment or empty line */
+          }
+          
+          /* Now, process the line */
+          lineNext = NULL;
+          
+          while(linePtr && *linePtr) { /* process space-separated items */
+            while(*linePtr == ' ') {
+              linePtr++;
             }
-            if((*linePtr == 0) || (*linePtr == '#')) {
-                continue; /* comment or empty line */
-            }
-            
-            /* Now, process the line */
-            lineNext = NULL;
-            
-            while(linePtr && *linePtr) {
-                while(*linePtr == ' ') {
-                    linePtr++;
-                }
-                /* Find the next */
-                if(linePtr[0] == '"')
-                {
-                    lineNext = uprv_strchr(linePtr+1, '"');
-                    if(lineNext == NULL) {
-                        fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
-                            l->str, 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, ln,  lineNext-line, (*lineNext)?*lineNext:'0');
-                                exit(1);
-                            }
-                            *lineNext = 0;
-                            lineNext++;
-                        }
-                    }
+            /* Find the next quote */
+            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 = uprv_strchr(linePtr, ' ');
-                    if(lineNext) {
-                        *lineNext = 0; /* terminate at space */
-                        lineNext++;
-                    }
-                }
-                
-                /* add the file */
-                s = (char*)getLongPathname(linePtr);
-                
-                baseName = findBasename(s);
-                
-                if(s != baseName) {
-                    /* s was something 'long' with a path */
-                    if(fixPrefix && uprv_strncmp(pkgPrefix, baseName, pkgPrefixLen)) {
-                        /* path don't have the prefix, add package prefix to short and longname */
-                        uprv_strcpy(tmp, pkgPrefix);
-                        uprv_strcpy(tmp+pkgPrefixLen, baseName);
-                        
-                        uprv_strncpy(tmp2, s, uprv_strlen(s)-uprv_strlen(baseName));  /* should be:   dirpath only, ending in sep */
-                        tmp2[uprv_strlen(s)-uprv_strlen(baseName)]=0;
-                        uprv_strcat(tmp2, pkgPrefix);
-                        uprv_strcat(tmp2, baseName);
-                        
-                        o->files = pkg_appendToList(o->files, &tail, uprv_strdup(tmp));
-                        o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp2));
-                    } else {
-                        /* paths already have the prefix */
-                        o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName));
-                        o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(s));
-                    }
-                    
-                } else { /* s was just a basename, we want to prepend source dir*/
-                    /* check for prefix of package */
-                    uprv_strcpy(tmp, o->srcDir);
-                    uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING);
-                    
-                    if(fixPrefix && strncmp(pkgPrefix,s, pkgPrefixLen)) {
-                        /* didn't have the prefix - add it */
-                        uprv_strcat(tmp, pkgPrefix);
-                        /* make up a new basename */
-                        uprv_strcpy(tmp2, pkgPrefix);
-                        uprv_strcat(tmp2, s);
-                        o->files = pkg_appendToList(o->files, &tail, uprv_strdup(tmp2));
-                    } else {
-                        o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName));
+                  lineNext++;
+                  if(*lineNext) {
+                    if(*lineNext != ' ') {
+                      fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
+                              l->str, (int)ln,  lineNext-line, (*lineNext)?*lineNext:'0');
+                      exit(1);
                     }
-                    uprv_strcat(tmp, s);
-                    o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
+                    *lineNext = 0;
+                    lineNext++;
+                  }
                 }
-                linePtr = lineNext;
+              } else {
+              lineNext = uprv_strchr(linePtr, ' ');
+              if(lineNext) {
+                *lineNext = 0; /* terminate at space */
+                lineNext++;
+              }
             }
-        }
+            
+            /* add the file */
+            s = (char*)getLongPathname(linePtr);
+            
+            if(o->embed == 0) {
+              /* normal mode.. o->files is just the bare list without package names */
+              o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
+              uprv_strcpy(tmp, o->srcDir);
+              uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING);
+              uprv_strcat(tmp, s);
+              o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
+            } else {/* embedded package_ mode */
+              baseName = findBasename(s);
+              
+              if(s != baseName) {
+                /* s was something 'long' with a path */
+                /* paths already have the prefix */
+                o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName));
+                o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(s));
+              } else { /* s was just a basename, we want to prepend source dir*/
+                /* check for prefix of package */
+                uprv_strcpy(tmp, o->srcDir);
+                uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING);
+                o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName));
+                uprv_strcat(tmp, s);
+                o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
+              }
+            } /* end compatibility mode */
+            linePtr = lineNext;
+          } /* for each entry on line */
+        } /* for each line */
         T_FileStream_close(in);
-  }
+    } /* for each file list file */
 }
 
 /* Try calling icu-config directly to get information */
-void fillInMakefileFromICUConfig(UOption *option)
+static void fillInMakefileFromICUConfig(UOption *option)
 {
 #if U_HAVE_POPEN
-  FILE *p;
-  size_t n;
-  static char buf[512] = "";
-  static const char cmd[] = "icu-config --incfile";
-
-  if(options[5].doesOccur)
-  {
-    /* informational */
-    fprintf(stderr, "%s: No -O option found, trying '%s'.\n", progname, 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;
-  }
-  
-  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;
-  }
-
-  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;
-  }
-
-  if(options[5].doesOccur)
-  {
-    /* informational */
-    fprintf(stderr, "%s: icu-config: using '-O %s'\n", progname, buf);
-  }
-  option->value = buf;
-  option->doesOccur = TRUE;
+    FILE *p;
+    size_t n;
+    static char buf[512] = "";
+    static const char cmd[] = "icu-config --incfile";
+    
+    if(options[5].doesOccur)
+    {
+        /* informational */
+        fprintf(stderr, "%s: No -O option found, trying '%s'.\n", progname, 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;
+    }
+    
+    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;
+    }
+    
+    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;
+    }
+    
+    if(options[5].doesOccur)
+    {
+        /* informational */
+        fprintf(stderr, "%s: icu-config: using '-O %s'\n", progname, buf);
+    }
+    option->value = buf;
+    option->doesOccur = TRUE;
 #else  /* ! U_HAVE_POPEN */
 
-  /* no popen available */
-  /* Put other OS specific ways to search for the Makefile.inc type 
-     information or else fail.. */
+#ifdef WIN32
+    char pathbuffer[_MAX_PATH] = {0};
+    char *fullEXEpath = NULL;
+    char *pathstuff = NULL;
+
+    if (strchr(progname, U_FILE_SEP_CHAR) != NULL || strchr(progname, U_FILE_ALT_SEP_CHAR) != NULL) {
+        /* pkgdata was executed with relative path */
+        fullEXEpath = _fullpath(pathbuffer, progname, sizeof(pathbuffer));
+        pathstuff = (char *)options[1].value;
+
+        if (fullEXEpath) {
+            pathstuff = strrchr(fullEXEpath, U_FILE_SEP_CHAR);
+            if (pathstuff) {
+                pathstuff[1] = 0;
+                uprv_memmove(fullEXEpath + 2, fullEXEpath, uprv_strlen(fullEXEpath)+1);
+                fullEXEpath[0] = PKGDATA_DERIVED_PATH;
+                fullEXEpath[1] = ':';
+                option->value = uprv_strdup(fullEXEpath);
+                option->doesOccur = TRUE;
+            }
+        }
+    }
+    else {
+        /* pkgdata was executed from the path */
+        /* Search for file in PATH environment variable: */
+        _searchenv("pkgdata.exe", "PATH", pathbuffer );
+        if( *pathbuffer != '\0' ) {
+            fullEXEpath = pathbuffer;
+            pathstuff = strrchr(pathbuffer, U_FILE_SEP_CHAR);
+            if (pathstuff) {
+                pathstuff[1] = 0;
+                uprv_memmove(fullEXEpath + 2, fullEXEpath, uprv_strlen(fullEXEpath)+1);
+                fullEXEpath[0] = PKGDATA_DERIVED_PATH;
+                fullEXEpath[1] = ':';
+                option->value = uprv_strdup(fullEXEpath);
+                option->doesOccur = TRUE;
+            }
+        }
+    }
+    /* else can't determine the path */
+#endif
+
+    /* no popen available */
+    /* Put other OS specific ways to search for the Makefile.inc type 
+       information or else fail.. */
 
 #endif
 }