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