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