]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gperf/src/input.cc
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gperf / src / input.cc
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
33 Input::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.  */
40 static const char *
41 pretty_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.  */
50 static bool
51 is_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.  */
92 static bool
93 is_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.  */
152 static bool
153 is_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.  */
231 void
232 Input::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
998 Input::~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 }