Back to index

glibc  2.9
ld-address.c
Go to the documentation of this file.
00001 /* Copyright (C) 1998-2002, 2005, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published
00007    by the Free Software Foundation; version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software Foundation,
00017    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022 
00023 #include <byteswap.h>
00024 #include <error.h>
00025 #include <langinfo.h>
00026 #include <string.h>
00027 #include <sys/uio.h>
00028 
00029 #include <assert.h>
00030 
00031 #include "localedef.h"
00032 #include "localeinfo.h"
00033 #include "locfile.h"
00034 
00035 
00036 static struct
00037 {
00038   const char ab2[3];
00039   const char ab3[4];
00040   uint32_t num;
00041 } iso3166[] =
00042 {
00043 #define DEFINE_COUNTRY_CODE(Name, Ab2, Ab3, Num) \
00044   { #Ab2, #Ab3, Num },
00045 #include "iso-3166.def"
00046 };
00047 
00048 
00049 static struct
00050 {
00051   const char ab[3];
00052   const char term[4];
00053   const char lib[4];
00054 } iso639[] =
00055 {
00056 #define DEFINE_LANGUAGE_CODE(Name, Ab, Term, Lib) \
00057   { #Ab, #Term, #Lib },
00058 #define DEFINE_LANGUAGE_CODE3(Name, Term, Lib) \
00059   { "", #Term, #Lib },
00060 #include "iso-639.def"
00061 };
00062 
00063 
00064 /* The real definition of the struct for the LC_ADDRESS locale.  */
00065 struct locale_address_t
00066 {
00067   const char *postal_fmt;
00068   const char *country_name;
00069   const char *country_post;
00070   const char *country_ab2;
00071   const char *country_ab3;
00072   uint32_t country_num;
00073   const char *country_car;
00074   const char *country_isbn;
00075   const char *lang_name;
00076   const char *lang_ab;
00077   const char *lang_term;
00078   const char *lang_lib;
00079 };
00080 
00081 
00082 static void
00083 address_startup (struct linereader *lr, struct localedef_t *locale,
00084                int ignore_content)
00085 {
00086   if (!ignore_content)
00087     locale->categories[LC_ADDRESS].address =
00088       (struct locale_address_t *) xcalloc (1,
00089                                       sizeof (struct locale_address_t));
00090 
00091   if (lr != NULL)
00092     {
00093       lr->translate_strings = 1;
00094       lr->return_widestr = 0;
00095     }
00096 }
00097 
00098 
00099 void
00100 address_finish (struct localedef_t *locale, const struct charmap_t *charmap)
00101 {
00102   struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
00103   size_t cnt;
00104   int helper;
00105   int nothing = 0;
00106 
00107   /* Now resolve copying and also handle completely missing definitions.  */
00108   if (address == NULL)
00109     {
00110       /* First see whether we were supposed to copy.  If yes, find the
00111         actual definition.  */
00112       if (locale->copy_name[LC_ADDRESS] != NULL)
00113        {
00114          /* Find the copying locale.  This has to happen transitively since
00115             the locale we are copying from might also copying another one.  */
00116          struct localedef_t *from = locale;
00117 
00118          do
00119            from = find_locale (LC_ADDRESS, from->copy_name[LC_ADDRESS],
00120                             from->repertoire_name, charmap);
00121          while (from->categories[LC_ADDRESS].address == NULL
00122                && from->copy_name[LC_ADDRESS] != NULL);
00123 
00124          address = locale->categories[LC_ADDRESS].address
00125            = from->categories[LC_ADDRESS].address;
00126        }
00127 
00128       /* If there is still no definition issue an warning and create an
00129         empty one.  */
00130       if (address == NULL)
00131        {
00132          if (! be_quiet)
00133            WITH_CUR_LOCALE (error (0, 0, _("\
00134 No definition for %s category found"), "LC_ADDRESS"));
00135          address_startup (NULL, locale, 0);
00136          address = locale->categories[LC_ADDRESS].address;
00137          nothing = 1;
00138        }
00139     }
00140 
00141   if (address->postal_fmt == NULL)
00142     {
00143       if (! nothing)
00144        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00145                             "LC_ADDRESS", "postal_fmt"));
00146       /* Use as the default value the value of the i18n locale.  */
00147       address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N";
00148     }
00149   else
00150     {
00151       /* We must check whether the format string contains only the
00152         allowed escape sequences.  */
00153       const char *cp = address->postal_fmt;
00154 
00155       if (*cp == '\0')
00156        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
00157                             "LC_ADDRESS", "postal_fmt"));
00158       else
00159        while (*cp != '\0')
00160          {
00161            if (*cp == '%')
00162              {
00163               if (*++cp == 'R')
00164                 /* Romanize-flag.  */
00165                 ++cp;
00166               if (strchr ("afdbshNtreCzTSc%", *cp) == NULL)
00167                 {
00168                   WITH_CUR_LOCALE (error (0, 0, _("\
00169 %s: invalid escape `%%%c' sequence in field `%s'"),
00170                                        "LC_ADDRESS", *cp, "postal_fmt"));
00171                   break;
00172                 }
00173              }
00174            ++cp;
00175          }
00176     }
00177 
00178 #define TEST_ELEM(cat) \
00179   if (address->cat == NULL)                                          \
00180     {                                                                \
00181       if (verbose && ! nothing)                                             \
00182        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),       \
00183                             "LC_ADDRESS", #cat));                           \
00184       address->cat = "";                                             \
00185     }
00186 
00187   TEST_ELEM (country_name);
00188   /* XXX Test against list of defined codes.  */
00189   TEST_ELEM (country_post);
00190   /* XXX Test against list of defined codes.  */
00191   TEST_ELEM (country_car);
00192   /* XXX Test against list of defined codes.  */
00193   TEST_ELEM (country_isbn);
00194   TEST_ELEM (lang_name);
00195 
00196   helper = 1;
00197   if (address->lang_term == NULL)
00198     {
00199       if (verbose && ! nothing)
00200        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00201                             "LC_ADDRESS", "lang_term"));
00202       address->lang_term = "";
00203       cnt = sizeof (iso639) / sizeof (iso639[0]);
00204     }
00205   else if (address->lang_term[0] == '\0')
00206     {
00207       if (verbose)
00208        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
00209                             "LC_ADDRESS", "lang_term"));
00210       cnt = sizeof (iso639) / sizeof (iso639[0]);
00211     }
00212   else
00213     {
00214       /* Look for this language in the table.  */
00215       for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
00216        if (strcmp (address->lang_term, iso639[cnt].term) == 0)
00217          break;
00218       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
00219        WITH_CUR_LOCALE (error (0, 0, _("\
00220 %s: terminology language code `%s' not defined"),
00221                             "LC_ADDRESS", address->lang_term));
00222     }
00223 
00224   if (address->lang_ab == NULL)
00225     {
00226       if ((cnt == sizeof (iso639) / sizeof (iso639[0])
00227           || iso639[cnt].ab[0] != '\0')
00228          && verbose && ! nothing)
00229        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00230                             "LC_ADDRESS", "lang_ab"));
00231       address->lang_ab = "";
00232     }
00233   else if (address->lang_ab[0] == '\0')
00234     {
00235       if ((cnt == sizeof (iso639) / sizeof (iso639[0])
00236           || iso639[cnt].ab[0] != '\0')
00237          && verbose)
00238        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
00239                             "LC_ADDRESS", "lang_ab"));
00240     }
00241   else if (cnt < sizeof (iso639) / sizeof (iso639[0])
00242           && iso639[cnt].ab[0] == '\0')
00243     {
00244       WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be defined"),
00245                            "LC_ADDRESS", "lang_ab"));
00246 
00247       address->lang_ab = "";
00248     }
00249   else
00250     {
00251       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
00252        {
00253          helper = 2;
00254          for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
00255            if (strcmp (address->lang_ab, iso639[cnt].ab) == 0)
00256              break;
00257          if (cnt == sizeof (iso639) / sizeof (iso639[0]))
00258            WITH_CUR_LOCALE (error (0, 0, _("\
00259 %s: language abbreviation `%s' not defined"),
00260                                 "LC_ADDRESS", address->lang_ab));
00261        }
00262       else
00263        if (strcmp (iso639[cnt].ab, address->lang_ab) != 0
00264            && iso639[cnt].ab[0] != '\0')
00265          WITH_CUR_LOCALE (error (0, 0, _("\
00266 %s: `%s' value does not match `%s' value"),
00267                               "LC_ADDRESS", "lang_ab", "lang_term"));
00268     }
00269 
00270   if (address->lang_lib == NULL)
00271     /* This is no error.  */
00272     address->lang_lib = address->lang_term;
00273   else if (address->lang_lib[0] == '\0')
00274     {
00275       if (verbose)
00276        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
00277                             "LC_ADDRESS", "lang_lib"));
00278     }
00279   else
00280     {
00281       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
00282        {
00283          for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
00284            if (strcmp (address->lang_lib, iso639[cnt].lib) == 0)
00285              break;
00286          if (cnt == sizeof (iso639) / sizeof (iso639[0]))
00287            WITH_CUR_LOCALE (error (0, 0, _("\
00288 %s: language abbreviation `%s' not defined"),
00289                                 "LC_ADDRESS", address->lang_lib));
00290        }
00291       else
00292        if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
00293          WITH_CUR_LOCALE (error (0, 0, _("\
00294 %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib",
00295                               helper == 1 ? "lang_term" : "lang_ab"));
00296     }
00297 
00298   if (address->country_num == 0)
00299     {
00300       if (verbose && ! nothing)
00301        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00302                             "LC_ADDRESS", "country_num"));
00303       cnt = sizeof (iso3166) / sizeof (iso3166[0]);
00304     }
00305   else
00306     {
00307       for (cnt = 0; cnt < sizeof (iso3166) / sizeof (iso3166[0]); ++cnt)
00308        if (address->country_num == iso3166[cnt].num)
00309          break;
00310 
00311       if (cnt == sizeof (iso3166) / sizeof (iso3166[0]))
00312        WITH_CUR_LOCALE (error (0, 0, _("\
00313 %s: numeric country code `%d' not valid"),
00314                             "LC_ADDRESS", address->country_num));
00315     }
00316 
00317   if (address->country_ab2 == NULL)
00318     {
00319       if (verbose && ! nothing)
00320        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00321                             "LC_ADDRESS", "country_ab2"));
00322       address->country_ab2 = "  ";
00323     }
00324   else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
00325           && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0)
00326     WITH_CUR_LOCALE (error (0, 0,
00327                          _("%s: `%s' value does not match `%s' value"),
00328                          "LC_ADDRESS", "country_ab2", "country_num"));
00329 
00330   if (address->country_ab3 == NULL)
00331     {
00332       if (verbose && ! nothing)
00333        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00334                             "LC_ADDRESS", "country_ab3"));
00335       address->country_ab3 = "   ";
00336     }
00337   else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
00338           && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0)
00339     WITH_CUR_LOCALE (error (0, 0, _("\
00340 %s: `%s' value does not match `%s' value"),
00341                          "LC_ADDRESS", "country_ab3", "country_num"));
00342 }
00343 
00344 
00345 void
00346 address_output (struct localedef_t *locale, const struct charmap_t *charmap,
00347               const char *output_path)
00348 {
00349   struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
00350   struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
00351   struct locale_file data;
00352   uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
00353   size_t cnt = 0;
00354 
00355   data.magic = LIMAGIC (LC_ADDRESS);
00356   data.n = _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS);
00357   iov[cnt].iov_base = (void *) &data;
00358   iov[cnt].iov_len = sizeof (data);
00359   ++cnt;
00360 
00361   iov[cnt].iov_base = (void *) idx;
00362   iov[cnt].iov_len = sizeof (idx);
00363   ++cnt;
00364 
00365   idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
00366   iov[cnt].iov_base = (void *) address->postal_fmt;
00367   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00368   ++cnt;
00369 
00370   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00371   iov[cnt].iov_base = (void *) address->country_name;
00372   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00373   ++cnt;
00374 
00375   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00376   iov[cnt].iov_base = (void *) address->country_post;
00377   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00378   ++cnt;
00379 
00380   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00381   iov[cnt].iov_base = (void *) address->country_ab2;
00382   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00383   ++cnt;
00384 
00385   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00386   iov[cnt].iov_base = (void *) address->country_ab3;
00387   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00388   ++cnt;
00389 
00390   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00391   iov[cnt].iov_base = (void *) address->country_car;
00392   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00393   ++cnt;
00394 
00395   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00396 
00397   /* Align following data */
00398   iov[cnt].iov_base = (void *) "\0\0";
00399   iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
00400   idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
00401   ++cnt;
00402 
00403   iov[cnt].iov_base = (void *) &address->country_num;
00404   iov[cnt].iov_len = sizeof (uint32_t);
00405   ++cnt;
00406 
00407   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
00408   iov[cnt].iov_base = (void *) address->country_isbn;
00409   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00410   ++cnt;
00411 
00412   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
00413   iov[cnt].iov_base = (void *) address->lang_name;
00414   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00415   ++cnt;
00416 
00417   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
00418   iov[cnt].iov_base = (void *) address->lang_ab;
00419   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00420   ++cnt;
00421 
00422   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
00423   iov[cnt].iov_base = (void *) address->lang_term;
00424   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00425   ++cnt;
00426 
00427   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
00428   iov[cnt].iov_base = (void *) address->lang_lib;
00429   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00430   ++cnt;
00431 
00432   idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
00433   iov[cnt].iov_base = (void *) charmap->code_set_name;
00434   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00435   ++cnt;
00436 
00437   assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
00438 
00439   write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS",
00440                    3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS), iov);
00441 }
00442 
00443 
00444 /* The parser for the LC_ADDRESS section of the locale definition.  */
00445 void
00446 address_read (struct linereader *ldfile, struct localedef_t *result,
00447              const struct charmap_t *charmap, const char *repertoire_name,
00448              int ignore_content)
00449 {
00450   struct locale_address_t *address;
00451   struct token *now;
00452   struct token *arg;
00453   enum token_t nowtok;
00454 
00455   /* The rest of the line containing `LC_ADDRESS' must be free.  */
00456   lr_ignore_rest (ldfile, 1);
00457 
00458 
00459   do
00460     {
00461       now = lr_token (ldfile, charmap, result, NULL, verbose);
00462       nowtok = now->tok;
00463     }
00464   while (nowtok == tok_eol);
00465 
00466   /* If we see `copy' now we are almost done.  */
00467   if (nowtok == tok_copy)
00468     {
00469       handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_address,
00470                  LC_ADDRESS, "LC_ADDRESS", ignore_content);
00471       return;
00472     }
00473 
00474   /* Prepare the data structures.  */
00475   address_startup (ldfile, result, ignore_content);
00476   address = result->categories[LC_ADDRESS].address;
00477 
00478   while (1)
00479     {
00480       /* Of course we don't proceed beyond the end of file.  */
00481       if (nowtok == tok_eof)
00482        break;
00483 
00484       /* Ignore empty lines.  */
00485       if (nowtok == tok_eol)
00486        {
00487          now = lr_token (ldfile, charmap, result, NULL, verbose);
00488          nowtok = now->tok;
00489          continue;
00490        }
00491 
00492       switch (nowtok)
00493        {
00494 #define STR_ELEM(cat) \
00495        case tok_##cat:                                                      \
00496          /* Ignore the rest of the line if we don't need the input of       \
00497             this line.  */                                           \
00498          if (ignore_content)                                                \
00499            {                                                         \
00500              lr_ignore_rest (ldfile, 0);                             \
00501              break;                                                  \
00502            }                                                         \
00503                                                                      \
00504          arg = lr_token (ldfile, charmap, result, NULL, verbose);           \
00505          if (arg->tok != tok_string)                                        \
00506            goto err_label;                                           \
00507          if (address->cat != NULL)                                   \
00508            lr_error (ldfile, _("\
00509 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat);              \
00510          else if (!ignore_content && arg->val.str.startmb == NULL)          \
00511            {                                                         \
00512              lr_error (ldfile, _("\
00513 %s: unknown character in field `%s'"), "LC_ADDRESS", #cat);                 \
00514              address->cat = "";                                      \
00515            }                                                         \
00516          else if (!ignore_content)                                   \
00517            address->cat = arg->val.str.startmb;                      \
00518          break
00519 
00520          STR_ELEM (postal_fmt);
00521          STR_ELEM (country_name);
00522          STR_ELEM (country_post);
00523          STR_ELEM (country_ab2);
00524          STR_ELEM (country_ab3);
00525          STR_ELEM (country_car);
00526          STR_ELEM (lang_name);
00527          STR_ELEM (lang_ab);
00528          STR_ELEM (lang_term);
00529          STR_ELEM (lang_lib);
00530 
00531 #define INT_STR_ELEM(cat) \
00532        case tok_##cat:                                                      \
00533          /* Ignore the rest of the line if we don't need the input of       \
00534             this line.  */                                           \
00535          if (ignore_content)                                                \
00536            {                                                         \
00537              lr_ignore_rest (ldfile, 0);                             \
00538              break;                                                  \
00539            }                                                         \
00540                                                                      \
00541          arg = lr_token (ldfile, charmap, result, NULL, verbose);           \
00542          if (arg->tok != tok_string && arg->tok != tok_number)              \
00543            goto err_label;                                           \
00544          if (address->cat != NULL)                                   \
00545            lr_error (ldfile, _("\
00546 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat);              \
00547          else if (!ignore_content && arg->tok == tok_string                 \
00548                  && arg->val.str.startmb == NULL)                           \
00549            {                                                         \
00550              lr_error (ldfile, _("\
00551 %s: unknown character in field `%s'"), "LC_ADDRESS", #cat);                 \
00552              address->cat = "";                                      \
00553            }                                                         \
00554          else if (!ignore_content)                                   \
00555            {                                                         \
00556              if (arg->tok == tok_string)                             \
00557               address->cat = arg->val.str.startmb;                          \
00558              else                                                    \
00559               {                                                      \
00560                 char *numbuf = (char *) xmalloc (11);                       \
00561                 snprintf (numbuf, 11, "%ld", arg->val.num);                 \
00562                 address->cat = numbuf;                               \
00563               }                                                      \
00564            }                                                         \
00565          break
00566 
00567          INT_STR_ELEM (country_isbn);
00568 
00569 #define INT_ELEM(cat) \
00570        case tok_##cat:                                                      \
00571          /* Ignore the rest of the line if we don't need the input of       \
00572             this line.  */                                           \
00573          if (ignore_content)                                                \
00574            {                                                         \
00575              lr_ignore_rest (ldfile, 0);                             \
00576              break;                                                  \
00577            }                                                         \
00578                                                                      \
00579          arg = lr_token (ldfile, charmap, result, NULL, verbose);           \
00580          if (arg->tok != tok_number)                                        \
00581            goto err_label;                                           \
00582          else if (address->cat != 0)                                        \
00583            lr_error (ldfile, _("\
00584 %s: field `%s' declared more than once"), "LC_ADDRESS", #cat);              \
00585          else if (!ignore_content)                                   \
00586            address->cat = arg->val.num;                              \
00587          break
00588 
00589          INT_ELEM (country_num);
00590 
00591        case tok_end:
00592          /* Next we assume `LC_ADDRESS'.  */
00593          arg = lr_token (ldfile, charmap, result, NULL, verbose);
00594          if (arg->tok == tok_eof)
00595            break;
00596          if (arg->tok == tok_eol)
00597            lr_error (ldfile, _("%s: incomplete `END' line"),
00598                     "LC_ADDRESS");
00599          else if (arg->tok != tok_lc_address)
00600            lr_error (ldfile, _("\
00601 %1$s: definition does not end with `END %1$s'"), "LC_ADDRESS");
00602          lr_ignore_rest (ldfile, arg->tok == tok_lc_address);
00603          return;
00604 
00605        default:
00606        err_label:
00607          SYNTAX_ERROR (_("%s: syntax error"), "LC_ADDRESS");
00608        }
00609 
00610       /* Prepare for the next round.  */
00611       now = lr_token (ldfile, charmap, result, NULL, verbose);
00612       nowtok = now->tok;
00613     }
00614 
00615   /* When we come here we reached the end of the file.  */
00616   lr_error (ldfile, _("%s: premature end of file"), "LC_ADDRESS");
00617 }