LCOV - GNU Libidn - lib/gltests/localename.c

LCOV - code coverage report
Current view: top level - lib/gltests - localename.c (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 57 65 87.7 %
Date: 2020年07月22日 17:53:13 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13

AltStyle によって変換されたページ (->オリジナル) /