root/maint/gnulib/lib/localename.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gl_locale_name_canonicalize
  2. gl_locale_name_canonicalize
  3. gl_locale_name_from_win32_LANGID
  4. gl_locale_name_from_win32_LCID
  5. enum_locales_fn
  6. gl_lock_define_initialized
  7. string_hash
  8. gl_lock_define_initialized
  9. get_locale_t_name
  10. newlocale
  11. duplocale
  12. freelocale
  13. gl_locale_name_thread_unsafe
  14. gl_locale_name_thread
  15. gl_locale_name_posix
  16. gl_locale_name_environ
  17. gl_locale_name_default
  18. gl_locale_name

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

/* [previous][next][first][last][top][bottom][index][help] */