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