Создание и опрос характеристик языково-культурной среды
Для создания целевой языково-культурной среды служит утилита localedef:
localedef [-c] [-f файл_отображения_символов] [-i исходный_файл] [-u имя_набора_символов] имя_целевой_среды
Утилита localedef преобразует рассмотренное выше определение категорий языково-культурной среды из исходного формата в целевой, пригодный для использования функциями и служебными программами, поведение которых зависит от значений переменных окружения.
Исходные данные для localedef поступают из файла с именем операнда опции -i или со стандартного ввода.
Операнд имя_целевой_среды определяет имя создаваемой среды. Она может быть как общедоступной, так и приватной, с ограниченным доступом.
Аргументом опции -f является маршрутное имя файла отображения символов. После опции -u можно задать имя нестандартного набора символов.
Опция -c предписывает генерировать выходной файл даже при наличии предупреждений.
Аргумент имя_целевой_среды идентифицирует созданную языково-культурную среду. Если это имя начинается с символа /, оно интерпретируется как маршрутное имя, под которым сохраняется сгенерированное определение целевой среды (формат результатов работы localedef стандартом не специфицируется); в противном случае интерпретация имени зависит от реализации, а созданная среда становится общедоступной.
Для получения информации о языково-культурных средах предназначена служебная программа locale:
locale [-a | -m] locale [-ck] имя ...
Будучи вызванной без аргументов, утилита locale выдает на стандартный вывод сводную информацию о среде, которая состоит из значений соответствующих переменных окружения (описанных выше, а также дополнительных, определенных, быть может, целевой системой). Результат может выглядеть так, как показано в пример 13.6. Кавычки вокруг значений всех переменных окружения, кроме LANG, означают, что они не были установлены явным образом, а определены по значению $LANG.
LANG=ru_RU.koi8r LC_CTYPE="ru_RU.koi8r" LC_NUMERIC="ru_RU.koi8r" LC_TIME="ru_RU.koi8r" LC_COLLATE="ru_RU.koi8r" LC_MONETARY="ru_RU.koi8r" LC_MESSAGES="ru_RU.koi8r" LC_PAPER="ru_RU.koi8r" LC_NAME="ru_RU.koi8r" LC_ADDRESS="ru_RU.koi8r" LC_TELEPHONE="ru_RU.koi8r" LC_MEASUREMENT="ru_RU.koi8r" LC_IDENTIFICATION="ru_RU.koi8r" LC_ALL=
Пример 13.6. Возможный результат работы служебной программы locale. (html, txt)
При наличии аргументов выдается информация о некоторых (если задано ключевое слово) или обо всех (если указано имя категории) элементах категорий.
Опциям служебной программы locale приписан следующий смысл.
-a
Выдать информацию обо всех общедоступных языково-культурных средах (включая POSIX-среду).
-m
Выдать имена доступных файлов отображения символов.
-c
Выдавать имена выбранных (прямо или косвенно, посредством ключевых слов) категорий, что делает результаты более читабельными, когда они охватывают несколько категорий.
-k
Выдавать имена и значения заданных элементов категорий.
Операнд имя может быть именем категории, элемента категории (ключевым словом) или зарезервированным словом charmap. В двух первых случаях выдается информация о поименованной категории или ее элементе, в последнем – имя файла отображения символов, который был использован при создании языково-культурной среды.
Приведем еще два примера употребления утилиты locale. Данные о категории LC_TIME, выдаваемые по команде
locale -ck LC_TIME
могут выглядеть так, как показано в пример 13.7.
LC_TIME abday="Вск;Пнд;Втр;Срд;Чтв;Птн;Сбт" day="Воскресенье;Понедельник;Вторник;Среда; Четверг;Пятница;Суббота" abmon="Янв;Фев;Мар;Апр;Май;Июн;Июл;Авг;Сен; Окт;Ноя;Дек" mon="Января;Февраля;Марта;Апреля;Мая;Июня; Июля;Августа;Сентября;Октября;Ноября;Декабря" d_t_fmt="%a %d %b %Y %T" d_fmt="%d.%m.%Y" t_fmt="%T" . . . first_weekday=1 first_workday=1 cal_direction=1 date_fmt="%a %b %e %H:%M:%S %Z %Y" time-codeset="KOI8-R"
Пример 13.7. Фрагмент возможного результата выполнения команды locale -ck LC_TIME. (html, txt)
Второй пример демонстрирует фрагмент интернационализированного варианта shell-процедуры, анализирующей интерактивный ответ пользователя. Предполагается, что ответ является значением переменной response.
if echo "$response" | grep -Eq "$(locale yesexpr)" then echo "Ответ положительный" else echo "Ответ отрицательный" fi
Пример 13.8. Фрагмент интернационализированного варианта shell-процедуры. (html, txt)
Пример 13.8. Фрагмент интернационализированного варианта shell-процедуры.
Программная установка и опрос характеристик языково-культурной среды
Мы приступаем к рассмотрению функций, предназначенных для работы с языково-культурной средой.
Функция setlocale() (см. пример 13.9) служит для установки и/или опроса всей языково-культурной среды вызывающего процесса или отдельных категорий.
#include <locale.h> char *setlocale (int category, const char *locale);
Пример 13.9. Описание функции setlocale().
Аргумент category задает категорию (LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME), а если его значение равно LC_ALL, то и всю среду.
Аргумент locale указывает на цепочку символов, содержащую требуемые установки для выбранной категории (категорий); в общем случае ее формат зависит от реализации. Имеется, однако, несколько предопределенных, стандартизованных цепочек.
"POSIX" или "C"
Специфицирует минимальную языково-культурную среду (POSIX-среду) для C-программ. При отсутствии явных обращений к функции setlocale() такая среда устанавливается по умолчанию при входе в main().
""
Специфицирует зависящую от реализации местную языково-культурную среду, определяемую значениями переменных окружения LC_* и LANG. Интернационализированная программа должна выполнять вызов вида
setlocale (LC_ALL, "");
для настройки на местную среду выполнения.
Если значением аргумента locale служит пустой указатель, функция setlocale() опрашивает текущее окружение и возвращает имя используемой языково-культурной среды или цепочку символов, ассоциированную с выбранной категорией. В противном случае в качестве результата возвращаются те же характеристики, но для новой среды. Результирующая цепочка (скопированная в отведенную прикладной программой область памяти) в сочетании с заданной категорией может быть использована в последующих вызовах функции setlocale() для восстановления соответствующей части языково-культурной среды.
Разумеется, в случае неудачного завершения вызова setlocale() результатом служит пустой указатель.
Пример 13.11. Пример использования функций setlocale() и localeconv().
Возможный результат работы этой программы показан в пример 13.12.
Текущая языково-культурная среда: подразумеваемая Цепочки символов, ассоциированные в текущей среде с LC_ALL: C LC_COLLATE: C LC_CTYPE: C LC_MESSAGES: C LC_MONETARY: C LC_NUMERIC: C LC_TIME: C Текущая языково-культурная среда: местная Цепочки символов, ассоциированные в текущей среде с LC_ALL: ru_RU.koi8r LC_COLLATE: ru_RU.koi8r LC_CTYPE: ru_RU.koi8r LC_MESSAGES: ru_RU.koi8r LC_MONETARY: ru_RU.koi8r LC_NUMERIC: ru_RU.koi8r LC_TIME: ru_RU.koi8r Некоторые элементы категорий LC_MONETARY и LC_NUMERIC int_curr_symbol: RUR currency_symbol: РУБ mon_decimal_point: . decimal_point: , thousands_sep: . Категория LC_MONETARY переустановлена для Украины Цепочки символов, ассоциированные в текущей среде с LC_ALL: LC_CTYPE=ru_RU.koi8r;LC_NUMERIC=ru_RU.koi8r; LC_TIME=ru_RU.koi8r;LC_COLLATE=ru_RU.koi8r; LC_MONETARY=ru_UA;LC_MESSAGES=ru_RU.koi8r; LC_PAPER=ru_RU.koi8r;LC_NAME=ru_RU.koi8r; LC_ADDRESS=ru_RU.koi8r;LC_TELEPHONE=ru_RU.koi8r; LC_MEASUREMENT=ru_RU.koi8r; LC_IDENTIFICATION=ru_RU.koi8r LC_COLLATE: ru_RU.koi8r LC_CTYPE: ru_RU.koi8r LC_MESSAGES: ru_RU.koi8r LC_MONETARY: ru_UA LC_NUMERIC: ru_RU.koi8r LC_TIME: ru_RU.koi8r Некоторые элементы категории LC_MONETARY int_curr_symbol: UAH currency_symbol: ГР
Пример 13.12. Возможный результат работы программы, использующей функции setlocale() и localeconv().
Для преобразования денежных величин в цепочку символов в соответствии с настройками текущей языково-культурной среды можно воспользоваться функцией strfmon() (см. пример 13.13), входящей в XSI-расширение стандарта POSIX-2001.
#include <monetary.h> ssize_t strfmon (char *restrict s, size_t maxsize, const char *restrict format, ...);
Пример 13.13. Описание функции strfmon().
Результат преобразования (длиной не более maxsize байт) помещается в буфер, на который указывает аргумент s. Само преобразование выполняется под управлением аргумента format.
Пример 13.14. Пример программы, работающей в нескольких языково-культурных средах.
Текущая языково-культурная среда: подразумеваемая
isalpha ('Б'): 0 tolower ('Б'): 'Б' Результат преобразования в денежную величину числа 1234.567 Международное обозначение: 1234.57 Местное обозначение: 1234.57 Текущая языково-культурная среда: местная isalpha ('Б'): 1024 tolower ('Б'): 'б' Результат преобразования в денежную величину числа 1234.567 Международное обозначение: 1 234.57 RUR Местное обозначение: 1 234. 57 руб Категория LC_MONETARY переустановлена для Украины Результат преобразования в денежную величину числа 1234.567 Международное обозначение: 1 234.57 UAH Местное обозначение: 1 234.57 ГР
Пример 13.15. Текущая языково-культурная среда: подразумеваемая
Если требуется получить детальную информацию обо всех аспектах языково-культурной среды, можно воспользоваться функцией nl_langinfo() (см. пример 13.16), отнесенной стандартом POSIX-2001 к расширению XSI.
#include <langinfo.h> char *nl_langinfo (nl_item item);
Пример 13.16. Описание функции nl_langinfo().
Аргументом функции nl_langinfo() могут служить именованные константы, определенные в заголовочном файле <langinfo.h>. В общем и целом они соответствуют описанным выше ключевым словам. В качестве результата nl_langinfo() возвращает указатель на цепочку символов, содержащую данные о выбранном элементе среды. Если в текущей среде этот элемент отсутствует, выдаются данные для POSIX-среды.
Пример программы, использующей функцию nl_langinfo(), показан в пример 13.17, возможные результаты ее работы – в пример 13.18.
#include <stdio.h> #include <locale.h> #include <langinfo.h> #include <regex.h> #include <limits.h>
int main (void) { regex_t cere; /* Скомпилированные расширенные */ /* регулярные выражения */ regex_t ceren; int reerrcode; /* Код ошибки от regcomp или */ /* regexec */ char reerrbuf [LINE_MAX]; /* Буфер для строк с */ /* сообщениями об ошибках */ char response [LINE_MAX]; /* Буфер для ответа */
Пример 13.18. Возможные результаты работы программы, использующей функцию nl_langinfo().
К сожалению, обязательная часть стандарта POSIX-2001 содержит лишь минимум средств для настройки на целевую среду выдаваемых диагностических сообщений. По сути он сводится к функции strerror() (см. пример 13.19), которая отображает номера (коды) ошибок в сообщения, зависящие от языково-культурной среды, точнее, от установки категории LC_MESSAGES.
#include <string.h> char *strerror (int errnum);
Пример 13.19. Описание функции strerror().
Обычно в качестве аргумента этой функции используют errno, но номера ошибок могут поступать и из произвольного источника.
В пример 13.20 показан пример программы, выдающей диагностические сообщения в разных средах и разными средствами – с помощью функций perror() и strerror().
#include <stdio.h> #include <locale.h> #include <string.h> #include <errno.h>
int main (void) { fprintf (stderr, "Текущая языково-культурная среда: подразумеваемая\n"); errno = 1; perror ("PERROR, сообщение номер 1"); fprintf (stderr, "STRERROR, сообщение номер 1: %s\n", strerror (1)); (void) setlocale (LC_ALL, ""); fprintf (stderr, "Текущая языково-культурная среда: местная\n"); errno = 1; perror ("PERROR, сообщение номер 1"); fprintf (stderr, "STRERROR, сообщение номер 1: %s\n", strerror (1)); (void) setlocale (LC_MESSAGES, "ru_UA"); fprintf (stderr, "Категория LC_MESSAGES переустановлена для Украины\n"); errno = 1; perror ("PERROR, сообщение номер 1"); fprintf (stderr, "STRERROR, сообщение номер 1: %s\n", strerror (1)); return 0; }
Пример 13.20. Пример программы, выдающей диагностические сообщения в разных языково-культурных средах и разными средствами.