You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/03/23 02:51:10 UTC

svn commit: r387997 - /incubator/stdcxx/trunk/etc/config/src/LOCALE_NAME_FMAT.cpp

Author: sebor
Date: Wed Mar 22 17:51:08 2006
New Revision: 387997

URL: http://svn.apache.org/viewcvs?rev=387997&view=rev
Log:
2006-03-22  Martin Sebor  <se...@roguewave.com>

        STDCXX-140
	* LOCALE_NAME_FMAT.cpp (setlocale): Added a definition for debugging
	(to emulate platforms with no locales installed) and disabled it.
	(test_locale_names, nlocales): Renamed from loc and and nloc, and
	made const.
	(print_lc_constants, print_categories, print_locale_name_format):
	New helper functions for better readability.
	(cat_seps): Renamed from cats and moved from main() to file scope.
	(lc_consts): Merged with lc_vars.
	(lc_vars): Moved to file scope.
	(print_locale_name_format): Hardcoded locale format for a bunch
	of platforms in case there are no locales installed on the system.
	(test_locale_names): Added more locales.

Modified:
    incubator/stdcxx/trunk/etc/config/src/LOCALE_NAME_FMAT.cpp

Modified: incubator/stdcxx/trunk/etc/config/src/LOCALE_NAME_FMAT.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/etc/config/src/LOCALE_NAME_FMAT.cpp?rev=387997&r1=387996&r2=387997&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/src/LOCALE_NAME_FMAT.cpp (original)
+++ incubator/stdcxx/trunk/etc/config/src/LOCALE_NAME_FMAT.cpp Wed Mar 22 17:51:08 2006
@@ -19,6 +19,26 @@
 #undef strcat
 
 
+#if 0   // disabled
+
+// enable for debugging to emulate a system with no locales installed
+
+extern "C" char* setlocale (int, const char *name)
+{
+    static char cname[] = "C";
+
+    if (0 == name)
+        return cname;
+
+    if ('C' != name [0] || '\0' != name [1])
+        return 0;
+
+    return cname;
+}
+
+#endif   // 0/1
+
+
 // define own version of the libc functions to prevent problems
 // caused by them being not declared (sometimes due to the fact
 // that they must be overloaded in C++ which may not be done in
@@ -69,8 +89,19 @@
 extern "C" int putenv (char*);
 
 
-extern const char* loc[];
-extern const unsigned nloc;
+extern const char* const test_locale_names[];
+extern const unsigned    nlocales;
+
+int print_lc_constants ();
+int print_categories (const char*, int, int&, int&, int, char&, char&);
+int print_locale_name_format (int, int, int, int, int, char, char);
+
+
+#if !defined (_WIN32) && !defined (_WIN64) || defined (__CYGWIN__)
+char cat_seps[] = " \n\t/\\:;#%";
+#else
+char cat_seps[] = "\n\t/\\:;#%";
+#endif
 
 
 int main ()
@@ -81,92 +112,13 @@
 
 #endif   // _RWSTD_USE_CONFIG
 
