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
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 "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
1001Input::~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