Annotation of src/usr.bin/lex/main.c, Revision 1.8
1.8 ! deraadt 1: /* $OpenBSD: main.c,v 1.6 2002/05/30 10:53:44 deraadt Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /* flex - tool to generate fast lexical analyzers */
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:
31: #ifndef lint
32: char copyright[] =
33: "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
34: All rights reserved.\n";
35: #endif /* not lint */
36:
1.8 ! deraadt 37: /* $Header: /cvs/src/usr.bin/lex/main.c,v 1.6 2002/05/30 10:53:44 deraadt Exp $ */
1.1 deraadt 38:
39:
40: #include "flexdef.h"
41: #include "version.h"
42:
43: static char flex_version[] = FLEX_VERSION;
44:
45:
46: /* declare functions that have forward references */
47:
48: void flexinit PROTO((int, char**));
49: void readin PROTO((void));
50: void set_up_initial_allocations PROTO((void));
51:
52: #ifdef NEED_ARGV_FIXUP
53: extern void argv_fixup PROTO((int *, char ***));
54: #endif
55:
56:
57: /* these globals are all defined and commented in flexdef.h */
58: int printstats, syntaxerror, eofseen, ddebug, trace, nowarn, spprdflt;
59: int interactive, caseins, lex_compat, do_yylineno, useecs, fulltbl, usemecs;
60: int fullspd, gen_line_dirs, performance_report, backing_up_report;
61: int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap, csize;
62: int yymore_used, reject, real_reject, continued_action, in_rule;
63: int yymore_really_used, reject_really_used;
64: int datapos, dataline, linenum, out_linenum;
65: FILE *skelfile = NULL;
66: int skel_ind = 0;
67: char *action_array;
68: int action_size, defs1_offset, prolog_offset, action_offset, action_index;
69: char *infilename = NULL, *outfilename = NULL;
70: int did_outfilename;
71: char *prefix, *yyclass;
72: int do_stdinit, use_stdout;
73: int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
74: int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
75: int current_mns, current_max_rules;
76: int num_rules, num_eof_rules, default_rule, lastnfa;
77: int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
78: int *accptnum, *assoc_rule, *state_type;
79: int *rule_type, *rule_linenum, *rule_useful;
80: int current_state_type;
81: int variable_trailing_context_rules;
82: int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
83: int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
84: int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
85: int tecbck[CSIZE + 1];
86: int lastsc, *scset, *scbol, *scxclu, *sceof;
87: int current_max_scs;
88: char **scname;
89: int current_max_dfa_size, current_max_xpairs;
90: int current_max_template_xpairs, current_max_dfas;
91: int lastdfa, *nxt, *chk, *tnxt;
92: int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz;
93: union dfaacc_union *dfaacc;
94: int *accsiz, *dhash, numas;
95: int numsnpairs, jambase, jamstate;
96: int lastccl, *cclmap, *ccllen, *cclng, cclreuse;
97: int current_maxccls, current_max_ccl_tbl_size;
98: Char *ccltbl;
99: char nmstr[MAXLINE];
100: int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
101: int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
102: int num_backing_up, bol_needed;
103: FILE *backing_up_file;
104: int end_of_buffer_state;
105: char **input_files;
106: int num_input_files;
107:
108: /* Make sure program_name is initialized so we don't crash if writing
109: * out an error message before getting the program name from argv[0].
110: */
111: char *program_name = "flex";
112:
113: #ifndef SHORT_FILE_NAMES
114: static char *outfile_template = "lex.%s.%s";
115: static char *backing_name = "lex.backup";
116: #else
117: static char *outfile_template = "lex%s.%s";
118: static char *backing_name = "lex.bck";
119: #endif
120:
121: #ifdef THINK_C
122: #include <console.h>
123: #endif
124:
125: #ifdef MS_DOS
126: extern unsigned _stklen = 16384;
127: #endif
128:
129: static char outfile_path[MAXLINE];
130: static int outfile_created = 0;
131: static char *skelname = NULL;
132:
133:
134: int main( argc, argv )
135: int argc;
136: char **argv;
137: {
138: int i;
139:
140: #ifdef THINK_C
141: argc = ccommand( &argv );
142: #endif
143: #ifdef NEED_ARGV_FIXUP
144: argv_fixup( &argc, &argv );
145: #endif
146:
147: flexinit( argc, argv );
148:
149: readin();
150:
151: ntod();
152:
153: for ( i = 1; i <= num_rules; ++i )
154: if ( ! rule_useful[i] && i != default_rule )
155: line_warning( _( "rule cannot be matched" ),
156: rule_linenum[i] );
157:
158: if ( spprdflt && ! reject && rule_useful[default_rule] )
159: line_warning(
160: _( "-s option given but default rule can be matched" ),
161: rule_linenum[default_rule] );
162:
163: /* Generate the C state transition tables from the DFA. */
164: make_tables();
165:
166: /* Note, flexend does not return. It exits with its argument
167: * as status.
168: */
169: flexend( 0 );
170:
171: return 0; /* keep compilers/lint happy */
172: }
173:
174:
175: /* check_options - check user-specified options */
176:
177: void check_options()
178: {
179: int i;
180:
181: if ( lex_compat )
182: {
183: if ( C_plus_plus )
184: flexerror( _( "Can't use -+ with -l option" ) );
185:
186: if ( fulltbl || fullspd )
187: flexerror( _( "Can't use -f or -F with -l option" ) );
188:
189: /* Don't rely on detecting use of yymore() and REJECT,
190: * just assume they'll be used.
191: */
192: yymore_really_used = reject_really_used = true;
193:
194: yytext_is_array = true;
195: do_yylineno = true;
196: use_read = false;
197: }
198:
199: if ( do_yylineno )
200: /* This should really be "maintain_backup_tables = true" */
201: reject_really_used = true;
202:
203: if ( csize == unspecified )
204: {
205: if ( (fulltbl || fullspd) && ! useecs )
206: csize = DEFAULT_CSIZE;
207: else
208: csize = CSIZE;
209: }
210:
211: if ( interactive == unspecified )
212: {
213: if ( fulltbl || fullspd )
214: interactive = false;
215: else
216: interactive = true;
217: }
218:
219: if ( fulltbl || fullspd )
220: {
221: if ( usemecs )
222: flexerror(
223: _( "-Cf/-CF and -Cm don't make sense together" ) );
224:
225: if ( interactive )
226: flexerror( _( "-Cf/-CF and -I are incompatible" ) );
227:
228: if ( lex_compat )
229: flexerror(
230: _( "-Cf/-CF are incompatible with lex-compatibility mode" ) );
231:
232: if ( do_yylineno )
233: flexerror(
234: _( "-Cf/-CF and %option yylineno are incompatible" ) );
235:
236: if ( fulltbl && fullspd )
237: flexerror( _( "-Cf and -CF are mutually exclusive" ) );
238: }
239:
240: if ( C_plus_plus && fullspd )
241: flexerror( _( "Can't use -+ with -CF option" ) );
242:
243: if ( C_plus_plus && yytext_is_array )
244: {
245: warn( _( "%array incompatible with -+ option" ) );
246: yytext_is_array = false;
247: }
248:
249: if ( useecs )
250: { /* Set up doubly-linked equivalence classes. */
251:
252: /* We loop all the way up to csize, since ecgroup[csize] is
253: * the position used for NUL characters.
254: */
255: ecgroup[1] = NIL;
256:
257: for ( i = 2; i <= csize; ++i )
258: {
259: ecgroup[i] = i - 1;
260: nextecm[i - 1] = i;
261: }
262:
263: nextecm[csize] = NIL;
264: }
265:
266: else
267: {
268: /* Put everything in its own equivalence class. */
269: for ( i = 1; i <= csize; ++i )
270: {
271: ecgroup[i] = i;
272: nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */
273: }
274: }
275:
276: if ( ! use_stdout )
277: {
278: FILE *prev_stdout;
279:
280: if ( ! did_outfilename )
281: {
282: char *suffix;
283:
284: if ( C_plus_plus )
285: suffix = "cc";
286: else
287: suffix = "c";
288:
1.8 ! deraadt 289: snprintf( outfile_path, sizeof outfile_path,
! 290: outfile_template, prefix, suffix );
1.1 deraadt 291:
292: outfilename = outfile_path;
293: }
294:
295: prev_stdout = freopen( outfilename, "w", stdout );
296:
297: if ( prev_stdout == NULL )
298: lerrsf( _( "could not create %s" ), outfilename );
299:
300: outfile_created = 1;
301: }
302:
303: if ( skelname && (skelfile = fopen( skelname, "r" )) == NULL )
304: lerrsf( _( "can't open skeleton file %s" ), skelname );
305:
306: if ( strcmp( prefix, "yy" ) )
307: {
308: #define GEN_PREFIX(name) out_str3( "#define yy%s %s%s\n", name, prefix, name )
309: if ( C_plus_plus )
310: GEN_PREFIX( "FlexLexer" );
311: else
312: {
313: GEN_PREFIX( "_create_buffer" );
314: GEN_PREFIX( "_delete_buffer" );
315: GEN_PREFIX( "_scan_buffer" );
316: GEN_PREFIX( "_scan_string" );
317: GEN_PREFIX( "_scan_bytes" );
318: GEN_PREFIX( "_flex_debug" );
319: GEN_PREFIX( "_init_buffer" );
320: GEN_PREFIX( "_flush_buffer" );
321: GEN_PREFIX( "_load_buffer_state" );
322: GEN_PREFIX( "_switch_to_buffer" );
323: GEN_PREFIX( "in" );
324: GEN_PREFIX( "leng" );
325: GEN_PREFIX( "lex" );
326: GEN_PREFIX( "out" );
327: GEN_PREFIX( "restart" );
328: GEN_PREFIX( "text" );
329:
330: if ( do_yylineno )
331: GEN_PREFIX( "lineno" );
332: }
333:
334: if ( do_yywrap )
335: GEN_PREFIX( "wrap" );
336:
337: outn( "" );
338: }
339:
340: if ( did_outfilename )
341: line_directive_out( stdout, 0 );
342:
343: skelout();
344: }
345:
346:
347: /* flexend - terminate flex
348: *
349: * note
350: * This routine does not return.
351: */
352:
353: void flexend( exit_status )
354: int exit_status;
355:
356: {
357: int tblsiz;
358: int unlink();
359:
360: if ( skelfile != NULL )
361: {
362: if ( ferror( skelfile ) )
363: lerrsf( _( "input error reading skeleton file %s" ),
364: skelname );
365:
366: else if ( fclose( skelfile ) )
367: lerrsf( _( "error closing skeleton file %s" ),
368: skelname );
369: }
370:
371: if ( exit_status != 0 && outfile_created )
372: {
373: if ( ferror( stdout ) )
374: lerrsf( _( "error writing output file %s" ),
375: outfilename );
376:
377: else if ( fclose( stdout ) )
378: lerrsf( _( "error closing output file %s" ),
379: outfilename );
380:
381: else if ( unlink( outfilename ) )
382: lerrsf( _( "error deleting output file %s" ),
383: outfilename );
384: }
385:
386: if ( backing_up_report && backing_up_file )
387: {
388: if ( num_backing_up == 0 )
389: fprintf( backing_up_file, _( "No backing up.\n" ) );
390: else if ( fullspd || fulltbl )
391: fprintf( backing_up_file,
392: _( "%d backing up (non-accepting) states.\n" ),
393: num_backing_up );
394: else
395: fprintf( backing_up_file,
396: _( "Compressed tables always back up.\n" ) );
397:
398: if ( ferror( backing_up_file ) )
399: lerrsf( _( "error writing backup file %s" ),
400: backing_name );
401:
402: else if ( fclose( backing_up_file ) )
403: lerrsf( _( "error closing backup file %s" ),
404: backing_name );
405: }
406:
407: if ( printstats )
408: {
409: fprintf( stderr, _( "%s version %s usage statistics:\n" ),
410: program_name, flex_version );
411:
412: fprintf( stderr, _( " scanner options: -" ) );
413:
414: if ( C_plus_plus )
415: putc( '+', stderr );
416: if ( backing_up_report )
417: putc( 'b', stderr );
418: if ( ddebug )
419: putc( 'd', stderr );
420: if ( caseins )
421: putc( 'i', stderr );
422: if ( lex_compat )
423: putc( 'l', stderr );
424: if ( performance_report > 0 )
425: putc( 'p', stderr );
426: if ( performance_report > 1 )
427: putc( 'p', stderr );
428: if ( spprdflt )
429: putc( 's', stderr );
430: if ( use_stdout )
431: putc( 't', stderr );
432: if ( printstats )
433: putc( 'v', stderr ); /* always true! */
434: if ( nowarn )
435: putc( 'w', stderr );
436: if ( interactive == false )
437: putc( 'B', stderr );
438: if ( interactive == true )
439: putc( 'I', stderr );
440: if ( ! gen_line_dirs )
441: putc( 'L', stderr );
442: if ( trace )
443: putc( 'T', stderr );
444:
445: if ( csize == unspecified )
446: /* We encountered an error fairly early on, so csize
447: * never got specified. Define it now, to prevent
448: * bogus table sizes being written out below.
449: */
450: csize = 256;
451:
452: if ( csize == 128 )
453: putc( '7', stderr );
454: else
455: putc( '8', stderr );
456:
457: fprintf( stderr, " -C" );
458:
459: if ( long_align )
460: putc( 'a', stderr );
461: if ( fulltbl )
462: putc( 'f', stderr );
463: if ( fullspd )
464: putc( 'F', stderr );
465: if ( useecs )
466: putc( 'e', stderr );
467: if ( usemecs )
468: putc( 'm', stderr );
469: if ( use_read )
470: putc( 'r', stderr );
471:
472: if ( did_outfilename )
473: fprintf( stderr, " -o%s", outfilename );
474:
475: if ( skelname )
476: fprintf( stderr, " -S%s", skelname );
477:
478: if ( strcmp( prefix, "yy" ) )
479: fprintf( stderr, " -P%s", prefix );
480:
481: putc( '\n', stderr );
482:
483: fprintf( stderr, _( " %d/%d NFA states\n" ),
484: lastnfa, current_mns );
485: fprintf( stderr, _( " %d/%d DFA states (%d words)\n" ),
486: lastdfa, current_max_dfas, totnst );
487: fprintf( stderr, _( " %d rules\n" ),
488: num_rules + num_eof_rules - 1 /* - 1 for def. rule */ );
489:
490: if ( num_backing_up == 0 )
491: fprintf( stderr, _( " No backing up\n" ) );
492: else if ( fullspd || fulltbl )
493: fprintf( stderr,
494: _( " %d backing-up (non-accepting) states\n" ),
495: num_backing_up );
496: else
497: fprintf( stderr,
498: _( " Compressed tables always back-up\n" ) );
499:
500: if ( bol_needed )
501: fprintf( stderr,
502: _( " Beginning-of-line patterns used\n" ) );
503:
504: fprintf( stderr, _( " %d/%d start conditions\n" ), lastsc,
505: current_max_scs );
506: fprintf( stderr,
507: _( " %d epsilon states, %d double epsilon states\n" ),
508: numeps, eps2 );
509:
510: if ( lastccl == 0 )
511: fprintf( stderr, _( " no character classes\n" ) );
512: else
513: fprintf( stderr,
514: _( " %d/%d character classes needed %d/%d words of storage, %d reused\n" ),
515: lastccl, current_maxccls,
516: cclmap[lastccl] + ccllen[lastccl],
517: current_max_ccl_tbl_size, cclreuse );
518:
519: fprintf( stderr, _( " %d state/nextstate pairs created\n" ),
520: numsnpairs );
521: fprintf( stderr, _( " %d/%d unique/duplicate transitions\n" ),
522: numuniq, numdup );
523:
524: if ( fulltbl )
525: {
526: tblsiz = lastdfa * numecs;
527: fprintf( stderr, _( " %d table entries\n" ), tblsiz );
528: }
529:
530: else
531: {
532: tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
533:
534: fprintf( stderr,
535: _( " %d/%d base-def entries created\n" ),
536: lastdfa + numtemps, current_max_dfas );
537: fprintf( stderr,
538: _( " %d/%d (peak %d) nxt-chk entries created\n" ),
539: tblend, current_max_xpairs, peakpairs );
540: fprintf( stderr,
541: _( " %d/%d (peak %d) template nxt-chk entries created\n" ),
542: numtemps * nummecs,
543: current_max_template_xpairs,
544: numtemps * numecs );
545: fprintf( stderr, _( " %d empty table entries\n" ),
546: nummt );
547: fprintf( stderr, _( " %d protos created\n" ),
548: numprots );
549: fprintf( stderr,
550: _( " %d templates created, %d uses\n" ),
551: numtemps, tmpuses );
552: }
553:
554: if ( useecs )
555: {
556: tblsiz = tblsiz + csize;
557: fprintf( stderr,
558: _( " %d/%d equivalence classes created\n" ),
559: numecs, csize );
560: }
561:
562: if ( usemecs )
563: {
564: tblsiz = tblsiz + numecs;
565: fprintf( stderr,
566: _( " %d/%d meta-equivalence classes created\n" ),
567: nummecs, csize );
568: }
569:
570: fprintf( stderr,
571: _( " %d (%d saved) hash collisions, %d DFAs equal\n" ),
572: hshcol, hshsave, dfaeql );
573: fprintf( stderr, _( " %d sets of reallocations needed\n" ),
574: num_reallocs );
575: fprintf( stderr, _( " %d total table entries needed\n" ),
576: tblsiz );
577: }
578:
579: exit( exit_status );
580: }
581:
582:
583: /* flexinit - initialize flex */
584:
585: void flexinit( argc, argv )
586: int argc;
587: char **argv;
588: {
589: int i, sawcmpflag;
1.3 millert 590: char *arg;
1.1 deraadt 591:
592: printstats = syntaxerror = trace = spprdflt = caseins = false;
593: lex_compat = C_plus_plus = backing_up_report = ddebug = fulltbl = false;
594: fullspd = long_align = nowarn = yymore_used = continued_action = false;
595: do_yylineno = yytext_is_array = in_rule = reject = do_stdinit = false;
596: yymore_really_used = reject_really_used = unspecified;
597: interactive = csize = unspecified;
598: do_yywrap = gen_line_dirs = usemecs = useecs = true;
599: performance_report = 0;
600: did_outfilename = 0;
601: prefix = "yy";
602: yyclass = 0;
603: use_read = use_stdout = false;
604:
605: sawcmpflag = false;
606:
607: /* Initialize dynamic array for holding the rule actions. */
608: action_size = 2048; /* default size of action array in bytes */
609: action_array = allocate_character_array( action_size );
610: defs1_offset = prolog_offset = action_offset = action_index = 0;
611: action_array[0] = '\0';
612:
613: program_name = argv[0];
614:
615: if ( program_name[0] != '\0' &&
616: program_name[strlen( program_name ) - 1] == '+' )
617: C_plus_plus = true;
618:
619: /* read flags */
620: for ( --argc, ++argv; argc ; --argc, ++argv )
621: {
622: arg = argv[0];
623:
624: if ( arg[0] != '-' || arg[1] == '\0' )
625: break;
626:
627: if ( arg[1] == '-' )
628: { /* --option */
629: if ( ! strcmp( arg, "--help" ) )
630: arg = "-h";
631:
632: else if ( ! strcmp( arg, "--version" ) )
633: arg = "-V";
634:
635: else if ( ! strcmp( arg, "--" ) )
636: { /* end of options */
637: --argc;
638: ++argv;
639: break;
640: }
641: }
642:
643: for ( i = 1; arg[i] != '\0'; ++i )
644: switch ( arg[i] )
645: {
646: case '+':
647: C_plus_plus = true;
648: break;
649:
650: case 'B':
651: interactive = false;
652: break;
653:
654: case 'b':
655: backing_up_report = true;
656: break;
657:
658: case 'c':
659: break;
660:
661: case 'C':
662: if ( i != 1 )
663: flexerror(
664: _( "-C flag must be given separately" ) );
665:
666: if ( ! sawcmpflag )
667: {
668: useecs = false;
669: usemecs = false;
670: fulltbl = false;
671: sawcmpflag = true;
672: }
673:
674: for ( ++i; arg[i] != '\0'; ++i )
675: switch ( arg[i] )
676: {
677: case 'a':
678: long_align =
679: true;
680: break;
681:
682: case 'e':
683: useecs = true;
684: break;
685:
686: case 'F':
687: fullspd = true;
688: break;
689:
690: case 'f':
691: fulltbl = true;
692: break;
693:
694: case 'm':
695: usemecs = true;
696: break;
697:
698: case 'r':
699: use_read = true;
700: break;
701:
702: default:
703: lerrif(
704: _( "unknown -C option '%c'" ),
705: (int) arg[i] );
706: break;
707: }
708:
709: goto get_next_arg;
710:
711: case 'd':
712: ddebug = true;
713: break;
714:
715: case 'f':
716: useecs = usemecs = false;
717: use_read = fulltbl = true;
718: break;
719:
720: case 'F':
721: useecs = usemecs = false;
722: use_read = fullspd = true;
723: break;
724:
725: case '?':
726: case 'h':
727: usage();
728: exit( 0 );
729:
730: case 'I':
731: interactive = true;
732: break;
733:
734: case 'i':
735: caseins = true;
736: break;
737:
738: case 'l':
739: lex_compat = true;
740: break;
741:
742: case 'L':
743: gen_line_dirs = false;
744: break;
745:
746: case 'n':
747: /* Stupid do-nothing deprecated
748: * option.
749: */
750: break;
751:
752: case 'o':
753: if ( i != 1 )
754: flexerror(
755: _( "-o flag must be given separately" ) );
756:
757: outfilename = arg + i + 1;
758: did_outfilename = 1;
759: goto get_next_arg;
760:
761: case 'P':
762: if ( i != 1 )
763: flexerror(
764: _( "-P flag must be given separately" ) );
765:
766: prefix = arg + i + 1;
767: goto get_next_arg;
768:
769: case 'p':
770: ++performance_report;
771: break;
772:
773: case 'S':
774: if ( i != 1 )
775: flexerror(
776: _( "-S flag must be given separately" ) );
777:
778: skelname = arg + i + 1;
779: goto get_next_arg;
780:
781: case 's':
782: spprdflt = true;
783: break;
784:
785: case 't':
786: use_stdout = true;
787: break;
788:
789: case 'T':
790: trace = true;
791: break;
792:
793: case 'v':
794: printstats = true;
795: break;
796:
797: case 'V':
798: printf( _( "%s version %s\n" ),
799: program_name, flex_version );
800: exit( 0 );
801:
802: case 'w':
803: nowarn = true;
804: break;
805:
806: case '7':
807: csize = 128;
808: break;
809:
810: case '8':
811: csize = CSIZE;
812: break;
813:
814: default:
815: fprintf( stderr,
816: _( "%s: unknown flag '%c'. For usage, try\n\t%s --help\n" ),
817: program_name, (int) arg[i],
818: program_name );
819: exit( 1 );
820: }
821:
822: /* Used by -C, -S, -o, and -P flags in lieu of a "continue 2"
823: * control.
824: */
825: get_next_arg: ;
826: }
827:
828: num_input_files = argc;
829: input_files = argv;
830: set_input_file( num_input_files > 0 ? input_files[0] : NULL );
831:
832: lastccl = lastsc = lastdfa = lastnfa = 0;
833: num_rules = num_eof_rules = default_rule = 0;
834: numas = numsnpairs = tmpuses = 0;
835: numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
836: numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
837: num_backing_up = onesp = numprots = 0;
838: variable_trailing_context_rules = bol_needed = false;
839:
840: out_linenum = linenum = sectnum = 1;
841: firstprot = NIL;
842:
843: /* Used in mkprot() so that the first proto goes in slot 1
844: * of the proto queue.
845: */
846: lastprot = 1;
847:
848: set_up_initial_allocations();
849: }
850:
851:
852: /* readin - read in the rules section of the input file(s) */
853:
854: void readin()
855: {
856: static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;";
857: static char yy_nostdinit[] =
858: "FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;";
859:
860: line_directive_out( (FILE *) 0, 1 );
861:
862: if ( yyparse() )
863: {
864: pinpoint_message( _( "fatal parse error" ) );
865: flexend( 1 );
866: }
867:
868: if ( syntaxerror )
869: flexend( 1 );
870:
871: if ( backing_up_report )
872: {
873: backing_up_file = fopen( backing_name, "w" );
874: if ( backing_up_file == NULL )
875: lerrsf(
876: _( "could not create backing-up info file %s" ),
877: backing_name );
878: }
879:
880: else
881: backing_up_file = NULL;
882:
883: if ( yymore_really_used == true )
884: yymore_used = true;
885: else if ( yymore_really_used == false )
886: yymore_used = false;
887:
888: if ( reject_really_used == true )
889: reject = true;
890: else if ( reject_really_used == false )
891: reject = false;
892:
893: if ( performance_report > 0 )
894: {
895: if ( lex_compat )
896: {
897: fprintf( stderr,
898: _( "-l AT&T lex compatibility option entails a large performance penalty\n" ) );
899: fprintf( stderr,
900: _( " and may be the actual source of other reported performance penalties\n" ) );
901: }
902:
903: else if ( do_yylineno )
904: {
905: fprintf( stderr,
906: _( "%%option yylineno entails a large performance penalty\n" ) );
907: }
908:
909: if ( performance_report > 1 )
910: {
911: if ( interactive )
912: fprintf( stderr,
913: _( "-I (interactive) entails a minor performance penalty\n" ) );
914:
915: if ( yymore_used )
916: fprintf( stderr,
917: _( "yymore() entails a minor performance penalty\n" ) );
918: }
919:
920: if ( reject )
921: fprintf( stderr,
922: _( "REJECT entails a large performance penalty\n" ) );
923:
924: if ( variable_trailing_context_rules )
925: fprintf( stderr,
926: _( "Variable trailing context rules entail a large performance penalty\n" ) );
927: }
928:
929: if ( reject )
930: real_reject = true;
931:
932: if ( variable_trailing_context_rules )
933: reject = true;
934:
935: if ( (fulltbl || fullspd) && reject )
936: {
937: if ( real_reject )
938: flexerror(
939: _( "REJECT cannot be used with -f or -F" ) );
940: else if ( do_yylineno )
941: flexerror(
942: _( "%option yylineno cannot be used with -f or -F" ) );
943: else
944: flexerror(
945: _( "variable trailing context rules cannot be used with -f or -F" ) );
946: }
947:
948: if ( reject )
949: outn( "\n#define YY_USES_REJECT" );
950:
951: if ( ! do_yywrap )
952: {
953: outn( "\n#define yywrap() 1" );
954: outn( "#define YY_SKIP_YYWRAP" );
955: }
956:
957: if ( ddebug )
958: outn( "\n#define FLEX_DEBUG" );
959:
960: if ( csize == 256 )
961: outn( "typedef unsigned char YY_CHAR;" );
962: else
963: outn( "typedef char YY_CHAR;" );
964:
965: if ( C_plus_plus )
966: {
967: outn( "#define yytext_ptr yytext" );
968:
969: if ( interactive )
970: outn( "#define YY_INTERACTIVE" );
971: }
972:
973: else
974: {
975: if ( do_stdinit )
976: {
977: outn( "#ifdef VMS" );
978: outn( "#ifndef __VMS_POSIX" );
979: outn( yy_nostdinit );
980: outn( "#else" );
981: outn( yy_stdinit );
982: outn( "#endif" );
983: outn( "#else" );
984: outn( yy_stdinit );
985: outn( "#endif" );
986: }
987:
988: else
989: outn( yy_nostdinit );
990: }
991:
992: if ( fullspd )
993: outn( "typedef yyconst struct yy_trans_info *yy_state_type;" );
994: else if ( ! C_plus_plus )
995: outn( "typedef int yy_state_type;" );
996:
997: if ( ddebug )
998: outn( "\n#define FLEX_DEBUG" );
999:
1000: if ( lex_compat )
1001: outn( "#define YY_FLEX_LEX_COMPAT" );
1002:
1003: if ( do_yylineno && ! C_plus_plus )
1004: {
1005: outn( "extern int yylineno;" );
1006: outn( "int yylineno = 1;" );
1007: }
1008:
1009: if ( C_plus_plus )
1010: {
1.4 deraadt 1011: outn( "\n#include <g++/FlexLexer.h>" );
1.1 deraadt 1012:
1013: if ( yyclass )
1014: {
1015: outn( "int yyFlexLexer::yylex()" );
1016: outn( "\t{" );
1017: outn(
1018: "\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );" );
1019: outn( "\treturn 0;" );
1020: outn( "\t}" );
1021:
1022: out_str( "\n#define YY_DECL int %s::yylex()\n",
1023: yyclass );
1024: }
1025: }
1026:
1027: else
1028: {
1029: if ( yytext_is_array )
1030: outn( "extern char yytext[];\n" );
1031:
1032: else
1033: {
1034: outn( "extern char *yytext;" );
1035: outn( "#define yytext_ptr yytext" );
1036: }
1037:
1038: if ( yyclass )
1039: flexerror(
1040: _( "%option yyclass only meaningful for C++ scanners" ) );
1041: }
1042:
1043: if ( useecs )
1044: numecs = cre8ecs( nextecm, ecgroup, csize );
1045: else
1046: numecs = csize;
1047:
1048: /* Now map the equivalence class for NUL to its expected place. */
1049: ecgroup[0] = ecgroup[csize];
1050: NUL_ec = ABS( ecgroup[0] );
1051:
1052: if ( useecs )
1053: ccl2ecl();
1054: }
1055:
1056:
1057: /* set_up_initial_allocations - allocate memory for internal tables */
1058:
1059: void set_up_initial_allocations()
1060: {
1061: current_mns = INITIAL_MNS;
1062: firstst = allocate_integer_array( current_mns );
1063: lastst = allocate_integer_array( current_mns );
1064: finalst = allocate_integer_array( current_mns );
1065: transchar = allocate_integer_array( current_mns );
1066: trans1 = allocate_integer_array( current_mns );
1067: trans2 = allocate_integer_array( current_mns );
1068: accptnum = allocate_integer_array( current_mns );
1069: assoc_rule = allocate_integer_array( current_mns );
1070: state_type = allocate_integer_array( current_mns );
1071:
1072: current_max_rules = INITIAL_MAX_RULES;
1073: rule_type = allocate_integer_array( current_max_rules );
1074: rule_linenum = allocate_integer_array( current_max_rules );
1075: rule_useful = allocate_integer_array( current_max_rules );
1076:
1077: current_max_scs = INITIAL_MAX_SCS;
1078: scset = allocate_integer_array( current_max_scs );
1079: scbol = allocate_integer_array( current_max_scs );
1080: scxclu = allocate_integer_array( current_max_scs );
1081: sceof = allocate_integer_array( current_max_scs );
1082: scname = allocate_char_ptr_array( current_max_scs );
1083:
1084: current_maxccls = INITIAL_MAX_CCLS;
1085: cclmap = allocate_integer_array( current_maxccls );
1086: ccllen = allocate_integer_array( current_maxccls );
1087: cclng = allocate_integer_array( current_maxccls );
1088:
1089: current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
1090: ccltbl = allocate_Character_array( current_max_ccl_tbl_size );
1091:
1092: current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
1093:
1094: current_max_xpairs = INITIAL_MAX_XPAIRS;
1095: nxt = allocate_integer_array( current_max_xpairs );
1096: chk = allocate_integer_array( current_max_xpairs );
1097:
1098: current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
1099: tnxt = allocate_integer_array( current_max_template_xpairs );
1100:
1101: current_max_dfas = INITIAL_MAX_DFAS;
1102: base = allocate_integer_array( current_max_dfas );
1103: def = allocate_integer_array( current_max_dfas );
1104: dfasiz = allocate_integer_array( current_max_dfas );
1105: accsiz = allocate_integer_array( current_max_dfas );
1106: dhash = allocate_integer_array( current_max_dfas );
1107: dss = allocate_int_ptr_array( current_max_dfas );
1108: dfaacc = allocate_dfaacc_union( current_max_dfas );
1109:
1110: nultrans = (int *) 0;
1111: }
1112:
1113:
1114: void usage()
1115: {
1116: FILE *f = stdout;
1117:
1118: fprintf( f,
1119: _( "%s [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -ooutput -Pprefix -Sskeleton]\n" ),
1120: program_name );
1121: fprintf( f, _( "\t[--help --version] [file ...]\n" ) );
1122:
1123: fprintf( f, _( "\t-b generate backing-up information to %s\n" ),
1124: backing_name );
1125: fprintf( f, _( "\t-c do-nothing POSIX option\n" ) );
1126: fprintf( f, _( "\t-d turn on debug mode in generated scanner\n" ) );
1127: fprintf( f, _( "\t-f generate fast, large scanner\n" ) );
1128: fprintf( f, _( "\t-h produce this help message\n" ) );
1129: fprintf( f, _( "\t-i generate case-insensitive scanner\n" ) );
1130: fprintf( f, _( "\t-l maximal compatibility with original lex\n" ) );
1131: fprintf( f, _( "\t-n do-nothing POSIX option\n" ) );
1132: fprintf( f, _( "\t-p generate performance report to stderr\n" ) );
1133: fprintf( f,
1134: _( "\t-s suppress default rule to ECHO unmatched text\n" ) );
1135:
1136: if ( ! did_outfilename )
1137: {
1.8 ! deraadt 1138: snprintf( outfile_path, sizeof outfile_path, outfile_template,
1.1 deraadt 1139: prefix, C_plus_plus ? "cc" : "c" );
1140: outfilename = outfile_path;
1141: }
1142:
1143: fprintf( f,
1144: _( "\t-t write generated scanner on stdout instead of %s\n" ),
1145: outfilename );
1146:
1147: fprintf( f,
1148: _( "\t-v write summary of scanner statistics to f\n" ) );
1149: fprintf( f, _( "\t-w do not generate warnings\n" ) );
1150: fprintf( f, _( "\t-B generate batch scanner (opposite of -I)\n" ) );
1151: fprintf( f,
1152: _( "\t-F use alternative fast scanner representation\n" ) );
1153: fprintf( f,
1154: _( "\t-I generate interactive scanner (opposite of -B)\n" ) );
1155: fprintf( f, _( "\t-L suppress #line directives in scanner\n" ) );
1156: fprintf( f, _( "\t-T %s should run in trace mode\n" ), program_name );
1157: fprintf( f, _( "\t-V report %s version\n" ), program_name );
1158: fprintf( f, _( "\t-7 generate 7-bit scanner\n" ) );
1159: fprintf( f, _( "\t-8 generate 8-bit scanner\n" ) );
1160: fprintf( f, _( "\t-+ generate C++ scanner class\n" ) );
1161: fprintf( f, _( "\t-? produce this help message\n" ) );
1162: fprintf( f,
1163: _( "\t-C specify degree of table compression (default is -Cem):\n" ) );
1164: fprintf( f,
1165: _( "\t\t-Ca trade off larger tables for better memory alignment\n" ) );
1166: fprintf( f, _( "\t\t-Ce construct equivalence classes\n" ) );
1167: fprintf( f,
1168: _( "\t\t-Cf do not compress scanner tables; use -f representation\n" ) );
1169: fprintf( f,
1170: _( "\t\t-CF do not compress scanner tables; use -F representation\n" ) );
1171: fprintf( f, _( "\t\t-Cm construct meta-equivalence classes\n" ) );
1172: fprintf( f,
1173: _( "\t\t-Cr use read() instead of stdio for scanner input\n" ) );
1174: fprintf( f, _( "\t-o specify output filename\n" ) );
1175: fprintf( f, _( "\t-P specify scanner prefix other than \"yy\"\n" ) );
1176: fprintf( f, _( "\t-S specify skeleton file\n" ) );
1177: fprintf( f, _( "\t--help produce this help message\n" ) );
1178: fprintf( f, _( "\t--version report %s version\n" ), program_name );
1179: }