LINUX.ORG.RU

Баг newlocale?

 , ,


0

3
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <locale.h>

int main(void) {

    locale_t loc = newlocale(LC_ALL_MASK, "en_US.utf8", NULL);
    if (loc == 0) {
        printf("NEW: %d %s\n", errno, strerror(errno));
        return 1;
    }
     if (uselocale(loc) == 0) {
        printf("USE: %d %s\n", errno, strerror(errno));
        return 1;
    }

    for (int i = 0; i < 50; i++)
        printf("%d %s\n", i, strerror(i));
        
    freelocale(loc);
    return 0;
}
$ ./error.elf 
0 Выполнено
1 Операция не позволена
2 Нет такого файла или каталога
3 Нет такого процесса
4 Прерван системный вызов
5 Ошибка ввода/вывода
...

ЧЯДНТ?

$ locale --all
C
C.UTF-8
en_AG
en_AG.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IL
en_IL.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW.utf8
POSIX
ru_RU.utf8
ru_UA.utf8
★★★★

Ответ на: комментарий от NAY_GIGGER

Это вы ещё ада с локалями на Windows не видели.

На Windows нет никакого ада с локалями.

Максимум есть люди кто не читал документацию…

fsb4000 ★★★★★ ()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от NAY_GIGGER

Есть, как минимум был во времена семёрки и до неё. Для примера - юникод в консоли со скрипом впихивали.

Юникод в консоли появился с момента стандарта юникода, с Windows NT 3.51

Говорю же, единственная проблема это ламерки…

fsb4000 ★★★★★ ()
Ответ на: комментарий от NAY_GIGGER

Это вы ещё ада с локалями на Windows не видели.

Там в FormatMessage передается локаль, (почти) то же самое, что и здесь.

Да, хочу английский. или китайский, если он есть в системе.

PPP328 ★★★★ ()
Последнее исправление: PPP328 (всего исправлений: 1)
locale_t loc = newlocale(LC_ALL_MASK, "en_US.utf8", (locale_t) 0);
Если значение base равно специальному объекту локали LC_GLOBAL_LOCALE (смотрите duplocale(3)) или не равно (locale_t) 0 и это некорректный указатель объекта локали, то поведение не определено.
olelookoe ()
Ответ на: комментарий от olelookoe

В xlocale.h:

typedef struct __locale_struct
{
  /* Note: LC_ALL is not a valid index into this array.  */
  struct __locale_data *__locales[13]; /* 13 = __LC_LAST. */

  /* To increase the speed of this solution we add some special members.  */
  const unsigned short int *__ctype_b;
  const int *__ctype_tolower;
  const int *__ctype_toupper;

  /* Note: LC_ALL is not a valid index into this array.  */
  const char *__names[13];
} *__locale_t;

/* POSIX 2008 makes locale_t official.  */
typedef __locale_t locale_t;

locale_t – это указатель на структуру __locale_struct, почему вместо (locale_t) 0 нельзя использовать NULL?

u-235 ()
Ответ на: комментарий от PPP328

почему вместо (locale_t) 0 нельзя использовать NULL?

NULL - это (void *)0.

приходилось встречать и #define NULL ((void*)-1), #define NULL __nullpointer , где __nullpointer это значение вшитое в компилятор и прочее затейливое хз.

а поскольку все остальное выглядит нормально, можно предположить что лажа где-то там, где мы предположили, что NULL это (void *)0.

olelookoe ()
Ответ на: комментарий от olelookoe

Не раблтает даже пример из мана setlocale - меняется дата и число, но если поменять на ALL, то не меняется strerror. А там 0.

PPP328 ★★★★ ()
Последнее исправление: PPP328 (всего исправлений: 1)
Ответ на: комментарий от NAY_GIGGER

Если брать пример из мана - то в нем работает NUMERIC и TIME, ALL в нем не используется, а как раз ALL и не работает. Если в примере из мана поменять на ALL (о чем я уже писал) и добавить strerror - то НЕ работает.

Указание C - выводит на английском, en_US.utf8 при этом на английском не выводит. Если указать кодировку, которая не установлена в системе - то ругается про «cannot find file locate», как и должно.

PPP328 ★★★★ ()
Ответ на: комментарий от PPP328

Я когда-то сталкивался с такой проблемой но немного в другом месте - неработала интернациализация в PHP хотя локали были. Как оно решилось, к сожалению, не помню но вроде, надо было перегенерировать что-то в самой системе и проблема была совсем не в коде\языке.

NAY_GIGGER ()
Ответ на: комментарий от NAY_GIGGER

надо было перегенерировать что-то в самой системе и проблема была совсем не в коде\языке.

Окей, я не спорю, что проблема может быть в самой системе, а не в glibc. Но тогда получается что в дефолтной бубунте это не работает.

PPP328 ★★★★ ()
Ответ на: комментарий от PPP328

Ну хоть что-то поменялось:

  • расскоментировал zh_CN и ru_RU (обе UTF-8)
  • sudo locale-gen

Вроде всё есть, но не работает.

P.S. Вылает на первой же проверке.

NAY_GIGGER ()
Последнее исправление: NAY_GIGGER (всего исправлений: 1)
Ответ на: комментарий от NAY_GIGGER

Попробовал запустить на винде, тот-же самый код из шапки темы, но MS не доложили легаси и в итоге либо сидеть и вчитываться в реализацию костылей из 2000х либо забить.

NAY_GIGGER ()
Последнее исправление: NAY_GIGGER (всего исправлений: 1)
Ответ на: комментарий от Toxo2

Поиграл ещё в эту игру.

В общем - если убрать каталог /usr/share/locale-langpack в Ubuntu, то всё работает. Просто переименовать в *.SAV - американские сообщения. Возвращаем обратно - русские сообщения.

Что это за зверь locale-langpack я ещё не понял. Тупо сравнивал strings a.out скомпилированные под разными ОС и разными libc (у меня тут ещё и Debian 9 установлен с libc 2.24) так вот эта строчка упоминается только в бинарниках собранных Ubuntu.

Пардон, если ещё сильнее всё запутал. Просто любопытство разбирало.

Toxo2 ()
Ответ на: комментарий от NAY_GIGGER

Ну, пока всё выглядит так. Это запчасть от language-pack-ru, сугубо Ubuntu пакета, который, как я понял, устанавливается автоматически. Но он не то чтобы про locale в целом. Какая-то пришлёпка сбоку. Вроде так.

Toxo2 ()
Ответ на: комментарий от Toxo2

Смеркалось. Неймалось.

Чтоб уж окончательно поставить точку. Взял исходники Ubuntu libc 2.31. Там есть заплатка /libc-2.31/debian/patches/ubuntu/local-altlocaledir.diff, вот она и делает это.

+  const char* langpack_dir = "/usr/share/locale-langpack";
+  if (strncmp(filename, "LC_MESSAGES", strlen("LC_MESSAGES")) == 0) {
+    for (cnt = mask; cnt >= 0; --cnt)
+      if ((cnt & ~mask) == 0)
+	{
+	    retval->successor[entries++]
+	      = _nl_make_l10nflist (l10nfile_list, langpack_dir, strlen (langpack_dir) + 1, cnt,
+				    language, territory, codeset,
+				    normalized_codeset, modifier, filename, 1);
+	}
+  }
Toxo2 ()