]> Savannah Git Hosting - gnulib.git/commitdiff
setlocale-null: Handle NULL result from setlocale.
authorBruno Haible <bruno@clisp.org>
Wed, 18 Dec 2019 09:49:44 +0000 (10:49 +0100)
committerBruno Haible <bruno@clisp.org>
Wed, 18 Dec 2019 09:49:44 +0000 (10:49 +0100)
* lib/locale.in.h (setlocale_null): Document EINVAL return value.
* lib/setlocale_null.c (setlocale_null_unlocked): Handle NULL result
from setlocale or _wsetlocale.

ChangeLog
lib/locale.in.h
lib/setlocale_null.c

index 2fffaf2a291a6f4c4b7963ac5c682ee270e29940..d0d4d11865e25243331a17087f1d5c5fcfa44ceb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2019-12-18  Bruno Haible  <bruno@clisp.org>
+
+       setlocale-null: Handle NULL result from setlocale.
+       * lib/locale.in.h (setlocale_null): Document EINVAL return value.
+       * lib/setlocale_null.c (setlocale_null_unlocked): Handle NULL result
+       from setlocale or _wsetlocale.
+
+2019-12-18  Bruno Haible  <bruno@clisp.org>
+
+       hard-locale: Make multithread-safe.
+       * lib/hard-locale.h (hard_locale): Move documentation to here.
+       * lib/hard-locale.c: Don't include <stdlib.h>.
+       (GLIBC_VERSION): Remove macro.
+       (hard_locale): Assume that all systems name the "C" and "POSIX" locales
+       "C" or "POSIX". Invoke setlocale_null instead of setlocale.
+       * modules/hard-locale (Depends-on): Remove strdup. Add setlocale-null.
+
 2019-12-18  Bruno Haible  <bruno@clisp.org>
 
        hard-locale: Add test.
index 598668308bbd9c5dd39e9218fcf8089182c40b0a..67e6020fabc58a25b2a5fa059c3570170f5063bf 100644 (file)
@@ -228,10 +228,10 @@ _GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - "
    The recommended minimum buffer size is
      - SETLOCALE_NULL_MAX for CATEGORY != LC_ALL, and
      - SETLOCALE_NULL_ALL_MAX for CATEGORY == LC_ALL.
-   The return value is an error code: 0 if the call is successful, ERANGE if
-   BUFSIZE is smaller than the length needed size (including the trailing NUL
-   byte).  In the latter case, a truncated result is returned in BUF, but
-   still NUL-terminated if BUFSIZE > 0.
+   The return value is an error code: 0 if the call is successful, EINVAL if
+   CATEGORY is invalid, or ERANGE if BUFSIZE is smaller than the length needed
+   size (including the trailing NUL byte).  In the latter case, a truncated
+   result is returned in BUF, but still NUL-terminated if BUFSIZE > 0.
    For this call to be multithread-safe, *all* calls to
    setlocale (CATEGORY, NULL) in all other threads must have been converted
    to use setlocale_null as well, and the other threads must not make other
index 350eca7299af2453460a6b50ada6a6659d671796..8072a4560e00251380dfe3607547ee0e27fcef87 100644 (file)
@@ -63,52 +63,103 @@ setlocale_null_unlocked (int category, char *buf, size_t bufsize)
      on _wsetlocale() and uses malloc() for the result.  We are better off
      using _wsetlocale() directly.  */
   const wchar_t *result = _wsetlocale (category, NULL);
-  size_t length = wcslen (result);
-  if (length < bufsize)
-    {
-      size_t i;
-
-      /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
-      for (i = 0; i <= length; i++)
-        buf[i] = result[i];
 
-      return 0;
+  if (result == NULL)
+    {
+      /* CATEGORY is invalid.  */
+      if (bufsize > 0)
+        /* Return an empty string in BUF.
+           This is a convenience for callers that don't want to write explicit
+           code for handling EINVAL.  */
+        buf[0] = '\0';
+      return EINVAL;
     }
   else
     {
-      if (bufsize > 0)
+      size_t length = wcslen (result);
+      if (length < bufsize)
         {
-          /* Return a truncated result in BUF.
-             This is a convenience for callers that don't want to write
-             explicit code for handling ERANGE.  */
           size_t i;
 
           /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
-          for (i = 0; i < bufsize; i++)
+          for (i = 0; i <= length; i++)
             buf[i] = result[i];
-          buf[bufsize - 1] = '\0';
+
+          return 0;
+        }
+      else
+        {
+          if (bufsize > 0)
+            {
+              /* Return a truncated result in BUF.
+                 This is a convenience for callers that don't want to write
+                 explicit code for handling ERANGE.  */
+              size_t i;
+
+              /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
+              for (i = 0; i < bufsize; i++)
+                buf[i] = result[i];
+              buf[bufsize - 1] = '\0';
+            }
+          return ERANGE;
         }
-      return ERANGE;
     }
 #else
   const char *result = setlocale (category, NULL);
-  size_t length = strlen (result);
-  if (length < bufsize)
+
+# ifdef __ANDROID__
+  if (result == NULL)
+    switch (category)
+      {
+      case LC_CTYPE:
+      case LC_NUMERIC:
+      case LC_TIME:
+      case LC_COLLATE:
+      case LC_MONETARY:
+      case LC_MESSAGES:
+      case LC_ALL:
+      case LC_PAPER:
+      case LC_NAME:
+      case LC_ADDRESS:
+      case LC_TELEPHONE:
+      case LC_MEASUREMENT:
+        result = "C";
+        break;
+      default:
+        break;
+      }
+# endif
+
+  if (result == NULL)
     {
-      memcpy (buf, result, length + 1);
-      return 0;
+      /* CATEGORY is invalid.  */
+      if (bufsize > 0)
+        /* Return an empty string in BUF.
+           This is a convenience for callers that don't want to write explicit
+           code for handling EINVAL.  */
+        buf[0] = '\0';
+      return EINVAL;
     }
   else
     {
-      if (bufsize > 0)
+      size_t length = strlen (result);
+      if (length < bufsize)
+        {
+          memcpy (buf, result, length + 1);
+          return 0;
+        }
+      else
         {
-          /* Return a truncated result in BUF.
-             This is a convenience for callers that don't want to write
-             explicit code for handling ERANGE.  */
-          memcpy (buf, result, bufsize - 1);
-          buf[bufsize - 1] = '\0';
+          if (bufsize > 0)
+            {
+              /* Return a truncated result in BUF.
+                 This is a convenience for callers that don't want to write
+                 explicit code for handling ERANGE.  */
+              memcpy (buf, result, bufsize - 1);
+              buf[bufsize - 1] = '\0';
+            }
+          return ERANGE;
         }
-      return ERANGE;
     }
 #endif
 }