Annotation of src/usr.bin/lex/misc.c, Revision 1.1.1.1
1.1 deraadt 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 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.
27: */
28:
29: /* $Header: /a/cvsroot/src/usr.bin/lex/misc.c,v 1.7 1995/05/05 05:35:35 jtc 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: }