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