]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - locale/programs/linereader.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / locale / programs / linereader.c
index f6532a479284d30fecf7d509374288920c0212ef..2e051301616e7821e31c6ba614af265bc1f01843 100644 (file)
@@ -1,38 +1,38 @@
-/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
 
-   The GNU C Library is distributed in the hope that it will be useful,
+   This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <libintl.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 
+#include "localedef.h"
 #include "charmap.h"
 #include "error.h"
 #include "linereader.h"
-#include "localedef.h"
-
+#include "locfile.h"
 
 /* Prototypes for local functions.  */
 static struct token *get_toplvl_escape (struct linereader *lr);
@@ -40,30 +40,38 @@ static struct token *get_symname (struct linereader *lr);
 static struct token *get_ident (struct linereader *lr);
 static struct token *get_string (struct linereader *lr,
                                 const struct charmap_t *charmap,
-                                const struct repertoire_t *repertoire);
+                                struct localedef_t *locale,
+                                const struct repertoire_t *repertoire,
+                                int verbose);
 
 
 struct linereader *
 lr_open (const char *fname, kw_hash_fct_t hf)
 {
   FILE *fp;
-  struct linereader *result;
-  int n;
 
   if (fname == NULL || strcmp (fname, "-") == 0
       || strcmp (fname, "/dev/stdin") == 0)
-    fp = stdin;
+    return lr_create (stdin, "<stdin>", hf);
   else
     {
-      fp = fopen (fname, "r");
+      fp = fopen (fname, "rm");
       if (fp == NULL)
        return NULL;
+      return lr_create (fp, fname, hf);
     }
+}
+
+struct linereader *
+lr_create (FILE *fp, const char *fname, kw_hash_fct_t hf)
+{
+  struct linereader *result;
+  int n;
 
   result = (struct linereader *) xmalloc (sizeof (*result));
 
   result->fp = fp;
-  result->fname = xstrdup (fname ? : "<stdin>");
+  result->fname = xstrdup (fname);
   result->buf = NULL;
   result->bufsize = 0;
   result->lineno = 1;
@@ -71,6 +79,7 @@ lr_open (const char *fname, kw_hash_fct_t hf)
   result->comment_char = '#';
   result->escape_char = '\\';
   result->translate_strings = 1;
+  result->return_widestr = 0;
 
   n = getdelim (&result->buf, &result->bufsize, '\n', result->fp);
   if (n < 0)
@@ -101,6 +110,35 @@ lr_eof (struct linereader *lr)
 }
 
 
