1 /* $NetBSD: misc.c,v 1.2 2016/01/09 17:38:57 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.2 2016/01/09 17:38:57 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 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 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 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 lerr (_("bad character '%s' detected in check_char()"), 237 readable_form (c)); 238 239 if (c >= csize) 240 lerr (_ 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 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 const char *str; 260 { 261 const char *c1; 262 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 Char *str; 288 { 289 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 /* lerr - report an error message */ 393 394 void lerr (const char *msg, ...) { 395 char errmsg[MAXLINE]; 396 va_list args; 397 398 va_start(args, msg); 399 vsnprintf (errmsg, sizeof(errmsg), msg, args); 400 va_end(args); 401 flexerror (errmsg); 402 } 403 404 405 /* lerr_fatal - as lerr, but call flexfatal */ 406 407 void lerr_fatal (const char *msg, ...) 408 { 409 char errmsg[MAXLINE]; 410 va_list args; 411 va_start(args, msg); 412 413 vsnprintf (errmsg, sizeof(errmsg), msg, args); 414 va_end(args); 415 flexfatal (errmsg); 416 } 417 418 419 /* line_directive_out - spit out a "#line" statement */ 420 421 void line_directive_out (output_file, do_infile) 422 FILE *output_file; 423 int do_infile; 424 { 425 char directive[MAXLINE], filename[MAXLINE]; 426 char *s1, *s2, *s3; 427 static const char line_fmt[] = "#line %d \"%s\"\n"; 428 429 if (!gen_line_dirs) 430 return; 431 432 s1 = do_infile ? infilename : "M4_YY_OUTFILE_NAME"; 433 434 if (do_infile && !s1) 435 s1 = "<stdin>"; 436 437 s2 = filename; 438 s3 = &filename[sizeof (filename) - 2]; 439 440 while (s2 < s3 && *s1) { 441 if (*s1 == '\\') 442 /* Escape the '\' */ 443 *s2++ = '\\'; 444 445 *s2++ = *s1++; 446 } 447 448 *s2 = '\0'; 449 450 if (do_infile) 451 snprintf (directive, sizeof(directive), line_fmt, linenum, filename); 452 else { 453 snprintf (directive, sizeof(directive), line_fmt, 0, filename); 454 } 455 456 /* If output_file is nil then we should put the directive in 457 * the accumulated actions. 458 */ 459 if (output_file) { 460 fputs (directive, output_file); 461 } 462 else 463 add_action (directive); 464 } 465 466 467 /* mark_defs1 - mark the current position in the action array as 468 * representing where the user's section 1 definitions end 469 * and the prolog begins 470 */ 471 void mark_defs1 () 472 { 473 defs1_offset = 0; 474 action_array[action_index++] = '\0'; 475 action_offset = prolog_offset = action_index; 476 action_array[action_index] = '\0'; 477 } 478 479 480 /* mark_prolog - mark the current position in the action array as 481 * representing the end of the action prolog 482 */ 483 void mark_prolog () 484 { 485 action_array[action_index++] = '\0'; 486 action_offset = action_index; 487 action_array[action_index] = '\0'; 488 } 489 490 491 /* mk2data - generate a data statement for a two-dimensional array 492 * 493 * Generates a data statement initializing the current 2-D array to "value". 494 */ 495 void mk2data (value) 496 int value; 497 { 498 /* short circuit any output */ 499 if (!gentables) 500 return; 501 502 if (datapos >= NUMDATAITEMS) { 503 outc (','); 504 dataflush (); 505 } 506 507 if (datapos == 0) 508 /* Indent. */ 509 out (" "); 510 511 else 512 outc (','); 513 514 ++datapos; 515 516 out_dec ("%5d", value); 517 } 518 519 520 /* mkdata - generate a data statement 521 * 522 * Generates a data statement initializing the current array element to 523 * "value". 524 */ 525 void mkdata (value) 526 int value; 527 { 528 /* short circuit any output */ 529 if (!gentables) 530 return; 531 532 if (datapos >= NUMDATAITEMS) { 533 outc (','); 534 dataflush (); 535 } 536 537 if (datapos == 0) 538 /* Indent. */ 539 out (" "); 540 else 541 outc (','); 542 543 ++datapos; 544 545 out_dec ("%5d", value); 546 } 547 548 549 /* myctoi - return the integer represented by a string of digits */ 550 551 int myctoi (array) 552 const char *array; 553 { 554 int val = 0; 555 556 (void) sscanf (array, "%d", &val); 557 558 return val; 559 } 560 561 562 /* myesc - return character corresponding to escape sequence */ 563 564 Char myesc (array) 565 Char array[]; 566 { 567 Char c, esc_char; 568 569 switch (array[1]) { 570 case 'b': 571 return '\b'; 572 case 'f': 573 return '\f'; 574 case 'n': 575 return '\n'; 576 case 'r': 577 return '\r'; 578 case 't': 579 return '\t'; 580 581 #if defined (__STDC__) 582 case 'a': 583 return '\a'; 584 case 'v': 585 return '\v'; 586 #else 587 case 'a': 588 return '\007'; 589 case 'v': 590 return '\013'; 591 #endif 592 593 case '0': 594 case '1': 595 case '2': 596 case '3': 597 case '4': 598 case '5': 599 case '6': 600 case '7': 601 { /* \<octal> */ 602 int sptr = 1; 603 604 while (isascii (array[sptr]) && 605 isdigit (array[sptr])) 606 /* Don't increment inside loop control 607 * because if isdigit() is a macro it might 608 * expand into multiple increments ... 609 */ 610 ++sptr; 611 612 c = array[sptr]; 613 array[sptr] = '\0'; 614 615 esc_char = otoi (array + 1); 616 617 array[sptr] = c; 618 619 return esc_char; 620 } 621 622 case 'x': 623 { /* \x<hex> */ 624 int sptr = 2; 625 626 while (isascii (array[sptr]) && 627 isxdigit (array[sptr])) 628 /* Don't increment inside loop control 629 * because if isdigit() is a macro it might 630 * expand into multiple increments ... 631 */ 632 ++sptr; 633 634 c = array[sptr]; 635 array[sptr] = '\0'; 636 637 esc_char = htoi (array + 2); 638 639 array[sptr] = c; 640 641 return esc_char; 642 } 643 644 default: 645 return array[1]; 646 } 647 } 648 649 650 /* otoi - convert an octal digit string to an integer value */ 651 652 int otoi (str) 653 Char str[]; 654 { 655 unsigned int result; 656 657 (void) sscanf ((char *) str, "%o", &result); 658 return result; 659 } 660 661 662 /* out - various flavors of outputing a (possibly formatted) string for the 663 * generated scanner, keeping track of the line count. 664 */ 665 666 void out (str) 667 const char *str; 668 { 669 fputs (str, stdout); 670 } 671 672 void out_dec (fmt, n) 673 const char *fmt; 674 int n; 675 { 676 fprintf (stdout, fmt, n); 677 } 678 679 void out_dec2 (fmt, n1, n2) 680 const char *fmt; 681 int n1, n2; 682 { 683 fprintf (stdout, fmt, n1, n2); 684 } 685 686 void out_hex (fmt, x) 687 const char *fmt; 688 unsigned int x; 689 { 690 fprintf (stdout, fmt, x); 691 } 692 693 void out_str (fmt, str) 694 const char *fmt, str[]; 695 { 696 fprintf (stdout,fmt, str); 697 } 698 699 void out_str3 (fmt, s1, s2, s3) 700 const char *fmt, s1[], s2[], s3[]; 701 { 702 fprintf (stdout,fmt, s1, s2, s3); 703 } 704 705 void out_str_dec (fmt, str, n) 706 const char *fmt, str[]; 707 int n; 708 { 709 fprintf (stdout,fmt, str, n); 710 } 711 712 void outc (c) 713 int c; 714 { 715 fputc (c, stdout); 716 } 717 718 void outn (str) 719 const char *str; 720 { 721 fputs (str,stdout); 722 fputc('\n',stdout); 723 } 724 725 /** Print "m4_define( [[def]], [[val]])m4_dnl\n". 726 * @param def The m4 symbol to define. 727 * @param val The definition; may be NULL. 728 */ 729 void out_m4_define (const char* def, const char* val) 730 { 731 const char * fmt = "m4_define( [[%s]], [[%s]])m4_dnl\n"; 732 fprintf(stdout, fmt, def, val?val:""); 733 } 734 735 736 /* readable_form - return the the human-readable form of a character 737 * 738 * The returned string is in static storage. 739 */ 740 741 char *readable_form (c) 742 int c; 743 { 744 static char rform[20]; 745 746 if ((c >= 0 && c < 32) || c >= 127) { 747 switch (c) { 748 case '\b': 749 return "\\b"; 750 case '\f': 751 return "\\f"; 752 case '\n': 753 return "\\n"; 754 case '\r': 755 return "\\r"; 756 case '\t': 757 return "\\t"; 758 759 #if defined (__STDC__) 760 case '\a': 761 return "\\a"; 762 case '\v': 763 return "\\v"; 764 #endif 765 766 default: 767 if(trace_hex) 768 snprintf (rform, sizeof(rform), "\\x%.2x", (unsigned int) c); 769 else 770 snprintf (rform, sizeof(rform), "\\%.3o", (unsigned int) c); 771 return rform; 772 } 773 } 774 775 else if (c == ' ') 776 return "' '"; 777 778 else { 779 rform[0] = c; 780 rform[1] = '\0'; 781 782 return rform; 783 } 784 } 785 786 787 /* reallocate_array - increase the size of a dynamic array */ 788 789 void *reallocate_array (array, size, element_size) 790 void *array; 791 int size; 792 size_t element_size; 793 { 794 void *new_array; 795 size_t num_bytes = element_size * size; 796 797 new_array = flex_realloc (array, num_bytes); 798 if (!new_array) 799 flexfatal (_("attempt to increase array size failed")); 800 801 return new_array; 802 } 803 804 805 /* skelout - write out one section of the skeleton file 806 * 807 * Description 808 * Copies skelfile or skel array to stdout until a line beginning with 809 * "%%" or EOF is found. 810 */ 811 void skelout () 812 { 813 char buf_storage[MAXLINE]; 814 char *buf = buf_storage; 815 bool do_copy = true; 816 817 /* "reset" the state by clearing the buffer and pushing a '1' */ 818 if(sko_len > 0) 819 sko_peek(&do_copy); 820 sko_len = 0; 821 sko_push(do_copy=true); 822 823 824 /* Loop pulling lines either from the skelfile, if we're using 825 * one, or from the skel[] array. 826 */ 827 while (skelfile ? 828 (fgets (buf, MAXLINE, skelfile) != NULL) : 829 ((buf = (char *) skel[skel_ind++]) != 0)) { 830 831 if (skelfile) 832 chomp (buf); 833 834 /* copy from skel array */ 835 if (buf[0] == '%') { /* control line */ 836 /* print the control line as a comment. */ 837 if (ddebug && buf[1] != '#') { 838 if (buf[strlen (buf) - 1] == '\\') 839 out_str ("/* %s */\\\n", buf); 840 else 841 out_str ("/* %s */\n", buf); 842 } 843 844 /* We've been accused of using cryptic markers in the skel. 845 * So we'll use emacs-style-hyphenated-commands. 846 * We might consider a hash if this if-else-if-else 847 * chain gets too large. 848 */ 849 #define cmd_match(s) (strncmp(buf,(s),strlen(s))==0) 850 851 if (buf[1] == '%') { 852 /* %% is a break point for skelout() */ 853 return; 854 } 855 else if (cmd_match (CMD_PUSH)){ 856 sko_push(do_copy); 857 if(ddebug){ 858 out_str("/*(state = (%s) */",do_copy?"true":"false"); 859 } 860 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : ""); 861 } 862 else if (cmd_match (CMD_POP)){ 863 sko_pop(&do_copy); 864 if(ddebug){ 865 out_str("/*(state = (%s) */",do_copy?"true":"false"); 866 } 867 out_str("%s\n", buf[strlen (buf) - 1] =='\\' ? "\\" : ""); 868 } 869 else if (cmd_match (CMD_IF_REENTRANT)){ 870 sko_push(do_copy); 871 do_copy = reentrant && do_copy; 872 } 873 else if (cmd_match (CMD_IF_NOT_REENTRANT)){ 874 sko_push(do_copy); 875 do_copy = !reentrant && do_copy; 876 } 877 else if (cmd_match(CMD_IF_BISON_BRIDGE)){ 878 sko_push(do_copy); 879 do_copy = bison_bridge_lval && do_copy; 880 } 881 else if (cmd_match(CMD_IF_NOT_BISON_BRIDGE)){ 882 sko_push(do_copy); 883 do_copy = !bison_bridge_lval && do_copy; 884 } 885 else if (cmd_match (CMD_ENDIF)){ 886 sko_pop(&do_copy); 887 } 888 else if (cmd_match (CMD_IF_TABLES_SER)) { 889 do_copy = do_copy && tablesext; 890 } 891 else if (cmd_match (CMD_TABLES_YYDMAP)) { 892 if (tablesext && yydmap_buf.elts) 893 outn ((char *) (yydmap_buf.elts)); 894 } 895 else if (cmd_match (CMD_DEFINE_YYTABLES)) { 896 out_str("#define YYTABLES_NAME \"%s\"\n", 897 tablesname?tablesname:"yytables"); 898 } 899 else if (cmd_match (CMD_IF_CPP_ONLY)) { 900 /* only for C++ */ 901 sko_push(do_copy); 902 do_copy = C_plus_plus; 903 } 904 else if (cmd_match (CMD_IF_C_ONLY)) { 905 /* %- only for C */ 906 sko_push(do_copy); 907 do_copy = !C_plus_plus; 908 } 909 else if (cmd_match (CMD_IF_C_OR_CPP)) { 910 /* %* for C and C++ */ 911 sko_push(do_copy); 912 do_copy = true; 913 } 914 else if (cmd_match (CMD_NOT_FOR_HEADER)) { 915 /* %c begin linkage-only (non-header) code. */ 916 OUT_BEGIN_CODE (); 917 } 918 else if (cmd_match (CMD_OK_FOR_HEADER)) { 919 /* %e end linkage-only code. */ 920 OUT_END_CODE (); 921 } 922 else if (buf[1] == '#') { 923 /* %# a comment in the skel. ignore. */ 924 } 925 else { 926 flexfatal (_("bad line in skeleton file")); 927 } 928 } 929 930 else if (do_copy) 931 outn (buf); 932 } /* end while */ 933 } 934 935 936 /* transition_struct_out - output a yy_trans_info structure 937 * 938 * outputs the yy_trans_info structure with the two elements, element_v and 939 * element_n. Formats the output with spaces and carriage returns. 940 */ 941 942 void transition_struct_out (element_v, element_n) 943 int element_v, element_n; 944 { 945 946 /* short circuit any output */ 947 if (!gentables) 948 return; 949 950 out_dec2 (" {%4d,%4d },", element_v, element_n); 951 952 datapos += TRANS_STRUCT_PRINT_LENGTH; 953 954 if (datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH) { 955 outc ('\n'); 956 957 if (++dataline % 10 == 0) 958 outc ('\n'); 959 960 datapos = 0; 961 } 962 } 963 964 965 /* The following is only needed when building flex's parser using certain 966 * broken versions of bison. 967 */ 968 void *yy_flex_xmalloc (size) 969 int size; 970 { 971 void *result = flex_alloc ((size_t) size); 972 973 if (!result) 974 flexfatal (_ 975 ("memory allocation failed in yy_flex_xmalloc()")); 976 977 return result; 978 } 979 980 981 /* zero_out - set a region of memory to 0 982 * 983 * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero. 984 */ 985 986 void zero_out (region_ptr, size_in_bytes) 987 char *region_ptr; 988 size_t size_in_bytes; 989 { 990 char *rp, *rp_end; 991 992 rp = region_ptr; 993 rp_end = region_ptr + size_in_bytes; 994 995 while (rp < rp_end) 996 *rp++ = 0; 997 } 998 999 /* Remove all '\n' and '\r' characters, if any, from the end of str. 1000 * str can be any null-terminated string, or NULL. 1001 * returns str. */ 1002 char *chomp (str) 1003 char *str; 1004 { 1005 char *p = str; 1006 1007 if (!str || !*str) /* s is null or empty string */ 1008 return str; 1009 1010 /* find end of string minus one */ 1011 while (*p) 1012 ++p; 1013 --p; 1014 1015 /* eat newlines */ 1016 while (p >= str && (*p == '\r' || *p == '\n')) 1017 *p-- = 0; 1018 return str; 1019 } 1020