|
|
1.1 root 1: /*-
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Vern Paxson.
7: *
8: * The United States Government has rights in this work pursuant
9: * to contract no. DE-AC03-76SF00098 between the United States
10: * Department of Energy and the University of California.
11: *
12: * Redistribution and use in source and binary forms are permitted provided
13: * that: (1) source distributions retain this entire copyright notice and
14: * comment, and (2) distributions including binaries display the following
15: * acknowledgement: ``This product includes software developed by the
16: * University of California, Berkeley and its contributors'' in the
17: * documentation or other materials provided with the distribution and in
18: * all advertising materials mentioning features or use of this software.
19: * Neither the name of the University nor the names of its contributors may
20: * be used to endorse or promote products derived from this software without
21: * specific prior written permission.
22: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
23: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
24: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25: */
26:
27: #ifndef lint
28: static char sccsid[] = "@(#)misc.c 5.2 (Berkeley) 6/18/90";
29: #endif /* not lint */
30:
31: /* misc - miscellaneous flex routines */
32:
33: #include <ctype.h>
34: #include "flexdef.h"
35:
36: /* ANSI C does not guarantee that isascii() is defined */
37: #ifndef isascii
38: #define isascii(c) ((c) <= 0177)
39: #endif
40:
41:
42:
43: /* declare functions that have forward references */
44:
45: void dataflush PROTO(());
46: int otoi PROTO((Char []));
47:
48:
49: /* action_out - write the actions from the temporary file to lex.yy.c
50: *
51: * synopsis
52: * action_out();
53: *
54: * Copies the action file up to %% (or end-of-file) to lex.yy.c
55: */
56:
57: void action_out()
58:
59: {
60: char buf[MAXLINE];
61:
62: while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
63: if ( buf[0] == '%' && buf[1] == '%' )
64: break;
65: else
66: fputs( buf, stdout );
67: }
68:
69:
70: /* allocate_array - allocate memory for an integer array of the given size */
71:
72: void *allocate_array( size, element_size )
73: int size, element_size;
74:
75: {
76: register void *mem;
77:
78: /* on 16-bit int machines (e.g., 80286) we might be trying to
79: * allocate more than a signed int can hold, and that won't
80: * work. Cheap test:
81: */
82: if ( element_size * size <= 0 )
83: flexfatal( "request for < 1 byte in allocate_array()" );
84:
85: mem = (void *) malloc( (unsigned) (element_size * size) );
86:
87: if ( mem == NULL )
88: flexfatal( "memory allocation failed in allocate_array()" );
89:
90: return ( mem );
91: }
92:
93:
94: /* all_lower - true if a string is all lower-case
95: *
96: * synopsis:
97: * Char *str;
98: * int all_lower();
99: * true/false = all_lower( str );
100: */
101:
102: int all_lower( str )
103: register Char *str;
104:
105: {
106: while ( *str )
107: {
108: if ( ! isascii( *str ) || ! islower( *str ) )
109: return ( 0 );
110: ++str;
111: }
112:
113: return ( 1 );
114: }
115:
116:
117: /* all_upper - true if a string is all upper-case
118: *
119: * synopsis:
120: * Char *str;
121: * int all_upper();
122: * true/false = all_upper( str );
123: */
124:
125: int all_upper( str )
126: register Char *str;
127:
128: {
129: while ( *str )
130: {
131: if ( ! isascii( *str ) || ! isupper( (char) *str ) )
132: return ( 0 );
133: ++str;
134: }
135:
136: return ( 1 );
137: }
138:
139:
140: /* bubble - bubble sort an integer array in increasing order
141: *
142: * synopsis
143: * int v[n], n;
144: * bubble( v, n );
145: *
146: * description
147: * sorts the first n elements of array v and replaces them in
148: * increasing order.
149: *
150: * passed
151: * v - the array to be sorted
152: * n - the number of elements of 'v' to be sorted */
153:
154: void bubble( v, n )
155: int v[], n;
156:
157: {
158: register int i, j, k;
159:
160: for ( i = n; i > 1; --i )
161: for ( j = 1; j < i; ++j )
162: if ( v[j] > v[j + 1] ) /* compare */
163: {
164: k = v[j]; /* exchange */
165: v[j] = v[j + 1];
166: v[j + 1] = k;
167: }
168: }
169:
170:
171: /* clower - replace upper-case letter to lower-case
172: *
173: * synopsis:
174: * Char clower();
175: * int c;
176: * c = clower( c );
177: */
178:
179: Char clower( c )
180: register int c;
181:
182: {
183: return ( (isascii( c ) && isupper( c )) ? tolower( c ) : c );
184: }
185:
186:
187: /* copy_string - returns a dynamically allocated copy of a string
188: *
189: * synopsis
190: * char *str, *copy, *copy_string();
191: * copy = copy_string( str );
192: */
193:
194: char *copy_string( str )
195: register char *str;
196:
197: {
198: register char *c;
199: char *copy;
200:
201: /* find length */
202: for ( c = str; *c; ++c )
203: ;
204:
205: copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
206:
207: if ( copy == NULL )
208: flexfatal( "dynamic memory failure in copy_string()" );
209:
210: for ( c = copy; (*c++ = *str++); )
211: ;
212:
213: return ( copy );
214: }
215:
216:
217: /* copy_unsigned_string -
218: * returns a dynamically allocated copy of a (potentially) unsigned string
219: *
220: * synopsis
221: * Char *str, *copy, *copy_unsigned_string();
222: * copy = copy_unsigned_string( str );
223: */
224:
225: Char *copy_unsigned_string( str )
226: register Char *str;
227:
228: {
229: register Char *c;
230: Char *copy;
231:
232: /* find length */
233: for ( c = str; *c; ++c )
234: ;
235:
236: copy = (Char *) malloc( (unsigned) ((c - str + 1) * sizeof( Char )) );
237:
238: if ( copy == NULL )
239: flexfatal( "dynamic memory failure in copy_unsigned_string()" );
240:
241: for ( c = copy; (*c++ = *str++); )
242: ;
243:
244: return ( copy );
245: }
246:
247:
248: /* cshell - shell sort a character array in increasing order
249: *
250: * synopsis
251: *
252: * Char v[n];
253: * int n, special_case_0;
254: * cshell( v, n, special_case_0 );
255: *
256: * description
257: * does a shell sort of the first n elements of array v.
258: * If special_case_0 is true, then any element equal to 0
259: * is instead assumed to have infinite weight.
260: *
261: * passed
262: * v - array to be sorted
263: * n - number of elements of v to be sorted
264: */
265:
266: void cshell( v, n, special_case_0 )
267: Char v[];
268: int n, special_case_0;
269:
270: {
271: int gap, i, j, jg;
272: Char k;
273:
274: for ( gap = n / 2; gap > 0; gap = gap / 2 )
275: for ( i = gap; i < n; ++i )
276: for ( j = i - gap; j >= 0; j = j - gap )
277: {
278: jg = j + gap;
279:
280: if ( special_case_0 )
281: {
282: if ( v[jg] == 0 )
283: break;
284:
285: else if ( v[j] != 0 && v[j] <= v[jg] )
286: break;
287: }
288:
289: else if ( v[j] <= v[jg] )
290: break;
291:
292: k = v[j];
293: v[j] = v[jg];
294: v[jg] = k;
295: }
296: }
297:
298:
299: /* dataend - finish up a block of data declarations
300: *
301: * synopsis
302: * dataend();
303: */
304:
305: void dataend()
306:
307: {
308: if ( datapos > 0 )
309: dataflush();
310:
311: /* add terminator for initialization */
312: puts( " } ;\n" );
313:
314: dataline = 0;
315: datapos = 0;
316: }
317:
318:
319:
320: /* dataflush - flush generated data statements
321: *
322: * synopsis
323: * dataflush();
324: */
325:
326: void dataflush()
327:
328: {
329: putchar( '\n' );
330:
331: if ( ++dataline >= NUMDATALINES )
332: {
333: /* put out a blank line so that the table is grouped into
334: * large blocks that enable the user to find elements easily
335: */
336: putchar( '\n' );
337: dataline = 0;
338: }
339:
340: /* reset the number of characters written on the current line */
341: datapos = 0;
342: }
343:
344:
345: /* flexerror - report an error message and terminate
346: *
347: * synopsis
348: * char msg[];
349: * flexerror( msg );
350: */
351:
352: void flexerror( msg )
353: char msg[];
354:
355: {
356: fprintf( stderr, "%s: %s\n", program_name, msg );
357:
358: flexend( 1 );
359: }
360:
361:
362: /* flexfatal - report a fatal error message and terminate
363: *
364: * synopsis
365: * char msg[];
366: * flexfatal( msg );
367: */
368:
369: void flexfatal( msg )
370: char msg[];
371:
372: {
373: fprintf( stderr, "%s: fatal internal error, %s\n", program_name, msg );
374: flexend( 1 );
375: }
376:
377:
378: /* flex_gettime - return current time
379: *
380: * synopsis
381: * char *flex_gettime(), *time_str;
382: * time_str = flex_gettime();
383: *
384: * note
385: * the routine name has the "flex_" prefix because of name clashes
386: * with Turbo-C
387: */
388:
389: /* include sys/types.h to use time_t and make lint happy */
390:
391: #ifndef MS_DOS
392: #ifndef VMS
393: #include <sys/types.h>
394: #else
395: #include <types.h>
396: #endif
397: #endif
398:
399: #ifdef MS_DOS
400: #include <time.h>
401: typedef long time_t;
402: #endif
403:
404: char *flex_gettime()
405:
406: {
407: time_t t, time();
408: char *result, *ctime(), *copy_string();
409:
410: t = time( (long *) 0 );
411:
412: result = copy_string( ctime( &t ) );
413:
414: /* get rid of trailing newline */
415: result[24] = '\0';
416:
417: return ( result );
418: }
419:
420:
421: /* lerrif - report an error message formatted with one integer argument
422: *
423: * synopsis
424: * char msg[];
425: * int arg;
426: * lerrif( msg, arg );
427: */
428:
429: void lerrif( msg, arg )
430: char msg[];
431: int arg;
432:
433: {
434: char errmsg[MAXLINE];
435: (void) sprintf( errmsg, msg, arg );
436: flexerror( errmsg );
437: }
438:
439:
440: /* lerrsf - report an error message formatted with one string argument
441: *
442: * synopsis
443: * char msg[], arg[];
444: * lerrsf( msg, arg );
445: */
446:
447: void lerrsf( msg, arg )
448: char msg[], arg[];
449:
450: {
451: char errmsg[MAXLINE];
452:
453: (void) sprintf( errmsg, msg, arg );
454: flexerror( errmsg );
455: }
456:
457:
458: /* htoi - convert a hexadecimal digit string to an integer value
459: *
460: * synopsis:
461: * int val, htoi();
462: * Char str[];
463: * val = htoi( str );
464: */
465:
466: int htoi( str )
467: Char str[];
468:
469: {
470: int result;
471:
472: (void) sscanf( (char *) str, "%x", &result );
473:
474: return ( result );
475: }
476:
477:
478: /* line_directive_out - spit out a "# line" statement */
479:
480: void line_directive_out( output_file_name )
481: FILE *output_file_name;
482:
483: {
484: if ( infilename && gen_line_dirs )
485: fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
486: }
487:
488:
489: /* mk2data - generate a data statement for a two-dimensional array
490: *
491: * synopsis
492: * int value;
493: * mk2data( value );
494: *
495: * generates a data statement initializing the current 2-D array to "value"
496: */
497: void mk2data( value )
498: int value;
499:
500: {
501: if ( datapos >= NUMDATAITEMS )
502: {
503: putchar( ',' );
504: dataflush();
505: }
506:
507: if ( datapos == 0 )
508: /* indent */
509: fputs( " ", stdout );
510:
511: else
512: putchar( ',' );
513:
514: ++datapos;
515:
516: printf( "%5d", value );
517: }
518:
519:
520: /* mkdata - generate a data statement
521: *
522: * synopsis
523: * int value;
524: * mkdata( value );
525: *
526: * generates a data statement initializing the current array element to
527: * "value"
528: */
529: void mkdata( value )
530: int value;
531:
532: {
533: if ( datapos >= NUMDATAITEMS )
534: {
535: putchar( ',' );
536: dataflush();
537: }
538:
539: if ( datapos == 0 )
540: /* indent */
541: fputs( " ", stdout );
542:
543: else
544: putchar( ',' );
545:
546: ++datapos;
547:
548: printf( "%5d", value );
549: }
550:
551:
552: /* myctoi - return the integer represented by a string of digits
553: *
554: * synopsis
555: * Char array[];
556: * int val, myctoi();
557: * val = myctoi( array );
558: *
559: */
560:
561: int myctoi( array )
562: Char array[];
563:
564: {
565: int val = 0;
566:
567: (void) sscanf( (char *) array, "%d", &val );
568:
569: return ( val );
570: }
571:
572:
573: /* myesc - return character corresponding to escape sequence
574: *
575: * synopsis
576: * Char array[], c, myesc();
577: * c = myesc( array );
578: *
579: */
580:
581: Char myesc( array )
582: Char array[];
583:
584: {
585: switch ( array[1] )
586: {
587: case 'a': return ( '\a' );
588: case 'b': return ( '\b' );
589: case 'f': return ( '\f' );
590: case 'n': return ( '\n' );
591: case 'r': return ( '\r' );
592: case 't': return ( '\t' );
593: case 'v': return ( '\v' );
594:
595: case 'x':
596: /* fall through */
597:
598: case '0':
599: case '1':
600: case '2':
601: case '3':
602: case '4':
603: case '5':
604: case '6':
605: case '7':
606: case '8':
607: case '9':
608:
609: { /* \<octal> or \x<hex> */
610: Char c, esc_char;
611: register int sptr = 1;
612:
613: if ( array[1] == 'x' )
614: ++sptr;
615:
616: while ( isascii( array[sptr] ) && isdigit( array[sptr] ) )
617: /* don't increment inside loop control because if
618: * isdigit() is a macro it will expand it to two
619: * increments ...
620: */
621: ++sptr;
622:
623: c = array[sptr];
624: array[sptr] = '\0';
625:
626: if ( array[1] == 'x' )
627: esc_char = htoi( array + 2 );
628: else
629: esc_char = otoi( array + 1 );
630:
631: array[sptr] = c;
632:
633: return ( esc_char );
634: }
635:
636: default:
637: return ( array[1] );
638: }
639: }
640:
641:
642: /* otoi - convert an octal digit string to an integer value
643: *
644: * synopsis:
645: * int val, otoi();
646: * Char str[];
647: * val = otoi( str );
648: */
649:
650: int otoi( str )
651: Char str[];
652:
653: {
654: int result;
655:
656: (void) sscanf( (char *) str, "%o", &result );
657:
658: return ( result );
659: }
660:
661:
662: /* readable_form - return the the human-readable form of a character
663: *
664: * synopsis:
665: * int c;
666: * char *readable_form();
667: * <string> = readable_form( c );
668: *
669: * The returned string is in static storage.
670: */
671:
672: char *readable_form( c )
673: register int c;
674:
675: {
676: static char rform[10];
677:
678: if ( (c >= 0 && c < 32) || c >= 127 )
679: {
680: switch ( c )
681: {
682: case '\n': return ( "\\n" );
683: case '\t': return ( "\\t" );
684: case '\f': return ( "\\f" );
685: case '\r': return ( "\\r" );
686: case '\b': return ( "\\b" );
687:
688: default:
689: (void) sprintf( rform, "\\%.3o", c );
690: return ( rform );
691: }
692: }
693:
694: else if ( c == ' ' )
695: return ( "' '" );
696:
697: else
698: {
699: rform[0] = c;
700: rform[1] = '\0';
701:
702: return ( rform );
703: }
704: }
705:
706:
707: /* reallocate_array - increase the size of a dynamic array */
708:
709: void *reallocate_array( array, size, element_size )
710: void *array;
711: int size, element_size;
712:
713: {
714: register void *new_array;
715:
716: /* same worry as in allocate_array(): */
717: if ( size * element_size <= 0 )
718: flexfatal( "attempt to increase array size by less than 1 byte" );
719:
720: new_array =
721: (void *) realloc( (char *)array, (unsigned) (size * element_size ));
722:
723: if ( new_array == NULL )
724: flexfatal( "attempt to increase array size failed" );
725:
726: return ( new_array );
727: }
728:
729:
730: /* skelout - write out one section of the skeleton file
731: *
732: * synopsis
733: * skelout();
734: *
735: * DESCRIPTION
736: * Copies from skelfile to stdout until a line beginning with "%%" or
737: * EOF is found.
738: */
739: void skelout()
740:
741: {
742: char buf[MAXLINE];
743:
744: while ( fgets( buf, MAXLINE, skelfile ) != NULL )
745: if ( buf[0] == '%' && buf[1] == '%' )
746: break;
747: else
748: fputs( buf, stdout );
749: }
750:
751:
752: /* transition_struct_out - output a yy_trans_info structure
753: *
754: * synopsis
755: * int element_v, element_n;
756: * transition_struct_out( element_v, element_n );
757: *
758: * outputs the yy_trans_info structure with the two elements, element_v and
759: * element_n. Formats the output with spaces and carriage returns.
760: */
761:
762: void transition_struct_out( element_v, element_n )
763: int element_v, element_n;
764:
765: {
766: printf( "%7d, %5d,", element_v, element_n );
767:
768: datapos += TRANS_STRUCT_PRINT_LENGTH;
769:
770: if ( datapos >= 75 )
771: {
772: putchar( '\n' );
773:
774: if ( ++dataline % 10 == 0 )
775: putchar( '\n' );
776:
777: datapos = 0;
778: }
779: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.