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