-    // determine the values of LC_XXX constants
-
-    const struct {
-        const char *name;
-        int         value;
-    } lc_consts[] = {
-
-#if defined (LC_COLLATE)
-        { "LC_COLLATE", LC_COLLATE },
-#endif
-
-#if defined (LC_CTYPE)
-        { "LC_CTYPE", LC_CTYPE },
-#endif
-
-#if defined (LC_MONETARY)
-        { "LC_MONETARY", LC_MONETARY },
-#endif
-
-#if defined (LC_NUMERIC)
-        { "LC_NUMERIC", LC_NUMERIC },
-#endif
-
-#if defined (LC_TIME)
-        { "LC_TIME", LC_TIME },
-#endif
-
-#if defined (LC_MESSAGES)
-        { "LC_MESSAGES", LC_MESSAGES },
-#endif
-
-#if defined (LC_ALL)
-        { "LC_ALL", LC_ALL },
-#endif
-
-        { 0, 0 }
-    };
-
-    unsigned lc_max_inx = 0;
-    unsigned lc_min_inx = 0;
-
-    unsigned i;
-
-    for (i = 0; lc_consts [i].name; ++i) {
-        printf ("#define _RWSTD_%-12s %d\n",
-                lc_consts [i].name, lc_consts [i].value);
-
-        if (lc_consts [i].value > lc_consts [lc_max_inx].value)
-            lc_max_inx = i;
-
-        if (lc_consts [i].value < lc_consts [lc_min_inx].value)
-            lc_min_inx = i;
-    }
-
-    printf ("#define _RWSTD_LC_MAX      _RWSTD_%s\n",
-            lc_consts [lc_max_inx].name);
-
-    printf ("#define _RWSTD_LC_MIN      _RWSTD_%s\n",
-            lc_consts [lc_min_inx].name);
-
-#if defined (_WIN64) && defined (_MSC_VER) && _MSC_VER <= 1310
-
-    // working around a bug in MSVC 7.1/WIN64 (PR #29313)
-
-    const char output[] = {
-        "// values below hardcoded to work around an MSVC 7.1/IA64 bug\n"
-        "#define _RWSTD_CAT_0(pfx) { 1, \"LC_COLLATE\", pfx::_C_collate }\n"
-        "#define _RWSTD_CAT_1(pfx) { 2, \"LC_CTYPE\", pfx::_C_ctype }\n"
-        "#define _RWSTD_CAT_2(pfx) { 3, \"LC_MONETARY\", pfx::_C_monetary }\n"
-        "#define _RWSTD_CAT_3(pfx) { 4, \"LC_NUMERIC\", pfx::_C_numeric }\n"
-        "#define _RWSTD_CAT_4(pfx) { 5, \"LC_TIME\", pfx::_C_time }\n"
-        "#define _RWSTD_CAT_5(pfx) _RWSTD_CAT_0(pfx)\n"
-        "#define _RWSTD_NO_SETLOCALE_ENVIRONMENT\n"
-        "// #define _RWSTD_NO_CAT_NAMES\n"
-        "#define _RWSTD_CAT_SEP \";\"\n"
-        "#define _RWSTD_CAT_EQ \"=\"\n"
-        "#define _RWSTD_NO_INITIAL_CAT_SEP\n"
-        "// #define _RWSTD_NO_CONDENSED_NAME\n"
-    };
-
-    printf ("%s", output);
-
-    return 0;
-
-#endif   // _WIN64 && _MSC_VER && _MSC_VER <= 1300
+    // compute and print the values of the LC_XXX constants
+    // and their relationship to the std::locale::category
+    // constants
+    if (print_lc_constants ())
+        return 0;
 
+    // try to determine the format of combined locale names
     int  setlocale_environ    = 0;
     int  loc_name_use_cat     = 0;
     int  loc_name_prepend_sep = 0;
@@ -174,12 +126,6 @@
     char loc_name_cat_sep     = '\0';
     char loc_name_cat_eq      = '\0';
 
-#if !defined (_WIN32) && !defined (_WIN64) || defined (__CYGWIN__)
-    char seps[] = " \n\t/\\:;#%";
-#else
-    char seps[] = "\n\t/\\:;#%";
-#endif
-
     char namebuf [1024];
     namebuf [0] = '\0';
 
@@ -189,13 +135,13 @@
     // equivalent names into just a single locale name
     const char *locname = setlocale (LC_ALL, "C");
 
