[PATCH] Read locale settings from environment
Jeff Johnston
jjohnstn@redhat.com
Fri Feb 20 08:01:00 GMT 2009
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
>
>
>
More information about the Newlib
mailing list