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