Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
glibc
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security
Insights
Files
1ecbb38
argp
assert
benchtests
bits
catgets
conf
conform
crypt
csu
ctype
debug
dirent
dlfcn
elf
gmon
gnulib
grp
gshadow
hesiod
hurd
iconv
iconvdata
include
inet
intl
io
libidn
libio
locale
bits
programs
3level.h
charmap-dir.c
charmap-dir.h
charmap-kw.gperf
charmap-kw.h
charmap.c
charmap.h
config.h
ld-address.c
ld-collate.c
ld-ctype.c
ld-identification.c
ld-measurement.c
ld-messages.c
ld-monetary.c
ld-name.c
ld-numeric.c
ld-paper.c
ld-telephone.c
ld-time.c
linereader.c
linereader.h
locale-spec.c
locale.c
localedef.c
localedef.h
locarchive.c
locfile-kw.gperf
locfile-kw.h
locfile-token.h
locfile.c
locfile.h
repertoire.c
repertoire.h
simple-hash.c
simple-hash.h
xmalloc.c
xstrdup.c
C-address.c
C-collate.c
C-ctype.c
C-identification.c
C-measurement.c
C-messages.c
C-monetary.c
C-name.c
C-numeric.c
C-paper.c
C-telephone.c
C-time.c
C-translit.h
C-translit.h.in
C_name.c
Makefile
SYS_libc.c
Versions
broken_cur_max.c
categories.def
coll-lookup.c
coll-lookup.h
duplocale.c
elem-hash.h
findlocale.c
freelocale.c
gen-translit.pl
global-locale.c
hashval.h
indigits.h
indigitswc.h
iso-3166.def
iso-4217.def
iso-639.def
langinfo.h
lc-address.c
lc-collate.c
lc-ctype.c
lc-identification.c
lc-measurement.c
lc-messages.c
lc-monetary.c
lc-name.c
lc-numeric.c
lc-paper.c
lc-telephone.c
lc-time.c
loadarchive.c
loadlocale.c
locale.h
localeconv.c
localeinfo.h
localename.c
locarchive.h
mb_cur_max.c
newlocale.c
nl_langinfo.c
nl_langinfo_l.c
outdigits.h
outdigitswc.h
setlocale.c
strlen-hash.h
tst-C-locale.c
tst-duplocale.c
tst-locname.c
uselocale.c
weight.h
weightwc.h
xlocale.c
xlocale.h
localedata
login
mach
malloc
manual
math
misc
nis
nptl
nptl_db
nscd
nss
po
ports
posix
pwd
resolv
resource
rt
scripts
setjmp
shadow
signal
socket
soft-fp
stdio-common
stdlib
streams
string
sunrpc
sysdeps
sysvipc
termios
time
timezone
wcsmbs
wctype
.gitattributes
.gitignore
BUGS
CANCEL-FCT-WAIVE
CANCEL-FILE-WAIVE
CONFORMANCE
COPYING
COPYING.LIB
ChangeLog
ChangeLog.1
ChangeLog.10
ChangeLog.11
ChangeLog.12
ChangeLog.13
ChangeLog.14
ChangeLog.15
ChangeLog.16
ChangeLog.17
ChangeLog.2
ChangeLog.3
ChangeLog.4
ChangeLog.5
ChangeLog.6
ChangeLog.7
ChangeLog.8
ChangeLog.9
INSTALL
LICENSES
Makeconfig
Makefile
Makefile.in
Makerules
NAMESPACE
NEWS
PROJECTS
README
Rules
Versions.def
WUR-REPORT
abi-tags
aclocal.m4
config.h.in
config.make.in
configure
configure.in
cppflags-iterator.mk
extra-lib.mk
extra-modules.mk
libc-abis
o-iterator.mk
shlib-versions
test-skeleton.c
version.h
Breadcrumbs
glibc
/
locale
/
programs
/
ld-address.c
Blame
Blame
Latest commit
History
History
545 lines (489 loc) · 16 KB
Breadcrumbs
glibc
/
locale
/
programs
/
ld-address.c
Top
File metadata and controls
Code
Blame
545 lines (489 loc) · 16 KB
Raw
/* Copyright (C) 1998-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <byteswap.h> #include <error.h> #include <langinfo.h> #include <string.h> #include <stdint.h> #include <sys/uio.h> #include <assert.h> #include "localedef.h" #include "localeinfo.h" #include "locfile.h" static struct { const char ab2[3]; const char ab3[4]; uint32_t num; } iso3166[] = { #define DEFINE_COUNTRY_CODE(Name, Ab2, Ab3, Num) \ { #Ab2, #Ab3, Num }, #include "iso-3166.def" }; static struct { const char ab[3]; const char term[4]; const char lib[4]; } iso639[] = { #define DEFINE_LANGUAGE_CODE(Name, Ab, Term, Lib) \ { #Ab, #Term, #Lib }, #define DEFINE_LANGUAGE_CODE3(Name, Term, Lib) \ { "", #Term, #Lib }, #define DEFINE_LANGUAGE_CODE2(Name, Term) \ { "", #Term, "" }, #include "iso-639.def" }; /* The real definition of the struct for the LC_ADDRESS locale. */ struct locale_address_t { const char *postal_fmt; const char *country_name; const char *country_post; const char *country_ab2; const char *country_ab3; uint32_t country_num; const char *country_car; const char *country_isbn; const char *lang_name; const char *lang_ab; const char *lang_term; const char *lang_lib; }; static void address_startup (struct linereader *lr, struct localedef_t *locale, int ignore_content) { if (!ignore_content) locale->categories[LC_ADDRESS].address = (struct locale_address_t *) xcalloc (1, sizeof (struct locale_address_t)); if (lr != NULL) { lr->translate_strings = 1; lr->return_widestr = 0; } } void address_finish (struct localedef_t *locale, const struct charmap_t *charmap) { struct locale_address_t *address = locale->categories[LC_ADDRESS].address; size_t cnt; int helper; int nothing = 0; /* Now resolve copying and also handle completely missing definitions. */ if (address == NULL) { /* First see whether we were supposed to copy. If yes, find the actual definition. */ if (locale->copy_name[LC_ADDRESS] != NULL) { /* Find the copying locale. This has to happen transitively since the locale we are copying from might also copying another one. */ struct localedef_t *from = locale; do from = find_locale (LC_ADDRESS, from->copy_name[LC_ADDRESS], from->repertoire_name, charmap); while (from->categories[LC_ADDRESS].address == NULL && from->copy_name[LC_ADDRESS] != NULL); address = locale->categories[LC_ADDRESS].address = from->categories[LC_ADDRESS].address; } /* If there is still no definition issue an warning and create an empty one. */ if (address == NULL) { if (! be_quiet) WITH_CUR_LOCALE (error (0, 0, _("\ No definition for %s category found"), "LC_ADDRESS")); address_startup (NULL, locale, 0); address = locale->categories[LC_ADDRESS].address; nothing = 1; } } if (address->postal_fmt == NULL) { if (! nothing) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "postal_fmt")); /* Use as the default value the value of the i18n locale. */ address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"; } else { /* We must check whether the format string contains only the allowed escape sequences. */ const char *cp = address->postal_fmt; if (*cp == '\0') WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"), "LC_ADDRESS", "postal_fmt")); else while (*cp != '\0') { if (*cp == '%') { if (*++cp == 'R') /* Romanize-flag. */ ++cp; if (strchr ("afdbshNtreCzTSc%", *cp) == NULL) { WITH_CUR_LOCALE (error (0, 0, _("\ %s: invalid escape `%%%c' sequence in field `%s'"), "LC_ADDRESS", *cp, "postal_fmt")); break; } } ++cp; } } #define TEST_ELEM(cat) \ if (address->cat == NULL) \ { \ if (verbose && ! nothing) \ WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \ "LC_ADDRESS", #cat)); \ address->cat = ""; \ } TEST_ELEM (country_name); /* XXX Test against list of defined codes. */ TEST_ELEM (country_post); /* XXX Test against list of defined codes. */ TEST_ELEM (country_car); /* XXX Test against list of defined codes. */ TEST_ELEM (country_isbn); TEST_ELEM (lang_name); helper = 1; if (address->lang_term == NULL) { if (verbose && ! nothing) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "lang_term")); address->lang_term = ""; cnt = sizeof (iso639) / sizeof (iso639[0]); } else if (address->lang_term[0] == '\0') { if (verbose) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"), "LC_ADDRESS", "lang_term")); cnt = sizeof (iso639) / sizeof (iso639[0]); } else { /* Look for this language in the table. */ for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt) if (strcmp (address->lang_term, iso639[cnt].term) == 0) break; if (cnt == sizeof (iso639) / sizeof (iso639[0])) WITH_CUR_LOCALE (error (0, 0, _("\ %s: terminology language code `%s' not defined"), "LC_ADDRESS", address->lang_term)); } if (address->lang_ab == NULL) { if ((cnt == sizeof (iso639) / sizeof (iso639[0]) || iso639[cnt].ab[0] != '\0') && verbose && ! nothing) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "lang_ab")); address->lang_ab = ""; } else if (address->lang_ab[0] == '\0') { if ((cnt == sizeof (iso639) / sizeof (iso639[0]) || iso639[cnt].ab[0] != '\0') && verbose) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"), "LC_ADDRESS", "lang_ab")); } else if (cnt < sizeof (iso639) / sizeof (iso639[0]) && iso639[cnt].ab[0] == '\0') { WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be defined"), "LC_ADDRESS", "lang_ab")); address->lang_ab = ""; } else { if (cnt == sizeof (iso639) / sizeof (iso639[0])) { helper = 2; for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt) if (strcmp (address->lang_ab, iso639[cnt].ab) == 0) break; if (cnt == sizeof (iso639) / sizeof (iso639[0])) WITH_CUR_LOCALE (error (0, 0, _("\ %s: language abbreviation `%s' not defined"), "LC_ADDRESS", address->lang_ab)); } else if (strcmp (iso639[cnt].ab, address->lang_ab) != 0 && iso639[cnt].ab[0] != '\0') WITH_CUR_LOCALE (error (0, 0, _("\ %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_ab", "lang_term")); } if (address->lang_lib == NULL) /* This is no error. */ address->lang_lib = address->lang_term; else if (address->lang_lib[0] == '\0') { if (verbose) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"), "LC_ADDRESS", "lang_lib")); } else { if (cnt == sizeof (iso639) / sizeof (iso639[0])) { for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt) if (strcmp (address->lang_lib, iso639[cnt].lib) == 0) break; if (cnt == sizeof (iso639) / sizeof (iso639[0])) WITH_CUR_LOCALE (error (0, 0, _("\ %s: language abbreviation `%s' not defined"), "LC_ADDRESS", address->lang_lib)); } else if (strcmp (iso639[cnt].ab, address->lang_ab) != 0) WITH_CUR_LOCALE (error (0, 0, _("\ %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib", helper == 1 ? "lang_term" : "lang_ab")); } if (address->country_num == 0) { if (verbose && ! nothing) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "country_num")); cnt = sizeof (iso3166) / sizeof (iso3166[0]); } else { for (cnt = 0; cnt < sizeof (iso3166) / sizeof (iso3166[0]); ++cnt) if (address->country_num == iso3166[cnt].num) break; if (cnt == sizeof (iso3166) / sizeof (iso3166[0])) WITH_CUR_LOCALE (error (0, 0, _("\ %s: numeric country code `%d' not valid"), "LC_ADDRESS", address->country_num)); } if (address->country_ab2 == NULL) { if (verbose && ! nothing) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "country_ab2")); address->country_ab2 = " "; } else if (cnt != sizeof (iso3166) / sizeof (iso3166[0]) && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0) WITH_CUR_LOCALE (error (0, 0, _("%s: `%s' value does not match `%s' value"), "LC_ADDRESS", "country_ab2", "country_num")); if (address->country_ab3 == NULL) { if (verbose && ! nothing) WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "country_ab3")); address->country_ab3 = " "; } else if (cnt != sizeof (iso3166) / sizeof (iso3166[0]) && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0) WITH_CUR_LOCALE (error (0, 0, _("\ %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "country_ab3", "country_num")); } void address_output (struct localedef_t *locale, const struct charmap_t *charmap, const char *output_path) { struct locale_address_t *address = locale->categories[LC_ADDRESS].address; struct locale_file file; init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)); add_locale_string (&file, address->postal_fmt); add_locale_string (&file, address->country_name); add_locale_string (&file, address->country_post); add_locale_string (&file, address->country_ab2); add_locale_string (&file, address->country_ab3); add_locale_string (&file, address->country_car); add_locale_uint32 (&file, address->country_num); add_locale_string (&file, address->country_isbn); add_locale_string (&file, address->lang_name); add_locale_string (&file, address->lang_ab); add_locale_string (&file, address->lang_term); add_locale_string (&file, address->lang_lib); add_locale_string (&file, charmap->code_set_name); write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS", &file); } /* The parser for the LC_ADDRESS section of the locale definition. */ void address_read (struct linereader *ldfile, struct localedef_t *result, const struct charmap_t *charmap, const char *repertoire_name, int ignore_content) { struct locale_address_t *address; struct token *now; struct token *arg; enum token_t nowtok; /* The rest of the line containing `LC_ADDRESS' must be free. */ lr_ignore_rest (ldfile, 1); do { now = lr_token (ldfile, charmap, result, NULL, verbose); nowtok = now->tok; } while (nowtok == tok_eol); /* If we see `copy' now we are almost done. */ if (nowtok == tok_copy) { handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_address, LC_ADDRESS, "LC_ADDRESS", ignore_content); return; } /* Prepare the data structures. */ address_startup (ldfile, result, ignore_content); address = result->categories[LC_ADDRESS].address; while (1) { /* Of course we don't proceed beyond the end of file. */ if (nowtok == tok_eof) break; /* Ignore empty lines. */ if (nowtok == tok_eol) { now = lr_token (ldfile, charmap, result, NULL, verbose); nowtok = now->tok; continue; } switch (nowtok) { #define STR_ELEM(cat) \ case tok_##cat: \ /* Ignore the rest of the line if we don't need the input of \ this line. */ \ if (ignore_content) \ { \ lr_ignore_rest (ldfile, 0); \ break; \ } \ \ arg = lr_token (ldfile, charmap, result, NULL, verbose); \ if (arg->tok != tok_string) \ goto err_label; \ if (address->cat != NULL) \ lr_error (ldfile, _("\ %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \ else if (!ignore_content && arg->val.str.startmb == NULL) \ { \ lr_error (ldfile, _("\ %s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \ address->cat = ""; \ } \ else if (!ignore_content) \ address->cat = arg->val.str.startmb; \ break STR_ELEM (postal_fmt); STR_ELEM (country_name); STR_ELEM (country_post); STR_ELEM (country_ab2); STR_ELEM (country_ab3); STR_ELEM (country_car); STR_ELEM (lang_name); STR_ELEM (lang_ab); STR_ELEM (lang_term); STR_ELEM (lang_lib); #define INT_STR_ELEM(cat) \ case tok_##cat: \ /* Ignore the rest of the line if we don't need the input of \ this line. */ \ if (ignore_content) \ { \ lr_ignore_rest (ldfile, 0); \ break; \ } \ \ arg = lr_token (ldfile, charmap, result, NULL, verbose); \ if (arg->tok != tok_string && arg->tok != tok_number) \ goto err_label; \ if (address->cat != NULL) \ lr_error (ldfile, _("\ %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \ else if (!ignore_content && arg->tok == tok_string \ && arg->val.str.startmb == NULL) \ { \ lr_error (ldfile, _("\ %s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \ address->cat = ""; \ } \ else if (!ignore_content) \ { \ if (arg->tok == tok_string) \ address->cat = arg->val.str.startmb; \ else \ { \ char *numbuf = (char *) xmalloc (11); \ snprintf (numbuf, 11, "%ld", arg->val.num); \ address->cat = numbuf; \ } \ } \ break INT_STR_ELEM (country_isbn); #define INT_ELEM(cat) \ case tok_##cat: \ /* Ignore the rest of the line if we don't need the input of \ this line. */ \ if (ignore_content) \ { \ lr_ignore_rest (ldfile, 0); \ break; \ } \ \ arg = lr_token (ldfile, charmap, result, NULL, verbose); \ if (arg->tok != tok_number) \ goto err_label; \ else if (address->cat != 0) \ lr_error (ldfile, _("\ %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \ else if (!ignore_content) \ address->cat = arg->val.num; \ break INT_ELEM (country_num); case tok_end: /* Next we assume `LC_ADDRESS'. */ arg = lr_token (ldfile, charmap, result, NULL, verbose); if (arg->tok == tok_eof) break; if (arg->tok == tok_eol) lr_error (ldfile, _("%s: incomplete `END' line"), "LC_ADDRESS"); else if (arg->tok != tok_lc_address) lr_error (ldfile, _("\ %1$s: definition does not end with `END %1$s'"), "LC_ADDRESS"); lr_ignore_rest (ldfile, arg->tok == tok_lc_address); return; default: err_label: SYNTAX_ERROR (_("%s: syntax error"), "LC_ADDRESS"); } /* Prepare for the next round. */ now = lr_token (ldfile, charmap, result, NULL, verbose); nowtok = now->tok; } /* When we come here we reached the end of the file. */ lr_error (ldfile, _("%s: premature end of file"), "LC_ADDRESS"); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
You can’t perform that action at this time.