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