-    char *sep = locname ? rw_strpbrk (locname, seps) : 0;
+    char *sep = locname ? rw_strpbrk (locname, cat_seps) : 0;
     if (sep) {
         if ('C' == sep [-1] && 1 == sep - locname)
             loc_name_cat_sep = *sep;
         else {
             loc_name_condense = 1;
-            *rw_strchr (seps, *sep) = '\n';
+            *rw_strchr (cat_seps, *sep) = '\n';
         }
     }
     else {
@@ -207,9 +153,11 @@
     if ((locname = setlocale (LC_ALL, "")))
         strcpy (namebuf, locname);
 
-    for (i = 0; i != nloc; ++i) {
+    unsigned i;
 
-        locname = loc [i];
+    for (i = 0; i != nlocales; ++i) {
+
+        locname = test_locale_names [i];
 
 #if defined (_MSC_VER) && _MSC_VER <= 1200
 
@@ -219,61 +167,203 @@
 
 #endif   // MSVC <= 6.0
 
-        if (   (locname = setlocale (LC_ALL, locname))
-            && strcmp (namebuf, locname)) {
+        locname = setlocale (LC_ALL, locname);
+        if (locname && strcmp (namebuf, locname))
             break;
-        }
     }
 
-    // no locale matched
-    if (!locname) {
-        // FIXME: use system ("locale -a > ...")
-        return 1;
-    }
-
-    locname = strcpy (namebuf, locname);
+    if (locname) {
+        locname = strcpy (namebuf, locname);
 
-    sep = rw_strpbrk (locname, seps);
-    if (sep)
-        *sep = '\0';
-
-    // determine if the environment has any effect on setlocale()
-    {
-        char def_locale [256];
-        def_locale [0] = '\0';
-
-        const char *tmpname = setlocale (LC_ALL, "");
-        if (tmpname)
-            strcpy (def_locale, tmpname);
-
-        char buf [256];
-        strcpy (buf, "LC_COLLATE=");
-        strcat (buf, locname);
-        putenv (buf);
+        sep = rw_strpbrk (locname, cat_seps);
+        if (sep)
+            *sep = '\0';
+
+        // determine if the environment has any effect on setlocale()
+        {
+            char def_locale [256];
+            def_locale [0] = '\0';
+
+            const char *tmpname = setlocale (LC_ALL, "");
+            if (tmpname)
+                strcpy (def_locale, tmpname);
+
+            char buf [256];
+            strcpy (buf, "LC_COLLATE=");
+            strcat (buf, locname);
+            putenv (buf);
 
-        tmpname = setlocale (LC_ALL, "");
-        setlocale_environ = tmpname ? strcmp (def_locale, tmpname) : 1;
+            tmpname = setlocale (LC_ALL, "");
+            setlocale_environ = tmpname ? strcmp (def_locale, tmpname) : 1;
+        }
     }
 
+    print_categories (locname,
+                      setlocale_environ,
+                      loc_name_use_cat,
+                      loc_name_prepend_sep,
+                      loc_name_condense,
+                      loc_name_cat_sep,
+                      loc_name_cat_eq);
+
+    return print_locale_name_format (0 == locname,
+                                     setlocale_environ,
+                                     loc_name_use_cat,
+                                     loc_name_prepend_sep,
+                                     loc_name_condense,
+                                     loc_name_cat_sep,
+                                     loc_name_cat_eq);
+}
+
+/*********************************************************************/
 
-    // using a static local to work around an IBM xlC 5.0.1.0 bug (PR #26163)
-    static struct {
-        int         cat;
-        char        name [64];
-        const char *lower;
-    } lc_vars [] = {
-        { LC_COLLATE,  "LC_COLLATE=C",  "collate" },
-        { LC_CTYPE,    "LC_CTYPE=C",    "ctype" },
-        { LC_MONETARY, "LC_MONETARY=C", "monetary" },
-        { LC_NUMERIC,  "LC_NUMERIC=C",  "numeric" },
-        { LC_TIME,     "LC_TIME=C",     "time" }
+static struct LC_vars
+{
+    int         ord;
+    int         cat;
+    char        name [64];
+    const char *lower;
+} lc_vars [] = {
+    { -1, LC_COLLATE,  "LC_COLLATE=C",  "collate" },
+    { -1, LC_CTYPE,    "LC_CTYPE=C",    "ctype" },
+    { -1, LC_MONETARY, "LC_MONETARY=C", "monetary" },
+    { -1, LC_NUMERIC,  "LC_NUMERIC=C",  "numeric" },
+    { -1, LC_TIME,     "LC_TIME=C",     "time" },
 
 #ifdef LC_MESSAGES
-        , { LC_MESSAGES, "LC_MESSAGES=C", "messages" }
+    { -1, LC_MESSAGES, "LC_MESSAGES=C", "messages" },
+#endif
+
+#ifdef LC_NAME
+    { -1, LC_NAME, "LC_NAME=C", "name" },
+#endif
+
+#ifdef LC_PAPER
+    { -1, LC_PAPER, "LC_PAPER=C", "paper" },
+#endif
+
+#ifdef LC_IDENTIFICATION
+    { -1, LC_IDENTIFICATION, "LC_IDENTIFICATION=C", "ident" },
+#endif
+
+#ifdef LC_ADDRESS
+    { -1, LC_ADDRESS, "LC_ADDRESS=C", "address" },
+#endif
+
+#ifdef LC_TELEPHONE
+    { -1, LC_TELEPHONE, "LC_TELEPHONE=C", "telephone" },
 #endif
 
-    };
+#ifdef LC_MEASUREMENT
+    { -1, LC_MEASUREMENT, "LC_MEASUREMENT=C", "measurement" },
+#endif
+
+    { -1, 0, "", 0 }
+};
+
+
+// the known order of categories in combined locale names
+const int lc_cat_order[] = {
+
+#if defined (_AIX)
+    LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES,
+    -1, -1, -1, -1, -1, -1
+#elif defined (__FreeBSD__) || defined (__NetBSD__)
+    LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES,
+    -1, -1, -1, -1, -1, -1
+#elif defined (__hpux)
+    LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES,
+    -1, -1, -1, -1, -1, -1
+#elif defined (__GLIBC__)
+    LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES,
+
+#  if defined (LC_PAPER)
+    LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
+    LC_IDENTIFICATION
+#  else
+    -1, -1, -1, -1, -1, -1
+#  endif
+#elif defined (__osf__)
+    LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES,
+    -1, -1, -1, -1, -1, -1
+#elif defined (__sgi)
+    LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES,
+    -1, -1, -1, -1, -1, -1
+#elif    (defined (__sun__) || defined (__sun) || defined (sun)) \
+      && defined (__svr4__)
+    LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES,
+    -1, -1, -1, -1, -1, -1
+#elif defined (_WIN32)
+    LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, -1,
+    -1, -1, -1, -1, -1, -1,
+#elif defined (__CYGWIN__)
+    // this is just a wild guess since localization support
+    // on CygWin seems to be very limited
+    LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, -1,
+    -1, -1, -1, -1, -1, -1,
+#else
+    -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1
+#endif
+
+};
 
+/*********************************************************************/
+
+int print_lc_constants ()
+{
+    // determine the values of LC_XXX constants
+
+    unsigned lc_max_inx = 0;
+    unsigned lc_min_inx = 0;
+
+    char *eq;
+
+    for (unsigned i = 0; *lc_vars [i].name; ++i) {
+        eq = rw_strchr (lc_vars [i].name, '=');
+        *eq = '\0';
+
+        printf ("#define _RWSTD_%-20s %2d\n",
+                lc_vars [i].name, lc_vars [i].cat);
+
+        if (lc_vars [i].cat > lc_vars [lc_max_inx].cat)
+            lc_max_inx = i;
+
+        if (lc_vars [i].cat < lc_vars [lc_min_inx].cat)
+            lc_min_inx = i;
+
+        *eq = '=';
+    }
+
+    eq = rw_strchr (lc_vars [lc_max_inx].name, '=');
+    *eq = '\0';
+
+    printf ("#define %-27s _RWSTD_%s\n",
+            "_RWSTD_LC_MAX", lc_vars [lc_max_inx].name);
+
+    *eq = '=';
+
+    eq = rw_strchr (lc_vars [lc_min_inx].name, '=');
+    *eq = '\0';
+
+    printf ("#define %-27s _RWSTD_%s\n",
+            "_RWSTD_LC_MIN", lc_vars [lc_min_inx].name);
+
+    *eq = '=';
+
+    return 0;
+}
+
+/*********************************************************************/
+
+int print_categories (const char *locname,
+                      int         setlocale_environ,
+                      int        &loc_name_use_cat,
+                      int        &loc_name_prepend_sep,
+                      int         loc_name_condense,
+                      char       &loc_name_cat_sep,
+                      char       &loc_name_cat_eq)
+{
     // set or overwrite LC_ALL to prevent it from
     // overriding the settings below, and also reset
     // the global C locale to "C"
@@ -281,11 +371,13 @@
     putenv (lc_all);
     setlocale (LC_ALL, "C");
 
-    // set up the default environment
-    for (i = 0; i != sizeof lc_vars / sizeof *lc_vars; ++i)
+    unsigned i;
+
+    // set up the default environment (i.e., LC_COLLATE=C; LC_CTYPE=C; etc.)
+    for (i = 0; *lc_vars [i].name; ++i)
         putenv (lc_vars [i].name);
 
-    for (i = 0; i != sizeof lc_vars / sizeof *lc_vars; ++i) {
+    for (i = 0; locname && *lc_vars [i].name; ++i) {
         if (i) {
             if (setlocale_environ) {
                 // replace previous LC_XXX environment variable
@@ -307,9 +399,13 @@
         // set the combined locale
         char *combined;
         
-        if (setlocale_environ)
+        if (setlocale_environ) {
+            // create combined name from the environment
             combined = setlocale (LC_ALL, "");
+        }
         else {
+            // create combined name programmatically
+            // by setting just one category
             setlocale (lc_vars [i].cat, locname);
             combined = setlocale (LC_ALL, 0);
         }
@@ -323,6 +419,8 @@
             combined ? rw_strstr (combined, lc_vars [i].name) : (char*)0;
 
         if (where) {
+            // found the name of the category constant
+            // in the name of the combined locale
             loc_name_use_cat = 1;
 
             // look for a separator between LC_XXX
@@ -332,14 +430,16 @@
 
             int j = -1;
 
-            sep = rw_strpbrk (combined, seps);
-            char *first = rw_strstr (combined, locname);
+            char* sep   = rw_strpbrk (combined, cat_seps);
+            char* first = rw_strstr (combined, locname);
+
             for (const char *s = combined; *s && s != first; ++j)
                 s = rw_strchr (s, loc_name_cat_eq) + 1;
 
-            printf ("#define _RWSTD_CAT_%d(pfx) "
-                    "{ %d, \"%s\", pfx::_C_%s }\n",
-                    j, lc_vars [i].cat, lc_vars [i].name, lc_vars [i].lower);
+            lc_vars [i].ord = j;
+//             printf ("#define _RWSTD_CAT_%d(pfx) "
+//                     "{ %d, \"%s\", pfx::_C_%s }\n",
+//                     j, lc_vars [i].cat, lc_vars [i].name, lc_vars [i].lower);
 
             // look for a separator between LC_XXX=name pairs
             // (typically ';')
@@ -349,7 +449,7 @@
         }
         else {
             // look for a separator between locale categories
-            sep = combined ? rw_strpbrk (combined, seps) : (char*)0; 
+            char* sep = combined ? rw_strpbrk (combined, cat_seps) : (char*)0; 
             if (sep == combined)
                 loc_name_prepend_sep = 1;
 
@@ -368,18 +468,12 @@
                         break;
                 }
 
-                printf ("#define _RWSTD_CAT_%d(pfx) "
-                        "{ %d, \"%s\", pfx::_C_%s }\n",
-                        j, lc_vars [i].cat, lc_vars [i].name,
-                        lc_vars [i].lower);
+                lc_vars [i].ord = j;
             }
             else {
-                // combined locale name is the same as the name of one of
-                // the combining locales (e.g., Windows)
-                printf ("#define _RWSTD_CAT_%d(pfx) "
-                        "{ %d, \"%s\", pfx::_C_%s }\n",
-                        i, lc_vars [i].cat, lc_vars [i].name,
-                        lc_vars [i].lower);
+                // combined locale name is the same as the name
+                // of one of the combining locales (e.g., Windows)
+                lc_vars [i].ord = i;
             }
         }
 
@@ -390,8 +484,167 @@
             loc_name_prepend_sep = 1;
     }
     
-    for (; i < 6 /* number of POSIX LC_XXX constants */; i++)
-        printf ("#define _RWSTD_CAT_%d(pfx) _RWSTD_CAT_0(pfx)\n", i);
+    for (i = 0; *lc_vars [i].name; ++i) {
+
+        char* eq = rw_strchr (lc_vars [i].name, '=');
+        if (eq)
+            *eq = '\0';
+
+        const char *comment = 0;
+        int inx = -1;
+
+        for (int j = 0; *lc_vars [j].name; ++j) {
+            if (lc_vars [i].ord == j) {
+                comment = 0;
+                inx     = j;
+                break;
+            }
+
+            if (lc_vars [i].cat == lc_cat_order [j]) {
+                comment = "   // assumed";
+                inx     = j;
+            }
+        }
+
+        if (-1 < inx)
+            printf ("#define _RWSTD_CAT_%d(pfx) "
+                    "{ %d, \"%s\", pfx::_C_%s }%s\n",
+                    inx, lc_vars [i].cat, lc_vars [i].name,
+                    lc_vars [i].lower, comment ? comment : "");
+    }
+
+    return 0;
+}
+
+/*********************************************************************/
+
+int print_locale_name_format (int  guess,
+                              int  setlocale_environ,
+                              int  loc_name_use_cat,
+                              int  loc_name_prepend_sep,
+                              int  loc_name_condense,
+                              char loc_name_cat_sep,
+                              char loc_name_cat_eq)
+{
+    const char* os_name = 0;
+
+    if (guess) {
+
+#ifdef _AIX
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 0;
+        loc_name_cat_sep     = ' ';
+        loc_name_cat_eq      = '\0';
+        os_name              = "AIX";
+
+#elif defined (__FreeBSD__)
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 1;
+        loc_name_cat_sep     = '/';
+        loc_name_cat_eq      = '\0';
+        os_name              = "FreeBSD";
+
+#elif defined (__hpux)
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 0;
+        loc_name_cat_sep     = ' ';
+        loc_name_cat_eq      = '\0';
+        os_name              = "HP-UX";
+
+#elif defined (__GLIBC__)
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 1;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 0;
+        loc_name_cat_sep     = ';';
+        loc_name_cat_eq      = '=';
+        os_name              = "GNU libc";
+
+#elif defined (__NetBSD__)
+
+        setlocale_environ    = 0;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 1;
+        loc_name_cat_sep     = '\0';
+        loc_name_cat_eq      = '\0';
+        os_name              = "NetBSD";
+
+#elif defined (__osf__)
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 0;
+        loc_name_cat_sep     = ' ';
+        loc_name_cat_eq      = '\0';
+        os_name              = "Tru64 UNIX";
+
+#elif defined (__sgi)
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 1;
+        loc_name_condense    = 1;
+        loc_name_cat_sep     = '/';
+        loc_name_cat_eq      = '\0';
+        os_name              = "SGI IRIX";
+
+#elif    (defined (__sun__) || defined (__sun) || defined (sun)) \
+      && defined (__svr4__)
+
+        setlocale_environ    = 1;
+        loc_name_use_cat     = 0;
+        loc_name_prepend_sep = 1;
+        loc_name_condense    = 1;
+        loc_name_cat_sep     = '/';
+        loc_name_cat_eq      = '\0';
+        os_name              = "SunOS";
+
+#elif defined (_WIN32)
+
+        setlocale_environ    = 0;
+        loc_name_use_cat     = 1;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 1;
+        loc_name_cat_sep     = ';';
+        loc_name_cat_eq      = '=';
+        os_name              = "Windows";
+
+#elif defined (__CYGWIN__)
+
+        // guessing this might be the same as Windows
+        setlocale_environ    = 0;
+        loc_name_use_cat     = 1;
+        loc_name_prepend_sep = 0;
+        loc_name_condense    = 1;
+        loc_name_cat_sep     = ';';
+        loc_name_cat_eq      = '=';
+        // change the OS name to CygWin as soon as CygWin
+        // has implemented locale support
+        os_name              = "Windows";
+
+#else
+
+        printf ("// no locales found, unknown system\n");
+        return -1;   // unknown OS, fail
+
+#endif
+
+    }
+
+    if (os_name)
+        printf ("// no locales found, using %s format\n", os_name);
 
     if (setlocale_environ)
         printf ("// #define _RWSTD_NO_SETLOCALE_ENVIRONMENT\n");
@@ -426,8 +679,15 @@
     return 0;
 }
 
+/*********************************************************************/
+
+const char* const test_locale_names[] = {
+    "ar", "ar_EG.UTF-8", "bg_BG", "bg_BG.ISO8859-5", "ca", "ca_ES",
+
 
-const char *loc[] = {
+    "C.iso88591",
+    "C.iso885915",
+    "C.utf8",
     "DE_AT",
     "DE_AT.UTF-8",
     "DE_AT.UTF-8@euro",
@@ -485,6 +745,7 @@
     "ar_DZ.arabic8",
     "ar_DZ.utf8",
     "ar_EG",
+    "ar_EG.UTF-8",
     "ar_EG.utf8",
     "ar_IN",
     "ar_IQ",
@@ -536,6 +797,7 @@
     "ca_ES@euro",
     "catalan",
     "chinese",
+    "common",
     "croatian",
     "cs",
     "cs.po",
@@ -784,6 +1046,8 @@
     "fr_BE.ISO8859-1",
     "fr_BE.ISO8859-15",
     "fr_BE.ISO8859-15@euro",
+    "fr_BE.UTF-8",
+    "fr_BE.UTF-8@euro",
     "fr_BE.utf8",
     "fr_BE.utf8@euro",
     "fr_BE@euro",
@@ -841,9 +1105,11 @@
     "gv_GB.utf8",
     "he",
     "he_IL",
+    "he_IL.UTF-8",
     "he_IL.utf8",
     "hebrew",
     "hi_IN",
+    "hi_IN.UTF-8",
     "hr",
     "hr_HR",
     "hr_HR.ISO8859-2",
@@ -870,6 +1136,13 @@
     "is_IS.iso885915@euro",
     "is_IS.roman8",
     "is_IS.utf8",
+    "iso_8859_1",
+    "iso_8859_13",
+    "iso_8859_15",
+    "iso_8859_2",
+    "iso_8859_5",
+    "iso_8859_7",
+    "iso_8859_9",
     "it",
     "it.ISO8859-15",
     "it.UTF-8",
@@ -919,7 +1192,9 @@
     "ko.UTF-8",
     "ko_KR",
     "ko_KR.EUC",
+    "ko_KR.EUC@dict",
     "ko_KR.UTF-8",
+    "ko_KR.UTF-8@dict",
     "ko_KR.eucKR",
     "ko_KR.euckr",
     "ko_KR.utf8",
@@ -1004,6 +1279,7 @@
     "pt_BR",
     "pt_BR.ISO8859-1",
     "pt_BR.ISO8859-15",
+    "pt_BR.UTF-8",
     "pt_BR.po",
     "pt_BR.utf8",
     "pt_PT",
@@ -1088,7 +1364,9 @@
     "tg_TJ",
     "th",
     "th_TH",
+    "th_TH.ISO8859-11",
     "th_TH.TIS620",
+    "th_TH.UTF-8",
     "th_TH.tis620",
     "th_TH.utf8",
     "thai",
@@ -1096,6 +1374,7 @@
     "tr",
     "tr_TR",
     "tr_TR.ISO8859-9",
+    "tr_TR.UTF-8",
     "tr_TR.iso88599",
     "tr_TR.turkish8",
     "tr_TR.utf8",
@@ -1117,39 +1396,58 @@
     "zh.UTF-8",
     "zh_CN",
     "zh_CN.EUC",
+    "zh_CN.EUC@pinyin",
+    "zh_CN.EUC@radical",
+    "zh_CN.EUC@stroke",
+    "zh_CN.GB18030",
+    "zh_CN.GB18030@pinyin",
+    "zh_CN.GB18030@radical",
+    "zh_CN.GB18030@stroke",
     "zh_CN.GB2312",
     "zh_CN.GBK",
+    "zh_CN.GBK@pinyin",
+    "zh_CN.GBK@radical",
+    "zh_CN.GBK@stroke",
     "zh_CN.UTF-8",
+    "zh_CN.UTF-8@pinyin",
+    "zh_CN.UTF-8@radical",
+    "zh_CN.UTF-8@stroke",
     "zh_CN.gb18030",
     "zh_CN.gbk",
     "zh_CN.hp15CN",
     "zh_CN.utf8",
     "zh_HK",
+    "zh_HK.BIG5HK",
+    "zh_HK.BIG5HK@radical",
+    "zh_HK.BIG5HK@stroke",
+    "zh_HK.UTF-8",
+    "zh_HK.UTF-8@radical",
+    "zh_HK.UTF-8@stroke",
     "zh_HK.big5",
     "zh_HK.utf8",
     "zh_TW",
     "zh_TW.BIG5",
+    "zh_TW.BIG5@pinyin",
+    "zh_TW.BIG5@radical",
+    "zh_TW.BIG5@stroke",
+    "zh_TW.BIG5@zhuyin",
     "zh_TW.Big5",
     "zh_TW.EUC",
+    "zh_TW.EUC@pinyin",
+    "zh_TW.EUC@radical",
+    "zh_TW.EUC@stroke",
+    "zh_TW.EUC@zhuyin",
     "zh_TW.UTF-8",
+    "zh_TW.UTF-8@pinyin",
+    "zh_TW.UTF-8@radical",
+    "zh_TW.UTF-8@stroke",
+    "zh_TW.UTF-8@zhuyin",
     "zh_TW.big5",
     "zh_TW.ccdc",
     "zh_TW.eucTW",
     "zh_TW.euctw",
     "zh_TW.utf8",
 
-    "C.iso88591",
-    "C.iso885915",
-    "C.utf8",
-    "common",
-    "iso_8859_1",
-    "iso_8859_13",
-    "iso_8859_15",
-    "iso_8859_2",
-    "iso_8859_5",
-    "iso_8859_7",
-    "iso_8859_9",
-
     // Windows names
     "ENU", "ENG", "ENA", "ENC", "ENZ", "ENI", "ENS", "ENJ", "ENB", "ENL",
     "ENT", "BGR", "CSY", "DAN", "DEU", "DES", "DEA", "DEL", "DEC", "ELL",
@@ -1161,4 +1459,4 @@
     "BEL", "CAT", "ETI", "FOS", "IND", "LVI", "LTH", "UKR"
 };
 
-const unsigned nloc = sizeof loc / sizeof *loc;
+const unsigned nlocales = sizeof test_locale_names / sizeof *test_locale_names;