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