Tizen 2.1 base
[external/libgpg-error.git] / src / w32-gettext.c
1 /* w32-gettext.h - A simple gettext implementation for Windows targets.
2    Copyright (C) 1995,1996,1997,1999,2005 Free Software Foundation, Inc.
3    Copyright (C) 2005 g10 Code GmbH
4
5    This file is part of libgpg-error.
6  
7    libgpg-error is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public License
9    as published by the Free Software Foundation; either version 2.1 of
10    the License, or (at your option) any later version.
11  
12    libgpg-error is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16  
17    You should have received a copy of the GNU Lesser General Public
18    License along with libgpg-error; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <stdint.h>
34
35 #include <gpg-error.h>
36
37 #include "gettext.h"
38
39 \f
40 /* localname.c from gettext.  */
41
42 /* Edit: Added a "static" to _nl_locale_name.  Note that the category
43    argument is ignored on w32.  */
44
45 /* Determine the current selected locale.
46    Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
47
48    This program is free software; you can redistribute it and/or modify it
49    under the terms of the GNU Library General Public License as published
50    by the Free Software Foundation; either version 2, or (at your option)
51    any later version.
52
53    This program is distributed in the hope that it will be useful,
54    but WITHOUT ANY WARRANTY; without even the implied warranty of
55    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
56    Library General Public License for more details.
57
58    You should have received a copy of the GNU Library General Public
59    License along with this program; if not, write to the Free Software
60    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
61    USA.  */
62
63 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
64 /* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
65
66 #ifdef HAVE_CONFIG_H
67 # include <config.h>
68 #endif
69
70 #include <stdlib.h>
71 #include <locale.h>
72
73 #ifdef HAVE_W32_SYSTEM
74 # include <windows.h>
75 /* List of language codes, sorted by value:
76    0x01 LANG_ARABIC
77    0x02 LANG_BULGARIAN
78    0x03 LANG_CATALAN
79    0x04 LANG_CHINESE
80    0x05 LANG_CZECH
81    0x06 LANG_DANISH
82    0x07 LANG_GERMAN
83    0x08 LANG_GREEK
84    0x09 LANG_ENGLISH
85    0x0a LANG_SPANISH
86    0x0b LANG_FINNISH
87    0x0c LANG_FRENCH
88    0x0d LANG_HEBREW
89    0x0e LANG_HUNGARIAN
90    0x0f LANG_ICELANDIC
91    0x10 LANG_ITALIAN
92    0x11 LANG_JAPANESE
93    0x12 LANG_KOREAN
94    0x13 LANG_DUTCH
95    0x14 LANG_NORWEGIAN
96    0x15 LANG_POLISH
97    0x16 LANG_PORTUGUESE
98    0x17 LANG_RHAETO_ROMANCE
99    0x18 LANG_ROMANIAN
100    0x19 LANG_RUSSIAN
101    0x1a LANG_CROATIAN == LANG_SERBIAN
102    0x1b LANG_SLOVAK
103    0x1c LANG_ALBANIAN
104    0x1d LANG_SWEDISH
105    0x1e LANG_THAI
106    0x1f LANG_TURKISH
107    0x20 LANG_URDU
108    0x21 LANG_INDONESIAN
109    0x22 LANG_UKRAINIAN
110    0x23 LANG_BELARUSIAN
111    0x24 LANG_SLOVENIAN
112    0x25 LANG_ESTONIAN
113    0x26 LANG_LATVIAN
114    0x27 LANG_LITHUANIAN
115    0x28 LANG_TAJIK
116    0x29 LANG_FARSI
117    0x2a LANG_VIETNAMESE
118    0x2b LANG_ARMENIAN
119    0x2c LANG_AZERI
120    0x2d LANG_BASQUE
121    0x2e LANG_SORBIAN
122    0x2f LANG_MACEDONIAN
123    0x30 LANG_SUTU
124    0x31 LANG_TSONGA
125    0x32 LANG_TSWANA
126    0x33 LANG_VENDA
127    0x34 LANG_XHOSA
128    0x35 LANG_ZULU
129    0x36 LANG_AFRIKAANS
130    0x37 LANG_GEORGIAN
131    0x38 LANG_FAEROESE
132    0x39 LANG_HINDI
133    0x3a LANG_MALTESE
134    0x3b LANG_SAAMI
135    0x3c LANG_GAELIC
136    0x3d LANG_YIDDISH
137    0x3e LANG_MALAY
138    0x3f LANG_KAZAK
139    0x40 LANG_KYRGYZ
140    0x41 LANG_SWAHILI
141    0x42 LANG_TURKMEN
142    0x43 LANG_UZBEK
143    0x44 LANG_TATAR
144    0x45 LANG_BENGALI
145    0x46 LANG_PUNJABI
146    0x47 LANG_GUJARATI
147    0x48 LANG_ORIYA
148    0x49 LANG_TAMIL
149    0x4a LANG_TELUGU
150    0x4b LANG_KANNADA
151    0x4c LANG_MALAYALAM
152    0x4d LANG_ASSAMESE
153    0x4e LANG_MARATHI
154    0x4f LANG_SANSKRIT
155    0x50 LANG_MONGOLIAN
156    0x51 LANG_TIBETAN
157    0x52 LANG_WELSH
158    0x53 LANG_CAMBODIAN
159    0x54 LANG_LAO
160    0x55 LANG_BURMESE
161    0x56 LANG_GALICIAN
162    0x57 LANG_KONKANI
163    0x58 LANG_MANIPURI
164    0x59 LANG_SINDHI
165    0x5a LANG_SYRIAC
166    0x5b LANG_SINHALESE
167    0x5c LANG_CHEROKEE
168    0x5d LANG_INUKTITUT
169    0x5e LANG_AMHARIC
170    0x5f LANG_TAMAZIGHT
171    0x60 LANG_KASHMIRI
172    0x61 LANG_NEPALI
173    0x62 LANG_FRISIAN
174    0x63 LANG_PASHTO
175    0x64 LANG_TAGALOG
176    0x65 LANG_DIVEHI
177    0x66 LANG_EDO
178    0x67 LANG_FULFULDE
179    0x68 LANG_HAUSA
180    0x69 LANG_IBIBIO
181    0x6a LANG_YORUBA
182    0x70 LANG_IGBO
183    0x71 LANG_KANURI
184    0x72 LANG_OROMO
185    0x73 LANG_TIGRINYA
186    0x74 LANG_GUARANI
187    0x75 LANG_HAWAIIAN
188    0x76 LANG_LATIN
189    0x77 LANG_SOMALI
190    0x78 LANG_YI
191    0x79 LANG_PAPIAMENTU
192 */
193 /* Mingw headers don't have latest language and sublanguage codes.  */
194 # ifndef LANG_AFRIKAANS
195 # define LANG_AFRIKAANS 0x36
196 # endif
197 # ifndef LANG_ALBANIAN
198 # define LANG_ALBANIAN 0x1c
199 # endif
200 # ifndef LANG_AMHARIC
201 # define LANG_AMHARIC 0x5e
202 # endif
203 # ifndef LANG_ARABIC
204 # define LANG_ARABIC 0x01
205 # endif
206 # ifndef LANG_ARMENIAN
207 # define LANG_ARMENIAN 0x2b
208 # endif
209 # ifndef LANG_ASSAMESE
210 # define LANG_ASSAMESE 0x4d
211 # endif
212 # ifndef LANG_AZERI
213 # define LANG_AZERI 0x2c
214 # endif
215 # ifndef LANG_BASQUE
216 # define LANG_BASQUE 0x2d
217 # endif
218 # ifndef LANG_BELARUSIAN
219 # define LANG_BELARUSIAN 0x23
220 # endif
221 # ifndef LANG_BENGALI
222 # define LANG_BENGALI 0x45
223 # endif
224 # ifndef LANG_BURMESE
225 # define LANG_BURMESE 0x55
226 # endif
227 # ifndef LANG_CAMBODIAN
228 # define LANG_CAMBODIAN 0x53
229 # endif
230 # ifndef LANG_CATALAN
231 # define LANG_CATALAN 0x03
232 # endif
233 # ifndef LANG_CHEROKEE
234 # define LANG_CHEROKEE 0x5c
235 # endif
236 # ifndef LANG_DIVEHI
237 # define LANG_DIVEHI 0x65
238 # endif
239 # ifndef LANG_EDO
240 # define LANG_EDO 0x66
241 # endif
242 # ifndef LANG_ESTONIAN
243 # define LANG_ESTONIAN 0x25
244 # endif
245 # ifndef LANG_FAEROESE
246 # define LANG_FAEROESE 0x38
247 # endif
248 # ifndef LANG_FARSI
249 # define LANG_FARSI 0x29
250 # endif
251 # ifndef LANG_FRISIAN
252 # define LANG_FRISIAN 0x62
253 # endif
254 # ifndef LANG_FULFULDE
255 # define LANG_FULFULDE 0x67
256 # endif
257 # ifndef LANG_GAELIC
258 # define LANG_GAELIC 0x3c
259 # endif
260 # ifndef LANG_GALICIAN
261 # define LANG_GALICIAN 0x56
262 # endif
263 # ifndef LANG_GEORGIAN
264 # define LANG_GEORGIAN 0x37
265 # endif
266 # ifndef LANG_GUARANI
267 # define LANG_GUARANI 0x74
268 # endif
269 # ifndef LANG_GUJARATI
270 # define LANG_GUJARATI 0x47
271 # endif
272 # ifndef LANG_HAUSA
273 # define LANG_HAUSA 0x68
274 # endif
275 # ifndef LANG_HAWAIIAN
276 # define LANG_HAWAIIAN 0x75
277 # endif
278 # ifndef LANG_HEBREW
279 # define LANG_HEBREW 0x0d
280 # endif
281 # ifndef LANG_HINDI
282 # define LANG_HINDI 0x39
283 # endif
284 # ifndef LANG_IBIBIO
285 # define LANG_IBIBIO 0x69
286 # endif
287 # ifndef LANG_IGBO
288 # define LANG_IGBO 0x70
289 # endif
290 # ifndef LANG_INDONESIAN
291 # define LANG_INDONESIAN 0x21
292 # endif
293 # ifndef LANG_INUKTITUT
294 # define LANG_INUKTITUT 0x5d
295 # endif
296 # ifndef LANG_KANNADA
297 # define LANG_KANNADA 0x4b
298 # endif
299 # ifndef LANG_KANURI
300 # define LANG_KANURI 0x71
301 # endif
302 # ifndef LANG_KASHMIRI
303 # define LANG_KASHMIRI 0x60
304 # endif
305 # ifndef LANG_KAZAK
306 # define LANG_KAZAK 0x3f
307 # endif
308 # ifndef LANG_KONKANI
309 # define LANG_KONKANI 0x57
310 # endif
311 # ifndef LANG_KYRGYZ
312 # define LANG_KYRGYZ 0x40
313 # endif
314 # ifndef LANG_LAO
315 # define LANG_LAO 0x54
316 # endif
317 # ifndef LANG_LATIN
318 # define LANG_LATIN 0x76
319 # endif
320 # ifndef LANG_LATVIAN
321 # define LANG_LATVIAN 0x26
322 # endif
323 # ifndef LANG_LITHUANIAN
324 # define LANG_LITHUANIAN 0x27
325 # endif
326 # ifndef LANG_MACEDONIAN
327 # define LANG_MACEDONIAN 0x2f
328 # endif
329 # ifndef LANG_MALAY
330 # define LANG_MALAY 0x3e
331 # endif
332 # ifndef LANG_MALAYALAM
333 # define LANG_MALAYALAM 0x4c
334 # endif
335 # ifndef LANG_MALTESE
336 # define LANG_MALTESE 0x3a
337 # endif
338 # ifndef LANG_MANIPURI
339 # define LANG_MANIPURI 0x58
340 # endif
341 # ifndef LANG_MARATHI
342 # define LANG_MARATHI 0x4e
343 # endif
344 # ifndef LANG_MONGOLIAN
345 # define LANG_MONGOLIAN 0x50
346 # endif
347 # ifndef LANG_NEPALI
348 # define LANG_NEPALI 0x61
349 # endif
350 # ifndef LANG_ORIYA
351 # define LANG_ORIYA 0x48
352 # endif
353 # ifndef LANG_OROMO
354 # define LANG_OROMO 0x72
355 # endif
356 # ifndef LANG_PAPIAMENTU
357 # define LANG_PAPIAMENTU 0x79
358 # endif
359 # ifndef LANG_PASHTO
360 # define LANG_PASHTO 0x63
361 # endif
362 # ifndef LANG_PUNJABI
363 # define LANG_PUNJABI 0x46
364 # endif
365 # ifndef LANG_RHAETO_ROMANCE
366 # define LANG_RHAETO_ROMANCE 0x17
367 # endif
368 # ifndef LANG_SAAMI
369 # define LANG_SAAMI 0x3b
370 # endif
371 # ifndef LANG_SANSKRIT
372 # define LANG_SANSKRIT 0x4f
373 # endif
374 # ifndef LANG_SERBIAN
375 # define LANG_SERBIAN 0x1a
376 # endif
377 # ifndef LANG_SINDHI
378 # define LANG_SINDHI 0x59
379 # endif
380 # ifndef LANG_SINHALESE
381 # define LANG_SINHALESE 0x5b
382 # endif
383 # ifndef LANG_SLOVAK
384 # define LANG_SLOVAK 0x1b
385 # endif
386 # ifndef LANG_SOMALI
387 # define LANG_SOMALI 0x77
388 # endif
389 # ifndef LANG_SORBIAN
390 # define LANG_SORBIAN 0x2e
391 # endif
392 # ifndef LANG_SUTU
393 # define LANG_SUTU 0x30
394 # endif
395 # ifndef LANG_SWAHILI
396 # define LANG_SWAHILI 0x41
397 # endif
398 # ifndef LANG_SYRIAC
399 # define LANG_SYRIAC 0x5a
400 # endif
401 # ifndef LANG_TAGALOG
402 # define LANG_TAGALOG 0x64
403 # endif
404 # ifndef LANG_TAJIK
405 # define LANG_TAJIK 0x28
406 # endif
407 # ifndef LANG_TAMAZIGHT
408 # define LANG_TAMAZIGHT 0x5f
409 # endif
410 # ifndef LANG_TAMIL
411 # define LANG_TAMIL 0x49
412 # endif
413 # ifndef LANG_TATAR
414 # define LANG_TATAR 0x44
415 # endif
416 # ifndef LANG_TELUGU
417 # define LANG_TELUGU 0x4a
418 # endif
419 # ifndef LANG_THAI
420 # define LANG_THAI 0x1e
421 # endif
422 # ifndef LANG_TIBETAN
423 # define LANG_TIBETAN 0x51
424 # endif
425 # ifndef LANG_TIGRINYA
426 # define LANG_TIGRINYA 0x73
427 # endif
428 # ifndef LANG_TSONGA
429 # define LANG_TSONGA 0x31
430 # endif
431 # ifndef LANG_TSWANA
432 # define LANG_TSWANA 0x32
433 # endif
434 # ifndef LANG_TURKMEN
435 # define LANG_TURKMEN 0x42
436 # endif
437 # ifndef LANG_UKRAINIAN
438 # define LANG_UKRAINIAN 0x22
439 # endif
440 # ifndef LANG_URDU
441 # define LANG_URDU 0x20
442 # endif
443 # ifndef LANG_UZBEK
444 # define LANG_UZBEK 0x43
445 # endif
446 # ifndef LANG_VENDA
447 # define LANG_VENDA 0x33
448 # endif
449 # ifndef LANG_VIETNAMESE
450 # define LANG_VIETNAMESE 0x2a
451 # endif
452 # ifndef LANG_WELSH
453 # define LANG_WELSH 0x52
454 # endif
455 # ifndef LANG_XHOSA
456 # define LANG_XHOSA 0x34
457 # endif
458 # ifndef LANG_YI
459 # define LANG_YI 0x78
460 # endif
461 # ifndef LANG_YIDDISH
462 # define LANG_YIDDISH 0x3d
463 # endif
464 # ifndef LANG_YORUBA
465 # define LANG_YORUBA 0x6a
466 # endif
467 # ifndef LANG_ZULU
468 # define LANG_ZULU 0x35
469 # endif
470 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
471 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
472 # endif
473 # ifndef SUBLANG_ARABIC_IRAQ
474 # define SUBLANG_ARABIC_IRAQ 0x02
475 # endif
476 # ifndef SUBLANG_ARABIC_EGYPT
477 # define SUBLANG_ARABIC_EGYPT 0x03
478 # endif
479 # ifndef SUBLANG_ARABIC_LIBYA
480 # define SUBLANG_ARABIC_LIBYA 0x04
481 # endif
482 # ifndef SUBLANG_ARABIC_ALGERIA
483 # define SUBLANG_ARABIC_ALGERIA 0x05
484 # endif
485 # ifndef SUBLANG_ARABIC_MOROCCO
486 # define SUBLANG_ARABIC_MOROCCO 0x06
487 # endif
488 # ifndef SUBLANG_ARABIC_TUNISIA
489 # define SUBLANG_ARABIC_TUNISIA 0x07
490 # endif
491 # ifndef SUBLANG_ARABIC_OMAN
492 # define SUBLANG_ARABIC_OMAN 0x08
493 # endif
494 # ifndef SUBLANG_ARABIC_YEMEN
495 # define SUBLANG_ARABIC_YEMEN 0x09
496 # endif
497 # ifndef SUBLANG_ARABIC_SYRIA
498 # define SUBLANG_ARABIC_SYRIA 0x0a
499 # endif
500 # ifndef SUBLANG_ARABIC_JORDAN
501 # define SUBLANG_ARABIC_JORDAN 0x0b
502 # endif
503 # ifndef SUBLANG_ARABIC_LEBANON
504 # define SUBLANG_ARABIC_LEBANON 0x0c
505 # endif
506 # ifndef SUBLANG_ARABIC_KUWAIT
507 # define SUBLANG_ARABIC_KUWAIT 0x0d
508 # endif
509 # ifndef SUBLANG_ARABIC_UAE
510 # define SUBLANG_ARABIC_UAE 0x0e
511 # endif
512 # ifndef SUBLANG_ARABIC_BAHRAIN
513 # define SUBLANG_ARABIC_BAHRAIN 0x0f
514 # endif
515 # ifndef SUBLANG_ARABIC_QATAR
516 # define SUBLANG_ARABIC_QATAR 0x10
517 # endif
518 # ifndef SUBLANG_AZERI_LATIN
519 # define SUBLANG_AZERI_LATIN 0x01
520 # endif
521 # ifndef SUBLANG_AZERI_CYRILLIC
522 # define SUBLANG_AZERI_CYRILLIC 0x02
523 # endif
524 # ifndef SUBLANG_BENGALI_INDIA
525 # define SUBLANG_BENGALI_INDIA 0x01
526 # endif
527 # ifndef SUBLANG_BENGALI_BANGLADESH
528 # define SUBLANG_BENGALI_BANGLADESH 0x02
529 # endif
530 # ifndef SUBLANG_CHINESE_MACAU
531 # define SUBLANG_CHINESE_MACAU 0x05
532 # endif
533 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
534 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
535 # endif
536 # ifndef SUBLANG_ENGLISH_JAMAICA
537 # define SUBLANG_ENGLISH_JAMAICA 0x08
538 # endif
539 # ifndef SUBLANG_ENGLISH_CARIBBEAN
540 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
541 # endif
542 # ifndef SUBLANG_ENGLISH_BELIZE
543 # define SUBLANG_ENGLISH_BELIZE 0x0a
544 # endif
545 # ifndef SUBLANG_ENGLISH_TRINIDAD
546 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
547 # endif
548 # ifndef SUBLANG_ENGLISH_ZIMBABWE
549 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
550 # endif
551 # ifndef SUBLANG_ENGLISH_PHILIPPINES
552 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
553 # endif
554 # ifndef SUBLANG_ENGLISH_INDONESIA
555 # define SUBLANG_ENGLISH_INDONESIA 0x0e
556 # endif
557 # ifndef SUBLANG_ENGLISH_HONGKONG
558 # define SUBLANG_ENGLISH_HONGKONG 0x0f
559 # endif
560 # ifndef SUBLANG_ENGLISH_INDIA
561 # define SUBLANG_ENGLISH_INDIA 0x10
562 # endif
563 # ifndef SUBLANG_ENGLISH_MALAYSIA
564 # define SUBLANG_ENGLISH_MALAYSIA 0x11
565 # endif
566 # ifndef SUBLANG_ENGLISH_SINGAPORE
567 # define SUBLANG_ENGLISH_SINGAPORE 0x12
568 # endif
569 # ifndef SUBLANG_FRENCH_LUXEMBOURG
570 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
571 # endif
572 # ifndef SUBLANG_FRENCH_MONACO
573 # define SUBLANG_FRENCH_MONACO 0x06
574 # endif
575 # ifndef SUBLANG_FRENCH_WESTINDIES
576 # define SUBLANG_FRENCH_WESTINDIES 0x07
577 # endif
578 # ifndef SUBLANG_FRENCH_REUNION
579 # define SUBLANG_FRENCH_REUNION 0x08
580 # endif
581 # ifndef SUBLANG_FRENCH_CONGO
582 # define SUBLANG_FRENCH_CONGO 0x09
583 # endif
584 # ifndef SUBLANG_FRENCH_SENEGAL
585 # define SUBLANG_FRENCH_SENEGAL 0x0a
586 # endif
587 # ifndef SUBLANG_FRENCH_CAMEROON
588 # define SUBLANG_FRENCH_CAMEROON 0x0b
589 # endif
590 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
591 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
592 # endif
593 # ifndef SUBLANG_FRENCH_MALI
594 # define SUBLANG_FRENCH_MALI 0x0d
595 # endif
596 # ifndef SUBLANG_FRENCH_MOROCCO
597 # define SUBLANG_FRENCH_MOROCCO 0x0e
598 # endif
599 # ifndef SUBLANG_FRENCH_HAITI
600 # define SUBLANG_FRENCH_HAITI 0x0f
601 # endif
602 # ifndef SUBLANG_GERMAN_LUXEMBOURG
603 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
604 # endif
605 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
606 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
607 # endif
608 # ifndef SUBLANG_KASHMIRI_INDIA
609 # define SUBLANG_KASHMIRI_INDIA 0x02
610 # endif
611 # ifndef SUBLANG_MALAY_MALAYSIA
612 # define SUBLANG_MALAY_MALAYSIA 0x01
613 # endif
614 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
615 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
616 # endif
617 # ifndef SUBLANG_NEPALI_INDIA
618 # define SUBLANG_NEPALI_INDIA 0x02
619 # endif
620 # ifndef SUBLANG_PUNJABI_INDIA
621 # define SUBLANG_PUNJABI_INDIA 0x01
622 # endif
623 # ifndef SUBLANG_ROMANIAN_ROMANIA
624 # define SUBLANG_ROMANIAN_ROMANIA 0x01
625 # endif
626 # ifndef SUBLANG_SERBIAN_LATIN
627 # define SUBLANG_SERBIAN_LATIN 0x02
628 # endif
629 # ifndef SUBLANG_SERBIAN_CYRILLIC
630 # define SUBLANG_SERBIAN_CYRILLIC 0x03
631 # endif
632 # ifndef SUBLANG_SINDHI_INDIA
633 # define SUBLANG_SINDHI_INDIA 0x00
634 # endif
635 # ifndef SUBLANG_SINDHI_PAKISTAN
636 # define SUBLANG_SINDHI_PAKISTAN 0x01
637 # endif
638 # ifndef SUBLANG_SPANISH_GUATEMALA
639 # define SUBLANG_SPANISH_GUATEMALA 0x04
640 # endif
641 # ifndef SUBLANG_SPANISH_COSTA_RICA
642 # define SUBLANG_SPANISH_COSTA_RICA 0x05
643 # endif
644 # ifndef SUBLANG_SPANISH_PANAMA
645 # define SUBLANG_SPANISH_PANAMA 0x06
646 # endif
647 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
648 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
649 # endif
650 # ifndef SUBLANG_SPANISH_VENEZUELA
651 # define SUBLANG_SPANISH_VENEZUELA 0x08
652 # endif
653 # ifndef SUBLANG_SPANISH_COLOMBIA
654 # define SUBLANG_SPANISH_COLOMBIA 0x09
655 # endif
656 # ifndef SUBLANG_SPANISH_PERU
657 # define SUBLANG_SPANISH_PERU 0x0a
658 # endif
659 # ifndef SUBLANG_SPANISH_ARGENTINA
660 # define SUBLANG_SPANISH_ARGENTINA 0x0b
661 # endif
662 # ifndef SUBLANG_SPANISH_ECUADOR
663 # define SUBLANG_SPANISH_ECUADOR 0x0c
664 # endif
665 # ifndef SUBLANG_SPANISH_CHILE
666 # define SUBLANG_SPANISH_CHILE 0x0d
667 # endif
668 # ifndef SUBLANG_SPANISH_URUGUAY
669 # define SUBLANG_SPANISH_URUGUAY 0x0e
670 # endif
671 # ifndef SUBLANG_SPANISH_PARAGUAY
672 # define SUBLANG_SPANISH_PARAGUAY 0x0f
673 # endif
674 # ifndef SUBLANG_SPANISH_BOLIVIA
675 # define SUBLANG_SPANISH_BOLIVIA 0x10
676 # endif
677 # ifndef SUBLANG_SPANISH_EL_SALVADOR
678 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
679 # endif
680 # ifndef SUBLANG_SPANISH_HONDURAS
681 # define SUBLANG_SPANISH_HONDURAS 0x12
682 # endif
683 # ifndef SUBLANG_SPANISH_NICARAGUA
684 # define SUBLANG_SPANISH_NICARAGUA 0x13
685 # endif
686 # ifndef SUBLANG_SPANISH_PUERTO_RICO
687 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
688 # endif
689 # ifndef SUBLANG_SWEDISH_FINLAND
690 # define SUBLANG_SWEDISH_FINLAND 0x02
691 # endif
692 # ifndef SUBLANG_TAMAZIGHT_ARABIC
693 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
694 # endif
695 # ifndef SUBLANG_TAMAZIGHT_LATIN
696 # define SUBLANG_TAMAZIGHT_LATIN 0x02
697 # endif
698 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
699 # define SUBLANG_TIGRINYA_ETHIOPIA 0x00
700 # endif
701 # ifndef SUBLANG_TIGRINYA_ERITREA
702 # define SUBLANG_TIGRINYA_ERITREA 0x01
703 # endif
704 # ifndef SUBLANG_URDU_PAKISTAN
705 # define SUBLANG_URDU_PAKISTAN 0x01
706 # endif
707 # ifndef SUBLANG_URDU_INDIA
708 # define SUBLANG_URDU_INDIA 0x02
709 # endif
710 # ifndef SUBLANG_UZBEK_LATIN
711 # define SUBLANG_UZBEK_LATIN 0x01
712 # endif
713 # ifndef SUBLANG_UZBEK_CYRILLIC
714 # define SUBLANG_UZBEK_CYRILLIC 0x02
715 # endif
716 #endif /* HAVE_W32_SYSTEM */
717
718 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
719    "Directs 'setlocale()' to query 'category' and return the current
720     setting of 'local'."
721    However it does not specify the exact format.  Neither do SUSV2 and
722    ISO C 99.  So we can use this feature only on selected systems (e.g.
723    those using GNU C Library).  */
724 #if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
725 # define HAVE_LOCALE_NULL
726 #endif
727
728 /* Determine the current locale's name, and canonicalize it into XPG syntax
729      language[_territory[.codeset]][@modifier]
730    The codeset part in the result is not reliable; the locale_charset()
731    should be used for codeset information instead.
732    The result must not be freed; it is statically allocated.  */
733
734 static const char *
735 _nl_locale_name (int category, const char *categoryname)
736 {
737   const char *retval;
738
739 #ifndef HAVE_W32_SYSTEM
740
741   /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
742      On some systems this can be done by the 'setlocale' function itself.  */
743 # if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
744   retval = setlocale (category, NULL);
745 # else 
746   /* Setting of LC_ALL overwrites all other.  */
747   retval = getenv ("LC_ALL");
748   if (retval == NULL || retval[0] == '\0')
749     {
750       /* Next comes the name of the desired category.  */
751       retval = getenv (categoryname);
752       if (retval == NULL || retval[0] == '\0')
753         {
754           /* Last possibility is the LANG environment variable.  */
755           retval = getenv ("LANG");
756           if (retval == NULL || retval[0] == '\0')
757             /* We use C as the default domain.  POSIX says this is
758                implementation defined.  */
759             retval = "C";
760         }
761     }
762 # endif
763
764   return retval;
765
766 #else /* HAVE_W32_SYSTEM */
767
768   /* Return an XPG style locale name language[_territory][@modifier].
769      Don't even bother determining the codeset; it's not useful in this
770      context, because message catalogs are not specific to a single
771      codeset.  */
772
773   LCID lcid;
774   LANGID langid;
775   int primary, sub;
776
777   /* Let the user override the system settings through environment
778      variables, as on POSIX systems.  */
779   retval = getenv ("LC_ALL");
780   if (retval != NULL && retval[0] != '\0')
781     return retval;
782   retval = getenv (categoryname);
783   if (retval != NULL && retval[0] != '\0')
784     return retval;
785   retval = getenv ("LANG");
786   if (retval != NULL && retval[0] != '\0')
787     return retval;
788
789   /* Use native Win32 API locale ID.  */
790   lcid = GetThreadLocale ();
791
792   /* Strip off the sorting rules, keep only the language part.  */
793   langid = LANGIDFROMLCID (lcid);
794
795   /* Split into language and territory part.  */
796   primary = PRIMARYLANGID (langid);
797   sub = SUBLANGID (langid);
798
799   /* Dispatch on language.
800      See also http://www.unicode.org/unicode/onlinedat/languages.html .
801      For details about languages, see http://www.ethnologue.com/ .  */
802   switch (primary)
803     {
804     case LANG_AFRIKAANS: return "af_ZA";
805     case LANG_ALBANIAN: return "sq_AL";
806     case LANG_AMHARIC: return "am_ET";
807     case LANG_ARABIC:
808       switch (sub)
809         {
810         case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
811         case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
812         case SUBLANG_ARABIC_EGYPT: return "ar_EG";
813         case SUBLANG_ARABIC_LIBYA: return "ar_LY";
814         case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
815         case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
816         case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
817         case SUBLANG_ARABIC_OMAN: return "ar_OM";
818         case SUBLANG_ARABIC_YEMEN: return "ar_YE";
819         case SUBLANG_ARABIC_SYRIA: return "ar_SY";
820         case SUBLANG_ARABIC_JORDAN: return "ar_JO";
821         case SUBLANG_ARABIC_LEBANON: return "ar_LB";
822         case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
823         case SUBLANG_ARABIC_UAE: return "ar_AE";
824         case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
825         case SUBLANG_ARABIC_QATAR: return "ar_QA";
826         }
827       return "ar";
828     case LANG_ARMENIAN: return "hy_AM";
829     case LANG_ASSAMESE: return "as_IN";
830     case LANG_AZERI:
831       switch (sub)
832         {
833         /* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
834         case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
835         case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
836         }
837       return "az";
838     case LANG_BASQUE:
839       return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
840     case LANG_BELARUSIAN: return "be_BY";
841     case LANG_BENGALI:
842       switch (sub)
843         {
844         case SUBLANG_BENGALI_INDIA: return "bn_IN";
845         case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
846         }
847       return "bn";
848     case LANG_BULGARIAN: return "bg_BG";
849     case LANG_BURMESE: return "my_MM";
850     case LANG_CAMBODIAN: return "km_KH";
851     case LANG_CATALAN: return "ca_ES";
852     case LANG_CHEROKEE: return "chr_US";
853     case LANG_CHINESE:
854       switch (sub)
855         {
856         case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
857         case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
858         case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
859         case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
860         case SUBLANG_CHINESE_MACAU: return "zh_MO";
861         }
862       return "zh";
863     case LANG_CROATIAN:         /* LANG_CROATIAN == LANG_SERBIAN
864                                  * What used to be called Serbo-Croatian
865                                  * should really now be two separate
866                                  * languages because of political reasons.
867                                  * (Says tml, who knows nothing about Serbian
868                                  * or Croatian.)
869                                  * (I can feel those flames coming already.)
870                                  */
871       switch (sub)
872         {
873         case SUBLANG_DEFAULT: return "hr_HR";
874         case SUBLANG_SERBIAN_LATIN: return "sr_CS";
875         case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
876         }
877       return "hr";
878     case LANG_CZECH: return "cs_CZ";
879     case LANG_DANISH: return "da_DK";
880     case LANG_DIVEHI: return "div_MV";
881     case LANG_DUTCH:
882       switch (sub)
883         {
884         case SUBLANG_DUTCH: return "nl_NL";
885         case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
886         }
887       return "nl";
888     case LANG_EDO: return "bin_NG";
889     case LANG_ENGLISH:
890       switch (sub)
891         {
892         /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
893          * English was the language spoken in England.
894          * Oh well.
895          */
896         case SUBLANG_ENGLISH_US: return "en_US";
897         case SUBLANG_ENGLISH_UK: return "en_GB";
898         case SUBLANG_ENGLISH_AUS: return "en_AU";
899         case SUBLANG_ENGLISH_CAN: return "en_CA";
900         case SUBLANG_ENGLISH_NZ: return "en_NZ";
901         case SUBLANG_ENGLISH_EIRE: return "en_IE";
902         case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
903         case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
904         case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
905         case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
906         case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
907         case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
908         case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
909         case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
910         case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
911         case SUBLANG_ENGLISH_INDIA: return "en_IN";
912         case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
913         case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
914         }
915       return "en";
916     case LANG_ESTONIAN: return "et_EE";
917     case LANG_FAEROESE: return "fo_FO";
918     case LANG_FARSI: return "fa_IR";
919     case LANG_FINNISH: return "fi_FI";
920     case LANG_FRENCH:
921       switch (sub)
922         {
923         case SUBLANG_FRENCH: return "fr_FR";
924         case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
925         case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
926         case SUBLANG_FRENCH_SWISS: return "fr_CH";
927         case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
928         case SUBLANG_FRENCH_MONACO: return "fr_MC";
929         case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
930         case SUBLANG_FRENCH_REUNION: return "fr_RE";
931         case SUBLANG_FRENCH_CONGO: return "fr_CG";
932         case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
933         case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
934         case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
935         case SUBLANG_FRENCH_MALI: return "fr_ML";
936         case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
937         case SUBLANG_FRENCH_HAITI: return "fr_HT";
938         }
939       return "fr";
940     case LANG_FRISIAN: return "fy_NL";
941     case LANG_FULFULDE: return "ful_NG";
942     case LANG_GAELIC:
943       switch (sub)
944         {
945         case 0x01: /* SCOTTISH */ return "gd_GB";
946         case 0x02: /* IRISH */ return "ga_IE";
947         }
948       return "C";
949     case LANG_GALICIAN: return "gl_ES";
950     case LANG_GEORGIAN: return "ka_GE";
951     case LANG_GERMAN:
952       switch (sub)
953         {
954         case SUBLANG_GERMAN: return "de_DE";
955         case SUBLANG_GERMAN_SWISS: return "de_CH";
956         case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
957         case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
958         case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
959         }
960       return "de";
961     case LANG_GREEK: return "el_GR";
962     case LANG_GUARANI: return "gn_PY";
963     case LANG_GUJARATI: return "gu_IN";
964     case LANG_HAUSA: return "ha_NG";
965     case LANG_HAWAIIAN:
966       /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
967          or Hawaii Creole English ("cpe_US", 600000 speakers)?  */
968       return "cpe_US";
969     case LANG_HEBREW: return "he_IL";
970     case LANG_HINDI: return "hi_IN";
971     case LANG_HUNGARIAN: return "hu_HU";
972     case LANG_IBIBIO: return "nic_NG";
973     case LANG_ICELANDIC: return "is_IS";
974     case LANG_IGBO: return "ibo_NG";
975     case LANG_INDONESIAN: return "id_ID";
976     case LANG_INUKTITUT: return "iu_CA";
977     case LANG_ITALIAN:
978       switch (sub)
979         {
980         case SUBLANG_ITALIAN: return "it_IT";
981         case SUBLANG_ITALIAN_SWISS: return "it_CH";
982         }
983       return "it";
984     case LANG_JAPANESE: return "ja_JP";
985     case LANG_KANNADA: return "kn_IN";
986     case LANG_KANURI: return "kau_NG";
987     case LANG_KASHMIRI:
988       switch (sub)
989         {
990         case SUBLANG_DEFAULT: return "ks_PK";
991         case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
992         }
993       return "ks";
994     case LANG_KAZAK: return "kk_KZ";
995     case LANG_KONKANI:
996       /* FIXME: Adjust this when such locales appear on Unix.  */
997       return "kok_IN";
998     case LANG_KOREAN: return "ko_KR";
999     case LANG_KYRGYZ: return "ky_KG";
1000     case LANG_LAO: return "lo_LA";
1001     case LANG_LATIN: return "la_VA";
1002     case LANG_LATVIAN: return "lv_LV";
1003     case LANG_LITHUANIAN: return "lt_LT";
1004     case LANG_MACEDONIAN: return "mk_MK";
1005     case LANG_MALAY:
1006       switch (sub)
1007         {
1008         case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
1009         case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
1010         }
1011       return "ms";
1012     case LANG_MALAYALAM: return "ml_IN";
1013     case LANG_MALTESE: return "mt_MT";
1014     case LANG_MANIPURI:
1015       /* FIXME: Adjust this when such locales appear on Unix.  */
1016       return "mni_IN";
1017     case LANG_MARATHI: return "mr_IN";
1018     case LANG_MONGOLIAN:
1019       return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN".  */
1020     case LANG_NEPALI:
1021       switch (sub)
1022         {
1023         case SUBLANG_DEFAULT: return "ne_NP";
1024         case SUBLANG_NEPALI_INDIA: return "ne_IN";
1025         }
1026       return "ne";
1027     case LANG_NORWEGIAN:
1028       switch (sub)
1029         {
1030         case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
1031         case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
1032         }
1033       return "no";
1034     case LANG_ORIYA: return "or_IN";
1035     case LANG_OROMO: return "om_ET";
1036     case LANG_PAPIAMENTU: return "pap_AN";
1037     case LANG_PASHTO:
1038       return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF".  */
1039     case LANG_POLISH: return "pl_PL";
1040     case LANG_PORTUGUESE:
1041       switch (sub)
1042         {
1043         case SUBLANG_PORTUGUESE: return "pt_PT";
1044         /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
1045            Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
1046         case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
1047         }
1048       return "pt";
1049     case LANG_PUNJABI:
1050       switch (sub)
1051         {
1052         case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
1053         }
1054       return "pa";
1055     case LANG_RHAETO_ROMANCE: return "rm_CH";
1056     case LANG_ROMANIAN:
1057       switch (sub)
1058         {
1059         case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
1060         }
1061       return "ro";
1062     case LANG_RUSSIAN:
1063       return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD".  */
1064     case LANG_SAAMI: /* actually Northern Sami */ return "se_NO";
1065     case LANG_SANSKRIT: return "sa_IN";
1066     case LANG_SINDHI:
1067       switch (sub)
1068         {
1069         case SUBLANG_SINDHI_INDIA: return "sd_IN";
1070         case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
1071         }
1072       return "sd";
1073     case LANG_SINHALESE: return "si_LK";
1074     case LANG_SLOVAK: return "sk_SK";
1075     case LANG_SLOVENIAN: return "sl_SI";
1076     case LANG_SOMALI: return "so_SO";
1077     case LANG_SORBIAN:
1078       /* FIXME: Adjust this when such locales appear on Unix.  */
1079       return "wen_DE";
1080     case LANG_SPANISH:
1081       switch (sub)
1082         {
1083         case SUBLANG_SPANISH: return "es_ES";
1084         case SUBLANG_SPANISH_MEXICAN: return "es_MX";
1085         case SUBLANG_SPANISH_MODERN:
1086           return "es_ES@modern";        /* not seen on Unix */
1087         case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
1088         case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
1089         case SUBLANG_SPANISH_PANAMA: return "es_PA";
1090         case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
1091         case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
1092         case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
1093         case SUBLANG_SPANISH_PERU: return "es_PE";
1094         case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
1095         case SUBLANG_SPANISH_ECUADOR: return "es_EC";
1096         case SUBLANG_SPANISH_CHILE: return "es_CL";
1097         case SUBLANG_SPANISH_URUGUAY: return "es_UY";
1098         case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
1099         case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
1100         case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
1101         case SUBLANG_SPANISH_HONDURAS: return "es_HN";
1102         case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
1103         case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
1104         }
1105       return "es";
1106     case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
1107     case LANG_SWAHILI: return "sw_KE";
1108     case LANG_SWEDISH:
1109       switch (sub)
1110         {
1111         case SUBLANG_DEFAULT: return "sv_SE";
1112         case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
1113         }
1114       return "sv";
1115     case LANG_SYRIAC: return "syr_TR"; /* An extinct language.  */
1116     case LANG_TAGALOG: return "tl_PH";
1117     case LANG_TAJIK: return "tg_TJ";
1118     case LANG_TAMAZIGHT:
1119       switch (sub)
1120         {
1121         /* FIXME: Adjust this when Tamazight locales appear on Unix.  */
1122         case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
1123         case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin";
1124         }
1125       return "ber_MA";
1126     case LANG_TAMIL:
1127       return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG".  */
1128     case LANG_TATAR: return "tt_RU";
1129     case LANG_TELUGU: return "te_IN";
1130     case LANG_THAI: return "th_TH";
1131     case LANG_TIBETAN: return "bo_CN";
1132     case LANG_TIGRINYA:
1133       switch (sub)
1134         {
1135         case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
1136         case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
1137         }
1138       return "ti";
1139     case LANG_TSONGA: return "ts_ZA";
1140     case LANG_TSWANA: return "tn_BW";
1141     case LANG_TURKISH: return "tr_TR";
1142     case LANG_TURKMEN: return "tk_TM";
1143     case LANG_UKRAINIAN: return "uk_UA";
1144     case LANG_URDU:
1145       switch (sub)
1146         {
1147         case SUBLANG_URDU_PAKISTAN: return "ur_PK";
1148         case SUBLANG_URDU_INDIA: return "ur_IN";
1149         }
1150       return "ur";
1151     case LANG_UZBEK:
1152       switch (sub)
1153         {
1154         case SUBLANG_UZBEK_LATIN: return "uz_UZ";
1155         case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
1156         }
1157       return "uz";
1158     case LANG_VENDA:
1159       /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
1160          "ve" or not.
1161          http://www.loc.gov/standards/iso639-2/englangn.html has it, but
1162          http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't,  */
1163       return "ven_ZA"; /* or "ve_ZA"? */
1164     case LANG_VIETNAMESE: return "vi_VN";
1165     case LANG_WELSH: return "cy_GB";
1166     case LANG_XHOSA: return "xh_ZA";
1167     case LANG_YI: return "sit_CN";
1168     case LANG_YIDDISH: return "yi_IL";
1169     case LANG_YORUBA: return "yo_NG";
1170     case LANG_ZULU: return "zu_ZA";
1171     default: return "C";
1172     }
1173
1174 #endif /* HAVE_W32_SYSTEM */
1175 }
1176
1177 /* localname.c from gettext END.  */
1178 \f
1179 /* Support functions.  */
1180
1181 typedef uint32_t u32;
1182 typedef unsigned long ulong;
1183
1184 static __inline__ u32
1185 do_swap_u32 (u32 i)
1186 {
1187   return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
1188 }
1189
1190 #define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data))
1191
1192
1193 /* We assume to have `unsigned long int' value with at least 32 bits.  */
1194 #define HASHWORDBITS 32
1195
1196 /* The so called `hashpjw' function by P.J. Weinberger
1197    [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1198    1986, 1987 Bell Telephone Laboratories, Inc.]  */
1199
1200 static __inline__ ulong
1201 hash_string( const char *str_param )
1202 {
1203     unsigned long int hval, g;
1204     const char *str = str_param;
1205
1206     hval = 0;
1207     while (*str != '\0')
1208     {
1209         hval <<= 4;
1210         hval += (unsigned long int) *str++;
1211         g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
1212         if (g != 0)
1213         {
1214           hval ^= g >> (HASHWORDBITS - 8);
1215           hval ^= g;
1216         }
1217     }
1218     return hval;
1219 }
1220
1221 \f
1222 /* Generic message catalog and gettext stuff.  */
1223
1224 /* The magic number of the GNU message catalog format.  */
1225 #define MAGIC         0x950412de
1226 #define MAGIC_SWAPPED 0xde120495
1227
1228 /* Revision number of the currently used .mo (binary) file format.  */
1229 #define MO_REVISION_NUMBER 0
1230
1231 /* Header for binary .mo file format.  */
1232 struct mo_file_header
1233 {
1234   /* The magic number.  */
1235   u32 magic;
1236   /* The revision number of the file format.  */
1237   u32 revision;
1238   /* The number of strings pairs.  */
1239   u32 nstrings;
1240   /* Offset of table with start offsets of original strings.  */
1241   u32 orig_tab_offset;
1242   /* Offset of table with start offsets of translation strings.  */
1243   u32 trans_tab_offset;
1244   /* Size of hashing table.  */
1245   u32 hash_tab_size;
1246   /* Offset of first hashing entry.  */
1247   u32 hash_tab_offset;
1248 };
1249
1250 struct string_desc
1251 {
1252   /* Length of addressed string.  */
1253   u32 length;
1254   /* Offset of string in file.  */
1255   u32 offset;
1256 };
1257
1258
1259 struct overflow_space_s
1260 {
1261   struct overflow_space_s *next;
1262   u32 idx;
1263   char d[1];
1264 };
1265
1266 struct loaded_domain
1267 {
1268   char *data;
1269   int must_swap;
1270   u32 nstrings;
1271   char *mapped;  /* 0 = not yet mapped, 1 = mapped,
1272                     2 = mapped to
1273                     overflow space */
1274   struct overflow_space_s *overflow_space;
1275   struct string_desc *orig_tab;
1276   struct string_desc *trans_tab;
1277   u32 hash_size;
1278   u32 *hash_tab;
1279 };
1280
1281 \f
1282 /* Free the domain data.  */
1283 static void
1284 free_domain (struct loaded_domain *domain)
1285 {
1286   struct overflow_space_s *os, *os2;
1287   free (domain->data);
1288   free (domain->mapped);
1289   for (os = domain->overflow_space; os; os = os2)
1290     {
1291       os2 = os->next;
1292       free (os);
1293     }
1294   free (domain);
1295 }
1296
1297   
1298 /* The gettext implementation; support functions.  */
1299 static struct loaded_domain *
1300 load_domain (const char *filename)
1301 {
1302   FILE *fp;
1303   size_t size;
1304   struct stat st;
1305   struct mo_file_header *data = NULL;
1306   struct loaded_domain *domain = NULL;
1307   size_t to_read;
1308   char *read_ptr;
1309   
1310   fp = fopen (filename, "rb");
1311   if (!fp)
1312     return NULL;
1313
1314   /* Determine the file size.  */
1315   if (fstat (fileno (fp), &st)
1316       || (size = (size_t) st.st_size) != st.st_size
1317       || size < sizeof (struct mo_file_header))
1318     {
1319       fclose (fp);
1320       return NULL;
1321     }
1322
1323   data = malloc (size);
1324   if (!data)
1325     {
1326       fclose (fp);
1327       return NULL;
1328     }
1329
1330   to_read = size;
1331   read_ptr = (char *) data;
1332   do
1333     {
1334       long int nb = fread (read_ptr, 1, to_read, fp);
1335       if (nb < to_read)
1336         {
1337           fclose (fp);
1338           free (data);
1339           return NULL;
1340         }
1341       read_ptr += nb;
1342       to_read -= nb;
1343     }
1344   while (to_read > 0);
1345   fclose (fp);
1346
1347   /* Using the magic number we can test whether it really is a message
1348      catalog file.  */
1349   if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
1350     {
1351       /* The magic number is wrong: not a message catalog file.  */
1352       free (data);
1353       return NULL;
1354     }
1355
1356   domain = calloc (1, sizeof *domain);
1357   if (!domain)
1358     {
1359       free (data);
1360       return NULL;
1361     }
1362   domain->data = (char *) data;
1363   domain->must_swap = data->magic != MAGIC;
1364   
1365   /* Fill in the information about the available tables.  */
1366   switch (SWAPIT (domain->must_swap, data->revision))
1367     {
1368     case 0:
1369       domain->nstrings = SWAPIT (domain->must_swap, data->nstrings);
1370       domain->orig_tab = (struct string_desc *)
1371         ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset));
1372       domain->trans_tab = (struct string_desc *)
1373         ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset));
1374       domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size);
1375       domain->hash_tab = (u32 *)
1376         ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset));
1377       break;
1378
1379     default:
1380       /* This is an invalid revision.   */
1381       free (data);
1382       free (domain);
1383       return NULL;
1384     }
1385
1386   /* Allocate an array to keep track of code page mappings.  */
1387   domain->mapped = calloc (1, domain->nstrings);
1388   if (!domain->mapped)
1389     {
1390       free (data);
1391       free (domain);
1392       return NULL;
1393     }
1394
1395   return domain;
1396 }
1397
1398
1399 /* Return a malloced string encoded in UTF-8 from the wide char input
1400    string STRING.  Caller must free this value. On failure returns
1401    NULL; caller may use GetLastError to get the actual error number.
1402    The result of calling this function with STRING set to NULL is not
1403    defined. */
1404 static char *
1405 wchar_to_native (const wchar_t *string)
1406 {
1407   int n;
1408   char *result;
1409
1410   n = WideCharToMultiByte (CP_ACP, 0, string, -1, NULL, 0, NULL, NULL);
1411   if (n < 0)
1412     return NULL;
1413
1414   result = malloc (n+1);
1415   if (!result)
1416     return NULL;
1417
1418   n = WideCharToMultiByte (CP_ACP, 0, string, -1, result, n, NULL, NULL);
1419   if (n < 0)
1420     {
1421       free (result);
1422       return NULL;
1423     }
1424   return result;
1425 }
1426
1427
1428 /* Return a malloced wide char string from an UTF-8 encoded input
1429    string STRING.  Caller must free this value. On failure returns
1430    NULL; caller may use GetLastError to get the actual error number.
1431    The result of calling this function with STRING set to NULL is not
1432    defined. */
1433 static wchar_t *
1434 utf8_to_wchar (const char *string)
1435 {
1436   int n;
1437   wchar_t *result;
1438
1439   n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
1440   if (n < 0)
1441     return NULL;
1442
1443   result = malloc ((n+1) * sizeof *result);
1444   if (!result)
1445     return NULL;
1446
1447   n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
1448   if (n < 0)
1449     {
1450       free (result);
1451       return NULL;
1452     }
1453   return result;
1454 }
1455
1456
1457 static char *
1458 utf8_to_native (const char *string)
1459 {
1460   wchar_t *wstring;
1461   char *result;
1462
1463   wstring = utf8_to_wchar (string);
1464   if (!wstring)
1465     return NULL;
1466
1467   result = wchar_to_native (wstring);
1468   free (wstring);
1469
1470   return result;
1471 }
1472
1473
1474 static const char*
1475 get_string (struct loaded_domain *domain, u32 idx)
1476 {
1477   struct overflow_space_s *os;
1478   char *p;
1479
1480   p = domain->data + SWAPIT (domain->must_swap, domain->trans_tab[idx].offset);
1481   if (!domain->mapped[idx]) 
1482     {
1483       size_t plen, buflen;
1484       char *buf;
1485
1486       domain->mapped[idx] = 1;
1487
1488       plen = strlen (p);
1489       buf = utf8_to_native (p);
1490       buflen = strlen (buf);
1491       if (buflen <= plen)
1492         strcpy (p, buf);
1493       else
1494         {
1495           /* There is not enough space for the translation - store it
1496              in the overflow_space else and mark that in the mapped
1497              array.  Because we expect that this won't happen too
1498              often, we use a simple linked list.  */
1499           os = malloc (sizeof *os + buflen);
1500           if (os)
1501             {
1502               os->idx = idx;
1503               strcpy (os->d, buf);
1504               os->next = domain->overflow_space;
1505               domain->overflow_space = os;
1506               p = os->d;
1507             }
1508           else
1509             p = "ERROR in GETTEXT MALLOC";
1510         }
1511       free (buf);
1512     }
1513   else if (domain->mapped[idx] == 2) 
1514     {
1515       /* We need to get the string from the overflow_space.  */
1516       for (os=domain->overflow_space; os; os = os->next)
1517         if (os->idx == idx)
1518           return (const char*) os->d;
1519       p = "ERROR in GETTEXT\n";
1520     }
1521   return (const char*) p;
1522 }
1523
1524 \f
1525
1526 /* The domain we use.  We only support one domain at this point.  This
1527    is why this implementation can not be shared.  Bindtextdomain and
1528    dgettext will simply cheat and always use this one domain.  */
1529 static struct loaded_domain *the_domain;
1530
1531 \f
1532 /* Specify that the DOMAINNAME message catalog will be found
1533    in DIRNAME rather than in the system locale data base.  */
1534 char *
1535 bindtextdomain (const char *domainname, const char *dirname)
1536 {
1537   struct loaded_domain *domain = NULL;
1538   const char *catval_full;
1539   char *catval;
1540   char *fname;
1541
1542   /* DOMAINNAME is ignored.  We only support one domain.  */
1543
1544   /* DIRNAME is "$INSTALLDIR\share\locale".  */
1545
1546   /* First found out the category value.  */
1547   catval = NULL;
1548   catval_full = _nl_locale_name (LC_MESSAGES, "LC_MESSAGES");
1549
1550   /* Normally, we would have to loop over all returned locales, and
1551      search for the right file.  See gettext intl/dcigettext.c for all
1552      the gory details.  Here, we only support the basic category, and
1553      ignore everything else.  */
1554   if (catval_full)
1555     {
1556       char *p;
1557
1558       catval = malloc (strlen (catval_full) + 1);
1559       if (catval)
1560         {
1561           strcpy (catval, catval_full);
1562           p = strchr (catval, '_');
1563           if (p)
1564             *p = '\0';
1565         }
1566     }
1567   if (!catval)
1568     return NULL;
1569
1570   /* Now build the filename string.  The complete filename is this:
1571      DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo  */
1572   {
1573     int len = strlen (dirname) + 1 + strlen (catval) + 13
1574       + strlen (domainname) + 3 + 1;
1575     char *p;
1576
1577     fname = malloc (len);
1578     if (!fname)
1579       {
1580         free (catval);
1581         return;
1582       }
1583
1584     p = fname;
1585     strcpy (p, dirname);
1586     p += strlen (dirname);
1587     *(p++) = '\\';
1588     strcpy (p, catval);
1589     p += strlen (catval);
1590     strcpy (p, "\\LC_MESSAGES\\");
1591     p += 13;
1592     strcpy (p, domainname);
1593     p += strlen (domainname);
1594     strcpy (p, ".mo");
1595   }
1596
1597   domain = load_domain (fname);
1598   free (catval);
1599   free (fname);
1600
1601   /* We should not be invoked twice, but this is how you would do
1602      it if it happened.  */
1603   if (the_domain)
1604     free_domain (the_domain);
1605   the_domain = domain;
1606
1607   /* For historic reasoins we are not allowed to return a const char*. */
1608   return (char*)dirname;
1609 }
1610
1611
1612 const char *
1613 gettext (const char *msgid)
1614 {
1615   struct loaded_domain *domain;
1616   size_t act = 0;
1617   size_t top, bottom;
1618   
1619   if (!(domain = the_domain))
1620     goto not_found;
1621
1622   /* Locate the MSGID and its translation.  */
1623   if (domain->hash_size > 2 && domain->hash_tab)
1624     {
1625       /* Use the hashing table.  */
1626       u32 len = strlen (msgid);
1627       u32 hash_val = hash_string (msgid);
1628       u32 idx = hash_val % domain->hash_size;
1629       u32 incr = 1 + (hash_val % (domain->hash_size - 2));
1630       u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
1631
1632       if (!nstr)
1633         /* Hash table entry is empty.  */
1634         goto not_found;
1635
1636       if (SWAPIT (domain->must_swap,
1637                   domain->orig_tab[nstr - 1].length) == len
1638           && !strcmp (msgid,
1639                       domain->data
1640                       + SWAPIT (domain->must_swap,
1641                                 domain->orig_tab[nstr - 1].offset)))
1642         return get_string (domain, nstr - 1);
1643       
1644         for(;;)
1645           {
1646             if (idx >= domain->hash_size - incr)
1647               idx -= domain->hash_size - incr;
1648             else
1649               idx += incr;
1650
1651             nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
1652             if (!nstr)
1653               /* Hash table entry is empty.  */
1654               goto not_found;
1655             
1656             if (SWAPIT (domain->must_swap,
1657                         domain->orig_tab[nstr - 1].length) == len
1658                 && !strcmp (msgid,
1659                             domain->data
1660                             + SWAPIT (domain->must_swap,
1661                                       domain->orig_tab[nstr - 1].offset)))
1662               return get_string (domain, nstr-1);
1663           }
1664         /* NOTREACHED */
1665     }
1666
1667   /* Now we try the default method: binary search in the sorted array
1668      of messages.  */
1669   bottom = 0;
1670   top = domain->nstrings;
1671   while (bottom < top)
1672     {
1673       int cmp_val;
1674       
1675       act = (bottom + top) / 2;
1676       cmp_val = strcmp(msgid, domain->data
1677                        + SWAPIT (domain->must_swap,
1678                                  domain->orig_tab[act].offset));
1679       if (cmp_val < 0)
1680         top = act;
1681       else if (cmp_val > 0)
1682         bottom = act + 1;
1683       else
1684         return get_string (domain, act);
1685     }
1686   
1687  not_found:
1688   return msgid;
1689 }
1690
1691
1692 char *
1693 textdomain (const char *domainname)
1694 {
1695   /* For now, support only one domain.  */
1696   return (char*)domainname;
1697 }
1698
1699 char *
1700 dgettext (const char *domainname, const char *msgid)
1701 {
1702   /* For now, support only one domain.  */
1703   return (char*)gettext (msgid);
1704 }