Back to index

glibc  2.9
ld-telephone.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 <string.h>
00026 #include <sys/uio.h>
00027 
00028 #include <assert.h>
00029 
00030 #include "localedef.h"
00031 #include "localeinfo.h"
00032 #include "locfile.h"
00033 
00034 
00035 /* The real definition of the struct for the LC_TELEPHONE locale.  */
00036 struct locale_telephone_t
00037 {
00038   const char *tel_int_fmt;
00039   const char *tel_dom_fmt;
00040   const char *int_select;
00041   const char *int_prefix;
00042 };
00043 
00044 
00045 static void
00046 telephone_startup (struct linereader *lr, struct localedef_t *locale,
00047                  int ignore_content)
00048 {
00049   if (!ignore_content)
00050     locale->categories[LC_TELEPHONE].telephone = (struct locale_telephone_t *)
00051       xcalloc (1, sizeof (struct locale_telephone_t));
00052 
00053   if (lr != NULL)
00054     {
00055       lr->translate_strings = 1;
00056       lr->return_widestr = 0;
00057     }
00058 }
00059 
00060 
00061 void
00062 telephone_finish (struct localedef_t *locale, const struct charmap_t *charmap)
00063 {
00064   struct locale_telephone_t *telephone =
00065     locale->categories[LC_TELEPHONE].telephone;
00066   int nothing = 0;
00067 
00068   /* Now resolve copying and also handle completely missing definitions.  */
00069   if (telephone == NULL)
00070     {
00071       /* First see whether we were supposed to copy.  If yes, find the
00072         actual definition.  */
00073       if (locale->copy_name[LC_TELEPHONE] != NULL)
00074        {
00075          /* Find the copying locale.  This has to happen transitively since
00076             the locale we are copying from might also copying another one.  */
00077          struct localedef_t *from = locale;
00078 
00079          do
00080            from = find_locale (LC_TELEPHONE, from->copy_name[LC_TELEPHONE],
00081                             from->repertoire_name, charmap);
00082          while (from->categories[LC_TELEPHONE].telephone == NULL
00083                && from->copy_name[LC_TELEPHONE] != NULL);
00084 
00085          telephone = locale->categories[LC_TELEPHONE].telephone
00086            = from->categories[LC_TELEPHONE].telephone;
00087        }
00088 
00089       /* If there is still no definition issue an warning and create an
00090         empty one.  */
00091       if (telephone == NULL)
00092        {
00093          if (! be_quiet)
00094            WITH_CUR_LOCALE (error (0, 0, _("\
00095 No definition for %s category found"), "LC_TELEPHONE"));
00096          telephone_startup (NULL, locale, 0);
00097          telephone = locale->categories[LC_TELEPHONE].telephone;
00098          nothing = 1;
00099        }
00100     }
00101 
00102   if (telephone->tel_int_fmt == NULL)
00103     {
00104       if (! nothing)
00105        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
00106                             "LC_TELEPHONE", "tel_int_fmt"));
00107       /* Use as the default value the value of the i18n locale.  */
00108       telephone->tel_int_fmt = "+%c %a %l";
00109     }
00110   else
00111     {
00112       /* We must check whether the format string contains only the
00113         allowed escape sequences.  */
00114       const char *cp = telephone->tel_int_fmt;
00115 
00116       if (*cp == '\0')
00117        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
00118                             "LC_TELEPHONE", "tel_int_fmt"));
00119       else
00120        while (*cp != '\0')
00121          {
00122            if (*cp == '%')
00123              {
00124               if (strchr ("aAlc", *++cp) == NULL)
00125                 {
00126                   WITH_CUR_LOCALE (error (0, 0, _("\
00127 %s: invalid escape sequence in field `%s'"), "LC_TELEPHONE", "tel_int_fmt"));
00128                   break;
00129                 }
00130              }
00131            ++cp;
00132          }
00133     }
00134 
00135   if (telephone->tel_dom_fmt == NULL)
00136     telephone->tel_dom_fmt = "";
00137   else if (telephone->tel_dom_fmt[0] != '\0')
00138     {
00139       /* We must check whether the format string contains only the
00140         allowed escape sequences.  */
00141       const char *cp = telephone->tel_dom_fmt;
00142 
00143       while (*cp != '\0')
00144        {
00145          if (*cp == '%')
00146            {
00147              if (strchr ("aAlc", *++cp) == NULL)
00148               {
00149                 WITH_CUR_LOCALE (error (0, 0, _("\
00150 %s: invalid escape sequence in field `%s'"), "LC_TELEPHONE", "tel_dom_fmt"));
00151                 break;
00152               }
00153            }
00154          ++cp;
00155        }
00156     }
00157 
00158 #define TEST_ELEM(cat) \
00159   if (telephone->cat == NULL)                                               \
00160     {                                                                \
00161       if (verbose && ! nothing)                                             \
00162        WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),       \
00163                             "LC_TELEPHONE", #cat));                         \
00164       telephone->cat = "";                                           \
00165     }
00166 
00167   TEST_ELEM (int_select);
00168   TEST_ELEM (int_prefix);
00169 }
00170 
00171 
00172 void
00173 telephone_output (struct localedef_t *locale, const struct charmap_t *charmap,
00174                 const char *output_path)
00175 {
00176   struct locale_telephone_t *telephone =
00177     locale->categories[LC_TELEPHONE].telephone;
00178   struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)];
00179   struct locale_file data;
00180   uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)];
00181   size_t cnt = 0;
00182 
00183   data.magic = LIMAGIC (LC_TELEPHONE);
00184   data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE);
00185   iov[cnt].iov_base = (void *) &data;
00186   iov[cnt].iov_len = sizeof (data);
00187   ++cnt;
00188 
00189   iov[cnt].iov_base = (void *) idx;
00190   iov[cnt].iov_len = sizeof (idx);
00191   ++cnt;
00192 
00193   idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
00194   iov[cnt].iov_base = (void *) telephone->tel_int_fmt;
00195   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00196   ++cnt;
00197 
00198   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00199   iov[cnt].iov_base = (void *) telephone->tel_dom_fmt;
00200   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00201   ++cnt;
00202 
00203   idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
00204   iov[cnt].iov_base = (void *) telephone->int_select;
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 *) telephone->int_prefix;
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 *) charmap->code_set_name;;
00215   iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
00216   ++cnt;
00217 
00218   assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE));
00219 
00220   write_locale_data (output_path, LC_TELEPHONE, "LC_TELEPHONE",
00221                    2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE), iov);
00222 }
00223 
00224 
00225 /* The parser for the LC_TELEPHONE section of the locale definition.  */
00226 void
00227 telephone_read (struct linereader *ldfile, struct localedef_t *result,
00228               const struct charmap_t *charmap, const char *repertoire_name,
00229               int ignore_content)
00230 {
00231   struct locale_telephone_t *telephone;
00232   struct token *now;
00233   struct token *arg;
00234   enum token_t nowtok;
00235 
00236   /* The rest of the line containing `LC_TELEPHONE' must be free.  */
00237   lr_ignore_rest (ldfile, 1);
00238 
00239   do
00240     {
00241       now = lr_token (ldfile, charmap, result, NULL, verbose);
00242       nowtok = now->tok;
00243     }
00244   while (nowtok == tok_eol);
00245 
00246   /* If we see `copy' now we are almost done.  */
00247   if (nowtok == tok_copy)
00248     {
00249       handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_telephone,
00250                  LC_TELEPHONE, "LC_TELEPHONE", ignore_content);
00251       return;
00252     }
00253 
00254   /* Prepare the data structures.  */
00255   telephone_startup (ldfile, result, ignore_content);
00256   telephone = result->categories[LC_TELEPHONE].telephone;
00257 
00258   while (1)
00259     {
00260       /* Of course we don't proceed beyond the end of file.  */
00261       if (nowtok == tok_eof)
00262        break;
00263 
00264       /* Ingore empty lines.  */
00265       if (nowtok == tok_eol)
00266        {
00267          now = lr_token (ldfile, charmap, result, NULL, verbose);
00268          nowtok = now->tok;
00269          continue;
00270        }
00271 
00272       switch (nowtok)
00273        {
00274 #define STR_ELEM(cat) \
00275        case tok_##cat:                                                      \
00276          /* Ignore the rest of the line if we don't need the input of       \
00277             this line.  */                                           \
00278          if (ignore_content)                                                \
00279            {                                                         \
00280              lr_ignore_rest (ldfile, 0);                             \
00281              break;                                                  \
00282            }                                                         \
00283                                                                      \
00284          arg = lr_token (ldfile, charmap, result, NULL, verbose);           \
00285          if (arg->tok != tok_string)                                        \
00286            goto err_label;                                           \
00287          if (telephone->cat != NULL)                                        \
00288            lr_error (ldfile, _("%s: field `%s' declared more than once"),    \
00289                     "LC_TELEPHONE", #cat);                                  \
00290          else if (!ignore_content && arg->val.str.startmb == NULL)          \
00291            {                                                         \
00292              lr_error (ldfile, _("%s: unknown character in field `%s'"),     \
00293                      "LC_TELEPHONE", #cat);                                 \
00294              telephone->cat = "";                                    \
00295            }                                                         \
00296          else if (!ignore_content)                                   \
00297            telephone->cat = arg->val.str.startmb;                           \
00298          break
00299 
00300          STR_ELEM (tel_int_fmt);
00301          STR_ELEM (tel_dom_fmt);
00302          STR_ELEM (int_select);
00303          STR_ELEM (int_prefix);
00304 
00305        case tok_end:
00306          /* Next we assume `LC_TELEPHONE'.  */
00307          arg = lr_token (ldfile, charmap, result, NULL, verbose);
00308          if (arg->tok == tok_eof)
00309            break;
00310          if (arg->tok == tok_eol)
00311            lr_error (ldfile, _("%s: incomplete `END' line"), "LC_TELEPHONE");
00312          else if (arg->tok != tok_lc_telephone)
00313            lr_error (ldfile, _("\
00314 %1$s: definition does not end with `END %1$s'"), "LC_TELEPHONE");
00315          lr_ignore_rest (ldfile, arg->tok == tok_lc_telephone);
00316          return;
00317 
00318        default:
00319        err_label:
00320          SYNTAX_ERROR (_("%s: syntax error"), "LC_TELEPHONE");
00321        }
00322 
00323       /* Prepare for the next round.  */
00324       now = lr_token (ldfile, charmap, result, NULL, verbose);
00325       nowtok = now->tok;
00326     }
00327 
00328   /* When we come here we reached the end of the file.  */
00329   lr_error (ldfile, _("%s: premature end of file"), "LC_TELEPHONE");
00330 }