]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/genpname/genpname.cpp
ICU-6.2.10.tar.gz
[apple/icu.git] / icuSources / tools / genpname / genpname.cpp
index 7f483168b5b96f46f68f0a27125a532d4caa645b..b2df4d5cfe3c380445acfa181a9cede731736f28 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2002, International Business Machines
+*   Copyright (C) 2002-2004, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -8,19 +8,21 @@
 **********************************************************************
 */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include "unicode/utypes.h"
 #include "unicode/putil.h"
+#include "unicode/uclean.h"
 #include "cmemory.h"
 #include "cstring.h"
 #include "filestrm.h"
+#include "uarrsort.h"
 #include "unewdata.h"
 #include "uoptions.h"
 #include "uprops.h"
 #include "propname.h"
 #include "uassert.h"
 
+#include <stdio.h>
+
 // TODO: Clean up and comment this code.
 
 //----------------------------------------------------------------------
@@ -32,6 +34,7 @@
 
 #include "unicode/uchar.h"
 #include "unicode/uscript.h"
+#include "unicode/unorm.h"
 
 class AliasName {
 public:
@@ -214,9 +217,12 @@ public:
     NameToEnumEntry(int32_t a, int32_t b) { nameIndex=a; enumValue=b; }
 };
 
-// Sort function for NameToEnumEntry (sort by name index)
-U_CAPI int compareNameToEnumEntry(const void* e1, const void* e2) {
-    return ((NameToEnumEntry*)e1)->nameIndex - ((NameToEnumEntry*)e2)->nameIndex;
+// Sort function for NameToEnumEntry (sort by name)
+U_CFUNC int32_t
+compareNameToEnumEntry(const void * /*context*/, const void* e1, const void* e2) {
+    return
+        STRING_TABLE[((NameToEnumEntry*)e1)->nameIndex].
+            compare(STRING_TABLE[((NameToEnumEntry*)e2)->nameIndex]);
 }
 
 //----------------------------------------------------------------------
@@ -245,7 +251,8 @@ public:
 };
 
 // Sort function for EnumToNameGroupEntry (sort by name index)
-U_CAPI int compareEnumToNameGroupEntry(const void* e1, const void* e2) {
+U_CFUNC int32_t
+compareEnumToNameGroupEntry(const void * /*context*/, const void* e1, const void* e2) {
     return ((EnumToNameGroupEntry*)e1)->enumValue - ((EnumToNameGroupEntry*)e2)->enumValue;
 }
 
@@ -276,7 +283,8 @@ public:
 };
 
 // Sort function for EnumToValueEntry (sort by enum)