+void
+lr_ignore_rest (struct linereader *lr, int verbose)
+{
+  if (verbose)
+    {
+      while (isspace (lr->buf[lr->idx]) && lr->buf[lr->idx] != '\n'
+            && lr->buf[lr->idx] != lr->comment_char)
+       if (lr->buf[lr->idx] == '\0')
+         {
+           if (lr_next (lr) < 0)
+             return;
+         }
+       else
+         ++lr->idx;
+
+      if (lr->buf[lr->idx] != '\n' && ! feof (lr->fp)
+         && lr->buf[lr->idx] != lr->comment_char)
+       lr_error (lr, _("trailing garbage at end of line"));
+    }
+
+  /* Ignore continued line.  */
+  while (lr->bufact > 0 && lr->buf[lr->bufact - 1] != '\n')
+    if (lr_next (lr) < 0)
+      break;
+
+  lr->idx = lr->bufact;
+}
+
+
 void
 lr_close (struct linereader *lr)
 {
@@ -152,7 +190,8 @@ extern char *program_name;
 
 struct token *
 lr_token (struct linereader *lr, const struct charmap_t *charmap,
-         const struct repertoire_t *repertoire)
+         struct localedef_t *locale, const struct repertoire_t *repertoire,
+         int verbose)
 {
   int ch;
 
@@ -176,15 +215,19 @@ lr_token (struct linereader *lr, const struct charmap_t *charmap,
        }
       while (isspace (ch));
 
-      if (ch == EOF)
-       {
-         lr->token.tok = tok_eof;
-         return &lr->token;
-       };
-
       if (ch != lr->comment_char)
        break;
 
+      /* Is there an newline at the end of the buffer?  */
+      if (lr->buf[lr->bufact - 1] != '\n')
+       {
+         /* No.  Some people want this to mean that only the line in
+            the file not the logical, concatenated line is ignored.
+            Let's try this.  */
+         lr->idx = lr->bufact;
+         continue;
+       }
+
       /* Ignore rest of line.  */
       lr_ignore_rest (lr, 0);
       lr->token.tok = tok_eol;
@@ -198,6 +241,14 @@ lr_token (struct linereader *lr, const struct charmap_t *charmap,
   /* Match ellipsis.  */
   if (ch == '.')
     {
+      if (strncmp (&lr->buf[lr->idx], "...(2)....", 10) == 0)
+       {
+         int cnt;
+         for (cnt = 0; cnt < 10; ++cnt)
+           lr_getc (lr);
+         lr->token.tok = tok_ellipsis4_2;
+         return &lr->token;
+       }
       if (strncmp (&lr->buf[lr->idx], "...", 3) == 0)
        {
          lr_getc (lr);
@@ -213,6 +264,14 @@ lr_token (struct linereader *lr, const struct charmap_t *charmap,
          lr->token.tok = tok_ellipsis3;
          return &lr->token;
        }
+      if (strncmp (&lr->buf[lr->idx], ".(2)..", 6) == 0)
+       {
+         int cnt;
+         for (cnt = 0; cnt < 6; ++cnt)
+           lr_getc (lr);
+         lr->token.tok = tok_ellipsis2_2;
+         return &lr->token;
+       }
       if (lr->buf[lr->idx] == '.')
        {
          lr_getc (lr);
@@ -258,7 +317,7 @@ lr_token (struct linereader *lr, const struct charmap_t *charmap,
       return &lr->token;
 
     case '"':
-      return get_string (lr, charmap, repertoire);
+      return get_string (lr, charmap, locale, repertoire, verbose);
 
     case '-':
       ch = lr_getc (lr);
@@ -281,8 +340,8 @@ get_toplvl_escape (struct linereader *lr)
   /* This is supposed to be a numeric value.  We return the
      numerical value and the number of bytes.  */
   size_t start_idx = lr->idx - 1;
-  char *bytes = lr->token.val.charcode.bytes;
-  int nbytes = 0;
+  unsigned char *bytes = lr->token.val.charcode.bytes;
+  size_t nbytes = 0;
   int ch;
 
   do
@@ -344,7 +403,8 @@ get_toplvl_escape (struct linereader *lr)
 
       bytes[nbytes++] = byte;
     }
-  while (ch == lr->escape_char && nbytes < 4);
+  while (ch == lr->escape_char
+        && nbytes < (int) sizeof (lr->token.val.charcode.bytes));
 
   if (!isspace (ch))
     lr_error (lr, _("garbage at end of character code specification"));
@@ -464,8 +524,8 @@ get_symname (struct linereader *lr)
     {
       lr->token.tok = tok_bsymbol;
 
-      buf[bufact] = '\0';
       buf = xrealloc (buf, bufact + 1);
+      buf[bufact] = '\0';
 
       lr->token.val.str.startmb = buf;
       lr->token.val.str.lenmb = bufact - 1;
@@ -490,7 +550,7 @@ get_ident (struct linereader *lr)
   ADDC (lr->buf[lr->idx - 1]);
 
   while (!isspace ((ch = lr_getc (lr))) && ch != '"' && ch != ';'
-        && ch != '<' && ch != ',')
+        && ch != '<' && ch != ',' && ch != EOF)
     {
       if (ch == lr->escape_char)
        {
@@ -504,7 +564,7 @@ get_ident (struct linereader *lr)
       ADDC (ch);
     }
 
-  lr_ungetn (lr, 1);
+  lr_ungetc (lr, ch);
 
   kw = lr->hash_fct (buf, bufact);
 
@@ -517,8 +577,8 @@ get_ident (struct linereader *lr)
     {
       lr->token.tok = tok_ident;
 
-      buf[bufact] = '\0';
       buf = xrealloc (buf, bufact + 1);
+      buf[bufact] = '\0';
 
       lr->token.val.str.startmb = buf;
       lr->token.val.str.lenmb = bufact;
@@ -530,7 +590,8 @@ get_ident (struct linereader *lr)
 
 static struct token *
 get_string (struct linereader *lr, const struct charmap_t *charmap,
-           const struct repertoire_t *repertoire)
+           struct localedef_t *locale, const struct repertoire_t *repertoire,
+           int verbose)
 {
   int return_widestr = lr->return_widestr;
   char *buf;
@@ -652,7 +713,6 @@ non-symbolic character value should not be used"));
              if (cp == &buf[bufact])
                {
                  char utmp[10];
-                 const char *symbol = NULL;
 
                  /* Yes, it is.  */
                  ADDC ('\0');
@@ -674,32 +734,65 @@ non-symbolic character value should not be used"));
                        the repertoire the name of the character and
                        find it in the charmap.  */
                      if (repertoire != NULL)
-                       symbol = repertoire_find_symbol (repertoire, wch);
-
-                     if (symbol == NULL)
                        {
-                         /* We cannot generate a string since we
-                            cannot map from the Unicode number to the
-                            character symbol.  */
-                         lr_error (lr, _("\
-character <U%0*X> not in repertoire map"),
-                                   wch > 0xffff ? 8 : 4, wch);
+                         const char *symbol;
 
-                         illegal_string = 1;
+                         symbol = repertoire_find_symbol (repertoire, wch);
+
+                         if (symbol != NULL)
+                           seq = charmap_find_value (charmap, symbol,
+                                                     strlen (symbol));
                        }
-                     else
-                       {
-                         seq = charmap_find_value (charmap, symbol,
-                                                   strlen (symbol));
 
-                         if (seq == NULL)
+                     if (seq == NULL)
+                       {
+#ifndef NO_TRANSLITERATION
+                         /* Transliterate if possible.  */
+                         if (locale != NULL)
                            {
-                             /* Not a known name.  */
-                             lr_error (lr,
-                                       _("symbol `%s' not in charmap"),
-                                       symbol);
-                             illegal_string = 1;
+                             uint32_t *translit;
+
+                             if ((locale->avail & CTYPE_LOCALE) == 0)
+                               {
+                                 /* Load the CTYPE data now.  */
+                                 int old_needed = locale->needed;
+
+                                 locale->needed = 0;
+                                 locale = load_locale (LC_CTYPE,
+                                                       locale->name,
+                                                       locale->repertoire_name,
+                                                       charmap, locale);
+                                 locale->needed = old_needed;
+                               }
+
+                             if ((locale->avail & CTYPE_LOCALE) != 0
+                                 && ((translit = find_translit (locale,
+                                                                charmap, wch))
+                                     != NULL))
+                               /* The CTYPE data contains a matching
+                                  transliteration.  */
+                               {
+                                 int i;
+
+                                 for (i = 0; translit[i] != 0; ++i)
+                                   {
+                                     char utmp[10];
+
+                                     snprintf (utmp, sizeof (utmp), "U%08X",
+                                               translit[i]);
+                                     seq = charmap_find_value (charmap, utmp,
+                                                               9);
+                                     assert (seq != NULL);
+                                     ADDS (seq->bytes, seq->nbytes);
+                                   }
+
+                                 continue;
+                               }
                            }
+#endif /* NO_TRANSLITERATION */
+
+                         /* Not a known name.  */
+                         illegal_string = 1;
                        }
                    }
 
@@ -766,10 +859,11 @@ character <U%0*X> not in repertoire map"),
       if (illegal_string)
        {
          free (buf);
-         if (buf2 != NULL)
-           free (buf2);
+         free (buf2);
          lr->token.val.str.startmb = NULL;
          lr->token.val.str.lenmb = 0;
+         lr->token.val.str.startwc = NULL;
+         lr->token.val.str.lenwc = 0;
 
          return &lr->token;
        }