1/* Input routines.
2   Copyright (C) 1989-1998, 2002-2004 Free Software Foundation, Inc.
3   Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
4   and Bruno Haible <bruno@clisp.org>.
5
6   This file is part of GNU GPERF.
7
8   GNU GPERF is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   GNU GPERF is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; see the file COPYING.
20   If not, write to the Free Software Foundation, Inc.,
21   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
22
23/* Specification. */
24#include "input.h"
25
26#include <stdio.h>
27#include <stdlib.h> /* declares exit() */
28#include <string.h> /* declares strncpy(), strchr() */
29#include <limits.h> /* defines UCHAR_MAX etc. */
30#include "options.h"
31#include "getline.h"
32
33Input::Input (FILE *stream, Keyword_Factory *keyword_factory)
34  : _stream (stream), _factory (keyword_factory)
35{
36}
37
38/* Returns a pretty representation of the input file name, for error and
39   warning messages.  */
40static const char *
41pretty_input_file_name ()
42{
43  if (option.get_input_file_name ())
44    return option.get_input_file_name ();
45  else
46    return "(standard input)";
47}
48
49/* Returns true if the given line contains a "%DECL" declaration.  */
50static bool
51is_declaration (const char *line, const char *line_end, unsigned int lineno,
52                const char *decl)
53{
54  /* Skip '%'.  */
55  line++;
56
57  /* Skip DECL.  */
58  for (const char *d = decl; *d; d++)
59    {
60      if (!(line < line_end))
61        return false;
62      if (!(*line == *d || (*d == '-' && *line == '_')))
63        return false;
64      line++;
65    }
66  if (line < line_end
67      && ((*line >= 'A' && *line <= 'Z')
68          || (*line >= 'a' && *line <= 'z')
69          || *line == '-' || *line == '_'))
70    return false;
71
72  /* OK, found DECL.  */
73
74  /* Skip whitespace.  */
75  while (line < line_end && (*line == ' ' || *line == '\t'))
76    line++;
77
78  /* Expect end of line.  */
79  if (line < line_end && *line != '\n')
80    {
81      fprintf (stderr, "%s:%u: junk after declaration\n",
82               pretty_input_file_name (), lineno);
83      exit (1);
84    }
85
86  return true;
87}
88
89/* Tests if the given line contains a "%DECL=ARG" declaration.
90   If yes, it sets *ARGP to the argument, and returns true.
91   Otherwise, it returns false.  */
92static bool
93is_declaration_with_arg (const char *line, const char *line_end,
94                         unsigned int lineno,
95                         const char *decl, char **argp)
96{
97  /* Skip '%'.  */
98  line++;
99
100  /* Skip DECL.  */
101  for (const char *d = decl; *d; d++)
102    {
103      if (!(line < line_end))
104        return false;
105      if (!(*line == *d || (*d == '-' && *line == '_')))
106        return false;
107      line++;
108    }
109  if (line < line_end
110      && ((*line >= 'A' && *line <= 'Z')
111          || (*line >= 'a' && *line <= 'z')
112          || *line == '-' || *line == '_'))
113    return false;
114
115  /* OK, found DECL.  */
116
117  /* Skip '='.  */
118  if (!(line < line_end && *line == '='))
119    {
120      fprintf (stderr, "%s:%u: missing argument in %%%s=ARG declaration.\n",
121               pretty_input_file_name (), lineno, decl);
122      exit (1);
123    }
124  line++;
125
126  /* The next word is the argument.  */
127  char *arg = new char[line_end - line + 1];
128  char *p = arg;
129  while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n'))
130    *p++ = *line++;
131  *p = '\0';
132
133  /* Skip whitespace.  */
134  while (line < line_end && (*line == ' ' || *line == '\t'))
135    line++;
136
137  /* Expect end of line.  */
138  if (line < line_end && *line != '\n')
139    {
140      fprintf (stderr, "%s:%u: junk after declaration\n",
141               pretty_input_file_name (), lineno);
142      exit (1);
143    }
144
145  *argp = arg;
146  return true;
147}
148
149/* Tests if the given line contains a "%define DECL ARG" declaration.
150   If yes, it sets *ARGP to the argument, and returns true.
151   Otherwise, it returns false.  */
152static bool
153is_define_declaration (const char *line, const char *line_end,
154                       unsigned int lineno,
155                       const char *decl, char **argp)
156{
157  /* Skip '%'.  */
158  line++;
159
160  /* Skip "define".  */
161  {
162    for (const char *d = "define"; *d; d++)
163      {
164        if (!(line < line_end))
165          return false;
166        if (!(*line == *d))
167          return false;
168        line++;
169      }
170    if (!(line < line_end && (*line == ' ' || *line == '\t')))
171      return false;
172  }
173
174  /* Skip whitespace.  */
175  while (line < line_end && (*line == ' ' || *line == '\t'))
176    line++;
177
178  /* Skip DECL.  */
179  for (const char *d = decl; *d; d++)
180    {
181      if (!(line < line_end))
182        return false;
183      if (!(*line == *d || (*d == '-' && *line == '_')))
184        return false;
185      line++;
186    }
187  if (line < line_end
188      && ((*line >= 'A' && *line <= 'Z')
189          || (*line >= 'a' && *line <= 'z')
190          || *line == '-' || *line == '_'))
191    return false;
192
193  /* OK, found DECL.  */
194
195  /* Skip whitespace.  */
196  if (!(line < line_end && (*line == ' ' || *line == '\t')))
197    {
198      fprintf (stderr, "%s:%u:"
199               " missing argument in %%define %s ARG declaration.\n",
200               pretty_input_file_name (), lineno, decl);
201      exit (1);
202    }
203  do
204    line++;
205  while (line < line_end && (*line == ' ' || *line == '\t'));
206
207  /* The next word is the argument.  */
208  char *arg = new char[line_end - line + 1];
209  char *p = arg;
210  while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n'))
211    *p++ = *line++;
212  *p = '\0';
213
214  /* Skip whitespace.  */
215  while (line < line_end && (*line == ' ' || *line == '\t'))
216    line++;
217
218  /* Expect end of line.  */
219  if (line < line_end && *line != '\n')
220    {
221      fprintf (stderr, "%s:%u: junk after declaration\n",
222               pretty_input_file_name (), lineno);
223      exit (1);
224    }
225
226  *argp = arg;
227  return true;
228}
229
230/* Reads the entire input file.  */
231void
232Input::read_input ()
233{
234  /* The input file has the following structure:
235        DECLARATIONS
236        %%
237        KEYWORDS
238        %%
239        ADDITIONAL_CODE
240     Since the DECLARATIONS and the ADDITIONAL_CODE sections are optional,
241     we have to read the entire file in the case there is only one %%
242     separator line, in order to determine whether the structure is
243        DECLARATIONS
244        %%
245        KEYWORDS
246     or
247        KEYWORDS
248        %%
249        ADDITIONAL_CODE
250     When the option -t is given or when the first section contains
251     declaration lines starting with %, we go for the first interpretation,
252     otherwise for the second interpretation.  */
253
254  char *input = NULL;
255  size_t input_size = 0;
256  int input_length = get_delim (&input, &input_size, EOF, _stream);
257  if (input_length < 0)
258    {
259      if (ferror (_stream))
260        fprintf (stderr, "%s: error while reading input file\n",
261                 pretty_input_file_name ());
262      else
263        fprintf (stderr, "%s: The input file is empty!\n",
264                 pretty_input_file_name ());
265      exit (1);
266    }
267
268  /* We use input_end as a limit, in order to cope with NUL bytes in the
269     input.  But note that one trailing NUL byte has been added after
270     input_end, for convenience.  */
271  char *input_end = input + input_length;
272
273  const char *declarations;
274  const char *declarations_end;
275  const char *keywords;
276  const char *keywords_end;
277  unsigned int keywords_lineno;
278
279  /* Break up the input into the three sections.  */
280  {
281    const char *separator[2] = { NULL, NULL };
282    unsigned int separator_lineno[2] = { 0, 0 };
283    int separators = 0;
284    {
285      unsigned int lineno = 1;
286      for (const char *p = input; p < input_end; )
287        {
288          if (p[0] == '%' && p[1] == '%')
289            {
290              separator[separators] = p;
291              separator_lineno[separators] = lineno;
292              if (++separators == 2)
293                break;
294            }
295          lineno++;
296          p = (const char *) memchr (p, '\n', input_end - p);
297          if (p != NULL)
298            p++;
299          else
300            p = input_end;
301        }
302    }
303
304    bool has_declarations;
305    if (separators == 1)
306      {
307        if (option[TYPE])
308          has_declarations = true;
309        else
310          {
311            has_declarations = false;
312            for (const char *p = input; p < separator[0]; )
313              {
314                if (p[0] == '%')
315                  {
316                    has_declarations = true;
317                    break;
318                  }
319                p = (const char *) memchr (p, '\n', separator[0] - p);
320                if (p != NULL)
321                  p++;
322                else
323                  p = separator[0];
324              }
325          }
326      }
327    else
328      has_declarations = (separators > 0);
329
330    if (has_declarations)
331      {
332        declarations = input;
333        declarations_end = separator[0];
334        /* Give a warning if the separator line is nonempty.  */
335        bool nonempty_line = false;
336        const char *p;
337        for (p = declarations_end + 2; p < input_end; )
338          {
339            if (*p == '\n')
340              {
341                p++;
342                break;
343              }
344            if (!(*p == ' ' || *p == '\t'))
345              nonempty_line = true;
346            p++;
347          }
348        if (nonempty_line)
349          fprintf (stderr, "%s:%u: warning: junk after %%%% is ignored\n",
350                   pretty_input_file_name (), separator_lineno[0]);
351        keywords = p;
352        keywords_lineno = separator_lineno[0] + 1;
353      }
354    else
355      {
356        declarations = NULL;
357        declarations_end = NULL;
358        keywords = input;
359        keywords_lineno = 1;
360      }
361
362    if (separators > (has_declarations ? 1 : 0))
363      {
364        keywords_end = separator[separators-1];
365        _verbatim_code = separator[separators-1] + 2;
366        _verbatim_code_end = input_end;
367        _verbatim_code_lineno = separator_lineno[separators-1];
368      }
369    else
370      {
371        keywords_end = input_end;
372        _verbatim_code = NULL;
373        _verbatim_code_end = NULL;
374        _verbatim_code_lineno = 0;
375      }
376  }
377
378  /* Parse the declarations section.  */
379
380  _verbatim_declarations = NULL;
381  _verbatim_declarations_end = NULL;
382  _verbatim_declarations_lineno = 0;
383  _struct_decl = NULL;
384  _struct_decl_lineno = 0;
385  _return_type = NULL;
386  _struct_tag = NULL;
387  {
388    unsigned int lineno = 1;
389    char *struct_decl = NULL;
390    unsigned int *struct_decl_linenos = NULL;
391    unsigned int struct_decl_linecount = 0;
392    for (const char *line = declarations; line < declarations_end; )
393      {
394        const char *line_end;
395        line_end = (const char *) memchr (line, '\n', declarations_end - line);
396        if (line_end != NULL)
397          line_end++;
398        else
399          line_end = declarations_end;
400
401        if (*line == '%')
402          {
403            if (line[1] == '{')
404              {
405                /* Handle %{.  */
406                if (_verbatim_declarations != NULL)
407                  {
408                    fprintf (stderr, "%s:%u:\n%s:%u:"
409                             " only one %%{...%%} section is allowed\n",
410                             pretty_input_file_name (),
411                             _verbatim_declarations_lineno,
412                             pretty_input_file_name (), lineno);
413                    exit (1);
414                  }
415                _verbatim_declarations = line + 2;
416                _verbatim_declarations_lineno = lineno;
417              }
418            else if (line[1] == '}')
419              {
420                /* Handle %}.  */
421                if (_verbatim_declarations == NULL)
422                  {
423                    fprintf (stderr, "%s:%u:"
424                             " %%} outside of %%{...%%} section\n",
425                             pretty_input_file_name (), lineno);
426                    exit (1);
427                  }
428                if (_verbatim_declarations_end != NULL)
429                  {
430                    fprintf (stderr, "%s:%u:"
431                             " %%{...%%} section already closed\n",
432                             pretty_input_file_name (), lineno);
433                    exit (1);
434                  }
435                _verbatim_declarations_end = line;
436                /* Give a warning if the rest of the line is nonempty.  */
437                bool nonempty_line = false;
438                const char *q;
439                for (q = line + 2; q < line_end; q++)
440                  {
441                    if (*q == '\n')
442                      {
443                        q++;
444                        break;
445                      }
446                    if (!(*q == ' ' || *q == '\t'))
447                      nonempty_line = true;
448                  }
449                if (nonempty_line)
450                  fprintf (stderr, "%s:%u:"
451                           " warning: junk after %%} is ignored\n",
452                           pretty_input_file_name (), lineno);
453              }
454            else if (_verbatim_declarations != NULL
455                     && _verbatim_declarations_end == NULL)
456              {
457                fprintf (stderr, "%s:%u:"
458                         " warning: %% directives are ignored"
459                         " inside the %%{...%%} section\n",
460                         pretty_input_file_name (), lineno);
461              }
462            else
463              {
464                char *arg;
465
466                if (is_declaration_with_arg (line, line_end, lineno,
467                                             "delimiters", &arg))
468                  option.set_delimiters (arg);
469                else
470
471                if (is_declaration (line, line_end, lineno, "struct-type"))
472                  option.set (TYPE);
473                else
474
475                if (is_declaration (line, line_end, lineno, "ignore-case"))
476                  option.set (UPPERLOWER);
477                else
478
479                if (is_declaration_with_arg (line, line_end, lineno,
480                                             "language", &arg))
481                  option.set_language (arg);
482                else
483
484                if (is_define_declaration (line, line_end, lineno,
485                                           "slot-name", &arg))
486                  option.set_slot_name (arg);
487                else
488
489                if (is_define_declaration (line, line_end, lineno,
490                                           "initializer-suffix", &arg))
491                  option.set_initializer_suffix (arg);
492                else
493
494                if (is_define_declaration (line, line_end, lineno,
495                                           "hash-function-name", &arg))
496                  option.set_hash_name (arg);
497                else
498
499                if (is_define_declaration (line, line_end, lineno,
500                                           "lookup-function-name", &arg))
501                  option.set_function_name (arg);
502                else
503
504                if (is_define_declaration (line, line_end, lineno,
505                                           "class-name", &arg))
506                  option.set_class_name (arg);
507                else
508
509                if (is_declaration (line, line_end, lineno, "7bit"))
510                  option.set (SEVENBIT);
511                else
512
513                if (is_declaration (line, line_end, lineno, "compare-lengths"))
514                  option.set (LENTABLE);
515                else
516
517                if (is_declaration (line, line_end, lineno, "compare-strncmp"))
518                  option.set (COMP);
519                else
520
521                if (is_declaration (line, line_end, lineno, "readonly-tables"))
522                  option.set (CONST);
523                else
524
525                if (is_declaration (line, line_end, lineno, "enum"))
526                  option.set (ENUM);
527                else
528
529                if (is_declaration (line, line_end, lineno, "includes"))
530                  option.set (INCLUDE);
531                else
532
533                if (is_declaration (line, line_end, lineno, "global-table"))
534                  option.set (GLOBAL);
535                else
536
537                if (is_declaration (line, line_end, lineno, "pic"))
538                  option.set (SHAREDLIB);
539                else
540
541                if (is_define_declaration (line, line_end, lineno,
542                                           "string-pool-name", &arg))
543                  option.set_stringpool_name (arg);
544                else
545
546                if (is_declaration (line, line_end, lineno, "null-strings"))
547                  option.set (NULLSTRINGS);
548                else
549
550                if (is_define_declaration (line, line_end, lineno,
551                                           "word-array-name", &arg))
552                  option.set_wordlist_name (arg);
553                else
554
555                if (is_define_declaration (line, line_end, lineno,
556                                           "length-table-name", &arg))
557                  option.set_lengthtable_name (arg);
558                else
559
560                if (is_declaration_with_arg (line, line_end, lineno,
561                                             "switch", &arg))
562                  {
563                    option.set_total_switches (atoi (arg));
564                    if (option.get_total_switches () <= 0)
565                      {
566                        fprintf (stderr, "%s:%u: number of switches %s"
567                                 " must be a positive number\n",
568                                 pretty_input_file_name (), lineno, arg);
569                        exit (1);
570                      }
571                  }
572                else
573
574                if (is_declaration (line, line_end, lineno, "omit-struct-type"))
575                  option.set (NOTYPE);
576                else
577
578                  {
579                    fprintf (stderr, "%s:%u: unrecognized %% directive\n",
580                             pretty_input_file_name (), lineno);
581                    exit (1);
582                  }
583              }
584          }
585        else if (!(_verbatim_declarations != NULL
586                   && _verbatim_declarations_end == NULL))
587          {
588            /* Append the line to struct_decl.  */
589            size_t old_len = (struct_decl ? strlen (struct_decl) : 0);
590            size_t line_len = line_end - line;
591            size_t new_len = old_len + line_len + 1;
592            char *new_struct_decl = new char[new_len];
593            if (old_len > 0)
594              memcpy (new_struct_decl, struct_decl, old_len);
595            memcpy (new_struct_decl + old_len, line, line_len);
596            new_struct_decl[old_len + line_len] = '\0';
597            if (struct_decl)
598              delete[] struct_decl;
599            struct_decl = new_struct_decl;
600            /* Append the lineno to struct_decl_linenos.  */
601            unsigned int *new_struct_decl_linenos =
602              new unsigned int[struct_decl_linecount + 1];
603            if (struct_decl_linecount > 0)
604              memcpy (new_struct_decl_linenos, struct_decl_linenos,
605                      struct_decl_linecount * sizeof (unsigned int));
606            new_struct_decl_linenos[struct_decl_linecount] = lineno;
607            if (struct_decl_linenos)
608              delete[] struct_decl_linenos;
609            struct_decl_linenos = new_struct_decl_linenos;
610            /* Increment struct_decl_linecount.  */
611            struct_decl_linecount++;
612          }
613        lineno++;
614        line = line_end;
615      }
616    if (_verbatim_declarations != NULL && _verbatim_declarations_end == NULL)
617      {
618        fprintf (stderr, "%s:%u: unterminated %%{ section\n",
619                 pretty_input_file_name (), _verbatim_declarations_lineno);
620        exit (1);
621      }
622
623    /* Determine _struct_decl, _return_type, _struct_tag.  */
624    if (option[TYPE])
625      {
626        if (struct_decl)
627          {
628            /* Drop leading whitespace and comments.  */
629            {
630              char *p = struct_decl;
631              unsigned int *l = struct_decl_linenos;
632              for (;;)
633                {
634                  if (p[0] == ' ' || p[0] == '\t')
635                    {
636                      p++;
637                      continue;
638                    }
639                  if (p[0] == '\n')
640                    {
641                      l++;
642                      p++;
643                      continue;
644                    }
645                  if (p[0] == '/')
646                    {
647                      if (p[1] == '*')
648                        {
649                          /* Skip over ANSI C style comment.  */
650                          p += 2;
651                          while (p[0] != '\0')
652                            {
653                              if (p[0] == '*' && p[1] == '/')
654                                {
655                                  p += 2;
656                                  break;
657                                }
658                              if (p[0] == '\n')
659                                l++;
660                              p++;
661                            }
662                          continue;
663                        }
664                      if (p[1] == '/')
665                        {
666                          /* Skip over ISO C99 or C++ style comment.  */
667                          p += 2;
668                          while (p[0] != '\0' && p[0] != '\n')
669                            p++;
670                          if (p[0] == '\n')
671                            {
672                              l++;
673                              p++;
674                            }
675                          continue;
676                        }
677                    }
678                  break;
679                }
680              if (p != struct_decl)
681                {
682                  size_t len = strlen (p);
683                  char *new_struct_decl = new char[len + 1];
684                  memcpy (new_struct_decl, p, len + 1);
685                  delete[] struct_decl;
686                  struct_decl = new_struct_decl;
687                }
688              _struct_decl_lineno = *l;
689            }
690            /* Drop trailing whitespace.  */
691            for (char *p = struct_decl + strlen (struct_decl); p > struct_decl;)
692              if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
693                *--p = '\0';
694              else
695                break;
696          }
697        if (struct_decl == NULL || struct_decl[0] == '\0')
698          {
699            fprintf (stderr, "%s: missing struct declaration"
700                     " for option --struct-type\n",
701                     pretty_input_file_name ());
702            exit (1);
703          }
704        {
705          /* Ensure trailing semicolon.  */
706          size_t old_len = strlen (struct_decl);
707          if (struct_decl[old_len - 1] != ';')
708            {
709              char *new_struct_decl = new char[old_len + 2];
710              memcpy (new_struct_decl, struct_decl, old_len);
711              new_struct_decl[old_len] = ';';
712              new_struct_decl[old_len + 1] = '\0';
713              delete[] struct_decl;
714              struct_decl = new_struct_decl;
715            }
716        }
717        /* Set _struct_decl to the entire declaration.  */
718        _struct_decl = struct_decl;
719        /* Set _struct_tag to the naked "struct something".  */
720        const char *p;
721        for (p = struct_decl; *p && *p != '{' && *p != ';' && *p != '\n'; p++)
722          ;
723        for (; p > struct_decl;)
724          if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
725            --p;
726          else
727            break;
728        size_t struct_tag_length = p - struct_decl;
729        char *struct_tag = new char[struct_tag_length + 1];
730        memcpy (struct_tag, struct_decl, struct_tag_length);
731        struct_tag[struct_tag_length] = '\0';
732        _struct_tag = struct_tag;
733        /* The return type of the lookup function is "struct something *".
734           No "const" here, because if !option[CONST], some user code might
735           want to modify the structure. */
736        char *return_type = new char[struct_tag_length + 3];
737        memcpy (return_type, struct_decl, struct_tag_length);
738        return_type[struct_tag_length] = ' ';
739        return_type[struct_tag_length + 1] = '*';
740        return_type[struct_tag_length + 2] = '\0';
741        _return_type = return_type;
742      }
743
744    if (struct_decl_linenos)
745      delete[] struct_decl_linenos;
746  }
747
748  /* Parse the keywords section.  */
749  {
750    Keyword_List **list_tail = &_head;
751    const char *delimiters = option.get_delimiters ();
752    unsigned int lineno = keywords_lineno;
753    bool charset_dependent = false;
754    for (const char *line = keywords; line < keywords_end; )
755      {
756        const char *line_end;
757        line_end = (const char *) memchr (line, '\n', keywords_end - line);
758        if (line_end != NULL)
759          line_end++;
760        else
761          line_end = keywords_end;
762
763        if (line[0] == '#')
764          ; /* Comment line.  */
765        else if (line[0] == '%')
766          {
767            fprintf (stderr, "%s:%u:"
768                     " declarations are not allowed in the keywords section.\n"
769                     "To declare a keyword starting with %%, enclose it in"
770                     " double-quotes.\n",
771                     pretty_input_file_name (), lineno);
772            exit (1);
773          }
774        else
775          {
776            /* An input line carrying a keyword.  */
777            const char *keyword;
778            size_t keyword_length;
779            const char *rest;
780
781            if (line[0] == '"')
782              {
783                /* Parse a string in ANSI C syntax.  */
784                char *kp = new char[line_end-line];
785                keyword = kp;
786                const char *lp = line + 1;
787
788                for (;;)
789                  {
790                    if (lp == line_end)
791                      {
792                        fprintf (stderr, "%s:%u: unterminated string\n",
793                                 pretty_input_file_name (), lineno);
794                        exit (1);
795                      }
796
797                    char c = *lp;
798                    if (c == '\\')
799                      {
800                        c = *++lp;
801                        switch (c)
802                          {
803                          case '0': case '1': case '2': case '3':
804                          case '4': case '5': case '6': case '7':
805                            {
806                              int code = 0;
807                              int count = 0;
808                              while (count < 3 && *lp >= '0' && *lp <= '7')
809                                {
810                                  code = (code << 3) + (*lp - '0');
811                                  lp++;
812                                  count++;
813                                }
814                              if (code > UCHAR_MAX)
815                                fprintf (stderr,
816                                         "%s:%u: octal escape out of range\n",
817                                         pretty_input_file_name (), lineno);
818                              *kp = static_cast<char>(code);
819                              break;
820                            }
821                          case 'x':
822                            {
823                              int code = 0;
824                              int count = 0;
825                              lp++;
826                              while ((*lp >= '0' && *lp <= '9')
827                                     || (*lp >= 'A' && *lp <= 'F')
828                                     || (*lp >= 'a' && *lp <= 'f'))
829                                {
830                                  code = (code << 4)
831                                         + (*lp >= 'A' && *lp <= 'F'
832                                            ? *lp - 'A' + 10 :
833                                            *lp >= 'a' && *lp <= 'f'
834                                            ? *lp - 'a' + 10 :
835                                            *lp - '0');
836                                  lp++;
837                                  count++;
838                                }
839                              if (count == 0)
840                                fprintf (stderr, "%s:%u: hexadecimal escape"
841                                         " without any hex digits\n",
842                                         pretty_input_file_name (), lineno);
843                              if (code > UCHAR_MAX)
844                                fprintf (stderr, "%s:%u: hexadecimal escape"
845                                         " out of range\n",
846                                         pretty_input_file_name (), lineno);
847                              *kp = static_cast<char>(code);
848                              break;
849                            }
850                          case '\\': case '\'': case '"':
851                            *kp = c;
852                            lp++;
853                            charset_dependent = true;
854                            break;
855                          case 'n':
856                            *kp = '\n';
857                            lp++;
858                            charset_dependent = true;
859                            break;
860                          case 't':
861                            *kp = '\t';
862                            lp++;
863                            charset_dependent = true;
864                            break;
865                          case 'r':
866                            *kp = '\r';
867                            lp++;
868                            charset_dependent = true;
869                            break;
870                          case 'f':
871                            *kp = '\f';
872                            lp++;
873                            charset_dependent = true;
874                            break;
875                          case 'b':
876                            *kp = '\b';
877                            lp++;
878                            charset_dependent = true;
879                            break;
880                          case 'a':
881                            *kp = '\a';
882                            lp++;
883                            charset_dependent = true;
884                            break;
885                          case 'v':
886                            *kp = '\v';
887                            lp++;
888                            charset_dependent = true;
889                            break;
890                          default:
891                            fprintf (stderr, "%s:%u: invalid escape sequence"
892                                     " in string\n",
893                                     pretty_input_file_name (), lineno);
894                            exit (1);
895                          }
896                      }
897                    else if (c == '"')
898                      break;
899                    else
900                      {
901                        *kp = c;
902                        lp++;
903                        charset_dependent = true;
904                      }
905                    kp++;
906                  }
907                lp++;
908                if (lp < line_end && *lp != '\n')
909                  {
910                    if (strchr (delimiters, *lp) == NULL)
911                      {
912                        fprintf (stderr, "%s:%u: string not followed"
913                                 " by delimiter\n",
914                                 pretty_input_file_name (), lineno);
915                        exit (1);
916                      }
917                    lp++;
918                  }
919                keyword_length = kp - keyword;
920                if (option[TYPE])
921                  {
922                    char *line_rest = new char[line_end - lp + 1];
923                    memcpy (line_rest, lp, line_end - lp);
924                    line_rest[line_end - lp -
925                              (line_end > lp && line_end[-1] == '\n' ? 1 : 0)]
926                      = '\0';
927                    rest = line_rest;
928                  }
929                else
930                  rest = empty_string;
931              }
932            else
933              {
934                /* Not a string.  Look for the delimiter.  */
935                const char *lp = line;
936                for (;;)
937                  {
938                    if (!(lp < line_end && *lp != '\n'))
939                      {
940                        keyword = line;
941                        keyword_length = lp - line;
942                        rest = empty_string;
943                        break;
944                      }
945                    if (strchr (delimiters, *lp) != NULL)
946                      {
947                        keyword = line;
948                        keyword_length = lp - line;
949                        lp++;
950                        if (option[TYPE])
951                          {
952                            char *line_rest = new char[line_end - lp + 1];
953                            memcpy (line_rest, lp, line_end - lp);
954                            line_rest[line_end - lp -
955                                      (line_end > lp && line_end[-1] == '\n'
956                                       ? 1 : 0)]
957                              = '\0';
958                            rest = line_rest;
959                          }
960                        else
961                          rest = empty_string;
962                        break;
963                      }
964                    lp++;
965                  }
966                if (keyword_length > 0)
967                  charset_dependent = true;
968              }
969
970            /* Allocate Keyword and add it to the list.  */
971            Keyword *new_kw = _factory->create_keyword (keyword, keyword_length,
972                                                        rest);
973            new_kw->_lineno = lineno;
974            *list_tail = new Keyword_List (new_kw);
975            list_tail = &(*list_tail)->rest();
976          }
977
978        lineno++;
979        line = line_end;
980      }
981    *list_tail = NULL;
982
983    if (_head == NULL)
984      {
985        fprintf (stderr, "%s: No keywords in input file!\n",
986                 pretty_input_file_name ());
987        exit (1);
988      }
989
990    _charset_dependent = charset_dependent;
991  }
992
993  /* To be freed in the destructor.  */
994  _input = input;
995  _input_end = input_end;
996}
997
998Input::~Input ()
999{
1000  /* Free allocated memory.  */
1001  delete[] const_cast<char*>(_return_type);
1002  delete[] const_cast<char*>(_struct_tag);
1003  delete[] const_cast<char*>(_struct_decl);
1004  delete[] _input;
1005}
1006