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