1 /* $OpenBSD: misc.c,v 1.19 2015/11/19 23:34:56 mmcc Exp $ */ 2 3 /* misc - miscellaneous flex routines */ 4 5 /* Copyright (c) 1990 The Regents of the University of California. */ 6 /* All rights reserved. */ 7 8 /* This code is derived from software contributed to Berkeley by */ 9 /* Vern Paxson. */ 10 11 /* The United States Government has rights in this work pursuant */ 12 /* to contract no. DE-AC03-76SF00098 between the United States */ 13 /* Department of Energy and the University of California. */ 14 15 /* This file is part of flex. */ 16 17 /* Redistribution and use in source and binary forms, with or without */ 18 /* modification, are permitted provided that the following conditions */ 19 /* are met: */ 20 21 /* 1. Redistributions of source code must retain the above copyright */ 22 /* notice, this list of conditions and the following disclaimer. */ 23 /* 2. Redistributions in binary form must reproduce the above copyright */ 24 /* notice, this list of conditions and the following disclaimer in the */ 25 /* documentation and/or other materials provided with the distribution. */ 26 27 /* Neither the name of the University nor the names of its contributors */ 28 /* may be used to endorse or promote products derived from this software */ 29 /* without specific prior written permission. */ 30 31 /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ 32 /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 33 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ 34 /* PURPOSE. */ 35 36 #include "flexdef.h" 37 #include "tables.h" 38 39 #define CMD_IF_TABLES_SER "%if-tables-serialization" 40 #define CMD_TABLES_YYDMAP "%tables-yydmap" 41 #define CMD_DEFINE_YYTABLES "%define-yytables" 42 #define CMD_IF_CPP_ONLY "%if-c++-only" 43 #define CMD_IF_C_ONLY "%if-c-only" 44 #define CMD_IF_C_OR_CPP "%if-c-or-c++" 45 #define CMD_NOT_FOR_HEADER "%not-for-header" 46 #define CMD_OK_FOR_HEADER "%ok-for-header" 47 #define CMD_PUSH "%push" 48 #define CMD_POP "%pop" 49 #define CMD_IF_REENTRANT "%if-reentrant" 50 #define CMD_IF_NOT_REENTRANT "%if-not-reentrant" 51 #define CMD_IF_BISON_BRIDGE "%if-bison-bridge" 52 #define CMD_IF_NOT_BISON_BRIDGE "%if-not-bison-bridge" 53 #define CMD_ENDIF "%endif" 54 55 /* we allow the skeleton to push and pop. */ 56 struct sko_state { 57 bool dc; /**< do_copy */ 58 }; 59 static struct sko_state *sko_stack = 0; 60 static int sko_len = 0, sko_sz = 0; 61 static void 62 sko_push(bool dc) 63 { 64 if (!sko_stack) { 65 sko_sz = 1; 66 sko_stack = malloc(sizeof(struct sko_state) * sko_sz); 67 if (!sko_stack) 68 flexfatal(_("allocation of sko_stack failed")); 69 sko_len = 0; 70 } 71 if (sko_len >= sko_sz) { 72 sko_sz *= 2; 73 sko_stack = realloc(sko_stack, sizeof(struct sko_state) * sko_sz); 74 } 75 /* initialize to zero and push */ 76 sko_stack[sko_len].dc = dc; 77 sko_len++; 78 } 79 static void 80 sko_peek(bool * dc) 81 { 82 if (sko_len <= 0) 83 flex_die("peek attempt when sko stack is empty"); 84 if (dc) 85 *dc = sko_stack[sko_len - 1].dc; 86 } 87 static void 88 sko_pop(bool * dc) 89 { 90 sko_peek(dc); 91 sko_len--; 92 if (sko_len < 0) 93 flex_die("popped too many times in skeleton."); 94 } 95 96 /* Append "#define defname value\n" to the running buffer. */ 97 void 98 action_define(defname, value) 99 const char *defname; 100 int value; 101 { 102 char buf[MAXLINE]; 103 char *cpy; 104 105 if ((int) strlen(defname) > MAXLINE / 2) { 106 format_pinpoint_message(_ 107 ("name \"%s\" ridiculously long"), 108 defname); 109 return; 110 } 111 snprintf(buf, sizeof(buf), "#define %s %d\n", defname, value); 112 add_action(buf); 113 114 /* track #defines so we can undef them when we're done. */ 115 cpy = copy_string(defname); 116 buf_append(&defs_buf, &cpy, 1); 117 } 118 119 120 /** Append "m4_define([[defname]],[[value]])m4_dnl\n" to the running buffer. 121 * @param defname The macro name. 122 * @param value The macro value, can be NULL, which is the same as the empty string. 123 */ 124 void 125 action_m4_define(const char *defname, const char *value) 126 { 127 char buf[MAXLINE]; 128 129 flexfatal("DO NOT USE THIS FUNCTION!"); 130 131 if ((int) strlen(defname) > MAXLINE / 2) { 132 format_pinpoint_message(_ 133 ("name \"%s\" ridiculously long"), 134 defname); 135 return; 136 } 137 snprintf(buf, sizeof(buf), "m4_define([[%s]],[[%s]])m4_dnl\n", defname, value ? value : ""); 138 add_action(buf); 139 } 140 141 /* Append "new_text" to the running buffer. */ 142 void 143 add_action(new_text) 144 const char *new_text; 145 { 146 int len = strlen(new_text); 147 148 while (len + action_index >= action_size - 10 /* slop */ ) { 149 int new_size = action_size * 2; 150 151 if (new_size <= 0) 152 /* 153 * Increase just a little, to try to avoid overflow 154 * on 16-bit machines. 155 */ 156 action_size += action_size / 8; 157 else 158 action_size = new_size; 159 160 action_array = 161 reallocate_character_array(action_array, 162 action_size); 163 } 164 165 strlcpy(&action_array[action_index], new_text, 166 action_size - action_index); 167 168 action_index += len; 169 } 170 171 172 /* allocate_array - allocate memory for an integer array of the given size */ 173 174 void * 175 allocate_array(size, element_size) 176 int size; 177 size_t element_size; 178 { 179 void *mem; 180 size_t num_bytes = element_size * size; 181 182 mem = malloc(num_bytes); 183 if (!mem) 184 flexfatal(_ 185 ("memory allocation failed in allocate_array()")); 186 187 return mem; 188 } 189 190 191 /* all_lower - true if a string is all lower-case */ 192 193 int 194 all_lower(str) 195 char *str; 196 { 197 while (*str) { 198 if (!isascii((u_char) * str) || !islower((u_char) * str)) 199 return 0; 200 ++str; 201 } 202 203 return 1; 204 } 205 206 207 /* all_upper - true if a string is all upper-case */ 208 209 int 210 all_upper(str) 211 char *str; 212 { 213 while (*str) { 214 if (!isascii((u_char) * str) || !isupper((u_char) * str)) 215 return 0; 216 ++str; 217 } 218 219 return 1; 220 } 221 222 223 /* intcmp - compares two integers for use by qsort. */ 224 225 int 226 intcmp(const void *a, const void *b) 227 { 228 return *(const int *) a - *(const int *) b; 229 } 230 231 232 /* check_char - checks a character to make sure it's within the range 233 * we're expecting. If not, generates fatal error message 234 * and exits. 235 */ 236 237 void 238 check_char(c) 239 int c; 240 { 241 if (c >= CSIZE) 242 lerrsf(_("bad character '%s' detected in check_char()"), 243 readable_form(c)); 244 245 if (c >= csize) 246 lerrsf(_ 247 ("scanner requires -8 flag to use the character %s"), 248 readable_form(c)); 249 } 250 251 252 253 /* clower - replace upper-case letter to lower-case */ 254 255 u_char 256 clower(c) 257 int c; 258 { 259 return (u_char) ((isascii(c) && isupper(c)) ? tolower(c) : c); 260 } 261 262 263 /* copy_string - returns a dynamically allocated copy of a string */ 264 265 char * 266 copy_string(str) 267 const char *str; 268 { 269 const char *c1; 270 char *c2; 271 char *copy; 272 unsigned int size; 273 274 /* find length */ 275 for (c1 = str; *c1; ++c1); 276 277 size = (c1 - str + 1) * sizeof(char); 278 279 copy = (char *) malloc(size); 280 281 if (copy == NULL) 282 flexfatal(_("dynamic memory failure in copy_string()")); 283 284 for (c2 = copy; (*c2++ = *str++) != 0;); 285 286 return copy; 287 } 288 289 290 /* copy_unsigned_string - 291 * returns a dynamically allocated copy of a (potentially) unsigned string 292 */ 293 294 u_char * 295 copy_unsigned_string(str) 296 u_char *str; 297 { 298 u_char *c; 299 u_char *copy; 300 301 /* find length */ 302 for (c = str; *c; ++c); 303 304 copy = allocate_Character_array(c - str + 1); 305 306 for (c = copy; (*c++ = *str++) != 0;); 307 308 return copy; 309 } 310 311 312 /* cclcmp - compares two characters for use by qsort with '\0' sorting last. */ 313 314 int 315 cclcmp(const void *a, const void *b) 316 { 317 if (!*(const u_char *) a) 318 return 1; 319 else if (!*(const u_char *) b) 320 return -1; 321 else 322 return *(const u_char *) a - *(const u_char *) b; 323 } 324 325 326 /* dataend - finish up a block of data declarations */ 327 328 void 329 dataend() 330 { 331 /* short circuit any output */ 332 if (gentables) { 333 334 if (datapos > 0) 335 dataflush(); 336 337 /* add terminator for initialization; { for vi */ 338 outn(" } ;\n"); 339 } 340 dataline = 0; 341 datapos = 0; 342 } 343 344 345 /* dataflush - flush generated data statements */ 346 347 void 348 dataflush() 349 { 350 /* short circuit any output */ 351 if (!gentables) 352 return; 353 354 outc('\n'); 355 356 if (++dataline >= NUMDATALINES) { 357 /* 358 * Put out a blank line so that the table is grouped into 359 * large blocks that enable the user to find elements easily. 360 */ 361 outc('\n'); 362 dataline = 0; 363 } 364 /* Reset the number of characters written on the current line. */ 365 datapos = 0; 366 } 367 368 369 /* flexerror - report an error message and terminate */ 370 371 void 372 flexerror(msg) 373 const char *msg; 374 { 375 fprintf(stderr, "%s: %s\n", program_name, msg); 376 flexend(1); 377 } 378 379 380 /* flexfatal - report a fatal error message and terminate */ 381 382 void 383 flexfatal(msg) 384 const char *msg; 385 { 386 fprintf(stderr, _("%s: fatal internal error, %s\n"), 387 program_name, msg); 388 FLEX_EXIT(1); 389 } 390 391 392 /* htoi - convert a hexadecimal digit string to an integer value */ 393 394 int 395 htoi(str) 396 u_char str[]; 397 { 398 unsigned int result; 399 400 (void) sscanf((char *) str, "%x", &result); 401 402 return result; 403 } 404 405 406 /* lerrif - report an error message formatted with one integer argument */ 407 408 void 409 lerrif(msg, arg) 410 const char *msg; 411 int arg; 412 { 413 char errmsg[MAXLINE]; 414 415 snprintf(errmsg, sizeof(errmsg), msg, arg); 416 flexerror(errmsg); 417 } 418 419 420 /* lerrsf - report an error message formatted with one string argument */ 421 422 void 423 lerrsf(msg, arg) 424 const char *msg, arg[]; 425 { 426 char errmsg[MAXLINE]; 427 428 snprintf(errmsg, sizeof(errmsg) - 1, msg, arg); 429 errmsg[sizeof(errmsg) - 1] = 0; /* ensure NULL termination */ 430 flexerror(errmsg); 431 } 432 433 434 /* lerrsf_fatal - as lerrsf, but call flexfatal */ 435 436 void 437 lerrsf_fatal(msg, arg) 438 const char *msg, arg[]; 439 { 440 char errmsg[MAXLINE]; 441 442 snprintf(errmsg, sizeof(errmsg) - 1, msg, arg); 443 errmsg[sizeof(errmsg) - 1] = 0; /* ensure NULL termination */ 444 flexfatal(errmsg); 445 } 446 447 448 /* line_directive_out - spit out a "#line" statement */ 449 450 void 451 line_directive_out(output_file, do_infile) 452 FILE *output_file; 453 int do_infile; 454 { 455 char directive[MAXLINE], filename[MAXLINE]; 456 char *s1, *s2, *s3; 457 static const char *line_fmt = "#line %d \"%s\"\n"; 458 459 if (!gen_line_dirs) 460 return; 461 462 s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME"; 463 464 if (do_infile && !s1) 465 s1 = "<stdin>"; 466 467 s2 = filename; 468 s3 = &filename[sizeof(filename) - 2]; 469 470 while (s2 < s3 && *s1) { 471 if (*s1 == '\\') 472 /* Escape the '\' */ 473 *s2++ = '\\'; 474 475 *s2++ = *s1++; 476 } 477 478 *s2 = '\0'; 479 480 if (do_infile) 481 snprintf(directive, sizeof(directive), line_fmt, linenum, filename); 482 else { 483 snprintf(directive, sizeof(directive), line_fmt, 0, filename); 484 } 485 486 /* 487 * If output_file is nil then we should put the directive in the 488 * accumulated actions. 489 */ 490 if (output_file) { 491 fputs(directive, output_file); 492 } else 493 add_action(directive); 494 } 495 496 497 /* mark_defs1 - mark the current position in the action array as 498 * representing where the user's section 1 definitions end 499 * and the prolog begins 500 */ 501 void 502 mark_defs1() 503 { 504 defs1_offset = 0; 505 action_array[action_index++] = '\0'; 506 action_offset = prolog_offset = action_index; 507 action_array[action_index] = '\0'; 508 } 509 510 511 /* mark_prolog - mark the current position in the action array as 512 * representing the end of the action prolog 513 */ 514 void 515 mark_prolog() 516 { 517 action_array[action_index++] = '\0'; 518 action_offset = action_index; 519 action_array[action_index] = '\0'; 520 } 521 522 523 /* mk2data - generate a data statement for a two-dimensional array 524 * 525 * Generates a data statement initializing the current 2-D array to "value". 526 */ 527 void 528 mk2data(value) 529 int value; 530 { 531 /* short circuit any output */ 532 if (!gentables) 533 return; 534 535 if (datapos >= NUMDATAITEMS) { 536 outc(','); 537 dataflush(); 538 } 539 if (datapos == 0) 540 /* Indent. */ 541 out(" "); 542 543 else 544 outc(','); 545 546 ++datapos; 547 548 out_dec("%5d", value); 549 } 550 551 552 /* mkdata - generate a data statement 553 * 554 * Generates a data statement initializing the current array element to 555 * "value". 556 */ 557 void 558 mkdata(value) 559 int value; 560 { 561 /* short circuit any output */ 562 if (!gentables) 563 return; 564 565 if (datapos >= NUMDATAITEMS) { 566 outc(','); 567 dataflush(); 568 } 569 if (datapos == 0) 570 /* Indent. */ 571 out(" "); 572 else 573 outc(','); 574 575 ++datapos; 576 577 out_dec("%5d", value); 578 } 579 580 581 /* myctoi - return the integer represented by a string of digits */ 582 583 int 584 myctoi(array) 585 const char *array; 586 { 587 int val = 0; 588 589 (void) sscanf(array, "%d", &val); 590 591 return val; 592 } 593 594 595 /* myesc - return character corresponding to escape sequence */ 596 597 u_char 598 myesc(array) 599 u_char array[]; 600 { 601 u_char c, esc_char; 602 603 switch (array[1]) { 604 case 'b': 605 return '\b'; 606 case 'f': 607 return '\f'; 608 case 'n': 609 return '\n'; 610 case 'r': 611 return '\r'; 612 case 't': 613 return '\t'; 614 615 #if defined (__STDC__) 616 case 'a': 617 return '\a'; 618 case 'v': 619 return '\v'; 620 #else 621 case 'a': 622 return '\007'; 623 case 'v': 624 return '\013'; 625 #endif 626 627 case '0': 628 case '1': 629 case '2': 630 case '3': 631 case '4': 632 case '5': 633 case '6': 634 case '7': 635 { /* \<octal> */ 636 int sptr = 1; 637 638 while (isascii(array[sptr]) && 639 isdigit(array[sptr])) 640 /* 641 * Don't increment inside loop control 642 * because if isdigit() is a macro it might 643 * expand into multiple increments ... 644 */ 645 ++sptr; 646 647 c = array[sptr]; 648 array[sptr] = '\0'; 649 650 esc_char = otoi(array + 1); 651 652 array[sptr] = c; 653 654 return esc_char; 655 } 656 657 case 'x': 658 { /* \x<hex> */ 659 int sptr = 2; 660 661 while (isascii(array[sptr]) && 662 isxdigit(array[sptr])) 663 /* 664 * Don't increment inside loop control 665 * because if isdigit() is a macro it might 666 * expand into multiple increments ... 667 */ 668 ++sptr; 669 670 c = array[sptr]; 671 array[sptr] = '\0'; 672 673 esc_char = htoi(array + 2); 674 675 array[sptr] = c; 676 677 return esc_char; 678 } 679 680 default: 681 return array[1]; 682 } 683 } 684 685 686 /* otoi - convert an octal digit string to an integer value */ 687 688 int 689 otoi(str) 690 u_char str[]; 691 { 692 unsigned int result; 693 694 (void) sscanf((char *) str, "%o", &result); 695 return result; 696 } 697 698 699 /* out - various flavors of outputing a (possibly formatted) string for the 700 * generated scanner, keeping track of the line count. 701 */ 702 703 void 704 out(str) 705 const char *str; 706 { 707 fputs(str, stdout); 708 } 709 710 void 711 out_dec(fmt, n) 712 const char *fmt; 713 int n; 714 { 715 fprintf(stdout, fmt, n); 716 } 717 718 void 719 out_dec2(fmt, n1, n2) 720 const char *fmt; 721 int n1, n2; 722 { 723 fprintf(stdout, fmt, n1, n2); 724 } 725 726 void 727 out_hex(fmt, x) 728 const char *fmt; 729 unsigned int x; 730 { 731 fprintf(stdout, fmt, x); 732 } 733 734 void 735 out_str(fmt, str) 736 const char *fmt, str[]; 737 { 738 fprintf(stdout, fmt, str); 739 } 740 741 void 742 out_str3(fmt, s1, s2, s3) 743 const char *fmt, s1[], s2[], s3[]; 744 { 745 fprintf(stdout, fmt, s1, s2, s3); 746 } 747 748 void 749 out_str_dec(fmt, str, n) 750 const char *fmt, str[]; 751 int n; 752 { 753 fprintf(stdout, fmt, str, n); 754 } 755 756 void 757 outc(c) 758 int c; 759 { 760 fputc(c, stdout); 761 } 762 763 void 764 outn(str) 765 const char *str; 766 { 767 fputs(str, stdout); 768 fputc('\n', stdout); 769 } 770 771 /** Print "m4_define( [[def]], [[val]])m4_dnl\n". 772 * @param def The m4 symbol to define. 773 * @param val The definition; may be NULL. 774 * @return buf 775 */ 776 void 777 out_m4_define(const char *def, const char *val) 778 { 779 const char *fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 780 fprintf(stdout, fmt, def, val ? val : ""); 781 } 782 783 784 /* readable_form - return the human-readable form of a character 785 * 786 * The returned string is in static storage. 787 */ 788 789 char * 790 readable_form(c) 791 int c; 792 { 793 static char rform[10]; 794 795 if ((c >= 0 && c < 32) || c >= 127) { 796 switch (c) { 797 case '\b': 798 return "\\b"; 799 case '\f': 800 return "\\f"; 801 case '\n': 802 return "\\n"; 803 case '\r': 804 return "\\r"; 805 case '\t': 806 return "\\t"; 807 808 #if defined (__STDC__) 809 case '\a': 810 return "\\a"; 811 case '\v': 812 return "\\v"; 813 #endif 814 815 default: 816 snprintf(rform, sizeof(rform), "\\%.3o", (unsigned int) c); 817 return rform; 818 } 819 } else if (c == ' ') 820 return "' '"; 821 822 else { 823 rform[0] = c; 824 rform[1] = '\0'; 825 826 return rform; 827 } 828 } 829 830 831 /* reallocate_array - increase the size of a dynamic array */ 832 833 void * 834 reallocate_array(array, size, element_size) 835 void *array; 836 int size; 837 size_t element_size; 838 { 839 void *new_array; 840 size_t num_bytes = element_size * size; 841 842 new_array = realloc(array, num_bytes); 843 if (!new_array) 844 flexfatal(_("attempt to increase array size failed")); 845 846 return new_array; 847 } 848 849 850 /* skelout - write out one section of the skeleton file 851 * 852 * Description 853 * Copies skelfile or skel array to stdout until a line beginning with 854 * "%%" or EOF is found. 855 */ 856 void 857 skelout() 858 { 859 char buf_storage[MAXLINE]; 860 char *buf = buf_storage; 861 bool do_copy = true; 862 863 /* "reset" the state by clearing the buffer and pushing a '1' */ 864 if (sko_len > 0) 865 sko_peek(&do_copy); 866 sko_len = 0; 867 sko_push(do_copy = true); 868 869 870 /* 871 * Loop pulling lines either from the skelfile, if we're using one, 872 * or from the skel[] array. 873 */ 874 while (skelfile ? 875 (fgets(buf, MAXLINE, skelfile) != NULL) : 876 ((buf = (char *) skel[skel_ind++]) != 0)) { 877 878 if (skelfile) 879 chomp(buf); 880 881 /* copy from skel array */ 882 if (buf[0] == '%') { /* control line */ 883 /* print the control line as a comment. */ 884 if (ddebug && buf[1] != '#') { 885 if (buf[strlen(buf) - 1] == '\\') 886 out_str("/* %s */\\\n", buf); 887 else 888 out_str("/* %s */\n", buf); 889 } 890 /* 891 * We've been accused of using cryptic markers in the 892 * skel. So we'll use 893 * emacs-style-hyphenated-commands. We might consider 894 * a hash if this if-else-if-else chain gets too 895 * large. 896 */ 897 #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0) 898 899 if (buf[1] == '%') { 900 /* %% is a break point for skelout() */ 901 return; 902 } else if (cmd_match(CMD_PUSH)) { 903 sko_push(do_copy); 904 if (ddebug) { 905 out_str("/*(state = (%s) */", do_copy ? "true" : "false"); 906 } 907 out_str("%s\n", buf[strlen(buf) - 1] == '\\' ? "\\" : ""); 908 } else if (cmd_match(CMD_POP)) { 909 sko_pop(&do_copy); 910 if (ddebug) { 911 out_str("/*(state = (%s) */", do_copy ? "true" : "false"); 912 } 913 out_str("%s\n", buf[strlen(buf) - 1] == '\\' ? "\\" : ""); 914 } else if (cmd_match(CMD_IF_REENTRANT)) { 915 sko_push(do_copy); 916 do_copy = reentrant && do_copy; 917 } else if (cmd_match(CMD_IF_NOT_REENTRANT)) { 918 sko_push(do_copy); 919 do_copy = !reentrant && do_copy; 920 } else if (cmd_match(CMD_IF_BISON_BRIDGE)) { 921 sko_push(do_copy); 922 do_copy = bison_bridge_lval && do_copy; 923 } else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)) { 924 sko_push(do_copy); 925 do_copy = !bison_bridge_lval && do_copy; 926 } else if (cmd_match(CMD_ENDIF)) { 927 sko_pop(&do_copy); 928 } else if (cmd_match(CMD_IF_TABLES_SER)) { 929 do_copy = do_copy && tablesext; 930 } else if (cmd_match(CMD_TABLES_YYDMAP)) { 931 if (tablesext && yydmap_buf.elts) 932 outn((char *) (yydmap_buf.elts)); 933 } else if (cmd_match(CMD_DEFINE_YYTABLES)) { 934 out_str("#define YYTABLES_NAME \"%s\"\n", 935 tablesname ? tablesname : "yytables"); 936 } else if (cmd_match(CMD_IF_CPP_ONLY)) { 937 /* only for C++ */ 938 sko_push(do_copy); 939 do_copy = C_plus_plus; 940 } else if (cmd_match(CMD_IF_C_ONLY)) { 941 /* %- only for C */ 942 sko_push(do_copy); 943 do_copy = !C_plus_plus; 944 } else if (cmd_match(CMD_IF_C_OR_CPP)) { 945 /* %* for C and C++ */ 946 sko_push(do_copy); 947 do_copy = true; 948 } else if (cmd_match(CMD_NOT_FOR_HEADER)) { 949 /* %c begin linkage-only (non-header) code. */ 950 OUT_BEGIN_CODE(); 951 } else if (cmd_match(CMD_OK_FOR_HEADER)) { 952 /* %e end linkage-only code. */ 953 OUT_END_CODE(); 954 } else if (buf[1] == '#') { 955 /* %# a comment in the skel. ignore. */ 956 } else { 957 flexfatal(_("bad line in skeleton file")); 958 } 959 } else if (do_copy) 960 outn(buf); 961 } /* end while */ 962 } 963 964 965 /* transition_struct_out - output a yy_trans_info structure 966 * 967 * outputs the yy_trans_info structure with the two elements, element_v and 968 * element_n. Formats the output with spaces and carriage returns. 969 */ 970 971 void 972 transition_struct_out(element_v, element_n) 973 int element_v, element_n; 974 { 975 976 /* short circuit any output */ 977 if (!gentables) 978 return; 979 980 out_dec2(" {%4d,%4d },", element_v, element_n); 981 982 datapos += TRANS_STRUCT_PRINT_LENGTH; 983 984 if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) { 985 outc('\n'); 986 987 if (++dataline % 10 == 0) 988 outc('\n'); 989 990 datapos = 0; 991 } 992 } 993 994 995 /* The following is only needed when building flex's parser using certain 996 * broken versions of bison. 997 */ 998 void * 999 yy_flex_xmalloc(size) 1000 int size; 1001 { 1002 void *result = malloc((size_t) size); 1003 1004 if (!result) 1005 flexfatal(_ 1006 ("memory allocation failed in yy_flex_xmalloc()")); 1007 1008 return result; 1009 } 1010 1011 1012 /* Remove all '\n' and '\r' characters, if any, from the end of str. 1013 * str can be any null-terminated string, or NULL. 1014 * returns str. */ 1015 char * 1016 chomp(str) 1017 char *str; 1018 { 1019 char *p = str; 1020 1021 if (!str || !*str) /* s is null or empty string */ 1022 return str; 1023 1024 /* find end of string minus one */ 1025 while (*p) 1026 ++p; 1027 --p; 1028 1029 /* eat newlines */ 1030 while (p >= str && (*p == '\r' || *p == '\n')) 1031 *p-- = 0; 1032 return str; 1033 } 1034