Skip to content

setlocale() always succeeds, even when the locale argument is unsupported #2630

Description

@b-spencer

The emscripten environment doesn't support multiple locales. It appears to only support the "C" locale (which is required), and this is fine. However, setlocale() seems to accept any locale name as an argument and succeeds, thus making it difficult to test if support for a given locale actually exists.

This issue is not requesting that locale support be added. It is asking if setlocale() should return NULL for unsupported locales (i.e. everything other than "C" or "POSIX").

For example, this program shows that setlocale() behaves differently than glibc on Linux:

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

int
main(const int argc, const char * const * const argv)
{
  const char * const locale = (argc > 1 ? argv[1] : "C");
  const char * const result = setlocale(LC_ALL, locale);
  printf("setlocale(LC_ALL, \"%s\") = %s%s%s\n", locale,
         result ? "\"" : "", result ? result : "NULL", result ? "\"" : "");
  return 0;
}
$ gcc -Wall -o setlocale setlocale.c
$ ./setlocale
setlocale(LC_ALL, "C") = "C"
$ ./setlocale C
setlocale(LC_ALL, "C") = "C"
$ ./setlocale POSIX
setlocale(LC_ALL, "POSIX") = "C"
$ ./setlocale en_CA.UTF-8
setlocale(LC_ALL, "en_CA.UTF-8") = "en_CA.UTF-8"
$ ./setlocale en_US.UTF-8
setlocale(LC_ALL, "en_US.UTF-8") = NULL
$ ./setlocale 'ThisLocaleCertainlyDoesNot!!!eXIST'
setlocale(LC_ALL, "ThisLocaleCertainlyDoesNot!!!eXIST") = NULL


$ emcc -Wall -o setlocale.js setlocale.c
$ node setlocale.js
setlocale(LC_ALL, "C") = ""

$ node setlocale.js C
setlocale(LC_ALL, "C") = ""

$ node setlocale.js POSIX
setlocale(LC_ALL, "POSIX") = ""
$ node setlocale.js en_CA.UTF-8
setlocale(LC_ALL, "en_CA.UTF-8") = ""

$ node setlocale.js en_US.UTF-8
setlocale(LC_ALL, "en_US.UTF-8") = ""

$ node setlocale.js 'ThisLocaleCertainlyDoesNot!!!eXIST'
setlocale(LC_ALL, "ThisLocaleCertainlyDoesNot!!!eXIST") = ""

Also, the default locale appears to be described by the empty string "". While this is legal, perhaps it should be "C", since that is the name of the actual required locale, and that name must be usable with setlocale().

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

int
main(const int argc, const char * const * const argv)
{
  const char * const result = setlocale(LC_ALL, NULL);
  printf("setlocale(LC_ALL, NULL) = %s%s%s\n",
         result ? "\"" : "", result ? result : "NULL", result ? "\"" : "");
  return 0;
}
$ ./showlocale
setlocale(LC_ALL, NULL) = "C"
$ node showlocale.js
setlocale(LC_ALL, NULL) = ""

Here's a program that demonstrates the locale not being honoured. In fact, this is really a separate bug because in the required "C" locale, iswalpha() shouldn't be returning 1 for non-ASCII characters, as far as I know.

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

int
main(const int argc, const char * const * const argv)
{
  const char * const locale = (argc > 1 ? argv[1] : "C");
  const char * const actual = setlocale(LC_ALL, locale);
  if(actual == NULL) {
    printf("%s locale not supported; skipped locale-dependent code\n",
           locale);
    return 0;
  }
  printf("locale set to %s: %s\n", locale, actual);

  const int result = iswalpha(0xf4); // ô
  printf("iswalpha(\"\xc3\xb4\") = %d\n", result);
  return 0;
}
$ gcc -Wall -o iswalpha iswalpha.c && ./iswalpha
locale set to C: C
iswalpha("ô") = 0
$ ./iswalpha nosuch
nosuch locale not supported; skipped locale-dependent code

$ emcc -Wall -o iswalpha.js iswalpha.c && node ./iswalpha.js
locale set to C:
iswalpha("ô") = 1
$ node ./iswalpha.js nosuch
locale set to nosuch:
iswalpha("ô") = 1

I can file a separate issue for the last test program above, if you wish to treat it separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions