fatbase

portable OpenBSD tools
git clone git://git.2f30.org/fatbase
Log | Files | Refs

main.c (28659B)


      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: /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 	}