VirtualBox

source: kBuild/vendor/grep/current/gnulib-tests/localename.c@ 3530

Last change on this file since 3530 was 3529, checked in by bird, 3 years ago

Imported grep 3.7 from grep-3.7.tar.gz (sha256: c22b0cf2d4f6bbe599c902387e8058990e1eee99aef333a203829e5fd3dbb342), applying minimal auto-props.

  • Property svn:eol-style set to native
File size: 98.5 KB
Line 
1/* Determine name of the currently selected locale.
2 Copyright (C) 1995-2021 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17/* Written by Ulrich Drepper <[email protected]>, 1995. */
18/* Native Windows code written by Tor Lillqvist <[email protected]>. */
19/* Mac OS X code written by Bruno Haible <[email protected]>. */
20
21#include <config.h>
22
23/* Specification. */
24#include "localename.h"
25
26#include <limits.h>
27#include <stdbool.h>
28#include <stddef.h>
29#include <stdlib.h>
30#include <locale.h>
31#include <string.h>
32
33#include "flexmember.h"
34#include "setlocale_null.h"
35#include "thread-optim.h"
36
37#if HAVE_GOOD_USELOCALE
38/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
39# if defined __APPLE__ && defined __MACH__
40# include <xlocale.h>
41# endif
42# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
43# include <langinfo.h>
44# endif
45# include "glthread/lock.h"
46# if defined __sun
47# if HAVE_GETLOCALENAME_L
48/* Solaris >= 12. */
49extern char * getlocalename_l(int, locale_t);
50# elif HAVE_SOLARIS114_LOCALES
51# include <sys/localedef.h>
52# endif
53# endif
54# if HAVE_NAMELESS_LOCALES
55# include "localename-table.h"
56# endif
57#endif
58
59#if HAVE_CFPREFERENCESCOPYAPPVALUE
60# include <CoreFoundation/CFString.h>
61# include <CoreFoundation/CFPreferences.h>
62#endif
63
64#if defined _WIN32 && !defined __CYGWIN__
65# define WINDOWS_NATIVE
66# include "glthread/lock.h"
67#endif
68
69#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
70# define WIN32_LEAN_AND_MEAN
71# include <windows.h>
72# include <winnls.h>
73/* List of language codes, sorted by value:
74 0x01 LANG_ARABIC
75 0x02 LANG_BULGARIAN
76 0x03 LANG_CATALAN
77 0x04 LANG_CHINESE
78 0x05 LANG_CZECH
79 0x06 LANG_DANISH
80 0x07 LANG_GERMAN
81 0x08 LANG_GREEK
82 0x09 LANG_ENGLISH
83 0x0a LANG_SPANISH
84 0x0b LANG_FINNISH
85 0x0c LANG_FRENCH
86 0x0d LANG_HEBREW
87 0x0e LANG_HUNGARIAN
88 0x0f LANG_ICELANDIC
89 0x10 LANG_ITALIAN
90 0x11 LANG_JAPANESE
91 0x12 LANG_KOREAN
92 0x13 LANG_DUTCH
93 0x14 LANG_NORWEGIAN
94 0x15 LANG_POLISH
95 0x16 LANG_PORTUGUESE
96 0x17 LANG_ROMANSH
97 0x18 LANG_ROMANIAN
98 0x19 LANG_RUSSIAN
99 0x1a LANG_CROATIAN == LANG_SERBIAN
100 0x1b LANG_SLOVAK
101 0x1c LANG_ALBANIAN
102 0x1d LANG_SWEDISH
103 0x1e LANG_THAI
104 0x1f LANG_TURKISH
105 0x20 LANG_URDU
106 0x21 LANG_INDONESIAN
107 0x22 LANG_UKRAINIAN
108 0x23 LANG_BELARUSIAN
109 0x24 LANG_SLOVENIAN
110 0x25 LANG_ESTONIAN
111 0x26 LANG_LATVIAN
112 0x27 LANG_LITHUANIAN
113 0x28 LANG_TAJIK
114 0x29 LANG_FARSI
115 0x2a LANG_VIETNAMESE
116 0x2b LANG_ARMENIAN
117 0x2c LANG_AZERI
118 0x2d LANG_BASQUE
119 0x2e LANG_SORBIAN
120 0x2f LANG_MACEDONIAN
121 0x30 LANG_SUTU
122 0x31 LANG_TSONGA
123 0x32 LANG_TSWANA
124 0x33 LANG_VENDA
125 0x34 LANG_XHOSA
126 0x35 LANG_ZULU
127 0x36 LANG_AFRIKAANS
128 0x37 LANG_GEORGIAN
129 0x38 LANG_FAEROESE
130 0x39 LANG_HINDI
131 0x3a LANG_MALTESE
132 0x3b LANG_SAMI
133 0x3c LANG_GAELIC
134 0x3d LANG_YIDDISH
135 0x3e LANG_MALAY
136 0x3f LANG_KAZAK
137 0x40 LANG_KYRGYZ
138 0x41 LANG_SWAHILI
139 0x42 LANG_TURKMEN
140 0x43 LANG_UZBEK
141 0x44 LANG_TATAR
142 0x45 LANG_BENGALI
143 0x46 LANG_PUNJABI
144 0x47 LANG_GUJARATI
145 0x48 LANG_ORIYA
146 0x49 LANG_TAMIL
147 0x4a LANG_TELUGU
148 0x4b LANG_KANNADA
149 0x4c LANG_MALAYALAM
150 0x4d LANG_ASSAMESE
151 0x4e LANG_MARATHI
152 0x4f LANG_SANSKRIT
153 0x50 LANG_MONGOLIAN
154 0x51 LANG_TIBETAN
155 0x52 LANG_WELSH
156 0x53 LANG_CAMBODIAN
157 0x54 LANG_LAO
158 0x55 LANG_BURMESE
159 0x56 LANG_GALICIAN
160 0x57 LANG_KONKANI
161 0x58 LANG_MANIPURI
162 0x59 LANG_SINDHI
163 0x5a LANG_SYRIAC
164 0x5b LANG_SINHALESE
165 0x5c LANG_CHEROKEE
166 0x5d LANG_INUKTITUT
167 0x5e LANG_AMHARIC
168 0x5f LANG_TAMAZIGHT
169 0x60 LANG_KASHMIRI
170 0x61 LANG_NEPALI
171 0x62 LANG_FRISIAN
172 0x63 LANG_PASHTO
173 0x64 LANG_TAGALOG
174 0x65 LANG_DIVEHI
175 0x66 LANG_EDO
176 0x67 LANG_FULFULDE
177 0x68 LANG_HAUSA
178 0x69 LANG_IBIBIO
179 0x6a LANG_YORUBA
180 0x6d LANG_BASHKIR
181 0x6e LANG_LUXEMBOURGISH
182 0x6f LANG_GREENLANDIC
183 0x70 LANG_IGBO
184 0x71 LANG_KANURI
185 0x72 LANG_OROMO
186 0x73 LANG_TIGRINYA
187 0x74 LANG_GUARANI
188 0x75 LANG_HAWAIIAN
189 0x76 LANG_LATIN
190 0x77 LANG_SOMALI
191 0x78 LANG_YI
192 0x79 LANG_PAPIAMENTU
193 0x7a LANG_MAPUDUNGUN
194 0x7c LANG_MOHAWK
195 0x7e LANG_BRETON
196 0x82 LANG_OCCITAN
197 0x83 LANG_CORSICAN
198 0x84 LANG_ALSATIAN
199 0x85 LANG_YAKUT
200 0x86 LANG_KICHE
201 0x87 LANG_KINYARWANDA
202 0x88 LANG_WOLOF
203 0x8c LANG_DARI
204 0x91 LANG_SCOTTISH_GAELIC
205*/
206/* Mingw headers don't have latest language and sublanguage codes. */
207# ifndef LANG_AFRIKAANS
208# define LANG_AFRIKAANS 0x36
209# endif
210# ifndef LANG_ALBANIAN
211# define LANG_ALBANIAN 0x1c
212# endif
213# ifndef LANG_ALSATIAN
214# define LANG_ALSATIAN 0x84
215# endif
216# ifndef LANG_AMHARIC
217# define LANG_AMHARIC 0x5e
218# endif
219# ifndef LANG_ARABIC
220# define LANG_ARABIC 0x01
221# endif
222# ifndef LANG_ARMENIAN
223# define LANG_ARMENIAN 0x2b
224# endif
225# ifndef LANG_ASSAMESE
226# define LANG_ASSAMESE 0x4d
227# endif
228# ifndef LANG_AZERI
229# define LANG_AZERI 0x2c
230# endif
231# ifndef LANG_BASHKIR
232# define LANG_BASHKIR 0x6d
233# endif
234# ifndef LANG_BASQUE
235# define LANG_BASQUE 0x2d
236# endif
237# ifndef LANG_BELARUSIAN
238# define LANG_BELARUSIAN 0x23
239# endif
240# ifndef LANG_BENGALI
241# define LANG_BENGALI 0x45
242# endif
243# ifndef LANG_BRETON
244# define LANG_BRETON 0x7e
245# endif
246# ifndef LANG_BURMESE
247# define LANG_BURMESE 0x55
248# endif
249# ifndef LANG_CAMBODIAN
250# define LANG_CAMBODIAN 0x53
251# endif
252# ifndef LANG_CATALAN
253# define LANG_CATALAN 0x03
254# endif
255# ifndef LANG_CHEROKEE
256# define LANG_CHEROKEE 0x5c
257# endif
258# ifndef LANG_CORSICAN
259# define LANG_CORSICAN 0x83
260# endif
261# ifndef LANG_DARI
262# define LANG_DARI 0x8c
263# endif
264# ifndef LANG_DIVEHI
265# define LANG_DIVEHI 0x65
266# endif
267# ifndef LANG_EDO
268# define LANG_EDO 0x66
269# endif
270# ifndef LANG_ESTONIAN
271# define LANG_ESTONIAN 0x25
272# endif
273# ifndef LANG_FAEROESE
274# define LANG_FAEROESE 0x38
275# endif
276# ifndef LANG_FARSI
277# define LANG_FARSI 0x29
278# endif
279# ifndef LANG_FRISIAN
280# define LANG_FRISIAN 0x62
281# endif
282# ifndef LANG_FULFULDE
283# define LANG_FULFULDE 0x67
284# endif
285# ifndef LANG_GAELIC
286# define LANG_GAELIC 0x3c
287# endif
288# ifndef LANG_GALICIAN
289# define LANG_GALICIAN 0x56
290# endif
291# ifndef LANG_GEORGIAN
292# define LANG_GEORGIAN 0x37
293# endif
294# ifndef LANG_GREENLANDIC
295# define LANG_GREENLANDIC 0x6f
296# endif
297# ifndef LANG_GUARANI
298# define LANG_GUARANI 0x74
299# endif
300# ifndef LANG_GUJARATI
301# define LANG_GUJARATI 0x47
302# endif
303# ifndef LANG_HAUSA
304# define LANG_HAUSA 0x68
305# endif
306# ifndef LANG_HAWAIIAN
307# define LANG_HAWAIIAN 0x75
308# endif
309# ifndef LANG_HEBREW
310# define LANG_HEBREW 0x0d
311# endif
312# ifndef LANG_HINDI
313# define LANG_HINDI 0x39
314# endif
315# ifndef LANG_IBIBIO
316# define LANG_IBIBIO 0x69
317# endif
318# ifndef LANG_IGBO
319# define LANG_IGBO 0x70
320# endif
321# ifndef LANG_INDONESIAN
322# define LANG_INDONESIAN 0x21
323# endif
324# ifndef LANG_INUKTITUT
325# define LANG_INUKTITUT 0x5d
326# endif
327# ifndef LANG_KANNADA
328# define LANG_KANNADA 0x4b
329# endif
330# ifndef LANG_KANURI
331# define LANG_KANURI 0x71
332# endif
333# ifndef LANG_KASHMIRI
334# define LANG_KASHMIRI 0x60
335# endif
336# ifndef LANG_KAZAK
337# define LANG_KAZAK 0x3f
338# endif
339# ifndef LANG_KICHE
340# define LANG_KICHE 0x86
341# endif
342# ifndef LANG_KINYARWANDA
343# define LANG_KINYARWANDA 0x87
344# endif
345# ifndef LANG_KONKANI
346# define LANG_KONKANI 0x57
347# endif
348# ifndef LANG_KYRGYZ
349# define LANG_KYRGYZ 0x40
350# endif
351# ifndef LANG_LAO
352# define LANG_LAO 0x54
353# endif
354# ifndef LANG_LATIN
355# define LANG_LATIN 0x76
356# endif
357# ifndef LANG_LATVIAN
358# define LANG_LATVIAN 0x26
359# endif
360# ifndef LANG_LITHUANIAN
361# define LANG_LITHUANIAN 0x27
362# endif
363# ifndef LANG_LUXEMBOURGISH
364# define LANG_LUXEMBOURGISH 0x6e
365# endif
366# ifndef LANG_MACEDONIAN
367# define LANG_MACEDONIAN 0x2f
368# endif
369# ifndef LANG_MALAY
370# define LANG_MALAY 0x3e
371# endif
372# ifndef LANG_MALAYALAM
373# define LANG_MALAYALAM 0x4c
374# endif
375# ifndef LANG_MALTESE
376# define LANG_MALTESE 0x3a
377# endif
378# ifndef LANG_MANIPURI
379# define LANG_MANIPURI 0x58
380# endif
381# ifndef LANG_MAORI
382# define LANG_MAORI 0x81
383# endif
384# ifndef LANG_MAPUDUNGUN
385# define LANG_MAPUDUNGUN 0x7a
386# endif
387# ifndef LANG_MARATHI
388# define LANG_MARATHI 0x4e
389# endif
390# ifndef LANG_MOHAWK
391# define LANG_MOHAWK 0x7c
392# endif
393# ifndef LANG_MONGOLIAN
394# define LANG_MONGOLIAN 0x50
395# endif
396# ifndef LANG_NEPALI
397# define LANG_NEPALI 0x61
398# endif
399# ifndef LANG_OCCITAN
400# define LANG_OCCITAN 0x82
401# endif
402# ifndef LANG_ORIYA
403# define LANG_ORIYA 0x48
404# endif
405# ifndef LANG_OROMO
406# define LANG_OROMO 0x72
407# endif
408# ifndef LANG_PAPIAMENTU
409# define LANG_PAPIAMENTU 0x79
410# endif
411# ifndef LANG_PASHTO
412# define LANG_PASHTO 0x63
413# endif
414# ifndef LANG_PUNJABI
415# define LANG_PUNJABI 0x46
416# endif
417# ifndef LANG_QUECHUA
418# define LANG_QUECHUA 0x6b
419# endif
420# ifndef LANG_ROMANSH
421# define LANG_ROMANSH 0x17
422# endif
423# ifndef LANG_SAMI
424# define LANG_SAMI 0x3b
425# endif
426# ifndef LANG_SANSKRIT
427# define LANG_SANSKRIT 0x4f
428# endif
429# ifndef LANG_SCOTTISH_GAELIC
430# define LANG_SCOTTISH_GAELIC 0x91
431# endif
432# ifndef LANG_SERBIAN
433# define LANG_SERBIAN 0x1a
434# endif
435# ifndef LANG_SINDHI
436# define LANG_SINDHI 0x59
437# endif
438# ifndef LANG_SINHALESE
439# define LANG_SINHALESE 0x5b
440# endif
441# ifndef LANG_SLOVAK
442# define LANG_SLOVAK 0x1b
443# endif
444# ifndef LANG_SOMALI
445# define LANG_SOMALI 0x77
446# endif
447# ifndef LANG_SORBIAN
448# define LANG_SORBIAN 0x2e
449# endif
450# ifndef LANG_SOTHO
451# define LANG_SOTHO 0x6c
452# endif
453# ifndef LANG_SUTU
454# define LANG_SUTU 0x30
455# endif
456# ifndef LANG_SWAHILI
457# define LANG_SWAHILI 0x41
458# endif
459# ifndef LANG_SYRIAC
460# define LANG_SYRIAC 0x5a
461# endif
462# ifndef LANG_TAGALOG
463# define LANG_TAGALOG 0x64
464# endif
465# ifndef LANG_TAJIK
466# define LANG_TAJIK 0x28
467# endif
468# ifndef LANG_TAMAZIGHT
469# define LANG_TAMAZIGHT 0x5f
470# endif
471# ifndef LANG_TAMIL
472# define LANG_TAMIL 0x49
473# endif
474# ifndef LANG_TATAR
475# define LANG_TATAR 0x44
476# endif
477# ifndef LANG_TELUGU
478# define LANG_TELUGU 0x4a
479# endif
480# ifndef LANG_THAI
481# define LANG_THAI 0x1e
482# endif
483# ifndef LANG_TIBETAN
484# define LANG_TIBETAN 0x51
485# endif
486# ifndef LANG_TIGRINYA
487# define LANG_TIGRINYA 0x73
488# endif
489# ifndef LANG_TSONGA
490# define LANG_TSONGA 0x31
491# endif
492# ifndef LANG_TSWANA
493# define LANG_TSWANA 0x32
494# endif
495# ifndef LANG_TURKMEN
496# define LANG_TURKMEN 0x42
497# endif
498# ifndef LANG_UIGHUR
499# define LANG_UIGHUR 0x80
500# endif
501# ifndef LANG_UKRAINIAN
502# define LANG_UKRAINIAN 0x22
503# endif
504# ifndef LANG_URDU
505# define LANG_URDU 0x20
506# endif
507# ifndef LANG_UZBEK
508# define LANG_UZBEK 0x43
509# endif
510# ifndef LANG_VENDA
511# define LANG_VENDA 0x33
512# endif
513# ifndef LANG_VIETNAMESE
514# define LANG_VIETNAMESE 0x2a
515# endif
516# ifndef LANG_WELSH
517# define LANG_WELSH 0x52
518# endif
519# ifndef LANG_WOLOF
520# define LANG_WOLOF 0x88
521# endif
522# ifndef LANG_XHOSA
523# define LANG_XHOSA 0x34
524# endif
525# ifndef LANG_YAKUT
526# define LANG_YAKUT 0x85
527# endif
528# ifndef LANG_YI
529# define LANG_YI 0x78
530# endif
531# ifndef LANG_YIDDISH
532# define LANG_YIDDISH 0x3d
533# endif
534# ifndef LANG_YORUBA
535# define LANG_YORUBA 0x6a
536# endif
537# ifndef LANG_ZULU
538# define LANG_ZULU 0x35
539# endif
540# ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
541# define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
542# endif
543# ifndef SUBLANG_ALBANIAN_ALBANIA
544# define SUBLANG_ALBANIAN_ALBANIA 0x01
545# endif
546# ifndef SUBLANG_ALSATIAN_FRANCE
547# define SUBLANG_ALSATIAN_FRANCE 0x01
548# endif
549# ifndef SUBLANG_AMHARIC_ETHIOPIA
550# define SUBLANG_AMHARIC_ETHIOPIA 0x01
551# endif
552# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
553# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
554# endif
555# ifndef SUBLANG_ARABIC_IRAQ
556# define SUBLANG_ARABIC_IRAQ 0x02
557# endif
558# ifndef SUBLANG_ARABIC_EGYPT
559# define SUBLANG_ARABIC_EGYPT 0x03
560# endif
561# ifndef SUBLANG_ARABIC_LIBYA
562# define SUBLANG_ARABIC_LIBYA 0x04
563# endif
564# ifndef SUBLANG_ARABIC_ALGERIA
565# define SUBLANG_ARABIC_ALGERIA 0x05
566# endif
567# ifndef SUBLANG_ARABIC_MOROCCO
568# define SUBLANG_ARABIC_MOROCCO 0x06
569# endif
570# ifndef SUBLANG_ARABIC_TUNISIA
571# define SUBLANG_ARABIC_TUNISIA 0x07
572# endif
573# ifndef SUBLANG_ARABIC_OMAN
574# define SUBLANG_ARABIC_OMAN 0x08
575# endif
576# ifndef SUBLANG_ARABIC_YEMEN
577# define SUBLANG_ARABIC_YEMEN 0x09
578# endif
579# ifndef SUBLANG_ARABIC_SYRIA
580# define SUBLANG_ARABIC_SYRIA 0x0a
581# endif
582# ifndef SUBLANG_ARABIC_JORDAN
583# define SUBLANG_ARABIC_JORDAN 0x0b
584# endif
585# ifndef SUBLANG_ARABIC_LEBANON
586# define SUBLANG_ARABIC_LEBANON 0x0c
587# endif
588# ifndef SUBLANG_ARABIC_KUWAIT
589# define SUBLANG_ARABIC_KUWAIT 0x0d
590# endif
591# ifndef SUBLANG_ARABIC_UAE
592# define SUBLANG_ARABIC_UAE 0x0e
593# endif
594# ifndef SUBLANG_ARABIC_BAHRAIN
595# define SUBLANG_ARABIC_BAHRAIN 0x0f
596# endif
597# ifndef SUBLANG_ARABIC_QATAR
598# define SUBLANG_ARABIC_QATAR 0x10
599# endif
600# ifndef SUBLANG_ARMENIAN_ARMENIA
601# define SUBLANG_ARMENIAN_ARMENIA 0x01
602# endif
603# ifndef SUBLANG_ASSAMESE_INDIA
604# define SUBLANG_ASSAMESE_INDIA 0x01
605# endif
606# ifndef SUBLANG_AZERI_LATIN
607# define SUBLANG_AZERI_LATIN 0x01
608# endif
609# ifndef SUBLANG_AZERI_CYRILLIC
610# define SUBLANG_AZERI_CYRILLIC 0x02
611# endif
612# ifndef SUBLANG_BASHKIR_RUSSIA
613# define SUBLANG_BASHKIR_RUSSIA 0x01
614# endif
615# ifndef SUBLANG_BASQUE_BASQUE
616# define SUBLANG_BASQUE_BASQUE 0x01
617# endif
618# ifndef SUBLANG_BELARUSIAN_BELARUS
619# define SUBLANG_BELARUSIAN_BELARUS 0x01
620# endif
621# ifndef SUBLANG_BENGALI_INDIA
622# define SUBLANG_BENGALI_INDIA 0x01
623# endif
624# ifndef SUBLANG_BENGALI_BANGLADESH
625# define SUBLANG_BENGALI_BANGLADESH 0x02
626# endif
627# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
628# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
629# endif
630# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
631# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
632# endif
633# ifndef SUBLANG_BRETON_FRANCE
634# define SUBLANG_BRETON_FRANCE 0x01
635# endif
636# ifndef SUBLANG_BULGARIAN_BULGARIA
637# define SUBLANG_BULGARIAN_BULGARIA 0x01
638# endif
639# ifndef SUBLANG_CAMBODIAN_CAMBODIA
640# define SUBLANG_CAMBODIAN_CAMBODIA 0x01
641# endif
642# ifndef SUBLANG_CATALAN_SPAIN
643# define SUBLANG_CATALAN_SPAIN 0x01
644# endif
645# ifndef SUBLANG_CORSICAN_FRANCE
646# define SUBLANG_CORSICAN_FRANCE 0x01
647# endif
648# ifndef SUBLANG_CROATIAN_CROATIA
649# define SUBLANG_CROATIAN_CROATIA 0x01
650# endif
651# ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
652# define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
653# endif
654# ifndef SUBLANG_CHINESE_MACAU
655# define SUBLANG_CHINESE_MACAU 0x05
656# endif
657# ifndef SUBLANG_CZECH_CZECH_REPUBLIC
658# define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
659# endif
660# ifndef SUBLANG_DANISH_DENMARK
661# define SUBLANG_DANISH_DENMARK 0x01
662# endif
663# ifndef SUBLANG_DARI_AFGHANISTAN
664# define SUBLANG_DARI_AFGHANISTAN 0x01
665# endif
666# ifndef SUBLANG_DIVEHI_MALDIVES
667# define SUBLANG_DIVEHI_MALDIVES 0x01
668# endif
669# ifndef SUBLANG_DUTCH_SURINAM
670# define SUBLANG_DUTCH_SURINAM 0x03
671# endif
672# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
673# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
674# endif
675# ifndef SUBLANG_ENGLISH_JAMAICA
676# define SUBLANG_ENGLISH_JAMAICA 0x08
677# endif
678# ifndef SUBLANG_ENGLISH_CARIBBEAN
679# define SUBLANG_ENGLISH_CARIBBEAN 0x09
680# endif
681# ifndef SUBLANG_ENGLISH_BELIZE
682# define SUBLANG_ENGLISH_BELIZE 0x0a
683# endif
684# ifndef SUBLANG_ENGLISH_TRINIDAD
685# define SUBLANG_ENGLISH_TRINIDAD 0x0b
686# endif
687# ifndef SUBLANG_ENGLISH_ZIMBABWE
688# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
689# endif
690# ifndef SUBLANG_ENGLISH_PHILIPPINES
691# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
692# endif
693# ifndef SUBLANG_ENGLISH_INDONESIA
694# define SUBLANG_ENGLISH_INDONESIA 0x0e
695# endif
696# ifndef SUBLANG_ENGLISH_HONGKONG
697# define SUBLANG_ENGLISH_HONGKONG 0x0f
698# endif
699# ifndef SUBLANG_ENGLISH_INDIA
700# define SUBLANG_ENGLISH_INDIA 0x10
701# endif
702# ifndef SUBLANG_ENGLISH_MALAYSIA
703# define SUBLANG_ENGLISH_MALAYSIA 0x11
704# endif
705# ifndef SUBLANG_ENGLISH_SINGAPORE
706# define SUBLANG_ENGLISH_SINGAPORE 0x12
707# endif
708# ifndef SUBLANG_ESTONIAN_ESTONIA
709# define SUBLANG_ESTONIAN_ESTONIA 0x01
710# endif
711# ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
712# define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
713# endif
714# ifndef SUBLANG_FARSI_IRAN
715# define SUBLANG_FARSI_IRAN 0x01
716# endif
717# ifndef SUBLANG_FINNISH_FINLAND
718# define SUBLANG_FINNISH_FINLAND 0x01
719# endif
720# ifndef SUBLANG_FRENCH_LUXEMBOURG
721# define SUBLANG_FRENCH_LUXEMBOURG 0x05
722# endif
723# ifndef SUBLANG_FRENCH_MONACO
724# define SUBLANG_FRENCH_MONACO 0x06
725# endif
726# ifndef SUBLANG_FRENCH_WESTINDIES
727# define SUBLANG_FRENCH_WESTINDIES 0x07
728# endif
729# ifndef SUBLANG_FRENCH_REUNION
730# define SUBLANG_FRENCH_REUNION 0x08
731# endif
732# ifndef SUBLANG_FRENCH_CONGO
733# define SUBLANG_FRENCH_CONGO 0x09
734# endif
735# ifndef SUBLANG_FRENCH_SENEGAL
736# define SUBLANG_FRENCH_SENEGAL 0x0a
737# endif
738# ifndef SUBLANG_FRENCH_CAMEROON
739# define SUBLANG_FRENCH_CAMEROON 0x0b
740# endif
741# ifndef SUBLANG_FRENCH_COTEDIVOIRE
742# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
743# endif
744# ifndef SUBLANG_FRENCH_MALI
745# define SUBLANG_FRENCH_MALI 0x0d
746# endif
747# ifndef SUBLANG_FRENCH_MOROCCO
748# define SUBLANG_FRENCH_MOROCCO 0x0e
749# endif
750# ifndef SUBLANG_FRENCH_HAITI
751# define SUBLANG_FRENCH_HAITI 0x0f
752# endif
753# ifndef SUBLANG_FRISIAN_NETHERLANDS
754# define SUBLANG_FRISIAN_NETHERLANDS 0x01
755# endif
756# ifndef SUBLANG_GALICIAN_SPAIN
757# define SUBLANG_GALICIAN_SPAIN 0x01
758# endif
759# ifndef SUBLANG_GEORGIAN_GEORGIA
760# define SUBLANG_GEORGIAN_GEORGIA 0x01
761# endif
762# ifndef SUBLANG_GERMAN_LUXEMBOURG
763# define SUBLANG_GERMAN_LUXEMBOURG 0x04
764# endif
765# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
766# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
767# endif
768# ifndef SUBLANG_GREEK_GREECE
769# define SUBLANG_GREEK_GREECE 0x01
770# endif
771# ifndef SUBLANG_GREENLANDIC_GREENLAND
772# define SUBLANG_GREENLANDIC_GREENLAND 0x01
773# endif
774# ifndef SUBLANG_GUJARATI_INDIA
775# define SUBLANG_GUJARATI_INDIA 0x01
776# endif
777# ifndef SUBLANG_HAUSA_NIGERIA_LATIN
778# define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
779# endif
780# ifndef SUBLANG_HEBREW_ISRAEL
781# define SUBLANG_HEBREW_ISRAEL 0x01
782# endif
783# ifndef SUBLANG_HINDI_INDIA
784# define SUBLANG_HINDI_INDIA 0x01
785# endif
786# ifndef SUBLANG_HUNGARIAN_HUNGARY
787# define SUBLANG_HUNGARIAN_HUNGARY 0x01
788# endif
789# ifndef SUBLANG_ICELANDIC_ICELAND
790# define SUBLANG_ICELANDIC_ICELAND 0x01
791# endif
792# ifndef SUBLANG_IGBO_NIGERIA
793# define SUBLANG_IGBO_NIGERIA 0x01
794# endif
795# ifndef SUBLANG_INDONESIAN_INDONESIA
796# define SUBLANG_INDONESIAN_INDONESIA 0x01
797# endif
798# ifndef SUBLANG_INUKTITUT_CANADA
799# define SUBLANG_INUKTITUT_CANADA 0x01
800# endif
801# undef SUBLANG_INUKTITUT_CANADA_LATIN
802# define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
803# undef SUBLANG_IRISH_IRELAND
804# define SUBLANG_IRISH_IRELAND 0x02
805# ifndef SUBLANG_JAPANESE_JAPAN
806# define SUBLANG_JAPANESE_JAPAN 0x01
807# endif
808# ifndef SUBLANG_KANNADA_INDIA
809# define SUBLANG_KANNADA_INDIA 0x01
810# endif
811# ifndef SUBLANG_KASHMIRI_INDIA
812# define SUBLANG_KASHMIRI_INDIA 0x02
813# endif
814# ifndef SUBLANG_KAZAK_KAZAKHSTAN
815# define SUBLANG_KAZAK_KAZAKHSTAN 0x01
816# endif
817# ifndef SUBLANG_KICHE_GUATEMALA
818# define SUBLANG_KICHE_GUATEMALA 0x01
819# endif
820# ifndef SUBLANG_KINYARWANDA_RWANDA
821# define SUBLANG_KINYARWANDA_RWANDA 0x01
822# endif
823# ifndef SUBLANG_KONKANI_INDIA
824# define SUBLANG_KONKANI_INDIA 0x01
825# endif
826# ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
827# define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
828# endif
829# ifndef SUBLANG_LAO_LAOS
830# define SUBLANG_LAO_LAOS 0x01
831# endif
832# ifndef SUBLANG_LATVIAN_LATVIA
833# define SUBLANG_LATVIAN_LATVIA 0x01
834# endif
835# ifndef SUBLANG_LITHUANIAN_LITHUANIA
836# define SUBLANG_LITHUANIAN_LITHUANIA 0x01
837# endif
838# undef SUBLANG_LOWER_SORBIAN_GERMANY
839# define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
840# ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
841# define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
842# endif
843# ifndef SUBLANG_MACEDONIAN_MACEDONIA
844# define SUBLANG_MACEDONIAN_MACEDONIA 0x01
845# endif
846# ifndef SUBLANG_MALAY_MALAYSIA
847# define SUBLANG_MALAY_MALAYSIA 0x01
848# endif
849# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
850# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
851# endif
852# ifndef SUBLANG_MALAYALAM_INDIA
853# define SUBLANG_MALAYALAM_INDIA 0x01
854# endif
855# ifndef SUBLANG_MALTESE_MALTA
856# define SUBLANG_MALTESE_MALTA 0x01
857# endif
858# ifndef SUBLANG_MAORI_NEW_ZEALAND
859# define SUBLANG_MAORI_NEW_ZEALAND 0x01
860# endif
861# ifndef SUBLANG_MAPUDUNGUN_CHILE
862# define SUBLANG_MAPUDUNGUN_CHILE 0x01
863# endif
864# ifndef SUBLANG_MARATHI_INDIA
865# define SUBLANG_MARATHI_INDIA 0x01
866# endif
867# ifndef SUBLANG_MOHAWK_CANADA
868# define SUBLANG_MOHAWK_CANADA 0x01
869# endif
870# ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
871# define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
872# endif
873# ifndef SUBLANG_MONGOLIAN_PRC
874# define SUBLANG_MONGOLIAN_PRC 0x02
875# endif
876# ifndef SUBLANG_NEPALI_NEPAL
877# define SUBLANG_NEPALI_NEPAL 0x01
878# endif
879# ifndef SUBLANG_NEPALI_INDIA
880# define SUBLANG_NEPALI_INDIA 0x02
881# endif
882# ifndef SUBLANG_OCCITAN_FRANCE
883# define SUBLANG_OCCITAN_FRANCE 0x01
884# endif
885# ifndef SUBLANG_ORIYA_INDIA
886# define SUBLANG_ORIYA_INDIA 0x01
887# endif
888# ifndef SUBLANG_PASHTO_AFGHANISTAN
889# define SUBLANG_PASHTO_AFGHANISTAN 0x01
890# endif
891# ifndef SUBLANG_POLISH_POLAND
892# define SUBLANG_POLISH_POLAND 0x01
893# endif
894# ifndef SUBLANG_PUNJABI_INDIA
895# define SUBLANG_PUNJABI_INDIA 0x01
896# endif
897# ifndef SUBLANG_PUNJABI_PAKISTAN
898# define SUBLANG_PUNJABI_PAKISTAN 0x02
899# endif
900# ifndef SUBLANG_QUECHUA_BOLIVIA
901# define SUBLANG_QUECHUA_BOLIVIA 0x01
902# endif
903# ifndef SUBLANG_QUECHUA_ECUADOR
904# define SUBLANG_QUECHUA_ECUADOR 0x02
905# endif
906# ifndef SUBLANG_QUECHUA_PERU
907# define SUBLANG_QUECHUA_PERU 0x03
908# endif
909# ifndef SUBLANG_ROMANIAN_ROMANIA
910# define SUBLANG_ROMANIAN_ROMANIA 0x01
911# endif
912# ifndef SUBLANG_ROMANIAN_MOLDOVA
913# define SUBLANG_ROMANIAN_MOLDOVA 0x02
914# endif
915# ifndef SUBLANG_ROMANSH_SWITZERLAND
916# define SUBLANG_ROMANSH_SWITZERLAND 0x01
917# endif
918# ifndef SUBLANG_RUSSIAN_RUSSIA
919# define SUBLANG_RUSSIAN_RUSSIA 0x01
920# endif
921# ifndef SUBLANG_RUSSIAN_MOLDAVIA
922# define SUBLANG_RUSSIAN_MOLDAVIA 0x02
923# endif
924# ifndef SUBLANG_SAMI_NORTHERN_NORWAY
925# define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
926# endif
927# ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
928# define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
929# endif
930# ifndef SUBLANG_SAMI_NORTHERN_FINLAND
931# define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
932# endif
933# ifndef SUBLANG_SAMI_LULE_NORWAY
934# define SUBLANG_SAMI_LULE_NORWAY 0x04
935# endif
936# ifndef SUBLANG_SAMI_LULE_SWEDEN
937# define SUBLANG_SAMI_LULE_SWEDEN 0x05
938# endif
939# ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
940# define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
941# endif
942# ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
943# define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
944# endif
945# undef SUBLANG_SAMI_SKOLT_FINLAND
946# define SUBLANG_SAMI_SKOLT_FINLAND 0x08
947# undef SUBLANG_SAMI_INARI_FINLAND
948# define SUBLANG_SAMI_INARI_FINLAND 0x09
949# ifndef SUBLANG_SANSKRIT_INDIA
950# define SUBLANG_SANSKRIT_INDIA 0x01
951# endif
952# ifndef SUBLANG_SERBIAN_LATIN
953# define SUBLANG_SERBIAN_LATIN 0x02
954# endif
955# ifndef SUBLANG_SERBIAN_CYRILLIC
956# define SUBLANG_SERBIAN_CYRILLIC 0x03
957# endif
958# ifndef SUBLANG_SINDHI_INDIA
959# define SUBLANG_SINDHI_INDIA 0x01
960# endif
961# undef SUBLANG_SINDHI_PAKISTAN
962# define SUBLANG_SINDHI_PAKISTAN 0x02
963# ifndef SUBLANG_SINDHI_AFGHANISTAN
964# define SUBLANG_SINDHI_AFGHANISTAN 0x02
965# endif
966# ifndef SUBLANG_SINHALESE_SRI_LANKA
967# define SUBLANG_SINHALESE_SRI_LANKA 0x01
968# endif
969# ifndef SUBLANG_SLOVAK_SLOVAKIA
970# define SUBLANG_SLOVAK_SLOVAKIA 0x01
971# endif
972# ifndef SUBLANG_SLOVENIAN_SLOVENIA
973# define SUBLANG_SLOVENIAN_SLOVENIA 0x01
974# endif
975# ifndef SUBLANG_SOTHO_SOUTH_AFRICA
976# define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
977# endif
978# ifndef SUBLANG_SPANISH_GUATEMALA
979# define SUBLANG_SPANISH_GUATEMALA 0x04
980# endif
981# ifndef SUBLANG_SPANISH_COSTA_RICA
982# define SUBLANG_SPANISH_COSTA_RICA 0x05
983# endif
984# ifndef SUBLANG_SPANISH_PANAMA
985# define SUBLANG_SPANISH_PANAMA 0x06
986# endif
987# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
988# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
989# endif
990# ifndef SUBLANG_SPANISH_VENEZUELA
991# define SUBLANG_SPANISH_VENEZUELA 0x08
992# endif
993# ifndef SUBLANG_SPANISH_COLOMBIA
994# define SUBLANG_SPANISH_COLOMBIA 0x09
995# endif
996# ifndef SUBLANG_SPANISH_PERU
997# define SUBLANG_SPANISH_PERU 0x0a
998# endif
999# ifndef SUBLANG_SPANISH_ARGENTINA
1000# define SUBLANG_SPANISH_ARGENTINA 0x0b
1001# endif
1002# ifndef SUBLANG_SPANISH_ECUADOR
1003# define SUBLANG_SPANISH_ECUADOR 0x0c
1004# endif
1005# ifndef SUBLANG_SPANISH_CHILE
1006# define SUBLANG_SPANISH_CHILE 0x0d
1007# endif
1008# ifndef SUBLANG_SPANISH_URUGUAY
1009# define SUBLANG_SPANISH_URUGUAY 0x0e
1010# endif
1011# ifndef SUBLANG_SPANISH_PARAGUAY
1012# define SUBLANG_SPANISH_PARAGUAY 0x0f
1013# endif
1014# ifndef SUBLANG_SPANISH_BOLIVIA
1015# define SUBLANG_SPANISH_BOLIVIA 0x10
1016# endif
1017# ifndef SUBLANG_SPANISH_EL_SALVADOR
1018# define SUBLANG_SPANISH_EL_SALVADOR 0x11
1019# endif
1020# ifndef SUBLANG_SPANISH_HONDURAS
1021# define SUBLANG_SPANISH_HONDURAS 0x12
1022# endif
1023# ifndef SUBLANG_SPANISH_NICARAGUA
1024# define SUBLANG_SPANISH_NICARAGUA 0x13
1025# endif
1026# ifndef SUBLANG_SPANISH_PUERTO_RICO
1027# define SUBLANG_SPANISH_PUERTO_RICO 0x14
1028# endif
1029# ifndef SUBLANG_SPANISH_US
1030# define SUBLANG_SPANISH_US 0x15
1031# endif
1032# ifndef SUBLANG_SWAHILI_KENYA
1033# define SUBLANG_SWAHILI_KENYA 0x01
1034# endif
1035# ifndef SUBLANG_SWEDISH_SWEDEN
1036# define SUBLANG_SWEDISH_SWEDEN 0x01
1037# endif
1038# ifndef SUBLANG_SWEDISH_FINLAND
1039# define SUBLANG_SWEDISH_FINLAND 0x02
1040# endif
1041# ifndef SUBLANG_SYRIAC_SYRIA
1042# define SUBLANG_SYRIAC_SYRIA 0x01
1043# endif
1044# ifndef SUBLANG_TAGALOG_PHILIPPINES
1045# define SUBLANG_TAGALOG_PHILIPPINES 0x01
1046# endif
1047# ifndef SUBLANG_TAJIK_TAJIKISTAN
1048# define SUBLANG_TAJIK_TAJIKISTAN 0x01
1049# endif
1050# ifndef SUBLANG_TAMAZIGHT_ARABIC
1051# define SUBLANG_TAMAZIGHT_ARABIC 0x01
1052# endif
1053# ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
1054# define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
1055# endif
1056# ifndef SUBLANG_TAMIL_INDIA
1057# define SUBLANG_TAMIL_INDIA 0x01
1058# endif
1059# ifndef SUBLANG_TATAR_RUSSIA
1060# define SUBLANG_TATAR_RUSSIA 0x01
1061# endif
1062# ifndef SUBLANG_TELUGU_INDIA
1063# define SUBLANG_TELUGU_INDIA 0x01
1064# endif
1065# ifndef SUBLANG_THAI_THAILAND
1066# define SUBLANG_THAI_THAILAND 0x01
1067# endif
1068# ifndef SUBLANG_TIBETAN_PRC
1069# define SUBLANG_TIBETAN_PRC 0x01
1070# endif
1071# undef SUBLANG_TIBETAN_BHUTAN
1072# define SUBLANG_TIBETAN_BHUTAN 0x02
1073# ifndef SUBLANG_TIGRINYA_ETHIOPIA
1074# define SUBLANG_TIGRINYA_ETHIOPIA 0x01
1075# endif
1076# ifndef SUBLANG_TIGRINYA_ERITREA
1077# define SUBLANG_TIGRINYA_ERITREA 0x02
1078# endif
1079# ifndef SUBLANG_TSWANA_SOUTH_AFRICA
1080# define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
1081# endif
1082# ifndef SUBLANG_TURKISH_TURKEY
1083# define SUBLANG_TURKISH_TURKEY 0x01
1084# endif
1085# ifndef SUBLANG_TURKMEN_TURKMENISTAN
1086# define SUBLANG_TURKMEN_TURKMENISTAN 0x01
1087# endif
1088# ifndef SUBLANG_UIGHUR_PRC
1089# define SUBLANG_UIGHUR_PRC 0x01
1090# endif
1091# ifndef SUBLANG_UKRAINIAN_UKRAINE
1092# define SUBLANG_UKRAINIAN_UKRAINE 0x01
1093# endif
1094# ifndef SUBLANG_UPPER_SORBIAN_GERMANY
1095# define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
1096# endif
1097# ifndef SUBLANG_URDU_PAKISTAN
1098# define SUBLANG_URDU_PAKISTAN 0x01
1099# endif
1100# ifndef SUBLANG_URDU_INDIA
1101# define SUBLANG_URDU_INDIA 0x02
1102# endif
1103# ifndef SUBLANG_UZBEK_LATIN
1104# define SUBLANG_UZBEK_LATIN 0x01
1105# endif
1106# ifndef SUBLANG_UZBEK_CYRILLIC
1107# define SUBLANG_UZBEK_CYRILLIC 0x02
1108# endif
1109# ifndef SUBLANG_VIETNAMESE_VIETNAM
1110# define SUBLANG_VIETNAMESE_VIETNAM 0x01
1111# endif
1112# ifndef SUBLANG_WELSH_UNITED_KINGDOM
1113# define SUBLANG_WELSH_UNITED_KINGDOM 0x01
1114# endif
1115# ifndef SUBLANG_WOLOF_SENEGAL
1116# define SUBLANG_WOLOF_SENEGAL 0x01
1117# endif
1118# ifndef SUBLANG_XHOSA_SOUTH_AFRICA
1119# define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
1120# endif
1121# ifndef SUBLANG_YAKUT_RUSSIA
1122# define SUBLANG_YAKUT_RUSSIA 0x01
1123# endif
1124# ifndef SUBLANG_YI_PRC
1125# define SUBLANG_YI_PRC 0x01
1126# endif
1127# ifndef SUBLANG_YORUBA_NIGERIA
1128# define SUBLANG_YORUBA_NIGERIA 0x01
1129# endif
1130# ifndef SUBLANG_ZULU_SOUTH_AFRICA
1131# define SUBLANG_ZULU_SOUTH_AFRICA 0x01
1132# endif
1133/* GetLocaleInfoA operations. */
1134# ifndef LOCALE_SNAME
1135# define LOCALE_SNAME 0x5c
1136# endif
1137# ifndef LOCALE_NAME_MAX_LENGTH
1138# define LOCALE_NAME_MAX_LENGTH 85
1139# endif
1140/* Don't assume that UNICODE is not defined. */
1141# undef GetLocaleInfo
1142# define GetLocaleInfo GetLocaleInfoA
1143# undef EnumSystemLocales
1144# define EnumSystemLocales EnumSystemLocalesA
1145#endif
1146
1147/* We want to use the system's setlocale() function here, not the gnulib
1148 override. */
1149#undef setlocale
1150
1151
1152#if HAVE_CFPREFERENCESCOPYAPPVALUE
1153/* Mac OS X 10.4 or newer */
1154
1155/* Canonicalize a Mac OS X locale name to a Unix locale name.
1156 NAME is a sufficiently large buffer.
1157 On input, it contains the Mac OS X locale name.
1158 On output, it contains the Unix locale name. */
1159# if !defined IN_LIBINTL
1160static
1161# endif
1162void
1163gl_locale_name_canonicalize (char *name)
1164{
1165 /* This conversion is based on a posting by
1166 Deborah GoldSmith <[email protected]> on 2005-03-08,
1167 https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
1168
1169 /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
1170 ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
1171 Therefore we do it ourselves, using a table based on the results of the
1172 Mac OS X 10.3.8 function
1173 CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
1174 typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
1175 legacy_entry;
1176 static const legacy_entry legacy_table[] = {
1177 { "Afrikaans", "af" },
1178 { "Albanian", "sq" },
1179 { "Amharic", "am" },
1180 { "Arabic", "ar" },
1181 { "Armenian", "hy" },
1182 { "Assamese", "as" },
1183 { "Aymara", "ay" },
1184 { "Azerbaijani", "az" },
1185 { "Basque", "eu" },
1186 { "Belarusian", "be" },
1187 { "Belorussian", "be" },
1188 { "Bengali", "bn" },
1189 { "Brazilian Portugese", "pt_BR" },
1190 { "Brazilian Portuguese", "pt_BR" },
1191 { "Breton", "br" },
1192 { "Bulgarian", "bg" },
1193 { "Burmese", "my" },
1194 { "Byelorussian", "be" },
1195 { "Catalan", "ca" },
1196 { "Chewa", "ny" },
1197 { "Chichewa", "ny" },
1198 { "Chinese", "zh" },
1199 { "Chinese, Simplified", "zh_CN" },
1200 { "Chinese, Traditional", "zh_TW" },
1201 { "Chinese, Tradtional", "zh_TW" },
1202 { "Croatian", "hr" },
1203 { "Czech", "cs" },
1204 { "Danish", "da" },
1205 { "Dutch", "nl" },
1206 { "Dzongkha", "dz" },
1207 { "English", "en" },
1208 { "Esperanto", "eo" },
1209 { "Estonian", "et" },
1210 { "Faroese", "fo" },
1211 { "Farsi", "fa" },
1212 { "Finnish", "fi" },
1213 { "Flemish", "nl_BE" },
1214 { "French", "fr" },
1215 { "Galician", "gl" },
1216 { "Gallegan", "gl" },
1217 { "Georgian", "ka" },
1218 { "German", "de" },
1219 { "Greek", "el" },
1220 { "Greenlandic", "kl" },
1221 { "Guarani", "gn" },
1222 { "Gujarati", "gu" },
1223 { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
1224 { "Hebrew", "he" },
1225 { "Hindi", "hi" },
1226 { "Hungarian", "hu" },
1227 { "Icelandic", "is" },
1228 { "Indonesian", "id" },
1229 { "Inuktitut", "iu" },
1230 { "Irish", "ga" },
1231 { "Italian", "it" },
1232 { "Japanese", "ja" },
1233 { "Javanese", "jv" },
1234 { "Kalaallisut", "kl" },
1235 { "Kannada", "kn" },
1236 { "Kashmiri", "ks" },
1237 { "Kazakh", "kk" },
1238 { "Khmer", "km" },
1239 { "Kinyarwanda", "rw" },
1240 { "Kirghiz", "ky" },
1241 { "Korean", "ko" },
1242 { "Kurdish", "ku" },
1243 { "Latin", "la" },
1244 { "Latvian", "lv" },
1245 { "Lithuanian", "lt" },
1246 { "Macedonian", "mk" },
1247 { "Malagasy", "mg" },
1248 { "Malay", "ms" },
1249 { "Malayalam", "ml" },
1250 { "Maltese", "mt" },
1251 { "Manx", "gv" },
1252 { "Marathi", "mr" },
1253 { "Moldavian", "mo" },
1254 { "Mongolian", "mn" },
1255 { "Nepali", "ne" },
1256 { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
1257 { "Nyanja", "ny" },
1258 { "Nynorsk", "nn" },
1259 { "Oriya", "or" },
1260 { "Oromo", "om" },
1261 { "Panjabi", "pa" },
1262 { "Pashto", "ps" },
1263 { "Persian", "fa" },
1264 { "Polish", "pl" },
1265 { "Portuguese", "pt" },
1266 { "Portuguese, Brazilian", "pt_BR" },
1267 { "Punjabi", "pa" },
1268 { "Pushto", "ps" },
1269 { "Quechua", "qu" },
1270 { "Romanian", "ro" },
1271 { "Ruanda", "rw" },
1272 { "Rundi", "rn" },
1273 { "Russian", "ru" },
1274 { "Sami", "se_NO" }, /* Not just "se". */
1275 { "Sanskrit", "sa" },
1276 { "Scottish", "gd" },
1277 { "Serbian", "sr" },
1278 { "Simplified Chinese", "zh_CN" },
1279 { "Sindhi", "sd" },
1280 { "Sinhalese", "si" },
1281 { "Slovak", "sk" },
1282 { "Slovenian", "sl" },
1283 { "Somali", "so" },
1284 { "Spanish", "es" },
1285 { "Sundanese", "su" },
1286 { "Swahili", "sw" },
1287 { "Swedish", "sv" },
1288 { "Tagalog", "tl" },
1289 { "Tajik", "tg" },
1290 { "Tajiki", "tg" },
1291 { "Tamil", "ta" },
1292 { "Tatar", "tt" },
1293 { "Telugu", "te" },
1294 { "Thai", "th" },
1295 { "Tibetan", "bo" },
1296 { "Tigrinya", "ti" },
1297 { "Tongan", "to" },
1298 { "Traditional Chinese", "zh_TW" },
1299 { "Turkish", "tr" },
1300 { "Turkmen", "tk" },
1301 { "Uighur", "ug" },
1302 { "Ukrainian", "uk" },
1303 { "Urdu", "ur" },
1304 { "Uzbek", "uz" },
1305 { "Vietnamese", "vi" },
1306 { "Welsh", "cy" },
1307 { "Yiddish", "yi" }
1308 };
1309
1310 /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
1311 to Unix (ISO 639 and ISO 3166) names. */
1312 typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
1313 langtag_entry;
1314 static const langtag_entry langtag_table[] = {
1315 /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
1316 The default script for az on Unix is Latin. */
1317 { "az-Latn", "az" },
1318 /* Mac OS X has "bs-Cyrl", "bs-Latn".
1319 The default script for bs on Unix is Latin. */
1320 { "bs-Latn", "bs" },
1321 /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
1322 { "ga-dots", "ga" },
1323 /* Mac OS X has "kk-Cyrl".
1324 The default script for kk on Unix is Cyrillic. */
1325 { "kk-Cyrl", "kk" },
1326 /* Mac OS X has "mn-Cyrl", "mn-Mong".
1327 The default script for mn on Unix is Cyrillic. */
1328 { "mn-Cyrl", "mn" },
1329 /* Mac OS X has "ms-Arab", "ms-Latn".
1330 The default script for ms on Unix is Latin. */
1331 { "ms-Latn", "ms" },
1332 /* Mac OS X has "pa-Arab", "pa-Guru".
1333 Country codes are used to distinguish these on Unix. */
1334 { "pa-Arab", "pa_PK" },
1335 { "pa-Guru", "pa_IN" },
1336 /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
1337 /* Mac OS X has "sr-Cyrl", "sr-Latn".
1338 The default script for sr on Unix is Cyrillic. */
1339 { "sr-Cyrl", "sr" },
1340 /* Mac OS X has "tg-Cyrl".
1341 The default script for tg on Unix is Cyrillic. */
1342 { "tg-Cyrl", "tg" },
1343 /* Mac OS X has "tk-Cyrl".
1344 The default script for tk on Unix is Cyrillic. */
1345 { "tk-Cyrl", "tk" },
1346 /* Mac OS X has "tt-Cyrl".
1347 The default script for tt on Unix is Cyrillic. */
1348 { "tt-Cyrl", "tt" },
1349 /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
1350 The default script for uz on Unix is Latin. */
1351 { "uz-Latn", "uz" },
1352 /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
1353 /* Mac OS X has "yue-Hans", "yue-Hant".
1354 The default script for yue on Unix is Simplified Han. */
1355 { "yue-Hans", "yue" },
1356 /* Mac OS X has "zh-Hans", "zh-Hant".
1357 Country codes are used to distinguish these on Unix. */
1358 { "zh-Hans", "zh_CN" },
1359 { "zh-Hant", "zh_TW" }
1360 };
1361
1362 /* Convert script names (ISO 15924) to Unix conventions.
1363 See https://www.unicode.org/iso15924/iso15924-codes.html */
1364 typedef struct { const char script[4+1]; const char unixy[9+1]; }
1365 script_entry;
1366 static const script_entry script_table[] = {
1367 { "Arab", "arabic" },
1368 { "Cyrl", "cyrillic" },
1369 { "Latn", "latin" },
1370 { "Mong", "mongolian" }
1371 };
1372
1373 /* Step 1: Convert using legacy_table. */
1374 if (name[0] >= 'A' && name[0] <= 'Z')
1375 {
1376 unsigned int i1, i2;
1377 i1 = 0;
1378 i2 = sizeof (legacy_table) / sizeof (legacy_entry);
1379 while (i2 - i1 > 1)
1380 {
1381 /* At this point we know that if name occurs in legacy_table,
1382 its index must be >= i1 and < i2. */
1383 unsigned int i = (i1 + i2) >> 1;
1384 const legacy_entry *p = &legacy_table[i];
1385 if (strcmp (name, p->legacy) < 0)
1386 i2 = i;
1387 else
1388 i1 = i;
1389 }
1390 if (strcmp (name, legacy_table[i1].legacy) == 0)
1391 {
1392 strcpy (name, legacy_table[i1].unixy);
1393 return;
1394 }
1395 }
1396
1397 /* Step 2: Convert using langtag_table and script_table. */
1398 if (strlen (name) == 7 && name[2] == '-')
1399 {
1400 unsigned int i1, i2;
1401 i1 = 0;
1402 i2 = sizeof (langtag_table) / sizeof (langtag_entry);
1403 while (i2 - i1 > 1)
1404 {
1405 /* At this point we know that if name occurs in langtag_table,
1406 its index must be >= i1 and < i2. */
1407 unsigned int i = (i1 + i2) >> 1;
1408 const langtag_entry *p = &langtag_table[i];
1409 if (strcmp (name, p->langtag) < 0)
1410 i2 = i;
1411 else
1412 i1 = i;
1413 }
1414 if (strcmp (name, langtag_table[i1].langtag) == 0)
1415 {
1416 strcpy (name, langtag_table[i1].unixy);
1417 return;
1418 }
1419
1420 i1 = 0;
1421 i2 = sizeof (script_table) / sizeof (script_entry);
1422 while (i2 - i1 > 1)
1423 {
1424 /* At this point we know that if (name + 3) occurs in script_table,
1425 its index must be >= i1 and < i2. */
1426 unsigned int i = (i1 + i2) >> 1;
1427 const script_entry *p = &script_table[i];
1428 if (strcmp (name + 3, p->script) < 0)
1429 i2 = i;
1430 else
1431 i1 = i;
1432 }
1433 if (strcmp (name + 3, script_table[i1].script) == 0)
1434 {
1435 name[2] = '@';
1436 strcpy (name + 3, script_table[i1].unixy);
1437 return;
1438 }
1439 }
1440
1441 /* Step 3: Convert new-style dash to Unix underscore. */
1442 {
1443 char *p;
1444 for (p = name; *p != '\0'; p++)
1445 if (*p == '-')
1446 *p = '_';
1447 }
1448}
1449
1450#endif
1451
1452
1453#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
1454
1455/* Canonicalize a Windows native locale name to a Unix locale name.
1456 NAME is a sufficiently large buffer.
1457 On input, it contains the Windows locale name.
1458 On output, it contains the Unix locale name. */
1459# if !defined IN_LIBINTL
1460static
1461# endif
1462void
1463gl_locale_name_canonicalize (char *name)
1464{
1465 /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1466 "zh-Hant". */
1467 char *p;
1468
1469 for (p = name; *p != '\0'; p++)
1470 if (*p == '-')
1471 {
1472 *p = '_';
1473 p++;
1474 for (; *p != '\0'; p++)
1475 {
1476 if (*p >= 'a' && *p <= 'z')
1477 *p += 'A' - 'a';
1478 if (*p == '-')
1479 {
1480 *p = '\0';
1481 return;
1482 }
1483 }
1484 return;
1485 }
1486}
1487
1488# if !defined IN_LIBINTL
1489static
1490# endif
1491const char *
1492gl_locale_name_from_win32_LANGID (LANGID langid)
1493{
1494 /* Activate the new code only when the GETTEXT_MUI environment variable is
1495 set, for the time being, since the new code is not well tested. */
1496 if (getenv ("GETTEXT_MUI") != NULL)
1497 {
1498 static char namebuf[256];
1499
1500 /* Query the system's notion of locale name.
1501 On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1502 But we don't need to support systems that are so old. */
1503 if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
1504 namebuf, sizeof (namebuf) - 1))
1505 {
1506 /* Convert it to a Unix locale name. */
1507 gl_locale_name_canonicalize (namebuf);
1508 return namebuf;
1509 }
1510 }
1511 /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1512 HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
1513 since IE's i18n subsystem is known to be inconsistent with the native
1514 Windows base (e.g. they have different character conversion facilities
1515 that produce different results). */
1516 /* Use our own table. */
1517 {
1518 int primary, sub;
1519
1520 /* Split into language and territory part. */
1521 primary = PRIMARYLANGID (langid);
1522 sub = SUBLANGID (langid);
1523
1524 /* Dispatch on language.
1525 See also https://www.unicode.org/unicode/onlinedat/languages.html .
1526 For details about languages, see https://www.ethnologue.com/ . */
1527 switch (primary)
1528 {
1529 case LANG_AFRIKAANS:
1530 switch (sub)
1531 {
1532 case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA";
1533 }
1534 return "af";
1535 case LANG_ALBANIAN:
1536 switch (sub)
1537 {
1538 case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL";
1539 }
1540 return "sq";
1541 case LANG_ALSATIAN:
1542 switch (sub)
1543 {
1544 case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR";
1545 }
1546 return "gsw";
1547 case LANG_AMHARIC:
1548 switch (sub)
1549 {
1550 case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET";
1551 }
1552 return "am";
1553 case LANG_ARABIC:
1554 switch (sub)
1555 {
1556 case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
1557 case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
1558 case SUBLANG_ARABIC_EGYPT: return "ar_EG";
1559 case SUBLANG_ARABIC_LIBYA: return "ar_LY";
1560 case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
1561 case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
1562 case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
1563 case SUBLANG_ARABIC_OMAN: return "ar_OM";
1564 case SUBLANG_ARABIC_YEMEN: return "ar_YE";
1565 case SUBLANG_ARABIC_SYRIA: return "ar_SY";
1566 case SUBLANG_ARABIC_JORDAN: return "ar_JO";
1567 case SUBLANG_ARABIC_LEBANON: return "ar_LB";
1568 case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
1569 case SUBLANG_ARABIC_UAE: return "ar_AE";
1570 case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
1571 case SUBLANG_ARABIC_QATAR: return "ar_QA";
1572 }
1573 return "ar";
1574 case LANG_ARMENIAN:
1575 switch (sub)
1576 {
1577 case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM";
1578 }
1579 return "hy";
1580 case LANG_ASSAMESE:
1581 switch (sub)
1582 {
1583 case SUBLANG_ASSAMESE_INDIA: return "as_IN";
1584 }
1585 return "as";
1586 case LANG_AZERI:
1587 switch (sub)
1588 {
1589 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
1590 case 0x1e: return "az@latin";
1591 case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
1592 case 0x1d: return "az@cyrillic";
1593 case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
1594 }
1595 return "az";
1596 case LANG_BASHKIR:
1597 switch (sub)
1598 {
1599 case SUBLANG_BASHKIR_RUSSIA: return "ba_RU";
1600 }
1601 return "ba";
1602 case LANG_BASQUE:
1603 switch (sub)
1604 {
1605 case SUBLANG_BASQUE_BASQUE: return "eu_ES";
1606 }
1607 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
1608 case LANG_BELARUSIAN:
1609 switch (sub)
1610 {
1611 case SUBLANG_BELARUSIAN_BELARUS: return "be_BY";
1612 }
1613 return "be";
1614 case LANG_BENGALI:
1615 switch (sub)
1616 {
1617 case SUBLANG_BENGALI_INDIA: return "bn_IN";
1618 case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
1619 }
1620 return "bn";
1621 case LANG_BRETON:
1622 switch (sub)
1623 {
1624 case SUBLANG_BRETON_FRANCE: return "br_FR";
1625 }
1626 return "br";
1627 case LANG_BULGARIAN:
1628 switch (sub)
1629 {
1630 case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG";
1631 }
1632 return "bg";
1633 case LANG_BURMESE:
1634 switch (sub)
1635 {
1636 case SUBLANG_DEFAULT: return "my_MM";
1637 }
1638 return "my";
1639 case LANG_CAMBODIAN:
1640 switch (sub)
1641 {
1642 case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH";
1643 }
1644 return "km";
1645 case LANG_CATALAN:
1646 switch (sub)
1647 {
1648 case SUBLANG_CATALAN_SPAIN: return "ca_ES";
1649 }
1650 return "ca";
1651 case LANG_CHEROKEE:
1652 switch (sub)
1653 {
1654 case SUBLANG_DEFAULT: return "chr_US";
1655 }
1656 return "chr";
1657 case LANG_CHINESE:
1658 switch (sub)
1659 {
1660 case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW";
1661 case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN";
1662 case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */
1663 case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */
1664 case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */
1665 }
1666 return "zh";
1667 case LANG_CORSICAN:
1668 switch (sub)
1669 {
1670 case SUBLANG_CORSICAN_FRANCE: return "co_FR";
1671 }
1672 return "co";
1673 case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
1674 * What used to be called Serbo-Croatian
1675 * should really now be two separate
1676 * languages because of political reasons.
1677 * (Says tml, who knows nothing about Serbian
1678 * or Croatian.)
1679 * (I can feel those flames coming already.)
1680 */
1681 switch (sub)
1682 {
1683 /* Croatian */
1684 case 0x00: return "hr";
1685 case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
1686 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
1687 /* Serbian */
1688 case 0x1f: return "sr";
1689 case 0x1c: return "sr"; /* latin */
1690 case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */
1691 case 0x09: return "sr_RS"; /* latin */
1692 case 0x0b: return "sr_ME"; /* latin */
1693 case 0x06: return "sr_BA"; /* latin */
1694 case 0x1b: return "sr@cyrillic";
1695 case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
1696 case 0x0a: return "sr_RS@cyrillic";
1697 case 0x0c: return "sr_ME@cyrillic";
1698 case 0x07: return "sr_BA@cyrillic";
1699 /* Bosnian */
1700 case 0x1e: return "bs";
1701 case 0x1a: return "bs"; /* latin */
1702 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */
1703 case 0x19: return "bs@cyrillic";
1704 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
1705 }
1706 return "hr";
1707 case LANG_CZECH:
1708 switch (sub)
1709 {
1710 case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ";
1711 }
1712 return "cs";
1713 case LANG_DANISH:
1714 switch (sub)
1715 {
1716 case SUBLANG_DANISH_DENMARK: return "da_DK";
1717 }
1718 return "da";
1719 case LANG_DARI:
1720 /* FIXME: Adjust this when such locales appear on Unix. */
1721 switch (sub)
1722 {
1723 case SUBLANG_DARI_AFGHANISTAN: return "prs_AF";
1724 }
1725 return "prs";
1726 case LANG_DIVEHI:
1727 switch (sub)
1728 {
1729 case SUBLANG_DIVEHI_MALDIVES: return "dv_MV";
1730 }
1731 return "dv";
1732 case LANG_DUTCH:
1733 switch (sub)
1734 {
1735 case SUBLANG_DUTCH: return "nl_NL";
1736 case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
1737 case SUBLANG_DUTCH_SURINAM: return "nl_SR";
1738 }
1739 return "nl";
1740 case LANG_EDO:
1741 switch (sub)
1742 {
1743 case SUBLANG_DEFAULT: return "bin_NG";
1744 }
1745 return "bin";
1746 case LANG_ENGLISH:
1747 switch (sub)
1748 {
1749 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1750 * English was the language spoken in England.
1751 * Oh well.
1752 */
1753 case SUBLANG_ENGLISH_US: return "en_US";
1754 case SUBLANG_ENGLISH_UK: return "en_GB";
1755 case SUBLANG_ENGLISH_AUS: return "en_AU";
1756 case SUBLANG_ENGLISH_CAN: return "en_CA";
1757 case SUBLANG_ENGLISH_NZ: return "en_NZ";
1758 case SUBLANG_ENGLISH_EIRE: return "en_IE";
1759 case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
1760 case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
1761 case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
1762 case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
1763 case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
1764 case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
1765 case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
1766 case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
1767 case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
1768 case SUBLANG_ENGLISH_INDIA: return "en_IN";
1769 case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
1770 case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
1771 }
1772 return "en";
1773 case LANG_ESTONIAN:
1774 switch (sub)
1775 {
1776 case SUBLANG_ESTONIAN_ESTONIA: return "et_EE";
1777 }
1778 return "et";
1779 case LANG_FAEROESE:
1780 switch (sub)
1781 {
1782 case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO";
1783 }
1784 return "fo";
1785 case LANG_FARSI:
1786 switch (sub)
1787 {
1788 case SUBLANG_FARSI_IRAN: return "fa_IR";
1789 }
1790 return "fa";
1791 case LANG_FINNISH:
1792 switch (sub)
1793 {
1794 case SUBLANG_FINNISH_FINLAND: return "fi_FI";
1795 }
1796 return "fi";
1797 case LANG_FRENCH:
1798 switch (sub)
1799 {
1800 case SUBLANG_FRENCH: return "fr_FR";
1801 case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
1802 case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
1803 case SUBLANG_FRENCH_SWISS: return "fr_CH";
1804 case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
1805 case SUBLANG_FRENCH_MONACO: return "fr_MC";
1806 case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
1807 case SUBLANG_FRENCH_REUNION: return "fr_RE";
1808 case SUBLANG_FRENCH_CONGO: return "fr_CG";
1809 case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
1810 case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
1811 case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
1812 case SUBLANG_FRENCH_MALI: return "fr_ML";
1813 case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
1814 case SUBLANG_FRENCH_HAITI: return "fr_HT";
1815 }
1816 return "fr";
1817 case LANG_FRISIAN:
1818 switch (sub)
1819 {
1820 case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL";
1821 }
1822 return "fy";
1823 case LANG_FULFULDE:
1824 /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
1825 switch (sub)
1826 {
1827 case SUBLANG_DEFAULT: return "ff_NG";
1828 }
1829 return "ff";
1830 case LANG_GAELIC:
1831 switch (sub)
1832 {
1833 case 0x01: /* SCOTTISH */
1834 /* old, superseded by LANG_SCOTTISH_GAELIC */
1835 return "gd_GB";
1836 case SUBLANG_IRISH_IRELAND: return "ga_IE";
1837 }
1838 return "ga";
1839 case LANG_GALICIAN:
1840 switch (sub)
1841 {
1842 case SUBLANG_GALICIAN_SPAIN: return "gl_ES";
1843 }
1844 return "gl";
1845 case LANG_GEORGIAN:
1846 switch (sub)
1847 {
1848 case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE";
1849 }
1850 return "ka";
1851 case LANG_GERMAN:
1852 switch (sub)
1853 {
1854 case SUBLANG_GERMAN: return "de_DE";
1855 case SUBLANG_GERMAN_SWISS: return "de_CH";
1856 case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
1857 case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
1858 case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
1859 }
1860 return "de";
1861 case LANG_GREEK:
1862 switch (sub)
1863 {
1864 case SUBLANG_GREEK_GREECE: return "el_GR";
1865 }
1866 return "el";
1867 case LANG_GREENLANDIC:
1868 switch (sub)
1869 {
1870 case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL";
1871 }
1872 return "kl";
1873 case LANG_GUARANI:
1874 switch (sub)
1875 {
1876 case SUBLANG_DEFAULT: return "gn_PY";
1877 }
1878 return "gn";
1879 case LANG_GUJARATI:
1880 switch (sub)
1881 {
1882 case SUBLANG_GUJARATI_INDIA: return "gu_IN";
1883 }
1884 return "gu";
1885 case LANG_HAUSA:
1886 switch (sub)
1887 {
1888 case 0x1f: return "ha";
1889 case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG";
1890 }
1891 return "ha";
1892 case LANG_HAWAIIAN:
1893 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1894 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
1895 switch (sub)
1896 {
1897 case SUBLANG_DEFAULT: return "cpe_US";
1898 }
1899 return "cpe";
1900 case LANG_HEBREW:
1901 switch (sub)
1902 {
1903 case SUBLANG_HEBREW_ISRAEL: return "he_IL";
1904 }
1905 return "he";
1906 case LANG_HINDI:
1907 switch (sub)
1908 {
1909 case SUBLANG_HINDI_INDIA: return "hi_IN";
1910 }
1911 return "hi";
1912 case LANG_HUNGARIAN:
1913 switch (sub)
1914 {
1915 case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU";
1916 }
1917 return "hu";
1918 case LANG_IBIBIO:
1919 switch (sub)
1920 {
1921 case SUBLANG_DEFAULT: return "nic_NG";
1922 }
1923 return "nic";
1924 case LANG_ICELANDIC:
1925 switch (sub)
1926 {
1927 case SUBLANG_ICELANDIC_ICELAND: return "is_IS";
1928 }
1929 return "is";
1930 case LANG_IGBO:
1931 switch (sub)
1932 {
1933 case SUBLANG_IGBO_NIGERIA: return "ig_NG";
1934 }
1935 return "ig";
1936 case LANG_INDONESIAN:
1937 switch (sub)
1938 {
1939 case SUBLANG_INDONESIAN_INDONESIA: return "id_ID";
1940 }
1941 return "id";
1942 case LANG_INUKTITUT:
1943 switch (sub)
1944 {
1945 case 0x1e: return "iu"; /* syllabic */
1946 case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */
1947 case 0x1f: return "iu@latin";
1948 case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin";
1949 }
1950 return "iu";
1951 case LANG_ITALIAN:
1952 switch (sub)
1953 {
1954 case SUBLANG_ITALIAN: return "it_IT";
1955 case SUBLANG_ITALIAN_SWISS: return "it_CH";
1956 }
1957 return "it";
1958 case LANG_JAPANESE:
1959 switch (sub)
1960 {
1961 case SUBLANG_JAPANESE_JAPAN: return "ja_JP";
1962 }
1963 return "ja";
1964 case LANG_KANNADA:
1965 switch (sub)
1966 {
1967 case SUBLANG_KANNADA_INDIA: return "kn_IN";
1968 }
1969 return "kn";
1970 case LANG_KANURI:
1971 switch (sub)
1972 {
1973 case SUBLANG_DEFAULT: return "kr_NG";
1974 }
1975 return "kr";
1976 case LANG_KASHMIRI:
1977 switch (sub)
1978 {
1979 case SUBLANG_DEFAULT: return "ks_PK";
1980 case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
1981 }
1982 return "ks";
1983 case LANG_KAZAK:
1984 switch (sub)
1985 {
1986 case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ";
1987 }
1988 return "kk";
1989 case LANG_KICHE:
1990 /* FIXME: Adjust this when such locales appear on Unix. */
1991 switch (sub)
1992 {
1993 case SUBLANG_KICHE_GUATEMALA: return "qut_GT";
1994 }
1995 return "qut";
1996 case LANG_KINYARWANDA:
1997 switch (sub)
1998 {
1999 case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW";
2000 }
2001 return "rw";
2002 case LANG_KONKANI:
2003 /* FIXME: Adjust this when such locales appear on Unix. */
2004 switch (sub)
2005 {
2006 case SUBLANG_KONKANI_INDIA: return "kok_IN";
2007 }
2008 return "kok";
2009 case LANG_KOREAN:
2010 switch (sub)
2011 {
2012 case SUBLANG_DEFAULT: return "ko_KR";
2013 }
2014 return "ko";
2015 case LANG_KYRGYZ:
2016 switch (sub)
2017 {
2018 case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG";
2019 }
2020 return "ky";
2021 case LANG_LAO:
2022 switch (sub)
2023 {
2024 case SUBLANG_LAO_LAOS: return "lo_LA";
2025 }
2026 return "lo";
2027 case LANG_LATIN:
2028 switch (sub)
2029 {
2030 case SUBLANG_DEFAULT: return "la_VA";
2031 }
2032 return "la";
2033 case LANG_LATVIAN:
2034 switch (sub)
2035 {
2036 case SUBLANG_LATVIAN_LATVIA: return "lv_LV";
2037 }
2038 return "lv";
2039 case LANG_LITHUANIAN:
2040 switch (sub)
2041 {
2042 case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT";
2043 }
2044 return "lt";
2045 case LANG_LUXEMBOURGISH:
2046 switch (sub)
2047 {
2048 case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU";
2049 }
2050 return "lb";
2051 case LANG_MACEDONIAN:
2052 switch (sub)
2053 {
2054 case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK";
2055 }
2056 return "mk";
2057 case LANG_MALAY:
2058 switch (sub)
2059 {
2060 case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
2061 case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
2062 }
2063 return "ms";
2064 case LANG_MALAYALAM:
2065 switch (sub)
2066 {
2067 case SUBLANG_MALAYALAM_INDIA: return "ml_IN";
2068 }
2069 return "ml";
2070 case LANG_MALTESE:
2071 switch (sub)
2072 {
2073 case SUBLANG_MALTESE_MALTA: return "mt_MT";
2074 }
2075 return "mt";
2076 case LANG_MANIPURI:
2077 /* FIXME: Adjust this when such locales appear on Unix. */
2078 switch (sub)
2079 {
2080 case SUBLANG_DEFAULT: return "mni_IN";
2081 }
2082 return "mni";
2083 case LANG_MAORI:
2084 switch (sub)
2085 {
2086 case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ";
2087 }
2088 return "mi";
2089 case LANG_MAPUDUNGUN:
2090 switch (sub)
2091 {
2092 case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL";
2093 }
2094 return "arn";
2095 case LANG_MARATHI:
2096 switch (sub)
2097 {
2098 case SUBLANG_MARATHI_INDIA: return "mr_IN";
2099 }
2100 return "mr";
2101 case LANG_MOHAWK:
2102 switch (sub)
2103 {
2104 case SUBLANG_MOHAWK_CANADA: return "moh_CA";
2105 }
2106 return "moh";
2107 case LANG_MONGOLIAN:
2108 switch (sub)
2109 {
2110 case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN";
2111 case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN";
2112 }
2113 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
2114 case LANG_NEPALI:
2115 switch (sub)
2116 {
2117 case SUBLANG_NEPALI_NEPAL: return "ne_NP";
2118 case SUBLANG_NEPALI_INDIA: return "ne_IN";
2119 }
2120 return "ne";
2121 case LANG_NORWEGIAN:
2122 switch (sub)
2123 {
2124 case 0x1f: return "nb";
2125 case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
2126 case 0x1e: return "nn";
2127 case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
2128 }
2129 return "no";
2130 case LANG_OCCITAN:
2131 switch (sub)
2132 {
2133 case SUBLANG_OCCITAN_FRANCE: return "oc_FR";
2134 }
2135 return "oc";
2136 case LANG_ORIYA:
2137 switch (sub)
2138 {
2139 case SUBLANG_ORIYA_INDIA: return "or_IN";
2140 }
2141 return "or";
2142 case LANG_OROMO:
2143 switch (sub)
2144 {
2145 case SUBLANG_DEFAULT: return "om_ET";
2146 }
2147 return "om";
2148 case LANG_PAPIAMENTU:
2149 switch (sub)
2150 {
2151 case SUBLANG_DEFAULT: return "pap_AN";
2152 }
2153 return "pap";
2154 case LANG_PASHTO:
2155 switch (sub)
2156 {
2157 case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF";
2158 }
2159 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
2160 case LANG_POLISH:
2161 switch (sub)
2162 {
2163 case SUBLANG_POLISH_POLAND: return "pl_PL";
2164 }
2165 return "pl";
2166 case LANG_PORTUGUESE:
2167 switch (sub)
2168 {
2169 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
2170 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
2171 case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
2172 case SUBLANG_PORTUGUESE: return "pt_PT";
2173 }
2174 return "pt";
2175 case LANG_PUNJABI:
2176 switch (sub)
2177 {
2178 case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
2179 case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
2180 }
2181 return "pa";
2182 case LANG_QUECHUA:
2183 /* Note: Microsoft uses the non-ISO language code "quz". */
2184 switch (sub)
2185 {
2186 case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
2187 case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
2188 case SUBLANG_QUECHUA_PERU: return "qu_PE";
2189 }
2190 return "qu";
2191 case LANG_ROMANIAN:
2192 switch (sub)
2193 {
2194 case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
2195 case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
2196 }
2197 return "ro";
2198 case LANG_ROMANSH:
2199 switch (sub)
2200 {
2201 case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH";
2202 }
2203 return "rm";
2204 case LANG_RUSSIAN:
2205 switch (sub)
2206 {
2207 case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
2208 case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
2209 }
2210 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
2211 case LANG_SAMI:
2212 switch (sub)
2213 {
2214 /* Northern Sami */
2215 case 0x00: return "se";
2216 case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO";
2217 case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE";
2218 case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI";
2219 /* Lule Sami */
2220 case 0x1f: return "smj";
2221 case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO";
2222 case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE";
2223 /* Southern Sami */
2224 case 0x1e: return "sma";
2225 case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO";
2226 case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE";
2227 /* Skolt Sami */
2228 case 0x1d: return "sms";
2229 case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI";
2230 /* Inari Sami */
2231 case 0x1c: return "smn";
2232 case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI";
2233 }
2234 return "se"; /* or "smi"? */
2235 case LANG_SANSKRIT:
2236 switch (sub)
2237 {
2238 case SUBLANG_SANSKRIT_INDIA: return "sa_IN";
2239 }
2240 return "sa";
2241 case LANG_SCOTTISH_GAELIC:
2242 switch (sub)
2243 {
2244 case SUBLANG_DEFAULT: return "gd_GB";
2245 }
2246 return "gd";
2247 case LANG_SINDHI:
2248 switch (sub)
2249 {
2250 case SUBLANG_SINDHI_INDIA: return "sd_IN";
2251 case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
2252 /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
2253 }
2254 return "sd";
2255 case LANG_SINHALESE:
2256 switch (sub)
2257 {
2258 case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK";
2259 }
2260 return "si";
2261 case LANG_SLOVAK:
2262 switch (sub)
2263 {
2264 case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK";
2265 }
2266 return "sk";
2267 case LANG_SLOVENIAN:
2268 switch (sub)
2269 {
2270 case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI";
2271 }
2272 return "sl";
2273 case LANG_SOMALI:
2274 switch (sub)
2275 {
2276 case SUBLANG_DEFAULT: return "so_SO";
2277 }
2278 return "so";
2279 case LANG_SORBIAN:
2280 /* FIXME: Adjust this when such locales appear on Unix. */
2281 switch (sub)
2282 {
2283 /* Upper Sorbian */
2284 case 0x00: return "hsb";
2285 case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE";
2286 /* Lower Sorbian */
2287 case 0x1f: return "dsb";
2288 case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE";
2289 }
2290 return "wen";
2291 case LANG_SOTHO:
2292 /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings>
2293 calls it "Sesotho sa Leboa"; according to
2294 <https://www.ethnologue.com/show_language.asp?code=nso>
2295 <https://www.ethnologue.com/show_language.asp?code=sot>
2296 it's the same as Northern Sotho. */
2297 switch (sub)
2298 {
2299 case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA";
2300 }
2301 return "nso";
2302 case LANG_SPANISH:
2303 switch (sub)
2304 {
2305 case SUBLANG_SPANISH: return "es_ES";
2306 case SUBLANG_SPANISH_MEXICAN: return "es_MX";
2307 case SUBLANG_SPANISH_MODERN:
2308 return "es_ES@modern"; /* not seen on Unix */
2309 case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
2310 case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
2311 case SUBLANG_SPANISH_PANAMA: return "es_PA";
2312 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
2313 case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
2314 case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
2315 case SUBLANG_SPANISH_PERU: return "es_PE";
2316 case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
2317 case SUBLANG_SPANISH_ECUADOR: return "es_EC";
2318 case SUBLANG_SPANISH_CHILE: return "es_CL";
2319 case SUBLANG_SPANISH_URUGUAY: return "es_UY";
2320 case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
2321 case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
2322 case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
2323 case SUBLANG_SPANISH_HONDURAS: return "es_HN";
2324 case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
2325 case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
2326 case SUBLANG_SPANISH_US: return "es_US";
2327 }
2328 return "es";
2329 case LANG_SUTU:
2330 switch (sub)
2331 {
2332 case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
2333 }
2334 return "bnt";
2335 case LANG_SWAHILI:
2336 switch (sub)
2337 {
2338 case SUBLANG_SWAHILI_KENYA: return "sw_KE";
2339 }
2340 return "sw";
2341 case LANG_SWEDISH:
2342 switch (sub)
2343 {
2344 case SUBLANG_SWEDISH_SWEDEN: return "sv_SE";
2345 case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
2346 }
2347 return "sv";
2348 case LANG_SYRIAC:
2349 switch (sub)
2350 {
2351 case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */
2352 }
2353 return "syr";
2354 case LANG_TAGALOG:
2355 switch (sub)
2356 {
2357 case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */
2358 }
2359 return "tl"; /* or "fil"? */
2360 case LANG_TAJIK:
2361 switch (sub)
2362 {
2363 case 0x1f: return "tg";
2364 case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ";
2365 }
2366 return "tg";
2367 case LANG_TAMAZIGHT:
2368 /* Note: Microsoft uses the non-ISO language code "tmz". */
2369 switch (sub)
2370 {
2371 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
2372 case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
2373 case 0x1f: return "ber@latin";
2374 case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
2375 }
2376 return "ber";
2377 case LANG_TAMIL:
2378 switch (sub)
2379 {
2380 case SUBLANG_TAMIL_INDIA: return "ta_IN";
2381 }
2382 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
2383 case LANG_TATAR:
2384 switch (sub)
2385 {
2386 case SUBLANG_TATAR_RUSSIA: return "tt_RU";
2387 }
2388 return "tt";
2389 case LANG_TELUGU:
2390 switch (sub)
2391 {
2392 case SUBLANG_TELUGU_INDIA: return "te_IN";
2393 }
2394 return "te";
2395 case LANG_THAI:
2396 switch (sub)
2397 {
2398 case SUBLANG_THAI_THAILAND: return "th_TH";
2399 }
2400 return "th";
2401 case LANG_TIBETAN:
2402 switch (sub)
2403 {
2404 case SUBLANG_TIBETAN_PRC:
2405 /* Most Tibetans would not like "bo_CN". But Tibet does not yet
2406 have a country code of its own. */
2407 return "bo";
2408 case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
2409 }
2410 return "bo";
2411 case LANG_TIGRINYA:
2412 switch (sub)
2413 {
2414 case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
2415 case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
2416 }
2417 return "ti";
2418 case LANG_TSONGA:
2419 switch (sub)
2420 {
2421 case SUBLANG_DEFAULT: return "ts_ZA";
2422 }
2423 return "ts";
2424 case LANG_TSWANA:
2425 /* Spoken in South Africa, Botswana. */
2426 switch (sub)
2427 {
2428 case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA";
2429 }
2430 return "tn";
2431 case LANG_TURKISH:
2432 switch (sub)
2433 {
2434 case SUBLANG_TURKISH_TURKEY: return "tr_TR";
2435 }
2436 return "tr";
2437 case LANG_TURKMEN:
2438 switch (sub)
2439 {
2440 case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM";
2441 }
2442 return "tk";
2443 case LANG_UIGHUR:
2444 switch (sub)
2445 {
2446 case SUBLANG_UIGHUR_PRC: return "ug_CN";
2447 }
2448 return "ug";
2449 case LANG_UKRAINIAN:
2450 switch (sub)
2451 {
2452 case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA";
2453 }
2454 return "uk";
2455 case LANG_URDU:
2456 switch (sub)
2457 {
2458 case SUBLANG_URDU_PAKISTAN: return "ur_PK";
2459 case SUBLANG_URDU_INDIA: return "ur_IN";
2460 }
2461 return "ur";
2462 case LANG_UZBEK:
2463 switch (sub)
2464 {
2465 case 0x1f: return "uz";
2466 case SUBLANG_UZBEK_LATIN: return "uz_UZ";
2467 case 0x1e: return "uz@cyrillic";
2468 case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
2469 }
2470 return "uz";
2471 case LANG_VENDA:
2472 switch (sub)
2473 {
2474 case SUBLANG_DEFAULT: return "ve_ZA";
2475 }
2476 return "ve";
2477 case LANG_VIETNAMESE:
2478 switch (sub)
2479 {
2480 case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN";
2481 }
2482 return "vi";
2483 case LANG_WELSH:
2484 switch (sub)
2485 {
2486 case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB";
2487 }
2488 return "cy";
2489 case LANG_WOLOF:
2490 switch (sub)
2491 {
2492 case SUBLANG_WOLOF_SENEGAL: return "wo_SN";
2493 }
2494 return "wo";
2495 case LANG_XHOSA:
2496 switch (sub)
2497 {
2498 case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA";
2499 }
2500 return "xh";
2501 case LANG_YAKUT:
2502 switch (sub)
2503 {
2504 case SUBLANG_YAKUT_RUSSIA: return "sah_RU";
2505 }
2506 return "sah";
2507 case LANG_YI:
2508 switch (sub)
2509 {
2510 case SUBLANG_YI_PRC: return "ii_CN";
2511 }
2512 return "ii";
2513 case LANG_YIDDISH:
2514 switch (sub)
2515 {
2516 case SUBLANG_DEFAULT: return "yi_IL";
2517 }
2518 return "yi";
2519 case LANG_YORUBA:
2520 switch (sub)
2521 {
2522 case SUBLANG_YORUBA_NIGERIA: return "yo_NG";
2523 }
2524 return "yo";
2525 case LANG_ZULU:
2526 switch (sub)
2527 {
2528 case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA";
2529 }
2530 return "zu";
2531 default: return "C";
2532 }
2533 }
2534}
2535
2536# if !defined IN_LIBINTL
2537static
2538# endif
2539const char *
2540gl_locale_name_from_win32_LCID (LCID lcid)
2541{
2542 LANGID langid;
2543
2544 /* Strip off the sorting rules, keep only the language part. */
2545 langid = LANGIDFROMLCID (lcid);
2546
2547 return gl_locale_name_from_win32_LANGID (langid);
2548}
2549
2550# ifdef WINDOWS_NATIVE
2551
2552/* Two variables to interface between get_lcid and the EnumLocales
2553 callback function below. */
2554static LCID found_lcid;
2555static char lname[LC_MAX * (LOCALE_NAME_MAX_LENGTH + 1) + 1];
2556
2557/* Callback function for EnumLocales. */
2558static BOOL CALLBACK
2559enum_locales_fn (LPSTR locale_num_str)
2560{
2561 char *endp;
2562 char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1];
2563 LCID try_lcid = strtoul (locale_num_str, &endp, 16);
2564
2565 if (GetLocaleInfo (try_lcid, LOCALE_SENGLANGUAGE,
2566 locval, LOCALE_NAME_MAX_LENGTH))
2567 {
2568 strcat (locval, "_");
2569 if (GetLocaleInfo (try_lcid, LOCALE_SENGCOUNTRY,
2570 locval + strlen (locval), LOCALE_NAME_MAX_LENGTH))
2571 {
2572 size_t locval_len = strlen (locval);
2573
2574 if (strncmp (locval, lname, locval_len) == 0
2575 && (lname[locval_len] == '.'
2576 || lname[locval_len] == '\0'))
2577 {
2578 found_lcid = try_lcid;
2579 return FALSE;
2580 }
2581 }
2582 }
2583 return TRUE;
2584}
2585
2586/* This lock protects the get_lcid against multiple simultaneous calls. */
2587gl_lock_define_initialized(static, get_lcid_lock)
2588
2589/* Return the Locale ID (LCID) number given the locale's name, a
2590 string, in LOCALE_NAME. This works by enumerating all the locales
2591 supported by the system, until we find one whose name matches
2592 LOCALE_NAME. */
2593static LCID
2594get_lcid (const char *locale_name)
2595{
2596 /* A simple cache. */
2597 static LCID last_lcid;
2598 static char last_locale[1000];
2599
2600 /* Lock while looking for an LCID, to protect access to static
2601 variables: last_lcid, last_locale, found_lcid, and lname. */
2602 gl_lock_lock (get_lcid_lock);
2603 if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0)
2604 {
2605 gl_lock_unlock (get_lcid_lock);
2606 return last_lcid;
2607 }
2608 strncpy (lname, locale_name, sizeof (lname) - 1);
2609 lname[sizeof (lname) - 1] = '\0';
2610 found_lcid = 0;
2611 EnumSystemLocales (enum_locales_fn, LCID_SUPPORTED);
2612 if (found_lcid > 0)
2613 {
2614 last_lcid = found_lcid;
2615 strcpy (last_locale, locale_name);
2616 }
2617 gl_lock_unlock (get_lcid_lock);
2618 return found_lcid;
2619}
2620
2621# endif
2622#endif
2623
2624
2625#if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6,
2626 Solaris 11 OpenIndiana, or Solaris >= 11.4 */
2627
2628/* Simple hash set of strings. We don't want to drag in lots of hash table
2629 code here. */
2630
2631# define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
2632
2633/* A hash function for NUL-terminated char* strings using
2634 the method described by Bruno Haible.
2635 See https://www.haible.de/bruno/hashfunc.html. */
2636static size_t _GL_ATTRIBUTE_PURE
2637string_hash (const void *x)
2638{
2639 const char *s = (const char *) x;
2640 size_t h = 0;
2641
2642 for (; *s; s++)
2643 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
2644
2645 return h;
2646}
2647
2648/* A hash table of fixed size. Multiple threads can access it read-only
2649 simultaneously, but only one thread can insert into it at the same time. */
2650
2651/* A node in a hash bucket collision list. */
2652struct struniq_hash_node
2653 {
2654 struct struniq_hash_node * volatile next;
2655 char contents[FLEXIBLE_ARRAY_MEMBER];
2656 };
2657
2658# define STRUNIQ_HASH_TABLE_SIZE 257
2659static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE_SIZE]
2660 /* = { NULL, ..., NULL } */;
2661
2662/* This lock protects the struniq_hash_table against multiple simultaneous
2663 insertions. */
2664gl_lock_define_initialized(static, struniq_lock)
2665
2666/* Store a copy of the given string in a string pool with indefinite extent.
2667 Return a pointer to this copy. */
2668static const char *
2669struniq (const char *string)
2670{
2671 size_t hashcode = string_hash (string);
2672 size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE;
2673 size_t size;
2674 struct struniq_hash_node *new_node;
2675 struct struniq_hash_node *p;
2676 for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
2677 if (strcmp (p->contents, string) == 0)
2678 return p->contents;
2679 size = strlen (string) + 1;
2680 new_node =
2681 (struct struniq_hash_node *)
2682 malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size));
2683 if (new_node == NULL)
2684 /* Out of memory. Return a statically allocated string. */
2685 return "C";
2686 memcpy (new_node->contents, string, size);
2687 {
2688 bool mt = gl_multithreaded ();
2689 /* Lock while inserting new_node. */
2690 if (mt) gl_lock_lock (struniq_lock);
2691 /* Check whether another thread already added the string while we were
2692 waiting on the lock. */
2693 for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
2694 if (strcmp (p->contents, string) == 0)
2695 {
2696 free (new_node);
2697 new_node = p;
2698 goto done;
2699 }
2700 /* Really insert new_node into the hash table. Fill new_node entirely
2701 first, because other threads may be iterating over the linked list. */
2702 new_node->next = struniq_hash_table[slot];
2703 struniq_hash_table[slot] = new_node;
2704 done:
2705 /* Unlock after new_node is inserted. */
2706 if (mt) gl_lock_unlock (struniq_lock);
2707 }
2708 return new_node->contents;
2709}
2710
2711#endif
2712
2713
2714#if LOCALENAME_ENHANCE_LOCALE_FUNCS
2715
2716/* The 'locale_t' object does not contain the names of the locale categories.
2717 We have to associate them with the object through a hash table.
2718 The hash table is defined in localename-table.[hc]. */
2719
2720/* Returns the name of a given locale category in a given locale_t object,
2721 allocated as a string with indefinite extent. */
2722static const char *
2723get_locale_t_name (int category, locale_t locale)
2724{
2725 if (locale == LC_GLOBAL_LOCALE)
2726 {
2727 /* Query the global locale. */
2728 const char *name = setlocale_null (category);
2729 if (name != NULL)
2730 return struniq (name);
2731 else
2732 /* Should normally not happen. */
2733 return "";
2734 }
2735 else
2736 {
2737 /* Look up the names in the hash table. */
2738 size_t hashcode = locale_hash_function (locale);
2739 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
2740 /* If the locale was not found in the table, return "". This can
2741 happen if the application uses the original newlocale()/duplocale()
2742 functions instead of the overridden ones. */
2743 const char *name = "";
2744 struct locale_hash_node *p;
2745 /* Lock while looking up the hash node. */
2746 gl_rwlock_rdlock (locale_lock);
2747 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
2748 if (p->locale == locale)
2749 {
2750 name = p->names.category_name[category];
2751 break;
2752 }
2753 gl_rwlock_unlock (locale_lock);
2754 return name;
2755 }
2756}
2757
2758# if !(defined newlocale && defined duplocale && defined freelocale)
2759# error "newlocale, duplocale, freelocale not being replaced as expected!"
2760# endif
2761
2762/* newlocale() override. */
2763locale_t
2764newlocale (int category_mask, const char *name, locale_t base)
2765#undef newlocale
2766{
2767 struct locale_categories_names names;
2768 struct locale_hash_node *node;
2769 locale_t result;
2770
2771 /* Make sure name has indefinite extent. */
2772 if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
2773 | LC_MONETARY_MASK | LC_MESSAGES_MASK)
2774 & category_mask) != 0)
2775 name = struniq (name);
2776
2777 /* Determine the category names of the result. */
2778 if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
2779 | LC_MONETARY_MASK | LC_MESSAGES_MASK)
2780 & ~category_mask) == 0)
2781 {
2782 /* Use name, ignore base. */
2783 int category;
2784
2785 name = struniq (name);
2786 for (category = 0; category < 6; category++)
2787 names.category_name[category] = name;
2788 }
2789 else
2790 {
2791 /* Use base, possibly also name. */
2792 if (base == NULL)
2793 {
2794 int category;
2795
2796 for (category = 0; category < 6; category++)
2797 {
2798 int mask;
2799
2800 switch (category)
2801 {
2802 case LC_CTYPE:
2803 mask = LC_CTYPE_MASK;
2804 break;
2805 case LC_NUMERIC:
2806 mask = LC_NUMERIC_MASK;
2807 break;
2808 case LC_TIME:
2809 mask = LC_TIME_MASK;
2810 break;
2811 case LC_COLLATE:
2812 mask = LC_COLLATE_MASK;
2813 break;
2814 case LC_MONETARY:
2815 mask = LC_MONETARY_MASK;
2816 break;
2817 case LC_MESSAGES:
2818 mask = LC_MESSAGES_MASK;
2819 break;
2820 default:
2821 abort ();
2822 }
2823 names.category_name[category] =
2824 ((mask & category_mask) != 0 ? name : "C");
2825 }
2826 }
2827 else if (base == LC_GLOBAL_LOCALE)
2828 {
2829 int category;
2830
2831 for (category = 0; category < 6; category++)
2832 {
2833 int mask;
2834
2835 switch (category)
2836 {
2837 case LC_CTYPE:
2838 mask = LC_CTYPE_MASK;
2839 break;
2840 case LC_NUMERIC:
2841 mask = LC_NUMERIC_MASK;
2842 break;
2843 case LC_TIME:
2844 mask = LC_TIME_MASK;
2845 break;
2846 case LC_COLLATE:
2847 mask = LC_COLLATE_MASK;
2848 break;
2849 case LC_MONETARY:
2850 mask = LC_MONETARY_MASK;
2851 break;
2852 case LC_MESSAGES:
2853 mask = LC_MESSAGES_MASK;
2854 break;
2855 default:
2856 abort ();
2857 }
2858 names.category_name[category] =
2859 ((mask & category_mask) != 0
2860 ? name
2861 : get_locale_t_name (category, LC_GLOBAL_LOCALE));
2862 }
2863 }
2864 else
2865 {
2866 /* Look up the names of base in the hash table. Like multiple calls
2867 of get_locale_t_name, but locking only once. */
2868 struct locale_hash_node *p;
2869 int category;
2870
2871 /* Lock while looking up the hash node. */
2872 gl_rwlock_rdlock (locale_lock);
2873 for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE];
2874 p != NULL;
2875 p = p->next)
2876 if (p->locale == base)
2877 break;
2878
2879 for (category = 0; category < 6; category++)
2880 {
2881 int mask;
2882
2883 switch (category)
2884 {
2885 case LC_CTYPE:
2886 mask = LC_CTYPE_MASK;
2887 break;
2888 case LC_NUMERIC:
2889 mask = LC_NUMERIC_MASK;
2890 break;
2891 case LC_TIME:
2892 mask = LC_TIME_MASK;
2893 break;
2894 case LC_COLLATE:
2895 mask = LC_COLLATE_MASK;
2896 break;
2897 case LC_MONETARY:
2898 mask = LC_MONETARY_MASK;
2899 break;
2900 case LC_MESSAGES:
2901 mask = LC_MESSAGES_MASK;
2902 break;
2903 default:
2904 abort ();
2905 }
2906 names.category_name[category] =
2907 ((mask & category_mask) != 0
2908 ? name
2909 : (p != NULL ? p->names.category_name[category] : ""));
2910 }
2911
2912 gl_rwlock_unlock (locale_lock);
2913 }
2914 }
2915
2916 node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
2917 if (node == NULL)
2918 /* errno is set to ENOMEM. */
2919 return NULL;
2920
2921 result = newlocale (category_mask, name, base);
2922 if (result == NULL)
2923 {
2924 free (node);
2925 return NULL;
2926 }
2927
2928 /* Fill the hash node. */
2929 node->locale = result;
2930 node->names = names;
2931
2932 /* Insert it in the hash table. */
2933 {
2934 size_t hashcode = locale_hash_function (result);
2935 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
2936 struct locale_hash_node *p;
2937
2938 /* Lock while inserting the new node. */
2939 gl_rwlock_wrlock (locale_lock);
2940 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
2941 if (p->locale == result)
2942 {
2943 /* This can happen if the application uses the original freelocale()
2944 function instead of the overridden one. */
2945 p->names = node->names;
2946 break;
2947 }
2948 if (p == NULL)
2949 {
2950 node->next = locale_hash_table[slot];
2951 locale_hash_table[slot] = node;
2952 }
2953
2954 gl_rwlock_unlock (locale_lock);
2955
2956 if (p != NULL)
2957 free (node);
2958 }
2959
2960 return result;
2961}
2962
2963/* duplocale() override. */
2964locale_t
2965duplocale (locale_t locale)
2966#undef duplocale
2967{
2968 struct locale_hash_node *node;
2969 locale_t result;
2970
2971 if (locale == NULL)
2972 /* Invalid argument. */
2973 abort ();
2974
2975 node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
2976 if (node == NULL)
2977 /* errno is set to ENOMEM. */
2978 return NULL;
2979
2980 result = duplocale (locale);
2981 if (result == NULL)
2982 {
2983 free (node);
2984 return NULL;
2985 }
2986
2987 /* Fill the hash node. */
2988 node->locale = result;
2989 if (locale == LC_GLOBAL_LOCALE)
2990 {
2991 int category;
2992
2993 for (category = 0; category < 6; category++)
2994 node->names.category_name[category] =
2995 get_locale_t_name (category, LC_GLOBAL_LOCALE);
2996
2997 /* Lock before inserting the new node. */
2998 gl_rwlock_wrlock (locale_lock);
2999 }
3000 else
3001 {
3002 struct locale_hash_node *p;
3003
3004 /* Lock once, for the lookup and the insertion. */
3005 gl_rwlock_wrlock (locale_lock);
3006
3007 for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE];
3008 p != NULL;
3009 p = p->next)
3010 if (p->locale == locale)
3011 break;
3012 if (p != NULL)
3013 node->names = p->names;
3014 else
3015 {
3016 /* This can happen if the application uses the original
3017 newlocale()/duplocale() functions instead of the overridden
3018 ones. */
3019 int category;
3020
3021 for (category = 0; category < 6; category++)
3022 node->names.category_name[category] = "";
3023 }
3024 }
3025
3026 /* Insert it in the hash table. */
3027 {
3028 size_t hashcode = locale_hash_function (result);
3029 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
3030 struct locale_hash_node *p;
3031
3032 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
3033 if (p->locale == result)
3034 {
3035 /* This can happen if the application uses the original freelocale()
3036 function instead of the overridden one. */
3037 p->names = node->names;
3038 break;
3039 }
3040 if (p == NULL)
3041 {
3042 node->next = locale_hash_table[slot];
3043 locale_hash_table[slot] = node;
3044 }
3045
3046 gl_rwlock_unlock (locale_lock);
3047
3048 if (p != NULL)
3049 free (node);
3050 }
3051
3052 return result;
3053}
3054
3055/* freelocale() override. */
3056void
3057freelocale (locale_t locale)
3058#undef freelocale
3059{
3060 if (locale == NULL || locale == LC_GLOBAL_LOCALE)
3061 /* Invalid argument. */
3062 abort ();
3063
3064 {
3065 size_t hashcode = locale_hash_function (locale);
3066 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
3067 struct locale_hash_node *found;
3068 struct locale_hash_node **p;
3069
3070 found = NULL;
3071 /* Lock while removing the hash node. */
3072 gl_rwlock_wrlock (locale_lock);
3073 for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next)
3074 if ((*p)->locale == locale)
3075 {
3076 found = *p;
3077 *p = (*p)->next;
3078 break;
3079 }
3080 gl_rwlock_unlock (locale_lock);
3081 free (found);
3082 }
3083
3084 freelocale (locale);
3085}
3086
3087#endif
3088
3089
3090#if defined IN_LIBINTL || HAVE_GOOD_USELOCALE
3091
3092/* Like gl_locale_name_thread, except that the result is not in storage of
3093 indefinite extent. */
3094# if !defined IN_LIBINTL
3095static
3096# endif
3097const char *
3098gl_locale_name_thread_unsafe (int category, const char *categoryname _GL_UNUSED)
3099{
3100# if HAVE_GOOD_USELOCALE
3101 {
3102 locale_t thread_locale = uselocale (NULL);
3103 if (thread_locale != LC_GLOBAL_LOCALE)
3104 {
3105# if __GLIBC__ >= 2 && !defined __UCLIBC__
3106 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
3107 glibc < 2.12.
3108 See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
3109 const char *name =
3110 nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
3111 if (name[0] == '\0')
3112 /* Fallback code for glibc < 2.4, which did not implement
3113 nl_langinfo (_NL_LOCALE_NAME (category)). */
3114 name = thread_locale->__names[category];
3115 return name;
3116# elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
3117 /* musl libc */
3118 return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
3119# elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
3120 /* FreeBSD, Mac OS X */
3121 int mask;
3122
3123 switch (category)
3124 {
3125 case LC_CTYPE:
3126 mask = LC_CTYPE_MASK;
3127 break;
3128 case LC_NUMERIC:
3129 mask = LC_NUMERIC_MASK;
3130 break;
3131 case LC_TIME:
3132 mask = LC_TIME_MASK;
3133 break;
3134 case LC_COLLATE:
3135 mask = LC_COLLATE_MASK;
3136 break;
3137 case LC_MONETARY:
3138 mask = LC_MONETARY_MASK;
3139 break;
3140 case LC_MESSAGES:
3141 mask = LC_MESSAGES_MASK;
3142 break;
3143 default: /* We shouldn't get here. */
3144 return "";
3145 }
3146 return querylocale (mask, thread_locale);
3147# elif defined __sun
3148# if HAVE_GETLOCALENAME_L
3149 /* Solaris >= 12. */
3150 return getlocalename_l (category, thread_locale);
3151# elif HAVE_SOLARIS114_LOCALES
3152 /* Solaris >= 11.4. */
3153 void *lcp = (*thread_locale)->core.data->lcp;
3154 if (lcp != NULL)
3155 switch (category)
3156 {
3157 case LC_CTYPE:
3158 case LC_NUMERIC:
3159 case LC_TIME:
3160 case LC_COLLATE:
3161 case LC_MONETARY:
3162 case LC_MESSAGES:
3163 return ((const char * const *) lcp)[category];
3164 default: /* We shouldn't get here. */
3165 return "";
3166 }
3167# elif HAVE_NAMELESS_LOCALES
3168 return get_locale_t_name (category, thread_locale);
3169# else
3170 /* Solaris 11 OpenIndiana.
3171 For the internal structure of locale objects, see
3172 https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
3173 switch (category)
3174 {
3175 case LC_CTYPE:
3176 case LC_NUMERIC:
3177 case LC_TIME:
3178 case LC_COLLATE:
3179 case LC_MONETARY:
3180 case LC_MESSAGES:
3181 return ((const char * const *) thread_locale)[category];
3182 default: /* We shouldn't get here. */
3183 return "";
3184 }
3185# endif
3186# elif defined _AIX && HAVE_NAMELESS_LOCALES
3187 return get_locale_t_name (category, thread_locale);
3188# elif defined __CYGWIN__
3189 /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
3190 Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
3191 an opaque struct. */
3192# ifdef NL_LOCALE_NAME
3193 return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
3194# else
3195 /* FIXME: Remove when we can assume new-enough Cygwin. */
3196 struct __locale_t {
3197 char categories[7][32];
3198 };
3199 return ((struct __locale_t *) thread_locale)->categories[category];
3200# endif
3201# elif defined __ANDROID__
3202 return MB_CUR_MAX == 4 ? "C.UTF-8" : "C";
3203# endif
3204 }
3205 }
3206# endif
3207 return NULL;
3208}
3209
3210#endif
3211
3212const char *
3213gl_locale_name_thread (int category, const char *categoryname _GL_UNUSED)
3214{
3215#if HAVE_GOOD_USELOCALE
3216 const char *name = gl_locale_name_thread_unsafe (category, categoryname);
3217 if (name != NULL)
3218 return struniq (name);
3219#endif
3220 /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
3221 SetThreadLocale has not been called - which is a very frequent case -
3222 the value of GetThreadLocale() ignores past calls to 'setlocale'. */
3223 return NULL;
3224}
3225
3226/* XPG3 defines the result of 'setlocale (category, NULL)' as:
3227 "Directs 'setlocale()' to query 'category' and return the current
3228 setting of 'local'."
3229 However it does not specify the exact format. Neither do SUSV2 and
3230 ISO C 99. So we can use this feature only on selected systems (e.g.
3231 those using GNU C Library). */
3232#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
3233# define HAVE_LOCALE_NULL
3234#endif
3235
3236const char *
3237gl_locale_name_posix (int category, const char *categoryname _GL_UNUSED)
3238{
3239#if defined WINDOWS_NATIVE
3240 if (LC_MIN <= category && category <= LC_MAX)
3241 {
3242 const char *locname =
3243 /* setlocale_null (category) is identical to setlocale (category, NULL)
3244 on this platform. */
3245 setlocale (category, NULL);
3246
3247 /* Convert locale name to LCID. We don't want to use
3248 LocaleNameToLCID because (a) it is only available since Vista,
3249 and (b) it doesn't accept locale names returned by 'setlocale'. */
3250 LCID lcid = get_lcid (locname);
3251
3252 if (lcid > 0)
3253 return gl_locale_name_from_win32_LCID (lcid);
3254 }
3255#endif
3256 {
3257 const char *locname;
3258
3259 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
3260 On some systems this can be done by the 'setlocale' function itself. */
3261#if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
3262 locname = setlocale_null (category);
3263#else
3264 /* On other systems we ignore what setlocale reports and instead look at the
3265 environment variables directly. This is necessary
3266 1. on systems which have a facility for customizing the default locale
3267 (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
3268 function ignores this default locale (Mac OS X, Cygwin), in two cases:
3269 a. when the user missed to use the setlocale() override from libintl
3270 (for example by not including <libintl.h>),
3271 b. when setlocale supports only the "C" locale, such as on Cygwin
3272 1.5.x. In this case even the override from libintl cannot help.
3273 2. on all systems where setlocale supports only the "C" locale. */
3274 /* Strictly speaking, it is a POSIX violation to look at the environment
3275 variables regardless whether setlocale has been called or not. POSIX
3276 says:
3277 "For C-language programs, the POSIX locale shall be the
3278 default locale when the setlocale() function is not called."
3279 But we assume that all programs that use internationalized APIs call
3280 setlocale (LC_ALL, ""). */
3281 locname = gl_locale_name_environ (category, categoryname);
3282#endif
3283 /* Convert the locale name from the format returned by setlocale() or found
3284 in the environment variables to the XPG syntax. */
3285#if defined WINDOWS_NATIVE
3286 if (locname != NULL)
3287 {
3288 /* Convert locale name to LCID. We don't want to use
3289 LocaleNameToLCID because (a) it is only available since Vista,
3290 and (b) it doesn't accept locale names returned by 'setlocale'. */
3291 LCID lcid = get_lcid (locname);
3292
3293 if (lcid > 0)
3294 return gl_locale_name_from_win32_LCID (lcid);
3295 }
3296#endif
3297 return locname;
3298 }
3299}
3300
3301const char *
3302gl_locale_name_environ (int category _GL_UNUSED, const char *categoryname)
3303{
3304 const char *retval;
3305
3306 /* Setting of LC_ALL overrides all other. */
3307 retval = getenv ("LC_ALL");
3308 if (retval != NULL && retval[0] != '\0')
3309 return retval;
3310 /* Next comes the name of the desired category. */
3311 retval = getenv (categoryname);
3312 if (retval != NULL && retval[0] != '\0')
3313 return retval;
3314 /* Last possibility is the LANG environment variable. */
3315 retval = getenv ("LANG");
3316 if (retval != NULL && retval[0] != '\0')
3317 {
3318#if HAVE_CFPREFERENCESCOPYAPPVALUE
3319 /* Mac OS X 10.2 or newer.
3320 Ignore invalid LANG value set by the Terminal application. */
3321 if (strcmp (retval, "UTF-8") != 0)
3322#endif
3323#if defined __CYGWIN__
3324 /* Cygwin.
3325 Ignore dummy LANG value set by ~/.profile. */
3326 if (strcmp (retval, "C.UTF-8") != 0)
3327#endif
3328 return retval;
3329 }
3330
3331 return NULL;
3332}
3333
3334const char *
3335gl_locale_name_default (void)
3336{
3337 /* POSIX:2001 says:
3338 "All implementations shall define a locale as the default locale, to be
3339 invoked when no environment variables are set, or set to the empty
3340 string. This default locale can be the POSIX locale or any other
3341 implementation-defined locale. Some implementations may provide
3342 facilities for local installation administrators to set the default
3343 locale, customizing it for each location. POSIX:2001 does not require
3344 such a facility.
3345
3346 The systems with such a facility are Mac OS X and Windows: They provide a
3347 GUI that allows the user to choose a locale.
3348 - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
3349 Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
3350 'Terminal' application (but sometimes to an incorrect value "UTF-8").
3351 When no environment variable is set, setlocale (LC_ALL, "") uses the
3352 "C" locale.
3353 - On native Windows, by default, none of LC_* or LANG are set.
3354 When no environment variable is set, setlocale (LC_ALL, "") uses the
3355 locale chosen by the user.
3356 - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
3357 When no environment variable is set, setlocale (LC_ALL, "") uses the
3358 "C" locale.
3359 - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
3360 ~/.profile is executed.
3361 When no environment variable is set, setlocale (LC_ALL, "") uses the
3362 "C.UTF-8" locale, which operates in the same way as the "C" locale.
3363 */
3364
3365#if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
3366
3367 /* The system does not have a way of setting the locale, other than the
3368 POSIX specified environment variables. We use C as default locale. */
3369 return "C";
3370
3371#else
3372
3373 /* Return an XPG style locale name language[_territory][@modifier].
3374 Don't even bother determining the codeset; it's not useful in this
3375 context, because message catalogs are not specific to a single
3376 codeset. */
3377
3378# if HAVE_CFPREFERENCESCOPYAPPVALUE
3379 /* Mac OS X 10.4 or newer */
3380 /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
3381 because in macOS 10.13.4 it has the following behaviour:
3382 When two or more languages are specified in the
3383 "System Preferences > Language & Region > Preferred Languages" panel,
3384 it returns en_CC where CC is the territory (even when English is not among
3385 the preferred languages!). What we want instead is what
3386 CFLocaleCopyCurrent returned in earlier macOS releases and what
3387 CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
3388 first among the preferred languages and CC is the territory. */
3389 {
3390 /* Cache the locale name, since CoreFoundation calls are expensive. */
3391 static const char *cached_localename;
3392
3393 if (cached_localename == NULL)
3394 {
3395 char namebuf[256];
3396 CFTypeRef value =
3397 CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
3398 kCFPreferencesCurrentApplication);
3399 if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
3400 {
3401 CFStringRef name = (CFStringRef)value;
3402
3403 if (CFStringGetCString (name, namebuf, sizeof (namebuf),
3404 kCFStringEncodingASCII))
3405 {
3406 gl_locale_name_canonicalize (namebuf);
3407 cached_localename = strdup (namebuf);
3408 }
3409 }
3410 if (cached_localename == NULL)
3411 cached_localename = "C";
3412 }
3413 return cached_localename;
3414 }
3415
3416# endif
3417
3418# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
3419 {
3420 LCID lcid;
3421
3422 /* Use native Windows API locale ID. */
3423 lcid = GetThreadLocale ();
3424
3425 return gl_locale_name_from_win32_LCID (lcid);
3426 }
3427# endif
3428#endif
3429}
3430
3431/* Determine the current locale's name, and canonicalize it into XPG syntax
3432 language[_territory][.codeset][@modifier]
3433 The codeset part in the result is not reliable; the locale_charset()
3434 should be used for codeset information instead.
3435 The result must not be freed; it is statically allocated. */
3436
3437const char *
3438gl_locale_name (int category, const char *categoryname)
3439{
3440 const char *retval;
3441
3442 retval = gl_locale_name_thread (category, categoryname);
3443 if (retval != NULL)
3444 return retval;
3445
3446 retval = gl_locale_name_posix (category, categoryname);
3447 if (retval != NULL)
3448 return retval;
3449
3450 return gl_locale_name_default ();
3451}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette