1 /* Input routines.
2    Copyright (C) 1989-1998, 2002-2004, 2011 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 
Input(FILE * stream,Keyword_Factory * keyword_factory)31 Input::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.  */
38 static const char *
pretty_input_file_name()39 pretty_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.  */
48 static bool
is_declaration(const char * line,const char * line_end,unsigned int lineno,const char * decl)49 is_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.  */
90 static bool
is_declaration_with_arg(const char * line,const char * line_end,unsigned int lineno,const char * decl,char ** argp)91 is_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.  */
150 static bool
is_define_declaration(const char * line,const char * line_end,unsigned int lineno,const char * decl,char ** argp)151 is_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.  */
229 void
read_input()230 Input::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                                            "constants-prefix", &arg))
550                   option.set_constants_prefix (arg);
551                 else
552 
553                 if (is_define_declaration (line, line_end, lineno,
554                                            "word-array-name", &arg))
555                   option.set_wordlist_name (arg);
556                 else
557 
558                 if (is_define_declaration (line, line_end, lineno,
559                                            "length-table-name", &arg))
560                   option.set_lengthtable_name (arg);
561                 else
562 
563                 if (is_declaration_with_arg (line, line_end, lineno,
564                                              "switch", &arg))
565                   {
566                     option.set_total_switches (atoi (arg));
567                     if (option.get_total_switches () <= 0)
568                       {
569                         fprintf (stderr, "%s:%u: number of switches %s"
570                                  " must be a positive number\n",
571                                  pretty_input_file_name (), lineno, arg);
572                         exit (1);
573                       }
574                   }
575                 else
576 
577                 if (is_declaration (line, line_end, lineno, "omit-struct-type"))
578                   option.set (NOTYPE);
579                 else
580 
581                   {
582                     fprintf (stderr, "%s:%u: unrecognized %% directive\n",
583                              pretty_input_file_name (), lineno);
584                     exit (1);
585                   }
586               }
587           }
588         else if (!(_verbatim_declarations != NULL
589                    && _verbatim_declarations_end == NULL))
590           {
591             /* Append the line to struct_decl.  */
592             size_t old_len = (struct_decl ? strlen (struct_decl) : 0);
593             size_t line_len = line_end - line;
594             size_t new_len = old_len + line_len + 1;
595             char *new_struct_decl = new char[new_len];
596             if (old_len > 0)
597               memcpy (new_struct_decl, struct_decl, old_len);
598             memcpy (new_struct_decl + old_len, line, line_len);
599             new_struct_decl[old_len + line_len] = '\0';
600             if (struct_decl)
601               delete[] struct_decl;
602             struct_decl = new_struct_decl;
603             /* Append the lineno to struct_decl_linenos.  */
604             unsigned int *new_struct_decl_linenos =
605               new unsigned int[struct_decl_linecount + 1];
606             if (struct_decl_linecount > 0)
607               memcpy (new_struct_decl_linenos, struct_decl_linenos,
608                       struct_decl_linecount * sizeof (unsigned int));
609             new_struct_decl_linenos[struct_decl_linecount] = lineno;
610             if (struct_decl_linenos)
611               delete[] struct_decl_linenos;
612             struct_decl_linenos = new_struct_decl_linenos;
613             /* Increment struct_decl_linecount.  */
614             struct_decl_linecount++;
615           }
616         lineno++;
617         line = line_end;
618       }
619     if (_verbatim_declarations != NULL && _verbatim_declarations_end == NULL)
620       {
621         fprintf (stderr, "%s:%u: unterminated %%{ section\n",
622                  pretty_input_file_name (), _verbatim_declarations_lineno);
623         exit (1);
624       }
625 
626     /* Determine _struct_decl, _return_type, _struct_tag.  */
627     if (option[TYPE])
628       {
629         if (struct_decl)
630           {
631             /* Drop leading whitespace and comments.  */
632             {
633               char *p = struct_decl;
634               unsigned int *l = struct_decl_linenos;
635               for (;;)
636                 {
637                   if (p[0] == ' ' || p[0] == '\t')
638                     {
639                       p++;
640                       continue;
641                     }
642                   if (p[0] == '\n')
643                     {
644                       l++;
645                       p++;
646                       continue;
647                     }
648                   if (p[0] == '/')
649                     {
650                       if (p[1] == '*')
651                         {
652                           /* Skip over ANSI C style comment.  */
653                           p += 2;
654                           while (p[0] != '\0')
655                             {
656                               if (p[0] == '*' && p[1] == '/')
657                                 {
658                                   p += 2;
659                                   break;
660                                 }
661                               if (p[0] == '\n')
662                                 l++;
663                               p++;
664                             }
665                           continue;
666                         }
667                       if (p[1] == '/')
668                         {
669                           /* Skip over ISO C99 or C++ style comment.  */
670                           p += 2;
671                           while (p[0] != '\0' && p[0] != '\n')
672                             p++;
673                           if (p[0] == '\n')
674                             {
675                               l++;
676                               p++;
677                             }
678                           continue;
679                         }
680                     }
681                   break;
682                 }
683               if (p != struct_decl)
684                 {
685                   size_t len = strlen (p);
686                   char *new_struct_decl = new char[len + 1];
687                   memcpy (new_struct_decl, p, len + 1);
688                   delete[] struct_decl;
689                   struct_decl = new_struct_decl;
690                 }
691               _struct_decl_lineno = *l;
692             }
693             /* Drop trailing whitespace.  */
694             for (char *p = struct_decl + strlen (struct_decl); p > struct_decl;)
695               if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
696                 *--p = '\0';
697               else
698                 break;
699           }
700         if (struct_decl == NULL || struct_decl[0] == '\0')
701           {
702             fprintf (stderr, "%s: missing struct declaration"
703                      " for option --struct-type\n",
704                      pretty_input_file_name ());
705             exit (1);
706           }
707         {
708           /* Ensure trailing semicolon.  */
709           size_t old_len = strlen (struct_decl);
710           if (struct_decl[old_len - 1] != ';')
711             {
712               char *new_struct_decl = new char[old_len + 2];
713               memcpy (new_struct_decl, struct_decl, old_len);
714               new_struct_decl[old_len] = ';';
715               new_struct_decl[old_len + 1] = '\0';
716               delete[] struct_decl;
717               struct_decl = new_struct_decl;
718             }
719         }
720         /* Set _struct_decl to the entire declaration.  */
721         _struct_decl = struct_decl;
722         /* Set _struct_tag to the naked "struct something".  */
723         const char *p;
724         for (p = struct_decl; *p && *p != '{' && *p != ';' && *p != '\n'; p++)
725           ;
726         for (; p > struct_decl;)
727           if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
728             --p;
729           else
730             break;
731         size_t struct_tag_length = p - struct_decl;
732         char *struct_tag = new char[struct_tag_length + 1];
733         memcpy (struct_tag, struct_decl, struct_tag_length);
734         struct_tag[struct_tag_length] = '\0';
735         _struct_tag = struct_tag;
736         /* The return type of the lookup function is "struct something *".
737            No "const" here, because if !option[CONST], some user code might
738            want to modify the structure. */
739         char *return_type = new char[struct_tag_length + 3];
740         memcpy (return_type, struct_decl, struct_tag_length);
741         return_type[struct_tag_length] = ' ';
742         return_type[struct_tag_length + 1] = '*';
743         return_type[struct_tag_length + 2] = '\0';
744         _return_type = return_type;
745       }
746 
747     if (struct_decl_linenos)
748       delete[] struct_decl_linenos;
749   }
750 
751   /* Parse the keywords section.  */
752   {
753     Keyword_List **list_tail = &_head;
754     const char *delimiters = option.get_delimiters ();
755     unsigned int lineno = keywords_lineno;
756     bool charset_dependent = false;
757     for (const char *line = keywords; line < keywords_end; )
758       {
759         const char *line_end;
760         line_end = (const char *) memchr (line, '\n', keywords_end - line);
761         if (line_end != NULL)
762           line_end++;
763         else
764           line_end = keywords_end;
765 
766         if (line[0] == '#')
767           ; /* Comment line.  */
768         else if (line[0] == '%')
769           {
770             fprintf (stderr, "%s:%u:"
771                      " declarations are not allowed in the keywords section.\n"
772                      "To declare a keyword starting with %%, enclose it in"
773                      " double-quotes.\n",
774                      pretty_input_file_name (), lineno);
775             exit (1);
776           }
777         else
778           {
779             /* An input line carrying a keyword.  */
780             const char *keyword;
781             size_t keyword_length;
782             const char *rest;
783 
784             if (line[0] == '"')
785               {
786                 /* Parse a string in ANSI C syntax.  */
787                 char *kp = new char[line_end-line];
788                 keyword = kp;
789                 const char *lp = line + 1;
790 
791                 for (;;)
792                   {
793                     if (lp == line_end)
794                       {
795                         fprintf (stderr, "%s:%u: unterminated string\n",
796                                  pretty_input_file_name (), lineno);
797                         exit (1);
798                       }
799 
800                     char c = *lp;
801                     if (c == '\\')
802                       {
803                         c = *++lp;
804                         switch (c)
805                           {
806                           case '0': case '1': case '2': case '3':
807                           case '4': case '5': case '6': case '7':
808                             {
809                               int code = 0;
810                               int count = 0;
811                               while (count < 3 && *lp >= '0' && *lp <= '7')
812                                 {
813                                   code = (code << 3) + (*lp - '0');
814                                   lp++;
815                                   count++;
816                                 }
817                               if (code > UCHAR_MAX)
818                                 fprintf (stderr,
819                                          "%s:%u: octal escape out of range\n",
820                                          pretty_input_file_name (), lineno);
821                               *kp = static_cast<char>(code);
822                               break;
823                             }
824                           case 'x':
825                             {
826                               int code = 0;
827                               int count = 0;
828                               lp++;
829                               while ((*lp >= '0' && *lp <= '9')
830                                      || (*lp >= 'A' && *lp <= 'F')
831                                      || (*lp >= 'a' && *lp <= 'f'))
832                                 {
833                                   code = (code << 4)
834                                          + (*lp >= 'A' && *lp <= 'F'
835                                             ? *lp - 'A' + 10 :
836                                             *lp >= 'a' && *lp <= 'f'
837                                             ? *lp - 'a' + 10 :
838                                             *lp - '0');
839                                   lp++;
840                                   count++;
841                                 }
842                               if (count == 0)
843                                 fprintf (stderr, "%s:%u: hexadecimal escape"
844                                          " without any hex digits\n",
845                                          pretty_input_file_name (), lineno);
846                               if (code > UCHAR_MAX)
847                                 fprintf (stderr, "%s:%u: hexadecimal escape"
848                                          " out of range\n",
849                                          pretty_input_file_name (), lineno);
850                               *kp = static_cast<char>(code);
851                               break;
852                             }
853                           case '\\': case '\'': case '"':
854                             *kp = c;
855                             lp++;
856                             charset_dependent = true;
857                             break;
858                           case 'n':
859                             *kp = '\n';
860                             lp++;
861                             charset_dependent = true;
862                             break;
863                           case 't':
864                             *kp = '\t';
865                             lp++;
866                             charset_dependent = true;
867                             break;
868                           case 'r':
869                             *kp = '\r';
870                             lp++;
871                             charset_dependent = true;
872                             break;
873                           case 'f':
874                             *kp = '\f';
875                             lp++;
876                             charset_dependent = true;
877                             break;
878                           case 'b':
879                             *kp = '\b';
880                             lp++;
881                             charset_dependent = true;
882                             break;
883                           case 'a':
884                             *kp = '\a';
885                             lp++;
886                             charset_dependent = true;
887                             break;
888                           case 'v':
889                             *kp = '\v';
890                             lp++;
891                             charset_dependent = true;
892                             break;
893                           default:
894                             fprintf (stderr, "%s:%u: invalid escape sequence"
895                                      " in string\n",
896                                      pretty_input_file_name (), lineno);
897                             exit (1);
898                           }
899                       }
900                     else if (c == '"')
901                       break;
902                     else
903                       {
904                         *kp = c;
905                         lp++;
906                         charset_dependent = true;
907                       }
908                     kp++;
909                   }
910                 lp++;
911                 if (lp < line_end && *lp != '\n')
912                   {
913                     if (strchr (delimiters, *lp) == NULL)
914                       {
915                         fprintf (stderr, "%s:%u: string not followed"
916                                  " by delimiter\n",
917                                  pretty_input_file_name (), lineno);
918                         exit (1);
919                       }
920                     lp++;
921                   }
922                 keyword_length = kp - keyword;
923                 if (option[TYPE])
924                   {
925                     char *line_rest = new char[line_end - lp + 1];
926                     memcpy (line_rest, lp, line_end - lp);
927                     line_rest[line_end - lp -
928                               (line_end > lp && line_end[-1] == '\n' ? 1 : 0)]
929                       = '\0';
930                     rest = line_rest;
931                   }
932                 else
933                   rest = empty_string;
934               }
935             else
936               {
937                 /* Not a string.  Look for the delimiter.  */
938                 const char *lp = line;
939                 for (;;)
940                   {
941                     if (!(lp < line_end && *lp != '\n'))
942                       {
943                         keyword = line;
944                         keyword_length = lp - line;
945                         rest = empty_string;
946                         break;
947                       }
948                     if (strchr (delimiters, *lp) != NULL)
949                       {
950                         keyword = line;
951                         keyword_length = lp - line;
952                         lp++;
953                         if (option[TYPE])
954                           {
955                             char *line_rest = new char[line_end - lp + 1];
956                             memcpy (line_rest, lp, line_end - lp);
957                             line_rest[line_end - lp -
958                                       (line_end > lp && line_end[-1] == '\n'
959                                        ? 1 : 0)]
960                               = '\0';
961                             rest = line_rest;
962                           }
963                         else
964                           rest = empty_string;
965                         break;
966                       }
967                     lp++;
968                   }
969                 if (keyword_length > 0)
970                   charset_dependent = true;
971               }
972 
973             /* Allocate Keyword and add it to the list.  */
974             Keyword *new_kw = _factory->create_keyword (keyword, keyword_length,
975                                                         rest);
976             new_kw->_lineno = lineno;
977             *list_tail = new Keyword_List (new_kw);
978             list_tail = &(*list_tail)->rest();
979           }
980 
981         lineno++;
982         line = line_end;
983       }
984     *list_tail = NULL;
985 
986     if (_head == NULL)
987       {
988         fprintf (stderr, "%s: No keywords in input file!\n",
989                  pretty_input_file_name ());
990         exit (1);
991       }
992 
993     _charset_dependent = charset_dependent;
994   }
995 
996   /* To be freed in the destructor.  */
997   _input = input;
998   _input_end = input_end;
999 }
1000 
~Input()1001 Input::~Input ()
1002 {
1003   /* Free allocated memory.  */
1004   delete[] const_cast<char*>(_return_type);
1005   delete[] const_cast<char*>(_struct_tag);
1006   delete[] const_cast<char*>(_struct_decl);
1007   delete[] _input;
1008 }
1009