[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