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