duplocale: Work around AIX 7.1 bug.
[gnulib.git] / lib / duplocale.c
index 78819cf..3f33030 100644 (file)
@@ -1,5 +1,5 @@
 /* Duplicate a locale object.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include <locale.h>
 
 #include <errno.h>
-#include <langinfo.h>
 #include <string.h>
 
-/* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
-   glibc < 2.12.
-   See <http://sourceware.org/bugzilla/show_bug.cgi?id=10968>.  */
-#undef _NL_LOCALE_NAME
-#define _NL_LOCALE_NAME(category) _NL_ITEM ((category), _NL_ITEM_INDEX (-1))
-
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
 
 #undef duplocale
@@ -39,74 +32,68 @@ locale_t
 rpl_duplocale (locale_t locale)
 {
   /* Work around crash in the duplocale function in glibc < 2.12.
-     See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>.  */
+     See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>.
+     Also, on AIX 7.1, duplocale(LC_GLOBAL_LOCALE) returns (locale_t)0 with
+     errno set to EINVAL.  */
   if (locale == LC_GLOBAL_LOCALE)
     {
       /* Create a copy of the locale by fetching the name of each locale
-        category, starting with LC_CTYPE.  */
-      static struct { int cat; int mask; } categories[] =
-       {
-           { LC_NUMERIC,        LC_NUMERIC_MASK },
-           { LC_TIME,           LC_TIME_MASK },
-           { LC_COLLATE,        LC_COLLATE_MASK },
-           { LC_MONETARY,       LC_MONETARY_MASK },
-           { LC_MESSAGES,       LC_MESSAGES_MASK }
+         category, starting with LC_CTYPE.  */
+      static struct { int cat; int mask; } const categories[] =
+        {
+            { LC_NUMERIC,        LC_NUMERIC_MASK },
+            { LC_TIME,           LC_TIME_MASK },
+            { LC_COLLATE,        LC_COLLATE_MASK },
+            { LC_MONETARY,       LC_MONETARY_MASK },
+            { LC_MESSAGES,       LC_MESSAGES_MASK }
 #ifdef LC_PAPER
-         , { LC_PAPER,          LC_PAPER_MASK }
+          , { LC_PAPER,          LC_PAPER_MASK }
 #endif
 #ifdef LC_NAME
-         , { LC_NAME,           LC_NAME_MASK }
+          , { LC_NAME,           LC_NAME_MASK }
 #endif
 #ifdef LC_ADDRESS
-         , { LC_ADDRESS,        LC_ADDRESS_MASK }
+          , { LC_ADDRESS,        LC_ADDRESS_MASK }
 #endif
 #ifdef LC_TELEPHONE
-         , { LC_TELEPHONE,      LC_TELEPHONE_MASK }
+          , { LC_TELEPHONE,      LC_TELEPHONE_MASK }
 #endif
 #ifdef LC_MEASUREMENT
-         , { LC_MEASUREMENT,    LC_MEASUREMENT_MASK }
+          , { LC_MEASUREMENT,    LC_MEASUREMENT_MASK }
 #endif
 #ifdef LC_IDENTIFICATION
-         , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK }
+          , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK }
 #endif
-       };
+        };
       const char *base_name;
       locale_t base_copy;
       unsigned int i;
 
-      base_name = nl_langinfo (_NL_LOCALE_NAME (LC_CTYPE));
-      if (base_name[0] == '\0')
-       /* Fallback code for glibc < 2.4, which did not implement
-          nl_langinfo (_NL_LOCALE_NAME (category)).  */
-       base_name = setlocale (LC_CTYPE, NULL);
+      base_name = setlocale (LC_CTYPE, NULL);
       base_copy = newlocale (LC_ALL_MASK, base_name, NULL);
       if (base_copy == NULL)
-       return NULL;
+        return NULL;
 
       for (i = 0; i < SIZEOF (categories); i++)
-       {
-         int category = categories[i].cat;
-         int category_mask = categories[i].mask;
-         const char *name = nl_langinfo (_NL_LOCALE_NAME (category));
-         if (name[0] == '\0')
-           /* Fallback code for glibc < 2.4, which did not implement
-              nl_langinfo (_NL_LOCALE_NAME (category)).  */
-           name = setlocale (category, NULL);
-         if (strcmp (name, base_name) != 0)
-           {
-             locale_t copy = newlocale (category_mask, name, base_copy);
-             if (copy == NULL)
-               {
-                 int saved_errno = errno;
-                 freelocale (base_copy);
-                 errno = saved_errno;
-                 return NULL;
-               }
-             /* No need to call freelocale (base_copy) if copy != base_copy;
-                the newlocale function already takes care of doing it.  */
-             base_copy = copy;
-           }
-       }
+        {
+          int category = categories[i].cat;
+          int category_mask = categories[i].mask;
+          const char *name = setlocale (category, NULL);
+          if (strcmp (name, base_name) != 0)
+            {
+              locale_t copy = newlocale (category_mask, name, base_copy);
+              if (copy == NULL)
+                {
+                  int saved_errno = errno;
+                  freelocale (base_copy);
+                  errno = saved_errno;
+                  return NULL;
+                }
+              /* No need to call freelocale (base_copy) if copy != base_copy;
+                 the newlocale function already takes care of doing it.  */
+              base_copy = copy;
+            }
+        }
 
       return base_copy;
     }