Can not `setlocale(3)' more than once in Linux

Discussion in 'C Programming' started by Steven Woody, Apr 25, 2008.

  1. Steven Woody

    Steven Woody Guest

    Hi,

    I am in Linux writing a program using setlocale(3). But I found, only
    the first invocation of setlocale(3) can be success, any subsequent
    calling of this function will fail ( return NULL ) and the locale is
    not changed. Is there any tip here?

    Thanks.


    #define _(String) gettext (String)

    static void init_lc( const char* lc )
    {
    setlocale( LC_ALL, "" );
    bindtextdomain( "hello", "/usr/local/share/locale" );
    textdomain( "hello" );
    }

    int main( void )
    {
    init_lc( "" );

    printf( _("Current locale is %s\n"), setlocale( LC_ALL, NULL ) );
    printf( _("press 'e' to select English, 'c' to select Simplified
    Chinese: ") );

    int c;
    while ( true ) {
    c = getch();
    if ( c == 'e' )
    setlocale( "en_US" );
    else if ( c == 'c' )
    setlocale( "zh_CN" );
    printf( _("press 'e' to select English, 'c' to select
    Simplified Chinese: ") );
    printf( _("Hello, world!\n") );
    }

    return 0;
    }
     
    Steven Woody, Apr 25, 2008
    #1
    1. Advertising

  2. Steven Woody <> writes:

    > I am in Linux writing a program using setlocale(3). But I found, only
    > the first invocation of setlocale(3) can be success, any subsequent
    > calling of this function will fail return NULL ) and the locale is
    > not changed. Is there any tip here?


    All I can say is that is not the case on my system. I can call
    setlocale as often as I like. The program you posted should not have
    compiled and certainly would not have been able to set the locale
    since all but on of the calls was badly formed so it is not clear to me
    how you even know there is a problem.

    Although the function is standard, the standard says very little about
    what locale strings mean, so you will need to post in, say,
    comp.unix.programmer to get more help. Before you do, prepare a small
    example that illustrates the problem you are having. The solution may
    be simple.

    --
    Ben.
     
    Ben Bacarisse, Apr 25, 2008
    #2
    1. Advertising

  3. On 25 Apr 2008 at 7:37, Steven Woody wrote:
    > I am in Linux writing a program using setlocale(3). But I found, only
    > the first invocation of setlocale(3) can be success, any subsequent
    > calling of this function will fail ( return NULL ) and the locale is
    > not changed. Is there any tip here?

    [snip]
    > if ( c == 'e' )
    > setlocale( "en_US" );
    > else if ( c == 'c' )
    > setlocale( "zh_CN" );


    The prototype for setlocale is
    char *setlocale(int category, const char *locale);

    You're missing an argument.
     
    Antoninus Twink, Apr 25, 2008
    #3
  4. Steven Woody

    Steven Woody Guest

    On Apr 25, 11:55 pm, Antoninus Twink <> wrote:
    > On 25 Apr 2008 at 7:37, Steven Woody wrote:
    >
    > > I am in Linux writing a program usingsetlocale(3). But I found, only
    > > the first invocation ofsetlocale(3) can be success, any subsequent
    > > calling of this function will fail ( return NULL ) and the locale is
    > > not changed. Is there any tip here?

    > [snip]
    > > if ( c == 'e' )
    > > setlocale( "en_US" );
    > > else if ( c == 'c' )
    > > setlocale( "zh_CN" );

    >
    > The prototype forsetlocaleis
    > char *setlocale(int category, const char *locale);
    >
    > You're missing an argument.


    Sorry, when I modified the original code to make it simple to show
    you, I made some errors. But the original code is right and I did
    supplied correct arguments. Well, below is a correct version of the
    code and I made it more simple to illustrate the problem:

    #include <libintl.h>
    #include <locale.h>
    #include <stdio.h>

    int main( void )
    {
    printf( "Current locale is %s\n", setlocale( LC_ALL, NULL ) );

    bindtextdomain( "hellonls", "/usr/local/share/locale" );
    textdomain( "hellonls" );

    const char* msg = gettext( "Hello, world!" );

    if ( ! setlocale( LC_ALL, "en_US" ) )
    fprintf( stderr, "setlocale( en_US ) error\n" );
    printf( "%s\n", msg );

    if ( ! setlocale( LC_ALL, "zh_CN" ) )
    fprintf( stderr, "setlocale( zh_CN ) error\n" );
    printf( "%s\n", msg );

    if ( ! setlocale( LC_ALL, "" ) )
    fprintf( stderr, "setlocale( \"\" ) error\n" );
    printf( "%s\n", msg );

    return 0;
    }

    I found only the 3rd invocation of setlocale( ... ) can be success,
    that is, I can only set locale to the system default. The calling
    lines with "en_US" and "zh_CN" failed and returned NULL. So if my
    system has LC_ALL=en_US, the code will print three same lines of
    "Hello, world!" in english on the stdout, and If I set the LC_ALL to
    zh_CN before run the code, I will got three same lines of "Hello,
    world!" in Chinese.

    Could you please try the code and tell me what's wrong here? You may
    need to change "zh_CN" to a suitable locale to you. Thanks.

    -
    woody
     
    Steven Woody, Apr 27, 2008
    #4
  5. On 27 Apr 2008 at 15:42, Steven Woody wrote:
    > I found only the 3rd invocation of setlocale( ... ) can be success,
    > that is, I can only set locale to the system default. The calling
    > lines with "en_US" and "zh_CN" failed and returned NULL.


    The first thing you could try is is perror(NULL) when setlocale() fails,
    and see if there's any useful error message.

    Then, try
    strace ./yourprog 2>&1 | grep locale
    and see if that provides any information.
     
    Antoninus Twink, Apr 27, 2008
    #5
  6. Steven Woody

    Flash Gordon Guest

    Steven Woody wrote, On 27/04/08 16:42:
    > On Apr 25, 11:55 pm, Antoninus Twink <> wrote:
    >> On 25 Apr 2008 at 7:37, Steven Woody wrote:


    <snip>

    >> You're missing an argument.

    >
    > Sorry, when I modified the original code to make it simple to show
    > you, I made some errors. But the original code is right and I did
    > supplied correct arguments.


    This, of course, is why you should always copy and paste actual tested code.

    > Well, below is a correct version of the
    > code and I made it more simple to illustrate the problem:
    >
    > #include <libintl.h>


    The above header is not defined by the C standard, so it would have been
    better if you provided an example which did not use it.

    > #include <locale.h>
    > #include <stdio.h>
    >
    > int main( void )
    > {
    > printf( "Current locale is %s\n", setlocale( LC_ALL, NULL ) );
    >
    > bindtextdomain( "hellonls", "/usr/local/share/locale" );
    > textdomain( "hellonls" );
    >
    > const char* msg = gettext( "Hello, world!" );


    The above three functions are not part of the C standard. It is possible
    they are doing something to affect the results, so try again without
    using them. If they are the problem then I suggest asking in a Linux
    group or if that is your platform or possibly comp.unix.programmer.

    > if ( ! setlocale( LC_ALL, "en_US" ) )
    > fprintf( stderr, "setlocale( en_US ) error\n" );


    I don't believe that errno is required to be set by setlocale, but it
    might be worth replacing the above (and the other error printouts) with
    calls to perror for testing just in case your implementation is helpful.
    I.e.
    perror( "setlocale( en_US ) error\n" );

    > printf( "%s\n", msg );
    >
    > if ( ! setlocale( LC_ALL, "zh_CN" ) )
    > fprintf( stderr, "setlocale( zh_CN ) error\n" );
    > printf( "%s\n", msg );
    >
    > if ( ! setlocale( LC_ALL, "" ) )
    > fprintf( stderr, "setlocale( \"\" ) error\n" );
    > printf( "%s\n", msg );
    >
    > return 0;
    > }
    >
    > I found only the 3rd invocation of setlocale( ... ) can be success,
    > that is, I can only set locale to the system default. The calling
    > lines with "en_US" and "zh_CN" failed and returned NULL. So if my
    > system has LC_ALL=en_US, the code will print three same lines of
    > "Hello, world!" in english on the stdout, and If I set the LC_ALL to
    > zh_CN before run the code, I will got three same lines of "Hello,
    > world!" in Chinese.
    >
    > Could you please try the code and tell me what's wrong here? You may
    > need to change "zh_CN" to a suitable locale to you. Thanks.


    Having removed the non-standard code and changed to supported locales it
    works, so I suspect either one of the non-standard function calls is
    breaking setlocale or you are selecting locales not supported on your
    system. If you ask on a group dedicated to your implementation they may
    be able to tell you how to check what locales are supported (you could
    try the command "locale -a") and as I say if removing the non-standard
    functions helps a group dedicated to your implementation may be able to
    tell you why.
    --
    Flash Gordon
     
    Flash Gordon, Apr 27, 2008
    #6
  7. Steven Woody <> writes:

    > Sorry, when I modified the original code to make it simple to show
    > you, I made some errors. But the original code is right and I did
    > supplied correct arguments. Well, below is a correct version of the
    > code and I made it more simple to illustrate the problem:


    <snip code>

    The problem is not (now) the call to setlocale but the way your system
    interprets the string it is passed. If you are using a POSIX system
    (most Unix-like OSes) then post in comp.unix.programmer and you will
    get access to lots of experts.

    Here, the topic is standard C, and your problem is no longer with that
    standard function but with what your system does with the string. The
    only help you are likely to get here is from Antoninus Twink who is
    single-handedly attempting to broaden the topicality here to include
    other languages as well as Linux locale commands. Over in c.u.p you
    will find lot of people who can help.

    --
    Ben.
     
    Ben Bacarisse, Apr 27, 2008
    #7
  8. Steven Woody

    Steven Woody Guest

    On Apr 28, 2:08 am, Ben Bacarisse <> wrote:
    > Steven Woody <> writes:
    > > Sorry, when I modified the original code to make it simple to show
    > > you, I made some errors. But the original code is right and I did
    > > supplied correct arguments. Well, below is a correct version of the
    > > code and I made it more simple to illustrate the problem:

    >
    > <snip code>
    >
    > The problem is not (now) the call to setlocale but the way your system
    > interprets the string it is passed. If you are using a POSIX system
    > (most Unix-like OSes) then post in comp.unix.programmer and you will
    > get access to lots of experts.
    >
    > Here, the topic is standard C, and your problem is no longer with that
    > standard function but with what your system does with the string. The
    > only help you are likely to get here is from Antoninus Twink who is
    > single-handedly attempting to broaden the topicality here to include
    > other languages as well as Linux locale commands. Over in c.u.p you
    > will find lot of people who can help.
    >
    > --
    > Ben.


    Yes, I think I am in wrong group. I will go to comp.unix.programmer.
    Thanks.
     
    Steven Woody, Apr 28, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rick Brandt
    Replies:
    7
    Views:
    472
    Rick Brandt
    Jun 24, 2004
  2. Replies:
    24
    Views:
    1,699
    alchemist
    Aug 4, 2005
  3. Gancy
    Replies:
    4
    Views:
    188
    Rasto Levrinc
    Feb 3, 2005
  4. Steven D'Aprano
    Replies:
    0
    Views:
    99
    Steven D'Aprano
    Dec 23, 2013
  5. Replies:
    3
    Views:
    89
    Gary Herron
    Dec 23, 2013
Loading...

Share This Page