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