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