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 33Input::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. */ 40static const char * 41pretty_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. */ 50static bool 51is_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. */ 92static bool 93is_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. */ 152static bool 153is_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. */ 231void 232Input::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 998Input::~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} 1006