Back to index

glibc  2.9
ld-identification.c
Go to the documentation of this file.
00001 /* Copyright (C) 1998,1999,2000,2001,2002,2005 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 <error.h>
00024 #include <langinfo.h>
00025 #include <stdlib.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 /* The real definition of the struct for the LC_IDENTIFICATION locale.  */
00037 struct locale_identification_t
00038 {
00039   const char *title;
00040   const char *source;
00041   const char *address;
00042   const char *contact;
00043   const char *email;
00044   const char *tel;
00045   const char *fax;
00046   const char *language;
00047   const char *territory;
00048   const char *audience;
00049   const char *application;
00050   const char *abbreviation;
00051   const char *revision;
00052   const char *date;
00053   const char *category[__LC_LAST];
00054 };
00055 
00056 
00057 static const char *category_name[__LC_LAST] =
00058 {
00059   [LC_CTYPE] = "LC_CTYPE",
00060   [LC_NUMERIC] = "LC_NUMERIC",
00061   [LC_TIME] = "LC_TIME",
00062   [LC_COLLATE] = "LC_COLLATE",
00063   [LC_MONETARY] = "LC_MONETARY",
00064   [LC_MESSAGES] = "LC_MESSAGES",
00065   [LC_ALL] = "LC_ALL",
00066   [LC_PAPER] = "LC_PAPER",
00067   [LC_NAME] = "LC_NAME",
00068   [LC_ADDRESS] = "LC_ADDRESS",
00069   [LC_TELEPHONE] = "LC_TELEPHONE",
00070   [LC_MEASUREMENT] = "LC_MEASUREMENT",
00071   [LC_IDENTIFICATION] = "LC_IDENTIFICATION"
00072 };
00073 
00074 
00075 static void
00076 identification_startup (struct linereader *lr, struct localedef_t *locale,
00077                      int ignore_content)
00078 {
00079   if (!ignore_content)
00080     {
00081       locale->categories[LC_IDENTIFICATION].identification =
00082        (struct locale_identification_t *)
00083        xcalloc (1, sizeof (struct locale_identification_t));
00084 
00085       locale->categories[LC_IDENTIFICATION].identification->category[LC_ALL] =
00086        "";
00087     }
00088 
00089   if (lr != NULL)
00090     {
00091       lr->translate_strings = 1;
00092       lr->return_widestr = 0;
00093     }
00094 }
00095 
00096 
00097 void
00098 identification_finish (struct localedef_t *locale,
00099                      const struct charmap_t *charmap)
00100 {
00101   struct locale_identification_t *identification
00102     = locale->categories[LC_IDENTIFICATION].identification;
00103   int nothing = 0;
00104   size_t num;
00105 
00106   /* Now resolve copying and also handle completely missing definitions.  */
00107   if (identification == NULL)
00108     {
00109       /* First see whether we were supposed to copy.  If yes, find the
00110         actual definition.  */
00111       if (locale->copy_name[LC_IDENTIFICATION] != NULL)
00112        {
00113          /* Find the copying locale.  This has to happen transitively since
00114             the locale we are copying from might also copying another one.  */
00115          struct localedef_t *from = locale;
00116 
00117          do
00118            from = find_locale (LC_IDENTIFICATION,
00119                             from->copy_name[LC_IDENTIFICATION],
00120                             from->repertoire_name, charmap);
00121          while (from->categories[LC_IDENTIFICATION].identification == NULL
00122                && from->copy_name[LC_IDENTIFICATION] != NULL);
00123 
00124          identification = locale->categories[LC_IDENTIFICATION].identification
00125            = from->categories[LC_IDENTIFICATION].identification;
00126        }
00127 
00128       /* If there is still no definition issue an warning and create an
00129         empty one.  */
00130       if (identification == NULL)
00131        {
00132          if (! be_quiet)
00133            WITH_CUR_LOCALE (error (0, 0, _("\
00134 No definition for %s category found"), "LC_IDENTIFICATION"));
00135          identification_startup (NULL, locale, 0);
00136          identification
00137            = locale->categories[LC_IDENTIFICATION].identification;
00138          nothing = 1;
00139        }
00140     }
00141 
00142 #define TEST_ELEM(cat) \
00143   if (identification->cat == NULL)                                   \
00144     {                                                                \
00145       if (verbose && ! nothing)                                             \
00146        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),       \
00147                                    "LC_IDENTIFICATION", #cat));                    \
00148       identification->cat = "";                                             \
00149     }
00150 
00151   TEST_ELEM (title);
00152   TEST_ELEM (source);
00153   TEST_ELEM (address);
00154   TEST_ELEM (contact);
00155   TEST_ELEM (email);
00156   TEST_ELEM (tel);
00157   TEST_ELEM (fax);
00158   TEST_ELEM (language);
00159   TEST_ELEM (territory);
00160   TEST_ELEM (audience);
00161   TEST_ELEM (application);
00162   TEST_ELEM (abbreviation);
00163   TEST_ELEM (revision);
00164   TEST_ELEM (date);
00165 
00166   for (num = 0; num < __LC_LAST; ++num)
00167     if (num != LC_ALL && identification->category[num] == NULL)
00168       {
00169        if (verbose && ! nothing)
00170          WITH_CUR_LOCALE (error (0, 0, _("\
00171 %s: no identification for category `%s'"),
00172                               "LC_IDENTIFICATION", category_name[num]));
00173        identification->category[num] = "";
00174       }
00175 }
00176 
00177 
00178 void
00179 identification_output (struct localedef_t *locale,
00180                      const struct charmap_t *charmap,
00181                      const char *output_path)
00182 {
00183   struct locale_identification_t *identification
00184     = locale->categories[LC_IDENTIFICATION].identification;
00185   struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
00186                 + (__LC_LAST - 2)];
00187   struct locale_file data;
00188   uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)];
00189   size_t cnt = 0;
00190   size_t num;
00191   size_t last_idx;
00192 
00193   data.magic = LIMAGIC (LC_IDENTIFICATION);
00194   data.n = _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION);
00195   iov[cnt].iov_base = (void *) &data;
00196   iov[cnt].iov_len = sizeof (data);
00197   ++cnt;
00198 
00199   iov[cnt].iov_base = (void *) idx;
00200   iov[cnt].iov_len = sizeof (idx);
00201   ++cnt;
00202 
00203   idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
00204   iov[cnt].iov_base = (void *) identification->title;
00205   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00206   ++cnt;
00207 
00208   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00209   iov[cnt].iov_base = (void *) identification->source;
00210   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00211   ++cnt;
00212 
00213   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00214   iov[cnt].iov_base = (void *) identification->address;
00215   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00216   ++cnt;
00217 
00218   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00219   iov[cnt].iov_base = (void *) identification->contact;
00220   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00221   ++cnt;
00222 
00223   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00224   iov[cnt].iov_base = (void *) identification->email;
00225   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00226   ++cnt;
00227 
00228   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00229   iov[cnt].iov_base = (void *) identification->tel;
00230   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00231   ++cnt;
00232 
00233   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00234   iov[cnt].iov_base = (void *) identification->fax;
00235   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00236   ++cnt;
00237 
00238   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00239   iov[cnt].iov_base = (void *) identification->language;
00240   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00241   ++cnt;
00242 
00243   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00244   iov[cnt].iov_base = (void *) identification->territory;
00245   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00246   ++cnt;
00247 
00248   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00249   iov[cnt].iov_base = (void *) identification->audience;
00250   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00251   ++cnt;
00252 
00253   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00254   iov[cnt].iov_base = (void *) identification->application;
00255   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00256   ++cnt;
00257 
00258   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00259   iov[cnt].iov_base = (void *) identification->abbreviation;
00260   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00261   ++cnt;
00262 
00263   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00264   iov[cnt].iov_base = (void *) identification->revision;
00265   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00266   ++cnt;
00267 
00268   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00269   iov[cnt].iov_base = (void *) identification->date;
00270   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00271   ++cnt;
00272 
00273   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00274   last_idx = cnt - 1;
00275   idx[last_idx] = idx[cnt - 2];
00276   for (num = 0; num < __LC_LAST; ++num)
00277     if (num != LC_ALL)
00278       {
00279        iov[cnt].iov_base = (void *) identification->category[num];
00280        iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00281        idx[last_idx] += iov[cnt].iov_len;
00282        ++cnt;
00283       }
00284 
00285   assert (last_idx == _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION) - 1);
00286   iov[cnt].iov_base = (void *) charmap->code_set_name;
00287   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00288   ++cnt;
00289 
00290   assert (cnt == (2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
00291                 + (__LC_LAST - 2)));
00292 
00293   write_locale_data (output_path, LC_IDENTIFICATION, "LC_IDENTIFICATION", cnt,
00294                    iov);
00295 }
00296 
00297 
00298 /* The parser for the LC_IDENTIFICATION section of the locale definition.  */
00299 void
00300 identification_read (struct linereader *ldfile, struct localedef_t *result,
00301               const struct charmap_t *charmap, const char *repertoire_name,
00302               int ignore_content)
00303 {
00304   struct locale_identification_t *identification;
00305   struct token *now;
00306   struct token *arg;
00307   struct token *cattok;
00308   int category;
00309   enum token_t nowtok;
00310 
00311   /* The rest of the line containing `LC_IDENTIFICATION' must be free.  */
00312   lr_ignore_rest (ldfile, 1);
00313 
00314   do
00315     {
00316       now = lr_token (ldfile, charmap, result, NULL, verbose);
00317       nowtok = now->tok;
00318     }
00319   while (nowtok == tok_eol);
00320 
00321   /* If we see `copy' now we are almost done.  */
00322   if (nowtok == tok_copy)
00323     {
00324       handle_copy (ldfile, charmap, repertoire_name, result,
00325                  tok_lc_identification, LC_IDENTIFICATION,
00326                  "LC_IDENTIFICATION", ignore_content);
00327       return;
00328     }
00329 
00330   /* Prepare the data structures.  */
00331   identification_startup (ldfile, result, ignore_content);
00332   identification = result->categories[LC_IDENTIFICATION].identification;
00333 
00334   while (1)
00335     {
00336       /* Of course we don't proceed beyond the end of file.  */
00337       if (nowtok == tok_eof)
00338        break;
00339 
00340       /* Ignore empty lines.  */
00341       if (nowtok == tok_eol)
00342        {
00343          now = lr_token (ldfile, charmap, result, NULL, verbose);
00344          nowtok = now->tok;
00345          continue;
00346        }
00347 
00348       switch (nowtok)
00349        {
00350 #define STR_ELEM(cat) \
00351        case tok_##cat:                                                      \
00352          /* Ignore the rest of the line if we don't need the input of       \
00353             this line.  */                                           \
00354          if (ignore_content)                                                \
00355            {                                                         \
00356              lr_ignore_rest (ldfile, 0);                             \
00357              break;                                                  \
00358            }                                                         \
00359                                                                      \
00360          arg = lr_token (ldfile, charmap, result, NULL, verbose);           \
00361          if (arg->tok != tok_string)                                        \
00362            goto err_label;                                           \
00363          if (identification->cat != NULL)                            \
00364            lr_error (ldfile, _("\
00365 %s: field `%s' declared more than once"), "LC_IDENTIFICATION", #cat);       \
00366          else if (!ignore_content && arg->val.str.startmb == NULL)          \
00367            {                                                         \
00368              lr_error (ldfile, _("\
00369 %s: unknown character in field `%s'"), "LC_IDENTIFICATION", #cat);          \
00370              identification->cat = "";                                      \
00371            }                                                         \
00372          else if (!ignore_content)                                   \
00373            identification->cat = arg->val.str.startmb;                      \
00374          break
00375 
00376          STR_ELEM (title);
00377          STR_ELEM (source);
00378          STR_ELEM (address);
00379          STR_ELEM (contact);
00380          STR_ELEM (email);
00381          STR_ELEM (tel);
00382          STR_ELEM (fax);
00383          STR_ELEM (language);
00384          STR_ELEM (territory);
00385          STR_ELEM (audience);
00386          STR_ELEM (application);
00387          STR_ELEM (abbreviation);
00388          STR_ELEM (revision);
00389          STR_ELEM (date);
00390 
00391        case tok_category:
00392          /* Ignore the rest of the line if we don't need the input of
00393             this line.  */
00394          if (ignore_content)
00395            {
00396              lr_ignore_rest (ldfile, 0);
00397              break;
00398            }
00399 
00400          /* We expect two operands.  */
00401          arg = lr_token (ldfile, charmap, result, NULL, verbose);
00402          if (arg->tok != tok_string && arg->tok != tok_ident)
00403            goto err_label;
00404          /* Next is a semicolon.  */
00405          cattok = lr_token (ldfile, charmap, result, NULL, verbose);
00406          if (cattok->tok != tok_semicolon)
00407            goto err_label;
00408          /* Now a LC_xxx identifier.  */
00409          cattok = lr_token (ldfile, charmap, result, NULL, verbose);
00410          switch (cattok->tok)
00411            {
00412 #define CATEGORY(lname, uname) \
00413            case tok_lc_##lname:                                      \
00414              category = LC_##uname;                                         \
00415              break
00416 
00417              CATEGORY (identification, IDENTIFICATION);
00418              CATEGORY (ctype, CTYPE);
00419              CATEGORY (collate, COLLATE);
00420              CATEGORY (time, TIME);
00421              CATEGORY (numeric, NUMERIC);
00422              CATEGORY (monetary, MONETARY);
00423              CATEGORY (messages, MESSAGES);
00424              CATEGORY (paper, PAPER);
00425              CATEGORY (name, NAME);
00426              CATEGORY (address, ADDRESS);
00427              CATEGORY (telephone, TELEPHONE);
00428              CATEGORY (measurement, MEASUREMENT);
00429 
00430            default:
00431              goto err_label;
00432            }
00433          if (identification->category[category] != NULL)
00434            {
00435              lr_error (ldfile, _("\
00436 %s: duplicate category version definition"), "LC_IDENTIFICATION");
00437              free (arg->val.str.startmb);
00438            }
00439          else
00440            identification->category[category] = arg->val.str.startmb;
00441          break;
00442 
00443        case tok_end:
00444          /* Next we assume `LC_IDENTIFICATION'.  */
00445          arg = lr_token (ldfile, charmap, result, NULL, verbose);
00446          if (arg->tok == tok_eof)
00447            break;
00448          if (arg->tok == tok_eol)
00449            lr_error (ldfile, _("%s: incomplete `END' line"),
00450                     "LC_IDENTIFICATION");
00451          else if (arg->tok != tok_lc_identification)
00452            lr_error (ldfile, _("\
00453 %1$s: definition does not end with `END %1$s'"), "LC_IDENTIFICATION");
00454          lr_ignore_rest (ldfile, arg->tok == tok_lc_identification);
00455          return;
00456 
00457        default:
00458        err_label:
00459          SYNTAX_ERROR (_("%s: syntax error"), "LC_IDENTIFICATION");
00460        }
00461 
00462       /* Prepare for the next round.  */
00463       now = lr_token (ldfile, charmap, result, NULL, verbose);
00464       nowtok = now->tok;
00465     }
00466 
00467   /* When we come here we reached the end of the file.  */
00468   lr_error (ldfile, _("%s: premature end of file"), "LC_IDENTIFICATION");
00469 }