This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Read locale settings from environment


Hi,

the below patch adds a bit of missing functionality to setlocale.  Per
POSIX the setlocale function is supposed to read the locale settings
from the environment if an application initializes locale support by
calling

  setlocale (LC_ALL, "");

Unfortunately this isn't done in newlib's implementation so far.

POSIX requires that a setting of $LC_ALL overrides all other settings,
while $LANG is just used as a fall back if any of the $LC_foo variables
are missing.  The below patch implements that.


Corinna


	* libc/locale/locale.c (_setlocale_r): Read environment settings
	as per POSIX.


Index: libc/locale/locale.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/locale.c,v
retrieving revision 1.8
diff -u -p -r1.8 locale.c
--- libc/locale/locale.c	23 Apr 2004 21:44:21 -0000	1.8
+++ libc/locale/locale.c	13 Feb 2009 18:03:31 -0000
@@ -91,6 +91,7 @@ No supporting OS subroutines are require
 #include <string.h>
 #include <limits.h>
 #include <reent.h>
+#include <stdlib.h>
 
 #ifdef __CYGWIN__
 int __declspec(dllexport) __mb_cur_max = 1;
@@ -144,11 +145,60 @@ _DEFUN(_setlocale_r, (p, category, local
             return 0;
           if (category == LC_ALL)
             {
-              strcpy (last_lc_ctype, __lc_ctype);
-              strcpy (__lc_ctype, "C");
-              strcpy (last_lc_messages, lc_messages);
-              strcpy (lc_messages, "C");
-              __mb_cur_max = 1;
+	      char *env, *ret;
+	      int saw_ctype = 0, saw_message = 0;
+
+	      /* Per POSIX, $LC_ALL has precedence over any of the other. */
+	      if ((env = _getenv_r (p, "LC_ALL")))
+	      	{
+		  ret = _setlocale_r (p, LC_CTYPE, env);
+		  if (ret)
+		    _setlocale_r (p, LC_MESSAGES, env);
+		  return last_lc_ctype;
+		}
+	      else
+	        {
+		  env = _getenv_r (p, "LC_CTYPE");
+		  if (env)
+		    {
+		      if (!(ret = _setlocale_r (p, LC_CTYPE, env)))
+			return NULL;
+		      saw_ctype = 1;
+		    }
+		  env = _getenv_r (p, "LC_MESSAGES");
+		  if (env)
+		    {
+		      if (!(ret = _setlocale_r (p, LC_MESSAGES, env)))
+			return NULL;
+		      saw_message = 1;
+		    }
+		  if (!saw_ctype || !saw_message)
+		    {
+		      /* Per POSIX, $LANG is fallback for any missing. */
+		      if ((env = _getenv_r (p, "LANG"))
+			  && (env = strchr (env, '.')))
+			{
+			  if (!saw_ctype
+			      && !(ret = _setlocale_r (p, LC_CTYPE, env + 1)))
+			    return NULL;
+			  if (!saw_message
+			      && !(ret = _setlocale_r (p, LC_MESSAGES, env + 1)))
+			    return NULL;
+			  saw_ctype = saw_message = 1;
+			}
+		    }
+		}
+	      if (!saw_ctype)
+		{
+		  strcpy (last_lc_ctype, __lc_ctype);
+		  strcpy (__lc_ctype, "C");
+		  __mb_cur_max = 1;
+		}
+	      if (!saw_message)
+		{
+		  strcpy (last_lc_messages, lc_messages);
+		  strcpy (lc_messages, "C");
+		}
             }
         }
       else


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]