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