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