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