-U_CAPI int compareEnumToValueEntry(const void* e1, const void* e2) {
+U_CFUNC int32_t
+compareEnumToValueEntry(const void * /*context*/, const void* e1, const void* e2) {
     return ((EnumToValueEntry*)e1)->enumValue - ((EnumToValueEntry*)e2)->enumValue;
 }
 
@@ -639,7 +647,7 @@ void Builder::buildStringPool(const AliasName* propertyNames,
     // first string must be "" -- we skip it
     U_ASSERT(*propertyNames[0].str == 0);
     for (i=1 /*sic*/; i<propertyNameCount; ++i) {
-        stringPool_size += uprv_strlen(propertyNames[i].str) + 1;
+        stringPool_size += (int32_t)(uprv_strlen(propertyNames[i].str) + 1);
     }
     stringPool = MALLOC(char, stringPool_size);
     stringPool_offsetArray = MALLOC(Offset, stringPool_count);
@@ -648,7 +656,7 @@ void Builder::buildStringPool(const AliasName* propertyNames,
     stringPool_offsetArray[0] = -1; // we don't use this entry
     for (i=1 /*sic*/; i<propertyNameCount; ++i) {
         const char* str = propertyNames[i].str;
-        int32_t len = uprv_strlen(str);
+        int32_t len = (int32_t)uprv_strlen(str);
         uprv_strcpy(p, str);
         p += len;
         *p++ = 0;
@@ -685,21 +693,22 @@ void Builder::computeOffsets() {
     #define COMPUTE_OFFSET(foo) COMPUTE_OFFSET2(foo,int32_t)
 
     #define COMPUTE_OFFSET2(foo,type) \
-      if (debug>0) printf(#foo "\t offset=%4d  size=%5d\n", off, foo##_size); \
-      foo##_offset = off;       \
-      U_ASSERT(IS_VALID_OFFSET(off + foo##_size)); \
-      U_ASSERT(foo##_offset % sizeof(type) == 0); \
+      if (debug>0)\
+        printf(#foo "\t offset=%4d  size=%5d\n", off, (int)foo##_size);\
+      foo##_offset = off;\
+      U_ASSERT(IS_VALID_OFFSET(off + foo##_size));\
+      U_ASSERT(foo##_offset % sizeof(type) == 0);\
       off = (Offset) (off + foo##_size);
 
     COMPUTE_OFFSET(enumToName);     // 0:
-    COMPUTE_OFFSET(nameToEnum);            // 2:
-    COMPUTE_OFFSET(enumToValue);           // 3:
-    COMPUTE_OFFSET(valueMap);              // 4:
+    COMPUTE_OFFSET(nameToEnum);     // 2:
+    COMPUTE_OFFSET(enumToValue);    // 3:
+    COMPUTE_OFFSET(valueMap);       // 4:
         
     for (i=0; i<valueMap_count; ++i) {
         if (debug>0) {
             printf(" enumToName[%d]\t offset=%4d  size=%5d\n",
-                   i, off, valueEnumToName_size[i]);
+                   (int)i, off, (int)valueEnumToName_size[i]);
         }
 
         valueEnumToName_offset[i] = off;   // 5:
@@ -708,7 +717,7 @@ void Builder::computeOffsets() {
 
         if (debug>0) {
             printf(" nameToEnum[%d]\t offset=%4d  size=%5d\n",
-                   i, off, valueNameToEnum_size[i]);
+                   (int)i, off, (int)valueNameToEnum_size[i]);
         }
 
         valueNameToEnum_offset[i] = off;   // 6:
@@ -721,7 +730,7 @@ void Builder::computeOffsets() {
     COMPUTE_OFFSET2(stringPool,char);      // 99:
 
     total_size = off;
-    if (debug>0) printf("total                         size=%5d\n\n", total_size);
+    if (debug>0) printf("total                         size=%5d\n\n", (int)total_size);
     U_ASSERT(total_size <= (MAX_OFFSET+1));
 }
 
@@ -761,7 +770,7 @@ void Builder::fixupEnumToNameGroup(EnumToOffset* e2ng) {
 
 void Builder::fixupNCEnumToNameGroup(NonContiguousEnumToOffset* e2ng) {
     int32_t i;
-    EnumValue* e = e2ng->getEnumArray();
+    /*EnumValue* e = e2ng->getEnumArray();*/
     Offset* p = e2ng->getOffsetArray();
     for (i=0; i<e2ng->count; ++i) {
         p[i] = nameGroupPool_offset + sizeof(Offset) * p[i];
@@ -798,7 +807,7 @@ void Builder::fixupMiscellaneousOffsets() {
     header.nameToEnum_offset = nameToEnum_offset;
     header.enumToValue_offset = enumToValue_offset;
     // header meta-info used by Java:
-       U_ASSERT(total_size > 0 && total_size < 0x7FFF);
+    U_ASSERT(total_size > 0 && total_size < 0x7FFF);
     header.total_size = (int16_t) total_size;
     header.valueMap_offset = valueMap_offset;
     header.valueMap_count = (int16_t) valueMap_count;
@@ -807,13 +816,13 @@ void Builder::fixupMiscellaneousOffsets() {
     header.stringPool_offset = stringPool_offset;
     header.stringPool_count = (int16_t) stringPool_count - 1; // don't include "" entry
 
-       U_ASSERT(valueMap_count <= 0x7FFF);
-       U_ASSERT(nameGroupPool_count <= 0x7FFF);
-       U_ASSERT(stringPool_count <= 0x7FFF);
+    U_ASSERT(valueMap_count <= 0x7FFF);
+    U_ASSERT(nameGroupPool_count <= 0x7FFF);
+    U_ASSERT(stringPool_count <= 0x7FFF);
 
     // 3:
     Offset* p = enumToValue->getOffsetArray();
-    EnumValue* e = enumToValue->getEnumArray();
+    /*EnumValue* e = enumToValue->getEnumArray();*/
     U_ASSERT(valueMap_count == enumToValue->count);
     for (i=0; i<valueMap_count; ++i) {
         p[i] = (Offset)(valueMap_offset + sizeof(ValueMap) * i);
@@ -875,7 +884,10 @@ int8_t* Builder::createData(int32_t& length) const {
     APPEND(nameGroupPool);
     APPEND(stringPool);
 
-    U_ASSERT(p == limit);
+    if (p != limit) {
+        fprintf(stderr, "p != limit; p = %p, limit = %p", p, limit);
+        exit(1);
+    }
     return result;
 }
 
@@ -897,11 +909,6 @@ static UDataInfo dataInfo = {
     {VERSION_0, VERSION_1, VERSION_2, VERSION_3} /* Unicode version */
 };
 
-// Glue for C<->C++
-U_CAPI int compareAliasNames(const void* elem1, const void* elem2) {
-    return ((const AliasName*)elem1)->compare(*(const AliasName*)elem2);
-}
-
 class genpname {
 
     // command-line options
@@ -922,9 +929,22 @@ private:
 };
 
 int main(int argc, char *argv[]) {
+    UErrorCode status = U_ZERO_ERROR;
+    u_init(&status);
+    if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
+        // Note: u_init() will try to open ICU property data.
+        //       failures here are expected when building ICU from scratch.
+        //       ignore them.
+        fprintf(stderr, "genpname: can not initialize ICU.  Status = %s\n",
+            u_errorName(status));
+        exit(1);
+    }
+
     genpname app;
     U_MAIN_INIT_ARGS(argc, argv);
-    return app.MMain(argc, argv);
+    int retVal = app.MMain(argc, argv);
+    u_cleanup();
+    return retVal;
 }
 
 static UOption options[]={
@@ -963,14 +983,20 @@ NameToEnumEntry* genpname::createNameIndex(const AliasList& list,
                 NameToEnumEntry(names[j], p.enumValue);
         }
     }
-    qsort((void*) nameIndex, nameIndexCount, sizeof(nameIndex[0]),
-          compareNameToEnumEntry);
+
+    /*
+     * use a stable sort to ensure consistent results between
+     * genpname.cpp and the propname.cpp swapping code
+     */
+    UErrorCode errorCode = U_ZERO_ERROR;
+    uprv_sortArray(nameIndex, nameIndexCount, sizeof(nameIndex[0]),
+                   compareNameToEnumEntry, NULL, TRUE, &errorCode);
     if (debug>1) {
-        printf("Alias names: %d\n", nameIndexCount);
+        printf("Alias names: %d\n", (int)nameIndexCount);
         for (i=0; i<nameIndexCount; ++i) {
             printf("%s => %d\n",
                    STRING_TABLE[nameIndex[i].nameIndex].str,
-                   nameIndex[i].enumValue);
+                   (int)nameIndex[i].enumValue);
         }
         printf("\n");
     }
@@ -1015,14 +1041,16 @@ EnumToNameGroupEntry* genpname::createEnumIndex(const AliasList& list) {
         const Alias& p = list[i];
         enumIndex[i] = EnumToNameGroupEntry(p.enumValue, p.nameGroupIndex);
     }
-    qsort((void*) enumIndex, count, sizeof(enumIndex[0]),
-          compareEnumToNameGroupEntry);
+
+    UErrorCode errorCode = U_ZERO_ERROR;
+    uprv_sortArray(enumIndex, count, sizeof(enumIndex[0]),
+                   compareEnumToNameGroupEntry, NULL, FALSE, &errorCode);
     if (debug>1) {
-        printf("Property enums: %d\n", count);
+        printf("Property enums: %d\n", (int)count);
         for (i=0; i<count; ++i) {
             printf("%d => %d: ",
-                   enumIndex[i].enumValue,
-                   enumIndex[i].nameGroupIndex);
+                   (int)enumIndex[i].enumValue,
+                   (int)enumIndex[i].nameGroupIndex);
             UBool done = FALSE;
             for (j=enumIndex[i].nameGroupIndex; !done; ++j) {
                 k = NAME_GROUP[j];
@@ -1040,9 +1068,17 @@ EnumToNameGroupEntry* genpname::createEnumIndex(const AliasList& list) {
     return enumIndex;
 }
 
-int genpname::MMain(int argc, char* argv[]) {
-
+int genpname::MMain(int argc, char* argv[])
+{
     int32_t i, j;
+    UErrorCode status = U_ZERO_ERROR;
+
+    u_init(&status);
+    if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
+        fprintf(stderr, "Error: u_init returned %s\n", u_errorName(status));
+        status = U_ZERO_ERROR;
+    }
+
 
     /* preset then read command line options */
     options[3].value=u_getDataDirectory();
@@ -1061,7 +1097,7 @@ int genpname::MMain(int argc, char* argv[]) {
        debug < 0 || debug > 9) {
         fprintf(stderr,
             "usage: %s [-options]\n"
-            "\tcreate " U_ICUDATA_NAME "_" PNAME_DATA_NAME "." PNAME_DATA_TYPE "\n"
+            "\tcreate " PNAME_DATA_NAME "." PNAME_DATA_TYPE "\n"
             "options:\n"
             "\t-h or -? or --help  this usage text\n"
             "\t-v or --verbose     turn on verbose output\n"
@@ -1077,35 +1113,22 @@ int genpname::MMain(int argc, char* argv[]) {
     verbose = options[4].doesOccur;
 
     // ------------------------------------------------------------
-    // Sort the string table.  This produces the proper sorting
-    // using the actual comparison function we will use.
-    qsort((void*) STRING_TABLE, STRING_COUNT, sizeof(STRING_TABLE[0]),
-          compareAliasNames);
+    // Do not sort the string table, instead keep it in data.h order.
+    // This simplifies data swapping and testing thereof because the string
+    // table itself need not be sorted during swapping.
+    // The NameToEnum sorter sorts each such map's string offsets instead.
+
     if (debug>1) {
-        printf("String pool: %d\n", STRING_COUNT);
-    }
-    for (i=0; i<STRING_COUNT; ++i) {
-        REMAP[STRING_TABLE[i].index] = i;
-        if (debug>1) {
-            if (i != 0) printf(", ");
-            printf("%s (%d)", STRING_TABLE[i].str, STRING_TABLE[i].index);
+        printf("String pool: %d\n", (int)STRING_COUNT);
+        for (i=0; i<STRING_COUNT; ++i) {
+            if (i != 0) {
+                printf(", ");
+            }
+            printf("%s (%d)", STRING_TABLE[i].str, (int)STRING_TABLE[i].index);
         }
-    }
-    if (debug>1) {
         printf("\n\n");
     }
 
-    // ------------------------------------------------------------
-    // Fixup the NAME_GROUP indices so they match the sorted order
-    for (i=0; i<NAME_GROUP_COUNT; ++i) {
-        // keep negative entries (end markers) negative
-        if (NAME_GROUP[i] < 0) {
-            NAME_GROUP[i] = -REMAP[-NAME_GROUP[i]];
-        } else {
-            NAME_GROUP[i] = REMAP[NAME_GROUP[i]];
-        }
-    }
-
     // ------------------------------------------------------------
     // Create top-level property indices
 
@@ -1132,8 +1155,9 @@ int genpname::MMain(int argc, char* argv[]) {
         ++j;
     }
     enumToValue_count = j;
-    qsort((void*) enumToValue, enumToValue_count, sizeof(enumToValue[0]),
-          compareEnumToValueEntry);
+
+    uprv_sortArray(enumToValue, enumToValue_count, sizeof(enumToValue[0]),
+                   compareEnumToValueEntry, NULL, FALSE, &status);
 
     // ------------------------------------------------------------
     // Build PropertyAliases layout in memory
@@ -1174,7 +1198,7 @@ int32_t genpname::writeDataFile(const char *destdir, const Builder& builder) {
     UNewDataMemory *pdata;
     UErrorCode status = U_ZERO_ERROR;
 
-    pdata = udata_create(destdir, PNAME_DATA_TYPE, U_ICUDATA_NAME "_" PNAME_DATA_NAME, &dataInfo,
+    pdata = udata_create(destdir, PNAME_DATA_TYPE, PNAME_DATA_NAME, &dataInfo,
                          useCopyright ? U_COPYRIGHT_STRING : 0, &status);
     if (U_FAILURE(status)) {
         die("Unable to create data memory");