1 /* misc - miscellaneous flex routines */
4 * Copyright (c) 1990 The Regents of the University of California.
7 * This code is derived from software contributed to Berkeley by
10 * The United States Government has rights in this work pursuant
11 * to contract no. DE-AC03-76SF00098 between the United States
12 * Department of Energy and the University of California.
14 * Redistribution and use in source and binary forms are permitted provided
15 * that: (1) source distributions retain this entire copyright notice and
16 * comment, and (2) distributions including binaries display the following
17 * acknowledgement: ``This product includes software developed by the
18 * University of California, Berkeley and its contributors'' in the
19 * documentation or other materials provided with the distribution and in
20 * all advertising materials mentioning features or use of this software.
21 * Neither the name of the University nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31 "@(#) $Id: misc.c,v 1.4 1994/06/24 10:57:12 ceriel Exp $ (LBL)";
38 /* ANSI C does not guarantee that isascii() is defined */
40 #define isascii(c) ((c) <= 0177)
45 /* declare functions that have forward references */
47 void dataflush PROTO(());
48 int otoi PROTO((Char []));
51 /* action_out - write the actions from the temporary file to lex.yy.c
56 * Copies the action file up to %% (or end-of-file) to lex.yy.c
64 while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
65 if ( buf[0] == '%' && buf[1] == '%' )
72 /* allocate_array - allocate memory for an integer array of the given size */
74 void *allocate_array( size, element_size )
75 int size, element_size;
80 /* on 16-bit int machines (e.g., 80286) we might be trying to
81 * allocate more than a signed int can hold, and that won't
84 if ( element_size * size <= 0 )
85 flexfatal( "request for < 1 byte in allocate_array()" );
87 mem = (void *) malloc( (unsigned) (element_size * size) );
90 flexfatal( "memory allocation failed in allocate_array()" );
96 /* all_lower - true if a string is all lower-case
101 * true/false = all_lower( str );
110 if ( ! isascii( *str ) || ! islower( *str ) )
119 /* all_upper - true if a string is all upper-case
124 * true/false = all_upper( str );
133 if ( ! isascii( *str ) || ! isupper( (char) *str ) )
142 /* bubble - bubble sort an integer array in increasing order
149 * sorts the first n elements of array v and replaces them in
153 * v - the array to be sorted
154 * n - the number of elements of 'v' to be sorted */
160 register int i, j, k;
162 for ( i = n; i > 1; --i )
163 for ( j = 1; j < i; ++j )
164 if ( v[j] > v[j + 1] ) /* compare */
166 k = v[j]; /* exchange */
173 /* clower - replace upper-case letter to lower-case
185 return ( (isascii( c ) && isupper( c )) ? tolower( c ) : c );
189 /* copy_string - returns a dynamically allocated copy of a string
192 * char *str, *copy, *copy_string();
193 * copy = copy_string( str );
196 char *copy_string( str )
204 for ( c = str; *c; ++c )
207 copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
210 flexfatal( "dynamic memory failure in copy_string()" );
212 for ( c = copy; (*c++ = *str++); )
219 /* copy_unsigned_string -
220 * returns a dynamically allocated copy of a (potentially) unsigned string
223 * Char *str, *copy, *copy_unsigned_string();
224 * copy = copy_unsigned_string( str );
227 Char *copy_unsigned_string( str )
235 for ( c = str; *c; ++c )
238 copy = (Char *) malloc( (unsigned) ((c - str + 1) * sizeof( Char )) );
241 flexfatal( "dynamic memory failure in copy_unsigned_string()" );
243 for ( c = copy; (*c++ = *str++); )
250 /* cshell - shell sort a character array in increasing order
255 * int n, special_case_0;
256 * cshell( v, n, special_case_0 );
259 * does a shell sort of the first n elements of array v.
260 * If special_case_0 is true, then any element equal to 0
261 * is instead assumed to have infinite weight.
264 * v - array to be sorted
265 * n - number of elements of v to be sorted
268 void cshell( v, n, special_case_0 )
270 int n, special_case_0;
276 for ( gap = n / 2; gap > 0; gap = gap / 2 )
277 for ( i = gap; i < n; ++i )
278 for ( j = i - gap; j >= 0; j = j - gap )
282 if ( special_case_0 )
287 else if ( v[j] != 0 && v[j] <= v[jg] )
291 else if ( v[j] <= v[jg] )
301 /* dataend - finish up a block of data declarations
313 /* add terminator for initialization */
322 /* dataflush - flush generated data statements
333 if ( ++dataline >= NUMDATALINES )
335 /* put out a blank line so that the table is grouped into
336 * large blocks that enable the user to find elements easily
342 /* reset the number of characters written on the current line */
347 /* flexerror - report an error message and terminate
354 void flexerror( msg )
358 fprintf( stderr, "%s: %s\n", program_name, msg );
364 /* flexfatal - report a fatal error message and terminate
371 void flexfatal( msg )
375 fprintf( stderr, "%s: fatal internal error, %s\n", program_name, msg );
380 /* flex_gettime - return current time
383 * char *flex_gettime(), *time_str;
384 * time_str = flex_gettime();
387 * the routine name has the "flex_" prefix because of name clashes
391 /* include sys/types.h to use time_t and make lint happy */
395 #include <sys/types.h>
410 char *result, *ctime(), *copy_string();
412 t = time( (long *) 0 );
414 result = copy_string( ctime( &t ) );
416 /* get rid of trailing newline */
423 /* lerrif - report an error message formatted with one integer argument
428 * lerrif( msg, arg );
431 void lerrif( msg, arg )
436 char errmsg[MAXLINE];
437 (void) sprintf( errmsg, msg, arg );
442 /* lerrsf - report an error message formatted with one string argument
446 * lerrsf( msg, arg );
449 void lerrsf( msg, arg )
453 char errmsg[MAXLINE];
455 (void) sprintf( errmsg, msg, arg );
460 /* htoi - convert a hexadecimal digit string to an integer value
474 (void) sscanf( (char *) str, "%x", &result );
480 /* is_hex_digit - returns true if a character is a valid hex digit, false
484 * int true_or_false, is_hex_digit();
486 * val = is_hex_digit( ch );
489 int is_hex_digit( ch )
496 switch ( clower( ch ) )
512 /* line_directive_out - spit out a "# line" statement */
514 void line_directive_out( output_file_name )
515 FILE *output_file_name;
518 if ( infilename && gen_line_dirs )
519 fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
523 /* mk2data - generate a data statement for a two-dimensional array
529 * generates a data statement initializing the current 2-D array to "value"
531 void mk2data( value )
535 if ( datapos >= NUMDATAITEMS )
543 fputs( " ", stdout );
550 printf( "%5d", value );
554 /* mkdata - generate a data statement
560 * generates a data statement initializing the current array element to
567 if ( datapos >= NUMDATAITEMS )
575 fputs( " ", stdout );
582 printf( "%5d", value );
586 /* myctoi - return the integer represented by a string of digits
591 * val = myctoi( array );
601 (void) sscanf( (char *) array, "%d", &val );
607 /* myesc - return character corresponding to escape sequence
610 * Char array[], c, myesc();
611 * c = myesc( array );
626 case 'a': return ( '\a' );
627 case 'v': return ( '\v' );
629 case 'a': return ( '\007' );
630 case 'v': return ( '\013' );
633 case 'a': return ( '\a' );
634 case 'v': return ( '\v' );
636 case 'b': return ( '\b' );
637 case 'f': return ( '\f' );
638 case 'n': return ( '\n' );
639 case 'r': return ( '\r' );
640 case 't': return ( '\t' );
655 while ( isascii( array[sptr] ) && isdigit( array[sptr] ) )
656 /* don't increment inside loop control because if
657 * isdigit() is a macro it might expand into multiple
665 esc_char = otoi( array + 1 );
676 while ( isascii( array[sptr] ) && is_hex_digit( array[sptr] ) )
677 /* don't increment inside loop control because if
678 * isdigit() is a macro it might expand into multiple
686 esc_char = htoi( array + 2 );
699 /* otoi - convert an octal digit string to an integer value
713 (void) sscanf( (char *) str, "%o", &result );
719 /* readable_form - return the the human-readable form of a character
723 * char *readable_form();
724 * <string> = readable_form( c );
726 * The returned string is in static storage.
729 char *readable_form( c )
733 static char rform[10];
735 if ( (c >= 0 && c < 32) || c >= 127 )
739 case '\n': return ( "\\n" );
740 case '\t': return ( "\\t" );
741 case '\f': return ( "\\f" );
742 case '\r': return ( "\\r" );
743 case '\b': return ( "\\b" );
746 (void) sprintf( rform, "\\%.3o", c );
764 /* reallocate_array - increase the size of a dynamic array */
766 void *reallocate_array( array, size, element_size )
768 int size, element_size;
771 register void *new_array;
773 /* same worry as in allocate_array(): */
774 if ( size * element_size <= 0 )
775 flexfatal( "attempt to increase array size by less than 1 byte" );
778 (void *) realloc( (char *)array, (unsigned) (size * element_size ));
780 if ( new_array == NULL )
781 flexfatal( "attempt to increase array size failed" );
783 return ( new_array );
787 /* skelout - write out one section of the skeleton file
793 * Copies from skelfile to stdout until a line beginning with "%%" or
801 while ( fgets( buf, MAXLINE, skelfile ) != NULL )
802 if ( buf[0] == '%' && buf[1] == '%' )
805 fputs( buf, stdout );
809 /* transition_struct_out - output a yy_trans_info structure
812 * int element_v, element_n;
813 * transition_struct_out( element_v, element_n );
815 * outputs the yy_trans_info structure with the two elements, element_v and
816 * element_n. Formats the output with spaces and carriage returns.
819 void transition_struct_out( element_v, element_n )
820 int element_v, element_n;
823 printf( "%7d, %5d,", element_v, element_n );
825 datapos += TRANS_STRUCT_PRINT_LENGTH;
831 if ( ++dataline % 10 == 0 )