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