gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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