Update.
[platform/upstream/glibc.git] / locale / programs / ld-address.c
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.
4
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.
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    Lesser General Public License for more details.
14
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
18    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 "localedef.h"
33 #include "localeinfo.h"
34 #include "locfile.h"
35
36
37 static struct
38 {
39   const char ab2[3];
40   const char ab3[4];
41   uint32_t num;
42 } iso3166[] =
43 {
44 #define DEFINE_COUNTRY_CODE(Name, Ab2, Ab3, Num) \
45   { #Ab2, #Ab3, Num },
46 #include "iso-3166.def"
47 };
48
49
50 static struct
51 {
52   const char ab[3];
53   const char term[4];
54   const char lib[4];
55 } iso639[] =
56 {
57 #define DEFINE_LANGUAGE_CODE(Name, Ab, Term, Lib) \
58   { #Ab, #Term, #Lib },
59 #define DEFINE_LANGUAGE_CODE3(Name, Term, Lib) \
60   { "", #Term, #Lib },
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;
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
92   if (lr != NULL)
93     {
94       lr->translate_strings = 1;
95       lr->return_widestr = 0;
96     }
97 }
98
99
100 void
101 address_finish (struct localedef_t *locale, const struct charmap_t *charmap)
102 {
103   struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
104   size_t cnt;
105   int helper;
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         {
133           if (! be_quiet)
134             WITH_CUR_LOCALE (error (0, 0, _("\
135 No definition for %s category found"), "LC_ADDRESS"));
136           address_startup (NULL, locale, 0);
137           address = locale->categories[LC_ADDRESS].address;
138           nothing = 1;
139         }
140     }
141
142   if (address->postal_fmt == NULL)
143     {
144       if (! nothing)
145         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
146                                 "LC_ADDRESS", "postal_fmt"));
147       /* Use as the default value the value of the i18n locale.  */
148       address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N";
149     }
150   else
151     {
152       /* We must check whether the format string contains only the
153          allowed escape sequences.  */
154       const char *cp = address->postal_fmt;
155
156       if (*cp == '\0')
157         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
158                                 "LC_ADDRESS", "postal_fmt"));
159       else
160         while (*cp != '\0')
161           {
162             if (*cp == '%')
163               {
164                 if (*++cp == 'R')
165                   /* Romanize-flag.  */
166                   ++cp;
167                 if (strchr ("afdbshNtreCzTSc%", *cp) == NULL)
168                   {
169                     WITH_CUR_LOCALE (error (0, 0, _("\
170 %s: invalid escape `%%%c' sequence in field `%s'"),
171                                             "LC_ADDRESS", *cp, "postal_fmt"));
172                     break;
173                   }
174               }
175             ++cp;
176           }
177     }
178
179 #define TEST_ELEM(cat) \
180   if (address->cat == NULL)                                                   \
181     {                                                                         \
182       if (verbose && ! nothing)                                               \
183         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),        \
184                                 "LC_ADDRESS", #cat));                         \
185       address->cat = "";                                                      \
186     }
187
188   TEST_ELEM (country_name);
189   /* XXX Test against list of defined codes.  */
190   TEST_ELEM (country_post);
191   /* XXX Test against list of defined codes.  */
192   TEST_ELEM (country_car);
193   /* XXX Test against list of defined codes.  */
194   TEST_ELEM (country_isbn);
195   TEST_ELEM (lang_name);
196
197   helper = 1;
198   if (address->lang_term == NULL)
199     {
200       if (verbose && ! nothing)
201         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
202                                 "LC_ADDRESS", "lang_term"));
203       address->lang_term = "";
204       cnt = sizeof (iso639) / sizeof (iso639[0]);
205     }
206   else if (address->lang_term[0] == '\0')
207     {
208       if (verbose)
209         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
210                                 "LC_ADDRESS", "lang_term"));
211       cnt = sizeof (iso639) / sizeof (iso639[0]);
212     }
213   else
214     {
215       /* Look for this language in the table.  */
216       for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
217         if (strcmp (address->lang_term, iso639[cnt].term) == 0)
218           break;
219       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
220         WITH_CUR_LOCALE (error (0, 0, _("\
221 %s: terminology language code `%s' not defined"),
222                                 "LC_ADDRESS", address->lang_term));
223     }
224
225   if (address->lang_ab == NULL)
226     {
227       if (verbose && ! nothing)
228         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
229                                 "LC_ADDRESS", "lang_ab"));
230       address->lang_ab = "";
231     }
232   else if (address->lang_ab[0] == '\0')
233     {
234       if (verbose)
235         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
236                                 "LC_ADDRESS", "lang_ab"));
237     }
238   else
239     {
240       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
241         {
242           helper = 2;
243           for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
244             if (strcmp (address->lang_ab, iso639[cnt].ab) == 0)
245               break;
246           if (cnt == sizeof (iso639) / sizeof (iso639[0]))
247             WITH_CUR_LOCALE (error (0, 0, _("\
248 %s: language abbreviation `%s' not defined"),
249                                     "LC_ADDRESS", address->lang_ab));
250         }
251       else
252         if (strcmp (iso639[cnt].ab, address->lang_ab) != 0
253             && iso639[cnt].ab[0] != '\0')
254           WITH_CUR_LOCALE (error (0, 0, _("\
255 %s: `%s' value does not match `%s' value"),
256                                   "LC_ADDRESS", "lang_ab", "lang_term"));
257     }
258
259   if (address->lang_lib == NULL)
260     /* This is no error.  */
261     address->lang_lib = address->lang_term;
262   else if (address->lang_lib[0] == '\0')
263     {
264       if (verbose)
265         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
266                                 "LC_ADDRESS", "lang_lib"));
267     }
268   else
269     {
270       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
271         {
272           for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
273             if (strcmp (address->lang_lib, iso639[cnt].lib) == 0)
274               break;
275           if (cnt == sizeof (iso639) / sizeof (iso639[0]))
276             WITH_CUR_LOCALE (error (0, 0, _("\
277 %s: language abbreviation `%s' not defined"),
278                                     "LC_ADDRESS", address->lang_lib));
279         }
280       else
281         if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
282           WITH_CUR_LOCALE (error (0, 0, _("\
283 %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib",
284                                   helper == 1 ? "lang_term" : "lang_ab"));
285     }
286
287   if (address->country_num == 0)
288     {
289       if (verbose && ! nothing)
290         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
291                                 "LC_ADDRESS", "country_num"));
292       cnt = sizeof (iso3166) / sizeof (iso3166[0]);
293     }
294   else
295     {
296       for (cnt = 0; cnt < sizeof (iso3166) / sizeof (iso3166[0]); ++cnt)
297         if (address->country_num == iso3166[cnt].num)
298           break;
299
300       if (cnt == sizeof (iso3166) / sizeof (iso3166[0]))
301         WITH_CUR_LOCALE (error (0, 0, _("\
302 %s: numeric country code `%d' not valid"),
303                                 "LC_ADDRESS", address->country_num));
304     }
305
306   if (address->country_ab2 == NULL)
307     {
308       if (verbose && ! nothing)
309         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
310                                 "LC_ADDRESS", "country_ab2"));
311       address->country_ab2 = "  ";
312     }
313   else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
314            && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0)
315     WITH_CUR_LOCALE (error (0, 0,
316                             _("%s: `%s' value does not match `%s' value"),
317                             "LC_ADDRESS", "country_ab2", "country_num"));
318
319   if (address->country_ab3 == NULL)
320     {
321       if (verbose && ! nothing)
322         WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
323                                 "LC_ADDRESS", "country_ab3"));
324       address->country_ab3 = "   ";
325     }
326   else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
327            && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0)
328     WITH_CUR_LOCALE (error (0, 0, _("\
329 %s: `%s' value does not match `%s' value"),
330                             "LC_ADDRESS", "country_ab3", "country_num"));
331 }
332
333
334 void
335 address_output (struct localedef_t *locale, const struct charmap_t *charmap,
336                 const char *output_path)
337 {
338   struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
339   struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
340   struct locale_file data;
341   uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
342   size_t cnt = 0;
343
344   data.magic = LIMAGIC (LC_ADDRESS);
345   data.n = _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS);
346   iov[cnt].iov_base = (void *) &data;
347   iov[cnt].iov_len = sizeof (data);
348   ++cnt;
349
350   iov[cnt].iov_base = (void *) idx;
351   iov[cnt].iov_len = sizeof (idx);
352   ++cnt;
353
354   idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
355   iov[cnt].iov_base = (void *) address->postal_fmt;
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_name;
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_post;
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_ab2;
371   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
372   ++cnt;
373
374   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
375   iov[cnt].iov_base = (void *) address->country_ab3;
376   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
377   ++cnt;
378
379   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
380   iov[cnt].iov_base = (void *) address->country_car;
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
386   /* Align following data */
387   iov[cnt].iov_base = (void *) "\0\0";
388   iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
389   idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
390   ++cnt;
391
392   iov[cnt].iov_base = (void *) &address->country_num;
393   iov[cnt].iov_len = sizeof (uint32_t);
394   ++cnt;
395
396   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
397   iov[cnt].iov_base = (void *) address->country_isbn;
398   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
399   ++cnt;
400
401   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
402   iov[cnt].iov_base = (void *) address->lang_name;
403   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
404   ++cnt;
405
406   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
407   iov[cnt].iov_base = (void *) address->lang_ab;
408   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
409   ++cnt;
410
411   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
412   iov[cnt].iov_base = (void *) address->lang_term;
413   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
414   ++cnt;
415
416   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
417   iov[cnt].iov_base = (void *) address->lang_lib;
418   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
419   ++cnt;
420
421   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
422   iov[cnt].iov_base = (void *) charmap->code_set_name;
423   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
424   ++cnt;
425
426   assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
427
428   write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS",
429                      3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS), iov);
430 }
431
432
433 /* The parser for the LC_ADDRESS section of the locale definition.  */
434 void
435 address_read (struct linereader *ldfile, struct localedef_t *result,
436               const struct charmap_t *charmap, const char *repertoire_name,
437               int ignore_content)
438 {
439   struct locale_address_t *address;
440   struct token *now;
441   struct token *arg;
442   enum token_t nowtok;
443
444   /* The rest of the line containing `LC_ADDRESS' must be free.  */
445   lr_ignore_rest (ldfile, 1);
446
447
448   do
449     {
450       now = lr_token (ldfile, charmap, result, NULL, verbose);
451       nowtok = now->tok;
452     }
453   while (nowtok == tok_eol);
454
455   /* If we see `copy' now we are almost done.  */
456   if (nowtok == tok_copy)
457     {
458       handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_address,
459                    LC_ADDRESS, "LC_ADDRESS", ignore_content);
460       return;
461     }
462
463   /* Prepare the data structures.  */
464   address_startup (ldfile, result, ignore_content);
465   address = result->categories[LC_ADDRESS].address;
466
467   while (1)
468     {
469       /* Of course we don't proceed beyond the end of file.  */
470       if (nowtok == tok_eof)
471         break;
472
473       /* Ignore empty lines.  */
474       if (nowtok == tok_eol)
475         {
476           now = lr_token (ldfile, charmap, result, NULL, verbose);
477           nowtok = now->tok;
478           continue;
479         }
480
481       switch (nowtok)
482         {
483 #define STR_ELEM(cat) \
484         case tok_##cat:                                                       \
485           /* Ignore the rest of the line if we don't need the input of        \
486              this line.  */                                                   \
487           if (ignore_content)                                                 \
488             {                                                                 \
489               lr_ignore_rest (ldfile, 0);                                     \
490               break;                                                          \
491             }                                                                 \
492                                                                               \
493           arg = lr_token (ldfile, charmap, result, NULL, verbose);            \
494           if (arg->tok != tok_string)                                         \
495             goto err_label;                                                   \
496           if (address->cat != NULL)                                           \
497             lr_error (ldfile, _("\
498 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat);                \
499           else if (!ignore_content && arg->val.str.startmb == NULL)           \
500             {                                                                 \
501               lr_error (ldfile, _("\
502 %s: unknown character in field `%s'"), "LC_ADDRESS", #cat);                   \
503               address->cat = "";                                              \
504             }                                                                 \
505           else if (!ignore_content)                                           \
506             address->cat = arg->val.str.startmb;                              \
507           break
508
509           STR_ELEM (postal_fmt);
510           STR_ELEM (country_name);
511           STR_ELEM (country_post);
512           STR_ELEM (country_ab2);
513           STR_ELEM (country_ab3);
514           STR_ELEM (country_car);
515           STR_ELEM (lang_name);
516           STR_ELEM (lang_ab);
517           STR_ELEM (lang_term);
518           STR_ELEM (lang_lib);
519
520 #define INT_STR_ELEM(cat) \
521         case tok_##cat:                                                       \
522           /* Ignore the rest of the line if we don't need the input of        \
523              this line.  */                                                   \
524           if (ignore_content)                                                 \
525             {                                                                 \
526               lr_ignore_rest (ldfile, 0);                                     \
527               break;                                                          \
528             }                                                                 \
529                                                                               \
530           arg = lr_token (ldfile, charmap, result, NULL, verbose);            \
531           if (arg->tok != tok_string && arg->tok != tok_number)               \
532             goto err_label;                                                   \
533           if (address->cat != NULL)                                           \
534             lr_error (ldfile, _("\
535 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat);                \
536           else if (!ignore_content && arg->tok == tok_string                  \
537                    && arg->val.str.startmb == NULL)                           \
538             {                                                                 \
539               lr_error (ldfile, _("\
540 %s: unknown character in field `%s'"), "LC_ADDRESS", #cat);                   \
541               address->cat = "";                                              \
542             }                                                                 \
543           else if (!ignore_content)                                           \
544             {                                                                 \
545               if (arg->tok == tok_string)                                     \
546                 address->cat = arg->val.str.startmb;                          \
547               else                                                            \
548                 {                                                             \
549                   char *numbuf = (char *) xmalloc (11);                       \
550                   snprintf (numbuf, 11, "%ld", arg->val.num);                 \
551                   address->cat = numbuf;                                      \
552                 }                                                             \
553             }                                                                 \
554           break
555
556           INT_STR_ELEM (country_isbn);
557
558 #define INT_ELEM(cat) \
559         case tok_##cat:                                                       \
560           /* Ignore the rest of the line if we don't need the input of        \
561              this line.  */                                                   \
562           if (ignore_content)                                                 \
563             {                                                                 \
564               lr_ignore_rest (ldfile, 0);                                     \
565               break;                                                          \
566             }                                                                 \
567                                                                               \
568           arg = lr_token (ldfile, charmap, result, NULL, verbose);            \
569           if (arg->tok != tok_number)                                         \
570             goto err_label;                                                   \
571           else if (address->cat != 0)                                         \
572             lr_error (ldfile, _("\
573 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat);                \
574           else if (!ignore_content)                                           \
575             address->cat = arg->val.num;                                      \
576           break
577
578           INT_ELEM (country_num);
579
580         case tok_end:
581           /* Next we assume `LC_ADDRESS'.  */
582           arg = lr_token (ldfile, charmap, result, NULL, verbose);
583           if (arg->tok == tok_eof)
584             break;
585           if (arg->tok == tok_eol)
586             lr_error (ldfile, _("%s: incomplete `END' line"),
587                       "LC_ADDRESS");
588           else if (arg->tok != tok_lc_address)
589             lr_error (ldfile, _("\
590 %1$s: definition does not end with `END %1$s'"), "LC_ADDRESS");
591           lr_ignore_rest (ldfile, arg->tok == tok_lc_address);
592           return;
593
594         default:
595         err_label:
596           SYNTAX_ERROR (_("%s: syntax error"), "LC_ADDRESS");
597         }
598
599       /* Prepare for the next round.  */
600       now = lr_token (ldfile, charmap, result, NULL, verbose);
601       nowtok = now->tok;
602     }
603
604   /* When we come here we reached the end of the file.  */
605   lr_error (ldfile, _("%s: premature end of file"), "LC_ADDRESS");
606 }