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]

Re: [PATCH] Read locale settings from environment


Hi Corinna,

There is a problem with this patch. The code path you have made changes to
applies when locale is set to "C" or "". In the case of "C" the old code should still be in place (i.e. if !strcmp(locale, "C")). A check is needed for when !strcmp(locale, ""). If you make that fix, it should be fine.


Another problem exists with the current code. The return value from LC_ALL should be a concatenation of the various locale settings separated by a special character (e.g. ':'). The LC_ALL category needs to check if that is the form of the input string given and separate them out and call for each category. This way, the original settings can be restored on a subsequent call to setlocale() with the string given back from LC_ALL. This form only applies to LC_ALL and is not valid input for any other category.

-- Jeff J.

Corinna Vinschen wrote:
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





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