xref: /openbsd/usr.bin/lex/main.c (revision 8529ddd3)
1 /*	$OpenBSD: main.c,v 1.14 2014/03/16 18:38:30 guenther Exp $	*/
2 
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  *
16  * Redistribution and use in source and binary forms, with or without
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.
34  */
35 
36 /* $Header: /home/cvs/src/usr.bin/lex/main.c,v 1.14 2014/03/16 18:38:30 guenther Exp $ */
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 const char outfile_template[] = "lex.%s.%s";
114 static const char backing_name[] = "lex.backup";
115 #else
116 static const char outfile_template[] = "lex%s.%s";
117 static const 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;
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 
288 			snprintf( outfile_path, sizeof outfile_path,
289 				outfile_template, prefix, suffix );
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;
589 	char *arg;
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 		{
1010 		outn( "\n#include <FlexLexer.h>" );
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,
1118 _( "%s [-bdfhilnpstvwBFILTV78+? -C[aefFmr] -ooutput -Pprefix -Sskeleton]\n" ),
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 		{
1136 		snprintf( outfile_path, sizeof outfile_path, outfile_template,
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 	}
1178