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