• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
action_define(defname,value)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 
add_action(new_text)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 
allocate_array(size,element_size)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 
all_lower(str)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 
all_upper(str)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 
bubble(v,n)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 
check_char(c)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 
clower(c)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 
copy_string(str)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 
copy_unsigned_string(str)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 
cshell(v,n,special_case_0)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 
dataend()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 
dataflush()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 
flexerror(msg)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 
flexfatal(msg)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 
htoi(str)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 
lerrif(msg,arg)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 
lerrsf(msg,arg)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 
line_directive_out(output_file,do_infile)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  */
mark_defs1()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  */
mark_prolog()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  */
mk2data(value)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  */
mkdata(value)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 
myctoi(array)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 
myesc(array)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 
otoi(str)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 
out(str)622 void out( str )
623 const char str[];
624 	{
625 	fputs( str, stdout );
626 	out_line_count( str );
627 	}
628 
out_dec(fmt,n)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 
out_dec2(fmt,n1,n2)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 
out_hex(fmt,x)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 
out_line_count(str)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 
out_str(fmt,str)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 
out_str3(fmt,s1,s2,s3)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 
out_str_dec(fmt,str,n)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 
outc(c)690 void outc( c )
691 int c;
692 	{
693 	putc( c, stdout );
694 
695 	if ( c == '\n' )
696 		++out_linenum;
697 	}
698 
outn(str)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 
readable_form(c)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 
reallocate_array(array,size,element_size)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  */
skelout()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 
transition_struct_out(element_v,element_n)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  */
yy_flex_xmalloc(size)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 
zero_out(region_ptr,size_in_bytes)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