]>
Commit | Line | Data |
---|---|---|
bfff8b1b | 1 | /* Copyright (C) 1998-2017 Free Software Foundation, Inc. |
4b10dd6c UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. | |
4 | ||
43bc8ac6 | 5 | This program is free software; you can redistribute it and/or modify |
2e2efe65 RM |
6 | it under the terms of the GNU General Public License as published |
7 | by the Free Software Foundation; version 2 of the License, or | |
8 | (at your option) any later version. | |
4b10dd6c | 9 | |
43bc8ac6 | 10 | This program is distributed in the hope that it will be useful, |
4b10dd6c | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
43bc8ac6 UD |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. | |
4b10dd6c | 14 | |
43bc8ac6 | 15 | You should have received a copy of the GNU General Public License |
59ba27a6 | 16 | along with this program; if not, see <http://www.gnu.org/licenses/>. */ |
4b10dd6c UD |
17 | |
18 | #ifdef HAVE_CONFIG_H | |
19 | # include <config.h> | |
20 | #endif | |
21 | ||
22 | #include <byteswap.h> | |
4b10dd6c UD |
23 | #include <langinfo.h> |
24 | #include <string.h> | |
e054f494 | 25 | #include <stdint.h> |
4b10dd6c UD |
26 | #include <sys/uio.h> |
27 | ||
28 | #include <assert.h> | |
29 | ||
f2b98f97 | 30 | #include "localedef.h" |
4b10dd6c UD |
31 | #include "localeinfo.h" |
32 | #include "locfile.h" | |
33 | ||
34 | ||
35 | static struct | |
36 | { | |
0ea5f1b8 UD |
37 | const char ab2[3]; |
38 | const char ab3[4]; | |
4b10dd6c UD |
39 | uint32_t num; |
40 | } iso3166[] = | |
41 | { | |
42 | #define DEFINE_COUNTRY_CODE(Name, Ab2, Ab3, Num) \ | |
43 | { #Ab2, #Ab3, Num }, | |
44 | #include "iso-3166.def" | |
45 | }; | |
46 | ||
47 | ||
48 | static struct | |
49 | { | |
17955ae2 UD |
50 | const char ab[3]; |
51 | const char term[4]; | |
52 | const char lib[4]; | |
4b10dd6c UD |
53 | } iso639[] = |
54 | { | |
55 | #define DEFINE_LANGUAGE_CODE(Name, Ab, Term, Lib) \ | |
56 | { #Ab, #Term, #Lib }, | |
690df9e7 UD |
57 | #define DEFINE_LANGUAGE_CODE3(Name, Term, Lib) \ |
58 | { "", #Term, #Lib }, | |
a53fd660 UD |
59 | #define DEFINE_LANGUAGE_CODE2(Name, Term) \ |
60 | { "", #Term, "" }, | |
4b10dd6c UD |
61 | #include "iso-639.def" |
62 | }; | |
63 | ||
64 | ||
65 | /* The real definition of the struct for the LC_ADDRESS locale. */ | |
66 | struct locale_address_t | |
67 | { | |
68 | const char *postal_fmt; | |
69 | const char *country_name; | |
70 | const char *country_post; | |
71 | const char *country_ab2; | |
72 | const char *country_ab3; | |
73 | uint32_t country_num; | |
4b10dd6c UD |
74 | const char *country_car; |
75 | const char *country_isbn; | |
76 | const char *lang_name; | |
77 | const char *lang_ab; | |
78 | const char *lang_term; | |
79 | const char *lang_lib; | |
80 | }; | |
81 | ||
82 | ||
83 | static void | |
84 | address_startup (struct linereader *lr, struct localedef_t *locale, | |
85 | int ignore_content) | |
86 | { | |
87 | if (!ignore_content) | |
88 | locale->categories[LC_ADDRESS].address = | |
89 | (struct locale_address_t *) xcalloc (1, | |
90 | sizeof (struct locale_address_t)); | |
91 | ||
b9eb05d6 UD |
92 | if (lr != NULL) |
93 | { | |
94 | lr->translate_strings = 1; | |
95 | lr->return_widestr = 0; | |
96 | } | |
4b10dd6c UD |
97 | } |
98 | ||
99 | ||
100 | void | |
47e8b443 | 101 | address_finish (struct localedef_t *locale, const struct charmap_t *charmap) |
4b10dd6c UD |
102 | { |
103 | struct locale_address_t *address = locale->categories[LC_ADDRESS].address; | |
104 | size_t cnt; | |
105 | int helper; | |
b9eb05d6 UD |
106 | int nothing = 0; |
107 | ||
108 | /* Now resolve copying and also handle completely missing definitions. */ | |
109 | if (address == NULL) | |
110 | { | |
111 | /* First see whether we were supposed to copy. If yes, find the | |
112 | actual definition. */ | |
113 | if (locale->copy_name[LC_ADDRESS] != NULL) | |
114 | { | |
115 | /* Find the copying locale. This has to happen transitively since | |
116 | the locale we are copying from might also copying another one. */ | |
117 | struct localedef_t *from = locale; | |
118 | ||
119 | do | |
120 | from = find_locale (LC_ADDRESS, from->copy_name[LC_ADDRESS], | |
121 | from->repertoire_name, charmap); | |
122 | while (from->categories[LC_ADDRESS].address == NULL | |
123 | && from->copy_name[LC_ADDRESS] != NULL); | |
124 | ||
125 | address = locale->categories[LC_ADDRESS].address | |
126 | = from->categories[LC_ADDRESS].address; | |
127 | } | |
128 | ||
129 | /* If there is still no definition issue an warning and create an | |
130 | empty one. */ | |
131 | if (address == NULL) | |
132 | { | |
f16491eb CD |
133 | record_warning (_("\ |
134 | No definition for %s category found"), "LC_ADDRESS"); | |
b9eb05d6 UD |
135 | address_startup (NULL, locale, 0); |
136 | address = locale->categories[LC_ADDRESS].address; | |
137 | nothing = 1; | |
138 | } | |
139 | } | |
4b10dd6c UD |
140 | |
141 | if (address->postal_fmt == NULL) | |
142 | { | |
b9eb05d6 | 143 | if (! nothing) |
f16491eb CD |
144 | record_error (0, 0, _("%s: field `%s' not defined"), |
145 | "LC_ADDRESS", "postal_fmt"); | |
4b10dd6c UD |
146 | /* Use as the default value the value of the i18n locale. */ |
147 | address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"; | |
148 | } | |
149 | else | |
150 | { | |
a8372571 MF |
151 | /* We must check whether the format string contains only the allowed |
152 | escape sequences. Last checked against ISO 30112 WD10 [2014]. */ | |
4b10dd6c UD |
153 | const char *cp = address->postal_fmt; |
154 | ||
155 | if (*cp == '\0') | |
f16491eb CD |
156 | record_error (0, 0, _("%s: field `%s' must not be empty"), |
157 | "LC_ADDRESS", "postal_fmt"); | |
4b10dd6c UD |
158 | else |
159 | while (*cp != '\0') | |
160 | { | |
161 | if (*cp == '%') | |
162 | { | |
163 | if (*++cp == 'R') | |
164 | /* Romanize-flag. */ | |
165 | ++cp; | |
a8372571 | 166 | if (strchr ("nafdbshNtreClzTSc%", *cp) == NULL) |
4b10dd6c | 167 | { |
f16491eb | 168 | record_error (0, 0, _("\ |
4b10dd6c | 169 | %s: invalid escape `%%%c' sequence in field `%s'"), |
f16491eb | 170 | "LC_ADDRESS", *cp, "postal_fmt"); |
4b10dd6c UD |
171 | break; |
172 | } | |
173 | } | |
174 | ++cp; | |
175 | } | |
176 | } | |
177 | ||
178 | #define TEST_ELEM(cat) \ | |
179 | if (address->cat == NULL) \ | |
180 | { \ | |
b9eb05d6 | 181 | if (verbose && ! nothing) \ |
f16491eb | 182 | record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", #cat); \ |
4b10dd6c UD |
183 | address->cat = ""; \ |
184 | } | |
185 | ||
186 | TEST_ELEM (country_name); | |
187 | /* XXX Test against list of defined codes. */ | |
188 | TEST_ELEM (country_post); | |
189 | /* XXX Test against list of defined codes. */ | |
190 | TEST_ELEM (country_car); | |
191 | /* XXX Test against list of defined codes. */ | |
192 | TEST_ELEM (country_isbn); | |
193 | TEST_ELEM (lang_name); | |
194 | ||
195 | helper = 1; | |
196 | if (address->lang_term == NULL) | |
197 | { | |
b9eb05d6 | 198 | if (verbose && ! nothing) |
f16491eb CD |
199 | record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", |
200 | "lang_term"); | |
4b10dd6c UD |
201 | address->lang_term = ""; |
202 | cnt = sizeof (iso639) / sizeof (iso639[0]); | |
203 | } | |
204 | else if (address->lang_term[0] == '\0') | |
205 | { | |
206 | if (verbose) | |
f16491eb CD |
207 | record_warning (_("%s: field `%s' must not be empty"), "LC_ADDRESS", |
208 | "lang_term"); | |
4b10dd6c UD |
209 | cnt = sizeof (iso639) / sizeof (iso639[0]); |
210 | } | |
211 | else | |
212 | { | |
213 | /* Look for this language in the table. */ | |
214 | for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt) | |
215 | if (strcmp (address->lang_term, iso639[cnt].term) == 0) | |
216 | break; | |
217 | if (cnt == sizeof (iso639) / sizeof (iso639[0])) | |
f16491eb | 218 | record_error (0, 0, _("\ |
4b10dd6c | 219 | %s: terminology language code `%s' not defined"), |
f16491eb | 220 | "LC_ADDRESS", address->lang_term); |
4b10dd6c UD |
221 | } |
222 | ||
223 | if (address->lang_ab == NULL) | |
224 | { | |
616d9133 UD |
225 | if ((cnt == sizeof (iso639) / sizeof (iso639[0]) |
226 | || iso639[cnt].ab[0] != '\0') | |
227 | && verbose && ! nothing) | |
f16491eb CD |
228 | record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", |
229 | "lang_ab"); | |
4b10dd6c UD |
230 | address->lang_ab = ""; |
231 | } | |
232 | else if (address->lang_ab[0] == '\0') | |
233 | { | |
616d9133 UD |
234 | if ((cnt == sizeof (iso639) / sizeof (iso639[0]) |
235 | || iso639[cnt].ab[0] != '\0') | |
236 | && verbose) | |
f16491eb CD |
237 | record_warning (_("%s: field `%s' must not be empty"), |
238 | "LC_ADDRESS", "lang_ab"); | |
4b10dd6c | 239 | } |
fff04b32 UD |
240 | else if (cnt < sizeof (iso639) / sizeof (iso639[0]) |
241 | && iso639[cnt].ab[0] == '\0') | |
c093ea4f | 242 | { |
f16491eb CD |
243 | record_error (0, 0, _("%s: field `%s' must not be defined"), |
244 | "LC_ADDRESS", "lang_ab"); | |
c093ea4f UD |
245 | |
246 | address->lang_ab = ""; | |
247 | } | |
4b10dd6c UD |
248 | else |
249 | { | |
250 | if (cnt == sizeof (iso639) / sizeof (iso639[0])) | |
251 | { | |
252 | helper = 2; | |
253 | for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt) | |
254 | if (strcmp (address->lang_ab, iso639[cnt].ab) == 0) | |
255 | break; | |
256 | if (cnt == sizeof (iso639) / sizeof (iso639[0])) | |
f16491eb | 257 | record_error (0, 0, _("\ |
4b10dd6c | 258 | %s: language abbreviation `%s' not defined"), |
f16491eb | 259 | "LC_ADDRESS", address->lang_ab); |
4b10dd6c UD |
260 | } |
261 | else | |
690df9e7 UD |
262 | if (strcmp (iso639[cnt].ab, address->lang_ab) != 0 |
263 | && iso639[cnt].ab[0] != '\0') | |
f16491eb | 264 | record_error (0, 0, _("\ |
4b10dd6c | 265 | %s: `%s' value does not match `%s' value"), |
f16491eb | 266 | "LC_ADDRESS", "lang_ab", "lang_term"); |
4b10dd6c UD |
267 | } |
268 | ||
269 | if (address->lang_lib == NULL) | |
270 | /* This is no error. */ | |
271 | address->lang_lib = address->lang_term; | |
272 | else if (address->lang_lib[0] == '\0') | |
273 | { | |
274 | if (verbose) | |
f16491eb CD |
275 | record_warning (_("%s: field `%s' must not be empty"), |
276 | "LC_ADDRESS", "lang_lib"); | |
4b10dd6c UD |
277 | } |
278 | else | |
279 | { | |
280 | if (cnt == sizeof (iso639) / sizeof (iso639[0])) | |
281 | { | |
282 | for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt) | |
283 | if (strcmp (address->lang_lib, iso639[cnt].lib) == 0) | |
284 | break; | |
285 | if (cnt == sizeof (iso639) / sizeof (iso639[0])) | |
f16491eb | 286 | record_error (0, 0, _("\ |
4b10dd6c | 287 | %s: language abbreviation `%s' not defined"), |
f16491eb | 288 | "LC_ADDRESS", address->lang_lib); |
4b10dd6c UD |
289 | } |
290 | else | |
291 | if (strcmp (iso639[cnt].ab, address->lang_ab) != 0) | |
f16491eb | 292 | record_error (0, 0, _("\ |
4b10dd6c | 293 | %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib", |
f16491eb | 294 | helper == 1 ? "lang_term" : "lang_ab"); |
4b10dd6c UD |
295 | } |
296 | ||
297 | if (address->country_num == 0) | |
298 | { | |
b9eb05d6 | 299 | if (verbose && ! nothing) |
f16491eb CD |
300 | record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", |
301 | "country_num"); | |
4b10dd6c UD |
302 | cnt = sizeof (iso3166) / sizeof (iso3166[0]); |
303 | } | |
304 | else | |
305 | { | |
306 | for (cnt = 0; cnt < sizeof (iso3166) / sizeof (iso3166[0]); ++cnt) | |
307 | if (address->country_num == iso3166[cnt].num) | |
308 | break; | |
309 | ||
310 | if (cnt == sizeof (iso3166) / sizeof (iso3166[0])) | |
f16491eb | 311 | record_error (0, 0, _("\ |
4b10dd6c | 312 | %s: numeric country code `%d' not valid"), |
f16491eb | 313 | "LC_ADDRESS", address->country_num); |
4b10dd6c | 314 | } |
4b10dd6c UD |
315 | |
316 | if (address->country_ab2 == NULL) | |
317 | { | |
b9eb05d6 | 318 | if (verbose && ! nothing) |
f16491eb CD |
319 | record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", |
320 | "country_ab2"); | |
4b10dd6c UD |
321 | address->country_ab2 = " "; |
322 | } | |
323 | else if (cnt != sizeof (iso3166) / sizeof (iso3166[0]) | |
324 | && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0) | |
f16491eb CD |
325 | record_error (0, 0, _("%s: `%s' value does not match `%s' value"), |
326 | "LC_ADDRESS", "country_ab2", "country_num"); | |
4b10dd6c UD |
327 | |
328 | if (address->country_ab3 == NULL) | |
329 | { | |
b9eb05d6 | 330 | if (verbose && ! nothing) |
f16491eb CD |
331 | record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", |
332 | "country_ab3"); | |
4b10dd6c UD |
333 | address->country_ab3 = " "; |
334 | } | |
335 | else if (cnt != sizeof (iso3166) / sizeof (iso3166[0]) | |
336 | && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0) | |
f16491eb | 337 | record_error (0, 0, _("\ |
f2b98f97 | 338 | %s: `%s' value does not match `%s' value"), |
f16491eb | 339 | "LC_ADDRESS", "country_ab3", "country_num"); |
4b10dd6c UD |
340 | } |
341 | ||
342 | ||
343 | void | |
47e8b443 | 344 | address_output (struct localedef_t *locale, const struct charmap_t *charmap, |
4b10dd6c UD |
345 | const char *output_path) |
346 | { | |
347 | struct locale_address_t *address = locale->categories[LC_ADDRESS].address; | |
1ecbb381 RS |
348 | struct locale_file file; |
349 | ||
350 | init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)); | |
351 | add_locale_string (&file, address->postal_fmt); | |
352 | add_locale_string (&file, address->country_name); | |
353 | add_locale_string (&file, address->country_post); | |
354 | add_locale_string (&file, address->country_ab2); | |
355 | add_locale_string (&file, address->country_ab3); | |
356 | add_locale_string (&file, address->country_car); | |
357 | add_locale_uint32 (&file, address->country_num); | |
358 | add_locale_string (&file, address->country_isbn); | |
359 | add_locale_string (&file, address->lang_name); | |
360 | add_locale_string (&file, address->lang_ab); | |
361 | add_locale_string (&file, address->lang_term); | |
362 | add_locale_string (&file, address->lang_lib); | |
363 | add_locale_string (&file, charmap->code_set_name); | |
364 | write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS", &file); | |
4b10dd6c UD |
365 | } |
366 | ||
367 | ||
368 | /* The parser for the LC_ADDRESS section of the locale definition. */ | |
369 | void | |
370 | address_read (struct linereader *ldfile, struct localedef_t *result, | |
47e8b443 | 371 | const struct charmap_t *charmap, const char *repertoire_name, |
4b10dd6c UD |
372 | int ignore_content) |
373 | { | |
4b10dd6c UD |
374 | struct locale_address_t *address; |
375 | struct token *now; | |
376 | struct token *arg; | |
377 | enum token_t nowtok; | |
378 | ||
4b10dd6c UD |
379 | /* The rest of the line containing `LC_ADDRESS' must be free. */ |
380 | lr_ignore_rest (ldfile, 1); | |
381 | ||
382 | ||
383 | do | |
384 | { | |
47e8b443 | 385 | now = lr_token (ldfile, charmap, result, NULL, verbose); |
4b10dd6c UD |
386 | nowtok = now->tok; |
387 | } | |
388 | while (nowtok == tok_eol); | |
389 | ||
390 | /* If we see `copy' now we are almost done. */ | |
391 | if (nowtok == tok_copy) | |
392 | { | |
01ff9d0b | 393 | handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_address, |
b9eb05d6 | 394 | LC_ADDRESS, "LC_ADDRESS", ignore_content); |
4b10dd6c UD |
395 | return; |
396 | } | |
397 | ||
398 | /* Prepare the data structures. */ | |
399 | address_startup (ldfile, result, ignore_content); | |
400 | address = result->categories[LC_ADDRESS].address; | |
401 | ||
402 | while (1) | |
403 | { | |
404 | /* Of course we don't proceed beyond the end of file. */ | |
405 | if (nowtok == tok_eof) | |
406 | break; | |
407 | ||
42d7c593 | 408 | /* Ignore empty lines. */ |
4b10dd6c UD |
409 | if (nowtok == tok_eol) |
410 | { | |
47e8b443 | 411 | now = lr_token (ldfile, charmap, result, NULL, verbose); |
4b10dd6c UD |
412 | nowtok = now->tok; |
413 | continue; | |
414 | } | |
415 | ||
416 | switch (nowtok) | |
417 | { | |
418 | #define STR_ELEM(cat) \ | |
419 | case tok_##cat: \ | |
b9eb05d6 UD |
420 | /* Ignore the rest of the line if we don't need the input of \ |
421 | this line. */ \ | |
422 | if (ignore_content) \ | |
423 | { \ | |
424 | lr_ignore_rest (ldfile, 0); \ | |
425 | break; \ | |
426 | } \ | |
427 | \ | |
47e8b443 | 428 | arg = lr_token (ldfile, charmap, result, NULL, verbose); \ |
4b10dd6c UD |
429 | if (arg->tok != tok_string) \ |
430 | goto err_label; \ | |
431 | if (address->cat != NULL) \ | |
432 | lr_error (ldfile, _("\ | |
433 | %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \ | |
434 | else if (!ignore_content && arg->val.str.startmb == NULL) \ | |
435 | { \ | |
436 | lr_error (ldfile, _("\ | |
437 | %s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \ | |
438 | address->cat = ""; \ | |
439 | } \ | |
440 | else if (!ignore_content) \ | |
441 | address->cat = arg->val.str.startmb; \ | |
442 | break | |
443 | ||
444 | STR_ELEM (postal_fmt); | |
445 | STR_ELEM (country_name); | |
446 | STR_ELEM (country_post); | |
447 | STR_ELEM (country_ab2); | |
448 | STR_ELEM (country_ab3); | |
449 | STR_ELEM (country_car); | |
4b10dd6c UD |
450 | STR_ELEM (lang_name); |
451 | STR_ELEM (lang_ab); | |
452 | STR_ELEM (lang_term); | |
453 | STR_ELEM (lang_lib); | |
454 | ||
17955ae2 UD |
455 | #define INT_STR_ELEM(cat) \ |
456 | case tok_##cat: \ | |
457 | /* Ignore the rest of the line if we don't need the input of \ | |
458 | this line. */ \ | |
459 | if (ignore_content) \ | |
460 | { \ | |
461 | lr_ignore_rest (ldfile, 0); \ | |
462 | break; \ | |
463 | } \ | |
464 | \ | |
47e8b443 | 465 | arg = lr_token (ldfile, charmap, result, NULL, verbose); \ |
17955ae2 UD |
466 | if (arg->tok != tok_string && arg->tok != tok_number) \ |
467 | goto err_label; \ | |
468 | if (address->cat != NULL) \ | |
469 | lr_error (ldfile, _("\ | |
470 | %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \ | |
45a9eda2 UD |
471 | else if (!ignore_content && arg->tok == tok_string \ |
472 | && arg->val.str.startmb == NULL) \ | |
17955ae2 UD |
473 | { \ |
474 | lr_error (ldfile, _("\ | |
475 | %s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \ | |
476 | address->cat = ""; \ | |
477 | } \ | |
478 | else if (!ignore_content) \ | |
479 | { \ | |
480 | if (arg->tok == tok_string) \ | |
481 | address->cat = arg->val.str.startmb; \ | |
482 | else \ | |
483 | { \ | |
436cfba0 JM |
484 | char *numbuf = (char *) xmalloc (21); \ |
485 | snprintf (numbuf, 21, "%ld", arg->val.num); \ | |
17955ae2 UD |
486 | address->cat = numbuf; \ |
487 | } \ | |
488 | } \ | |
489 | break | |
490 | ||
491 | INT_STR_ELEM (country_isbn); | |
492 | ||
4b10dd6c UD |
493 | #define INT_ELEM(cat) \ |
494 | case tok_##cat: \ | |
b9eb05d6 UD |
495 | /* Ignore the rest of the line if we don't need the input of \ |
496 | this line. */ \ | |
497 | if (ignore_content) \ | |
498 | { \ | |
499 | lr_ignore_rest (ldfile, 0); \ | |
500 | break; \ | |
501 | } \ | |
502 | \ | |
47e8b443 | 503 | arg = lr_token (ldfile, charmap, result, NULL, verbose); \ |
4b10dd6c UD |
504 | if (arg->tok != tok_number) \ |
505 | goto err_label; \ | |
506 | else if (address->cat != 0) \ | |
507 | lr_error (ldfile, _("\ | |
508 | %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \ | |
509 | else if (!ignore_content) \ | |
510 | address->cat = arg->val.num; \ | |
511 | break | |
512 | ||
513 | INT_ELEM (country_num); | |
514 | ||
515 | case tok_end: | |
516 | /* Next we assume `LC_ADDRESS'. */ | |
47e8b443 | 517 | arg = lr_token (ldfile, charmap, result, NULL, verbose); |
4b10dd6c UD |
518 | if (arg->tok == tok_eof) |
519 | break; | |
520 | if (arg->tok == tok_eol) | |
521 | lr_error (ldfile, _("%s: incomplete `END' line"), | |
522 | "LC_ADDRESS"); | |
523 | else if (arg->tok != tok_lc_address) | |
524 | lr_error (ldfile, _("\ | |
525 | %1$s: definition does not end with `END %1$s'"), "LC_ADDRESS"); | |
526 | lr_ignore_rest (ldfile, arg->tok == tok_lc_address); | |
527 | return; | |
528 | ||
529 | default: | |
530 | err_label: | |
531 | SYNTAX_ERROR (_("%s: syntax error"), "LC_ADDRESS"); | |
532 | } | |
533 | ||
534 | /* Prepare for the next round. */ | |
47e8b443 | 535 | now = lr_token (ldfile, charmap, result, NULL, verbose); |
4b10dd6c UD |
536 | nowtok = now->tok; |
537 | } | |
538 | ||
539 | /* When we come here we reached the end of the file. */ | |
540 | lr_error (ldfile, _("%s: premature end of file"), "LC_ADDRESS"); | |
541 | } |