1 /* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
32 #include "localedef.h"
33 #include "localeinfo.h"
44 #define DEFINE_COUNTRY_CODE(Name, Ab2, Ab3, Num) \
46 #include "iso-3166.def"
57 #define DEFINE_LANGUAGE_CODE(Name, Ab, Term, Lib) \
59 #include "iso-639.def"
63 /* The real definition of the struct for the LC_ADDRESS locale. */
64 struct locale_address_t
66 const char *postal_fmt;
67 const char *country_name;
68 const char *country_post;
69 const char *country_ab2;
70 const char *country_ab3;
72 const char *country_car;
73 const char *country_isbn;
74 const char *lang_name;
76 const char *lang_term;
82 address_startup (struct linereader *lr, struct localedef_t *locale,
86 locale->categories[LC_ADDRESS].address =
87 (struct locale_address_t *) xcalloc (1,
88 sizeof (struct locale_address_t));
92 lr->translate_strings = 1;
93 lr->return_widestr = 0;
99 address_finish (struct localedef_t *locale, const struct charmap_t *charmap)
101 struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
106 /* Now resolve copying and also handle completely missing definitions. */
109 /* First see whether we were supposed to copy. If yes, find the
110 actual definition. */
111 if (locale->copy_name[LC_ADDRESS] != NULL)
113 /* Find the copying locale. This has to happen transitively since
114 the locale we are copying from might also copying another one. */
115 struct localedef_t *from = locale;
118 from = find_locale (LC_ADDRESS, from->copy_name[LC_ADDRESS],
119 from->repertoire_name, charmap);
120 while (from->categories[LC_ADDRESS].address == NULL
121 && from->copy_name[LC_ADDRESS] != NULL);
123 address = locale->categories[LC_ADDRESS].address
124 = from->categories[LC_ADDRESS].address;
127 /* If there is still no definition issue an warning and create an
132 WITH_CUR_LOCALE (error (0, 0, _("\
133 No definition for %s category found"), "LC_ADDRESS"));
134 address_startup (NULL, locale, 0);
135 address = locale->categories[LC_ADDRESS].address;
140 if (address->postal_fmt == NULL)
143 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
144 "LC_ADDRESS", "postal_fmt"));
145 /* Use as the default value the value of the i18n locale. */
146 address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N";
150 /* We must check whether the format string contains only the
151 allowed escape sequences. */
152 const char *cp = address->postal_fmt;
155 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
156 "LC_ADDRESS", "postal_fmt"));
165 if (strchr ("afdbshNtreCzTSc%", *cp) == NULL)
167 WITH_CUR_LOCALE (error (0, 0, _("\
168 %s: invalid escape `%%%c' sequence in field `%s'"),
169 "LC_ADDRESS", *cp, "postal_fmt"));
177 #define TEST_ELEM(cat) \
178 if (address->cat == NULL) \
180 if (verbose && ! nothing) \
181 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"), \
182 "LC_ADDRESS", #cat)); \
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);
196 if (address->lang_term == NULL)
198 if (verbose && ! nothing)
199 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
200 "LC_ADDRESS", "lang_term"));
201 address->lang_term = "";
202 cnt = sizeof (iso639) / sizeof (iso639[0]);
204 else if (address->lang_term[0] == '\0')
207 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
208 "LC_ADDRESS", "lang_term"));
209 cnt = sizeof (iso639) / sizeof (iso639[0]);
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)
217 if (cnt == sizeof (iso639) / sizeof (iso639[0]))
218 WITH_CUR_LOCALE (error (0, 0, _("\
219 %s: terminology language code `%s' not defined"),
220 "LC_ADDRESS", address->lang_term));
223 if (address->lang_ab == NULL)
225 if (verbose && ! nothing)
226 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
227 "LC_ADDRESS", "lang_ab"));
228 address->lang_ab = "";
230 else if (address->lang_ab[0] == '\0')
233 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
234 "LC_ADDRESS", "lang_ab"));
238 if (cnt == sizeof (iso639) / sizeof (iso639[0]))
241 for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
242 if (strcmp (address->lang_ab, iso639[cnt].ab) == 0)
244 if (cnt == sizeof (iso639) / sizeof (iso639[0]))
245 WITH_CUR_LOCALE (error (0, 0, _("\
246 %s: language abbreviation `%s' not defined"),
247 "LC_ADDRESS", address->lang_ab));
250 if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
251 WITH_CUR_LOCALE (error (0, 0, _("\
252 %s: `%s' value does not match `%s' value"),
253 "LC_ADDRESS", "lang_ab", "lang_term"));
256 if (address->lang_lib == NULL)
257 /* This is no error. */
258 address->lang_lib = address->lang_term;
259 else if (address->lang_lib[0] == '\0')
262 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
263 "LC_ADDRESS", "lang_lib"));
267 if (cnt == sizeof (iso639) / sizeof (iso639[0]))
269 for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
270 if (strcmp (address->lang_lib, iso639[cnt].lib) == 0)
272 if (cnt == sizeof (iso639) / sizeof (iso639[0]))
273 WITH_CUR_LOCALE (error (0, 0, _("\
274 %s: language abbreviation `%s' not defined"),
275 "LC_ADDRESS", address->lang_lib));
278 if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
279 WITH_CUR_LOCALE (error (0, 0, _("\
280 %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib",
281 helper == 1 ? "lang_term" : "lang_ab"));
284 if (address->country_num == 0)
286 if (verbose && ! nothing)
287 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
288 "LC_ADDRESS", "country_num"));
289 cnt = sizeof (iso3166) / sizeof (iso3166[0]);
293 for (cnt = 0; cnt < sizeof (iso3166) / sizeof (iso3166[0]); ++cnt)
294 if (address->country_num == iso3166[cnt].num)
297 if (cnt == sizeof (iso3166) / sizeof (iso3166[0]))
298 WITH_CUR_LOCALE (error (0, 0, _("\
299 %s: numeric country code `%d' not valid"),
300 "LC_ADDRESS", address->country_num));
303 if (address->country_ab2 == NULL)
305 if (verbose && ! nothing)
306 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
307 "LC_ADDRESS", "country_ab2"));
308 address->country_ab2 = " ";
310 else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
311 && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0)
312 WITH_CUR_LOCALE (error (0, 0,
313 _("%s: `%s' value does not match `%s' value"),
314 "LC_ADDRESS", "country_ab2", "country_num"));
316 if (address->country_ab3 == NULL)
318 if (verbose && ! nothing)
319 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
320 "LC_ADDRESS", "country_ab3"));
321 address->country_ab3 = " ";
323 else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
324 && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0)
325 WITH_CUR_LOCALE (error (0, 0, _("\
326 %s: `%s' value does not match `%s' value"),
327 "LC_ADDRESS", "country_ab3", "country_num"));
332 address_output (struct localedef_t *locale, const struct charmap_t *charmap,
333 const char *output_path)
335 struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
336 struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
337 struct locale_file data;
338 uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
341 data.magic = LIMAGIC (LC_ADDRESS);
342 data.n = _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS);
343 iov[cnt].iov_base = (void *) &data;
344 iov[cnt].iov_len = sizeof (data);
347 iov[cnt].iov_base = (void *) idx;
348 iov[cnt].iov_len = sizeof (idx);
351 idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
352 iov[cnt].iov_base = (void *) address->postal_fmt;
353 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
356 idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
357 iov[cnt].iov_base = (void *) address->country_name;
358 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
361 idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
362 iov[cnt].iov_base = (void *) address->country_post;
363 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
366 idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
367 iov[cnt].iov_base = (void *) address->country_ab2;
368 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
371 idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
372 iov[cnt].iov_base = (void *) address->country_ab3;
373 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
376 idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
377 iov[cnt].iov_base = (void *) address->country_car;
378 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
381 idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
383 /* Align following data */
384 iov[cnt].iov_base = (void *) "\0\0";
385 iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
386 idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
389 iov[cnt].iov_base = (void *) &address->country_num;
390 iov[cnt].iov_len = sizeof (uint32_t);
393 idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
394 iov[cnt].iov_base = (void *) address->country_isbn;
395 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
398 idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
399 iov[cnt].iov_base = (void *) address->lang_name;
400 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
403 idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
404 iov[cnt].iov_base = (void *) address->lang_ab;
405 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
408 idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
409 iov[cnt].iov_base = (void *) address->lang_term;
410 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
413 idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
414 iov[cnt].iov_base = (void *) address->lang_lib;
415 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
418 idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
419 iov[cnt].iov_base = (void *) charmap->code_set_name;
420 iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
423 assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
425 write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS",
426 3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS), iov);
430 /* The parser for the LC_ADDRESS section of the locale definition. */
432 address_read (struct linereader *ldfile, struct localedef_t *result,
433 const struct charmap_t *charmap, const char *repertoire_name,
436 struct locale_address_t *address;
441 /* The rest of the line containing `LC_ADDRESS' must be free. */
442 lr_ignore_rest (ldfile, 1);
447 now = lr_token (ldfile, charmap, result, NULL, verbose);
450 while (nowtok == tok_eol);
452 /* If we see `copy' now we are almost done. */
453 if (nowtok == tok_copy)
455 handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_address,
456 LC_ADDRESS, "LC_ADDRESS", ignore_content);
460 /* Prepare the data structures. */
461 address_startup (ldfile, result, ignore_content);
462 address = result->categories[LC_ADDRESS].address;
466 /* Of course we don't proceed beyond the end of file. */
467 if (nowtok == tok_eof)
470 /* Ignore empty lines. */
471 if (nowtok == tok_eol)
473 now = lr_token (ldfile, charmap, result, NULL, verbose);
480 #define STR_ELEM(cat) \
482 /* Ignore the rest of the line if we don't need the input of \
484 if (ignore_content) \
486 lr_ignore_rest (ldfile, 0); \
490 arg = lr_token (ldfile, charmap, result, NULL, verbose); \
491 if (arg->tok != tok_string) \
493 if (address->cat != NULL) \
494 lr_error (ldfile, _("\
495 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \
496 else if (!ignore_content && arg->val.str.startmb == NULL) \
498 lr_error (ldfile, _("\
499 %s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \
502 else if (!ignore_content) \
503 address->cat = arg->val.str.startmb; \
506 STR_ELEM (postal_fmt);
507 STR_ELEM (country_name);
508 STR_ELEM (country_post);
509 STR_ELEM (country_ab2);
510 STR_ELEM (country_ab3);
511 STR_ELEM (country_car);
512 STR_ELEM (lang_name);
514 STR_ELEM (lang_term);
517 #define INT_STR_ELEM(cat) \
519 /* Ignore the rest of the line if we don't need the input of \
521 if (ignore_content) \
523 lr_ignore_rest (ldfile, 0); \
527 arg = lr_token (ldfile, charmap, result, NULL, verbose); \
528 if (arg->tok != tok_string && arg->tok != tok_number) \
530 if (address->cat != NULL) \
531 lr_error (ldfile, _("\
532 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \
533 else if (!ignore_content && arg->tok == tok_string \
534 && arg->val.str.startmb == NULL) \
536 lr_error (ldfile, _("\
537 %s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \
540 else if (!ignore_content) \
542 if (arg->tok == tok_string) \
543 address->cat = arg->val.str.startmb; \
546 char *numbuf = (char *) xmalloc (11); \
547 snprintf (numbuf, 11, "%ld", arg->val.num); \
548 address->cat = numbuf; \
553 INT_STR_ELEM (country_isbn);
555 #define INT_ELEM(cat) \
557 /* Ignore the rest of the line if we don't need the input of \
559 if (ignore_content) \
561 lr_ignore_rest (ldfile, 0); \
565 arg = lr_token (ldfile, charmap, result, NULL, verbose); \
566 if (arg->tok != tok_number) \
568 else if (address->cat != 0) \
569 lr_error (ldfile, _("\
570 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \
571 else if (!ignore_content) \
572 address->cat = arg->val.num; \
575 INT_ELEM (country_num);
578 /* Next we assume `LC_ADDRESS'. */
579 arg = lr_token (ldfile, charmap, result, NULL, verbose);
580 if (arg->tok == tok_eof)
582 if (arg->tok == tok_eol)
583 lr_error (ldfile, _("%s: incomplete `END' line"),
585 else if (arg->tok != tok_lc_address)
586 lr_error (ldfile, _("\
587 %1$s: definition does not end with `END %1$s'"), "LC_ADDRESS");
588 lr_ignore_rest (ldfile, arg->tok == tok_lc_address);
593 SYNTAX_ERROR (_("%s: syntax error"), "LC_ADDRESS");
596 /* Prepare for the next round. */
597 now = lr_token (ldfile, charmap, result, NULL, verbose);
601 /* When we come here we reached the end of the file. */
602 lr_error (ldfile, _("%s: premature end of file"), "LC_ADDRESS");