xref: /openbsd/usr.bin/lex/main.c (revision 9b7c3dbb)
1 /*	$OpenBSD: main.c,v 1.25 2015/12/11 00:08:43 mmcc Exp $	*/
2 
3 /* flex - tool to generate fast lexical analyzers */
4 
5 /*  Copyright (c) 1990 The Regents of the University of California. */
6 /*  All rights reserved. */
7 
8 /*  This code is derived from software contributed to Berkeley by */
9 /*  Vern Paxson. */
10 
11 /*  The United States Government has rights in this work pursuant */
12 /*  to contract no. DE-AC03-76SF00098 between the United States */
13 /*  Department of Energy and the University of California. */
14 
15 /*  This file is part of flex. */
16 
17 /*  Redistribution and use in source and binary forms, with or without */
18 /*  modification, are permitted provided that the following conditions */
19 /*  are met: */
20 
21 /*  1. Redistributions of source code must retain the above copyright */
22 /*     notice, this list of conditions and the following disclaimer. */
23 /*  2. Redistributions in binary form must reproduce the above copyright */
24 /*     notice, this list of conditions and the following disclaimer in the */
25 /*     documentation and/or other materials provided with the distribution. */
26 
27 /*  Neither the name of the University nor the names of its contributors */
28 /*  may be used to endorse or promote products derived from this software */
29 /*  without specific prior written permission. */
30 
31 /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
32 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
33 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
34 /*  PURPOSE. */
35 
36 
37 
38 #include "flexdef.h"
39 #include "version.h"
40 #include "options.h"
41 #include "tables.h"
42 
43 static char flex_version[] = FLEX_VERSION;
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 static char *basename2 PROTO((char *path, int should_strip_ext));
51 
52 
53 /* these globals are all defined and commented in flexdef.h */
54 int printstats, syntaxerror, eofseen, ddebug, trace, nowarn, spprdflt;
55 int interactive, lex_compat, posix_compat, do_yylineno, useecs, fulltbl,
56  usemecs;
57 int fullspd, gen_line_dirs, performance_report, backing_up_report;
58 int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap, csize;
59 int reentrant, bison_bridge_lval, bison_bridge_lloc;
60 int yymore_used, reject, real_reject, continued_action, in_rule;
61 int yymore_really_used, reject_really_used;
62 int datapos, dataline, linenum;
63 FILE *skelfile = NULL;
64 int skel_ind = 0;
65 char *action_array;
66 int action_size, defs1_offset, prolog_offset, action_offset, action_index;
67 char *infilename = NULL, *outfilename = NULL, *headerfilename = NULL;
68 int did_outfilename;
69 char *prefix, *yyclass, *extra_type = NULL;
70 int do_stdinit, use_stdout;
71 int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
72 int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
73 int maximum_mns, current_mns, current_max_rules;
74 int num_rules, num_eof_rules, default_rule, lastnfa;
75 int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
76 int *accptnum, *assoc_rule, *state_type;
77 int *rule_type, *rule_linenum, *rule_useful;
78 int current_state_type;
79 int variable_trailing_context_rules;
80 int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
81 int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
82 int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
83 int tecbck[CSIZE + 1];
84 int lastsc, *scset, *scbol, *scxclu, *sceof;
85 int current_max_scs;
86 char **scname;
87 int current_max_dfa_size, current_max_xpairs;
88 int current_max_template_xpairs, current_max_dfas;
89 int lastdfa, *nxt, *chk, *tnxt;
90 int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz;
91 union dfaacc_union *dfaacc;
92 int *accsiz, *dhash, numas;
93 int numsnpairs, jambase, jamstate;
94 int lastccl, *cclmap, *ccllen, *cclng, cclreuse;
95 int current_maxccls, current_max_ccl_tbl_size;
96 u_char *ccltbl;
97 char nmstr[MAXLINE];
98 int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
99 int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
100 int num_backing_up, bol_needed;
101 FILE *backing_up_file;
102 int end_of_buffer_state;
103 char **input_files;
104 int num_input_files;
105 jmp_buf flex_main_jmp_buf;
106 bool *rule_has_nl, *ccl_has_nl;
107 int nlch = '\n';
108 bool ansi_func_defs, ansi_func_protos;
109 
110 bool tablesext, tablesverify, gentables;
111 char *tablesfilename = 0, *tablesname = 0;
112 struct yytbl_writer tableswr;
113 
114 /* Make sure program_name is initialized so we don't crash if writing
115  * out an error message before getting the program name from argv[0].
116  */
117 char *program_name = "flex";
118 
119 static const char *outfile_template = "lex.%s.%s";
120 static const char *backing_name = "lex.backup";
121 static const char *tablesfile_template = "lex.%s.tables";
122 
123 /* From scan.l */
124 extern FILE *yyout;
125 
126 static char outfile_path[MAXLINE];
127 static int outfile_created = 0;
128 static char *skelname = NULL;
129 static int _stdout_closed = 0;	/* flag to prevent double-fclose() on stdout. */
130 const char *escaped_qstart = "[[]]M4_YY_NOOP[M4_YY_NOOP[M4_YY_NOOP[[]]";
131 const char *escaped_qend = "[[]]M4_YY_NOOP]M4_YY_NOOP]M4_YY_NOOP[[]]";
132 
133 /* For debugging. The max number of filters to apply to skeleton. */
134 static int preproc_level = 1000;
135 
136 int flex_main PROTO((int argc, char *argv[]));
137 int main PROTO((int argc, char *argv[]));
138 
139 int
140 flex_main(argc, argv)
141 	int argc;
142 	char *argv[];
143 {
144 	int i, exit_status, child_status;
145 
146 	/*
147 	 * Set a longjmp target. Yes, I know it's a hack, but it gets worse:
148 	 * The return value of setjmp, if non-zero, is the desired exit code
149 	 * PLUS ONE. For example, if you want 'main' to return with code '2',
150 	 * then call longjmp() with an argument of 3. This is because it is
151 	 * invalid to specify a value of 0 to longjmp. FLEX_EXIT(n) should be
152 	 * used instead of exit(n);
153 	 */
154 	exit_status = setjmp(flex_main_jmp_buf);
155 	if (exit_status) {
156 		if (stdout && !_stdout_closed && !ferror(stdout)) {
157 			fflush(stdout);
158 			fclose(stdout);
159 		}
160 		while (wait(&child_status) > 0) {
161 			if (!WIFEXITED(child_status)
162 			    || WEXITSTATUS(child_status) != 0) {
163 				/*
164 				 * report an error of a child
165 				 */
166 				if (exit_status <= 1)
167 					exit_status = 2;
168 
169 			}
170 		}
171 		return exit_status - 1;
172 	}
173 	flexinit(argc, argv);
174 
175 	readin();
176 
177 	skelout();
178 	/* %% [1.5] DFA */
179 	ntod();
180 
181 	for (i = 1; i <= num_rules; ++i)
182 		if (!rule_useful[i] && i != default_rule)
183 			line_warning(_("rule cannot be matched"),
184 			    rule_linenum[i]);
185 
186 	if (spprdflt && !reject && rule_useful[default_rule])
187 		line_warning(_
188 		    ("-s option given but default rule can be matched"),
189 		    rule_linenum[default_rule]);
190 
191 	/* Generate the C state transition tables from the DFA. */
192 	make_tables();
193 
194 	/*
195 	 * Note, flexend does not return.  It exits with its argument as
196 	 * status.
197 	 */
198 	flexend(0);
199 
200 	return 0;		/* keep compilers/lint happy */
201 }
202 
203 /* Wrapper around flex_main, so flex_main can be built as a library. */
204 int
205 main(argc, argv)
206 	int argc;
207 	char *argv[];
208 {
209 #if ENABLE_NLS
210 #if HAVE_LOCALE_H
211 	setlocale(LC_MESSAGES, "");
212 	setlocale(LC_CTYPE, "");
213 	textdomain(PACKAGE);
214 	bindtextdomain(PACKAGE, LOCALEDIR);
215 #endif
216 #endif
217 
218 	if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) {
219 		fprintf(stderr, _("%s: pledge\n"),
220 		    program_name);
221 		exit(1);
222 	}
223 	return flex_main(argc, argv);
224 }
225 
226 /* check_options - check user-specified options */
227 
228 void
229 check_options()
230 {
231 	int i;
232 
233 	if (lex_compat) {
234 		if (C_plus_plus)
235 			flexerror(_("Can't use -+ with -l option"));
236 
237 		if (fulltbl || fullspd)
238 			flexerror(_("Can't use -f or -F with -l option"));
239 
240 		if (reentrant || bison_bridge_lval)
241 			flexerror(_
242 			    ("Can't use --reentrant or --bison-bridge with -l option"));
243 
244 		yytext_is_array = true;
245 		do_yylineno = true;
246 		use_read = false;
247 	}
248 #if 0
249 	/* This makes no sense whatsoever. I'm removing it. */
250 	if (do_yylineno)
251 		/* This should really be "maintain_backup_tables = true" */
252 		reject_really_used = true;
253 #endif
254 
255 	if (csize == unspecified) {
256 		if ((fulltbl || fullspd) && !useecs)
257 			csize = DEFAULT_CSIZE;
258 		else
259 			csize = CSIZE;
260 	}
261 	if (interactive == unspecified) {
262 		if (fulltbl || fullspd)
263 			interactive = false;
264 		else
265 			interactive = true;
266 	}
267 	if (fulltbl || fullspd) {
268 		if (usemecs)
269 			flexerror(_
270 			    ("-Cf/-CF and -Cm don't make sense together"));
271 
272 		if (interactive)
273 			flexerror(_("-Cf/-CF and -I are incompatible"));
274 
275 		if (lex_compat)
276 			flexerror(_
277 			    ("-Cf/-CF are incompatible with lex-compatibility mode"));
278 
279 
280 		if (fulltbl && fullspd)
281 			flexerror(_
282 			    ("-Cf and -CF are mutually exclusive"));
283 	}
284 	if (C_plus_plus && fullspd)
285 		flexerror(_("Can't use -+ with -CF option"));
286 
287 	if (C_plus_plus && yytext_is_array) {
288 		warn(_("%array incompatible with -+ option"));
289 		yytext_is_array = false;
290 	}
291 	if (C_plus_plus && (reentrant))
292 		flexerror(_("Options -+ and --reentrant are mutually exclusive."));
293 
294 	if (C_plus_plus && bison_bridge_lval)
295 		flexerror(_("bison bridge not supported for the C++ scanner."));
296 
297 
298 	if (useecs) {		/* Set up doubly-linked equivalence classes. */
299 
300 		/*
301 		 * We loop all the way up to csize, since ecgroup[csize] is
302 		 * the position used for NUL characters.
303 		 */
304 		ecgroup[1] = NIL;
305 
306 		for (i = 2; i <= csize; ++i) {
307 			ecgroup[i] = i - 1;
308 			nextecm[i - 1] = i;
309 		}
310 
311 		nextecm[csize] = NIL;
312 	} else {
313 		/* Put everything in its own equivalence class. */
314 		for (i = 1; i <= csize; ++i) {
315 			ecgroup[i] = i;
316 			nextecm[i] = BAD_SUBSCRIPT;	/* to catch errors */
317 		}
318 	}
319 
320 	if (!ansi_func_defs)
321 		buf_m4_define(&m4defs_buf, "M4_YY_NO_ANSI_FUNC_DEFS", NULL);
322 
323 	if (!ansi_func_protos)
324 		buf_m4_define(&m4defs_buf, "M4_YY_NO_ANSI_FUNC_PROTOS", NULL);
325 
326 	if (extra_type)
327 		buf_m4_define(&m4defs_buf, "M4_EXTRA_TYPE_DEFS", extra_type);
328 
329 	if (!use_stdout) {
330 		FILE *prev_stdout;
331 
332 		if (!did_outfilename) {
333 			char *suffix;
334 
335 			if (C_plus_plus)
336 				suffix = "cc";
337 			else
338 				suffix = "c";
339 
340 			snprintf(outfile_path, sizeof(outfile_path), outfile_template,
341 			    prefix, suffix);
342 
343 			outfilename = outfile_path;
344 		}
345 		prev_stdout = freopen(outfilename, "w+", stdout);
346 
347 		if (prev_stdout == NULL)
348 			lerrsf(_("could not create %s"), outfilename);
349 
350 		outfile_created = 1;
351 	}
352 	/* Setup the filter chain. */
353 	output_chain = filter_create_int(NULL, filter_tee_header, headerfilename);
354 	filter_create_ext(output_chain, M4, "-P", 0);
355 	filter_create_int(output_chain, filter_fix_linedirs, NULL);
356 
357 	/* For debugging, only run the requested number of filters. */
358 	if (preproc_level > 0) {
359 		filter_truncate(output_chain, preproc_level);
360 		filter_apply_chain(output_chain);
361 	}
362 	yyout = stdout;
363 
364 
365 	/* always generate the tablesverify flag. */
366 	buf_m4_define(&m4defs_buf, "M4_YY_TABLES_VERIFY", tablesverify ? "1" : "0");
367 	if (tablesext)
368 		gentables = false;
369 
370 	if (tablesverify)
371 		/* force generation of C tables. */
372 		gentables = true;
373 
374 
375 	if (tablesext) {
376 		FILE *tablesout;
377 		struct yytbl_hdr hdr;
378 		char *pname = 0;
379 		int nbytes = 0;
380 
381 		buf_m4_define(&m4defs_buf, "M4_YY_TABLES_EXTERNAL", NULL);
382 
383 		if (!tablesfilename) {
384 			nbytes = strlen(prefix) + strlen(tablesfile_template) + 2;
385 			tablesfilename = pname = (char *) calloc(nbytes, 1);
386 			snprintf(pname, nbytes, tablesfile_template, prefix);
387 		}
388 		if ((tablesout = fopen(tablesfilename, "w")) == NULL)
389 			lerrsf(_("could not create %s"), tablesfilename);
390 		free(pname);
391 		tablesfilename = 0;
392 
393 		yytbl_writer_init(&tableswr, tablesout);
394 
395 		nbytes = strlen(prefix) + strlen("tables") + 2;
396 		tablesname = (char *) calloc(nbytes, 1);
397 		snprintf(tablesname, nbytes, "%stables", prefix);
398 		yytbl_hdr_init(&hdr, flex_version, tablesname);
399 
400 		if (yytbl_hdr_fwrite(&tableswr, &hdr) <= 0)
401 			flexerror(_("could not write tables header"));
402 	}
403 	if (skelname && (skelfile = fopen(skelname, "r")) == NULL)
404 		lerrsf(_("can't open skeleton file %s"), skelname);
405 
406 	if (reentrant) {
407 		buf_m4_define(&m4defs_buf, "M4_YY_REENTRANT", NULL);
408 		if (yytext_is_array)
409 			buf_m4_define(&m4defs_buf, "M4_YY_TEXT_IS_ARRAY", NULL);
410 	}
411 	if (bison_bridge_lval)
412 		buf_m4_define(&m4defs_buf, "M4_YY_BISON_LVAL", NULL);
413 
414 	if (bison_bridge_lloc)
415 		buf_m4_define(&m4defs_buf, "<M4_YY_BISON_LLOC>", NULL);
416 
417 	buf_m4_define(&m4defs_buf, "M4_YY_PREFIX", prefix);
418 
419 	if (did_outfilename)
420 		line_directive_out(stdout, 0);
421 
422 	if (do_yylineno)
423 		buf_m4_define(&m4defs_buf, "M4_YY_USE_LINENO", NULL);
424 
425 	/* Create the alignment type. */
426 	buf_strdefine(&userdef_buf, "YY_INT_ALIGNED",
427 	    long_align ? "long int" : "short int");
428 
429 	/* Define the start condition macros. */
430 	{
431 		struct Buf tmpbuf;
432 		buf_init(&tmpbuf, sizeof(char));
433 		for (i = 1; i <= lastsc; i++) {
434 			char *str, *fmt = "#define %s %d\n";
435 			size_t strsz;
436 
437 			str = (char *) malloc(strsz = strlen(fmt) + strlen(scname[i]) + (int) (1 + log10(i)) + 2);
438 			if (!str)
439 				flexfatal(_("allocation of macro definition failed"));
440 			snprintf(str, strsz, fmt, scname[i], i - 1);
441 			buf_strappend(&tmpbuf, str);
442 			free(str);
443 		}
444 		buf_m4_define(&m4defs_buf, "M4_YY_SC_DEFS", tmpbuf.elts);
445 		buf_destroy(&tmpbuf);
446 	}
447 
448 	/* This is where we begin writing to the file. */
449 
450 	/* Dump the %top code. */
451 	if (top_buf.elts)
452 		outn((char *) top_buf.elts);
453 
454 	/* Dump the m4 definitions. */
455 	buf_print_strings(&m4defs_buf, stdout);
456 	m4defs_buf.nelts = 0;	/* memory leak here. */
457 
458 	/* Place a bogus line directive, it will be fixed in the filter. */
459 	outn("#line 0 \"M4_YY_OUTFILE_NAME\"\n");
460 
461 	/* Dump the user defined preproc directives. */
462 	if (userdef_buf.elts)
463 		outn((char *) (userdef_buf.elts));
464 
465 	skelout();
466 	/* %% [1.0] */
467 }
468 
469 /* flexend - terminate flex
470  *
471  * note
472  *    This routine does not return.
473  */
474 
475 void
476 flexend(exit_status)
477 	int exit_status;
478 
479 {
480 	static int called_before = -1;	/* prevent infinite recursion. */
481 	int tblsiz;
482 
483 	if (++called_before)
484 		FLEX_EXIT(exit_status);
485 
486 	if (skelfile != NULL) {
487 		if (ferror(skelfile))
488 			lerrsf(_("input error reading skeleton file %s"),
489 			    skelname);
490 
491 		else if (fclose(skelfile))
492 			lerrsf(_("error closing skeleton file %s"),
493 			    skelname);
494 	}
495 #if 0
496 	fprintf(header_out,
497 	    "#ifdef YY_HEADER_EXPORT_START_CONDITIONS\n");
498 	fprintf(header_out,
499 	    "/* Beware! Start conditions are not prefixed. */\n");
500 
501 	/* Special case for "INITIAL" */
502 	fprintf(header_out,
503 	    "#undef INITIAL\n#define INITIAL 0\n");
504 	for (i = 2; i <= lastsc; i++)
505 		fprintf(header_out, "#define %s %d\n", scname[i], i - 1);
506 	fprintf(header_out,
507 	    "#endif /* YY_HEADER_EXPORT_START_CONDITIONS */\n\n");
508 
509 	/*
510 	 * Kill ALL flex-related macros. This is so the user can #include
511 	 * more than one generated header file.
512 	 */
513 	fprintf(header_out, "#ifndef YY_HEADER_NO_UNDEFS\n");
514 	fprintf(header_out,
515 	    "/* Undefine all internal macros, etc., that do no belong in the header. */\n\n");
516 
517 	{
518 		const char *undef_list[] = {
519 
520 			"BEGIN",
521 			"ECHO",
522 			"EOB_ACT_CONTINUE_SCAN",
523 			"EOB_ACT_END_OF_FILE",
524 			"EOB_ACT_LAST_MATCH",
525 			"FLEX_SCANNER",
526 			"FLEX_STD",
527 			"REJECT",
528 			"YYFARGS0",
529 			"YYFARGS1",
530 			"YYFARGS2",
531 			"YYFARGS3",
532 			"YYLMAX",
533 			"YYSTATE",
534 			"YY_AT_BOL",
535 			"YY_BREAK",
536 			"YY_BUFFER_EOF_PENDING",
537 			"YY_BUFFER_NEW",
538 			"YY_BUFFER_NORMAL",
539 			"YY_BUF_SIZE",
540 			"M4_YY_CALL_LAST_ARG",
541 			"M4_YY_CALL_ONLY_ARG",
542 			"YY_CURRENT_BUFFER",
543 			"YY_DECL",
544 			"M4_YY_DECL_LAST_ARG",
545 			"M4_YY_DEF_LAST_ARG",
546 			"M4_YY_DEF_ONLY_ARG",
547 			"YY_DO_BEFORE_ACTION",
548 			"YY_END_OF_BUFFER",
549 			"YY_END_OF_BUFFER_CHAR",
550 			"YY_EXIT_FAILURE",
551 			"YY_EXTRA_TYPE",
552 			"YY_FATAL_ERROR",
553 			"YY_FLEX_DEFINED_ECHO",
554 			"YY_FLEX_LEX_COMPAT",
555 			"YY_FLEX_MAJOR_VERSION",
556 			"YY_FLEX_MINOR_VERSION",
557 			"YY_FLEX_SUBMINOR_VERSION",
558 			"YY_FLUSH_BUFFER",
559 			"YY_G",
560 			"YY_INPUT",
561 			"YY_INTERACTIVE",
562 			"YY_INT_ALIGNED",
563 			"YY_LAST_ARG",
564 			"YY_LESS_LINENO",
565 			"YY_LEX_ARGS",
566 			"YY_LEX_DECLARATION",
567 			"YY_LEX_PROTO",
568 			"YY_MAIN",
569 			"YY_MORE_ADJ",
570 			"YY_NEED_STRLEN",
571 			"YY_NEW_FILE",
572 			"YY_NULL",
573 			"YY_NUM_RULES",
574 			"YY_ONLY_ARG",
575 			"YY_PARAMS",
576 			"YY_PROTO",
577 			"M4_YY_PROTO_LAST_ARG",
578 			"M4_YY_PROTO_ONLY_ARG void",
579 			"YY_READ_BUF_SIZE",
580 			"YY_REENTRANT",
581 			"YY_RESTORE_YY_MORE_OFFSET",
582 			"YY_RULE_SETUP",
583 			"YY_SC_TO_UI",
584 			"YY_SKIP_YYWRAP",
585 			"YY_START",
586 			"YY_START_STACK_INCR",
587 			"YY_STATE_EOF",
588 			"YY_STDINIT",
589 			"YY_TRAILING_HEAD_MASK",
590 			"YY_TRAILING_MASK",
591 			"YY_USER_ACTION",
592 			"YY_USE_CONST",
593 			"YY_USE_PROTOS",
594 			"unput",
595 			"yyTABLES_NAME",
596 			"yy_create_buffer",
597 			"yy_delete_buffer",
598 			"yy_flex_debug",
599 			"yy_flush_buffer",
600 			"yy_init_buffer",
601 			"yy_load_buffer_state",
602 			"yy_new_buffer",
603 			"yy_scan_buffer",
604 			"yy_scan_bytes",
605 			"yy_scan_string",
606 			"yy_set_bol",
607 			"yy_set_interactive",
608 			"yy_switch_to_buffer",
609 			"yypush_buffer_state",
610 			"yypop_buffer_state",
611 			"yyensure_buffer_stack",
612 			"yyalloc",
613 			"yyconst",
614 			"yyextra",
615 			"yyfree",
616 			"yyget_debug",
617 			"yyget_extra",
618 			"yyget_in",
619 			"yyget_leng",
620 			"yyget_lineno",
621 			"yyget_lloc",
622 			"yyget_lval",
623 			"yyget_out",
624 			"yyget_text",
625 			"yyin",
626 			"yyleng",
627 			"yyless",
628 			"yylex",
629 			"yylex_destroy",
630 			"yylex_init",
631 			"yylex_init_extra",
632 			"yylineno",
633 			"yylloc",
634 			"yylval",
635 			"yymore",
636 			"yyout",
637 			"yyrealloc",
638 			"yyrestart",
639 			"yyset_debug",
640 			"yyset_extra",
641 			"yyset_in",
642 			"yyset_lineno",
643 			"yyset_lloc",
644 			"yyset_lval",
645 			"yyset_out",
646 			"yytables_destroy",
647 			"yytables_fload",
648 			"yyterminate",
649 			"yytext",
650 			"yytext_ptr",
651 			"yywrap",
652 
653 			/* must be null-terminated */
654 		NULL};
655 
656 
657 		for (i = 0; undef_list[i] != NULL; i++)
658 			fprintf(header_out, "#undef %s\n", undef_list[i]);
659 	}
660 
661 	/* undef any of the auto-generated symbols. */
662 	for (i = 0; i < defs_buf.nelts; i++) {
663 
664 		/* don't undef start conditions */
665 		if (sclookup(((char **) defs_buf.elts)[i]) > 0)
666 			continue;
667 		fprintf(header_out, "#undef %s\n",
668 		    ((char **) defs_buf.elts)[i]);
669 	}
670 
671 	fprintf(header_out,
672 	    "#endif /* !YY_HEADER_NO_UNDEFS */\n");
673 	fprintf(header_out, "\n");
674 	fprintf(header_out, "#undef %sIN_HEADER\n", prefix);
675 	fprintf(header_out, "#endif /* %sHEADER_H */\n", prefix);
676 
677 	if (ferror(header_out))
678 		lerrsf(_("error creating header file %s"),
679 		    headerfilename);
680 	fflush(header_out);
681 	fclose(header_out);
682 #endif
683 
684 	if (exit_status != 0 && outfile_created) {
685 		if (ferror(stdout))
686 			lerrsf(_("error writing output file %s"),
687 			    outfilename);
688 
689 		else if ((_stdout_closed = 1) && fclose(stdout))
690 			lerrsf(_("error closing output file %s"),
691 			    outfilename);
692 
693 		else if (unlink(outfilename))
694 			lerrsf(_("error deleting output file %s"),
695 			    outfilename);
696 	}
697 	if (backing_up_report && backing_up_file) {
698 		if (num_backing_up == 0)
699 			fprintf(backing_up_file, _("No backing up.\n"));
700 		else if (fullspd || fulltbl)
701 			fprintf(backing_up_file,
702 			    _
703 			    ("%d backing up (non-accepting) states.\n"),
704 			    num_backing_up);
705 		else
706 			fprintf(backing_up_file,
707 			    _("Compressed tables always back up.\n"));
708 
709 		if (ferror(backing_up_file))
710 			lerrsf(_("error writing backup file %s"),
711 			    backing_name);
712 
713 		else if (fclose(backing_up_file))
714 			lerrsf(_("error closing backup file %s"),
715 			    backing_name);
716 	}
717 	if (printstats) {
718 		fprintf(stderr, _("%s version %s usage statistics:\n"),
719 		    program_name, flex_version);
720 
721 		fprintf(stderr, _("  scanner options: -"));
722 
723 		if (C_plus_plus)
724 			putc('+', stderr);
725 		if (backing_up_report)
726 			putc('b', stderr);
727 		if (ddebug)
728 			putc('d', stderr);
729 		if (sf_case_ins())
730 			putc('i', stderr);
731 		if (lex_compat)
732 			putc('l', stderr);
733 		if (posix_compat)
734 			putc('X', stderr);
735 		if (performance_report > 0)
736 			putc('p', stderr);
737 		if (performance_report > 1)
738 			putc('p', stderr);
739 		if (spprdflt)
740 			putc('s', stderr);
741 		if (reentrant)
742 			fputs("--reentrant", stderr);
743 		if (bison_bridge_lval)
744 			fputs("--bison-bridge", stderr);
745 		if (bison_bridge_lloc)
746 			fputs("--bison-locations", stderr);
747 		if (use_stdout)
748 			putc('t', stderr);
749 		if (printstats)
750 			putc('v', stderr);	/* always true! */
751 		if (nowarn)
752 			putc('w', stderr);
753 		if (interactive == false)
754 			putc('B', stderr);
755 		if (interactive == true)
756 			putc('I', stderr);
757 		if (!gen_line_dirs)
758 			putc('L', stderr);
759 		if (trace)
760 			putc('T', stderr);
761 
762 		if (csize == unspecified)
763 			/*
764 			 * We encountered an error fairly early on, so csize
765 			 * never got specified.  Define it now, to prevent
766 			 * bogus table sizes being written out below.
767 			 */
768 			csize = 256;
769 
770 		if (csize == 128)
771 			putc('7', stderr);
772 		else
773 			putc('8', stderr);
774 
775 		fprintf(stderr, " -C");
776 
777 		if (long_align)
778 			putc('a', stderr);
779 		if (fulltbl)
780 			putc('f', stderr);
781 		if (fullspd)
782 			putc('F', stderr);
783 		if (useecs)
784 			putc('e', stderr);
785 		if (usemecs)
786 			putc('m', stderr);
787 		if (use_read)
788 			putc('r', stderr);
789 
790 		if (did_outfilename)
791 			fprintf(stderr, " -o%s", outfilename);
792 
793 		if (skelname)
794 			fprintf(stderr, " -S%s", skelname);
795 
796 		if (strcmp(prefix, "yy"))
797 			fprintf(stderr, " -P%s", prefix);
798 
799 		putc('\n', stderr);
800 
801 		fprintf(stderr, _("  %d/%d NFA states\n"),
802 		    lastnfa, current_mns);
803 		fprintf(stderr, _("  %d/%d DFA states (%d words)\n"),
804 		    lastdfa, current_max_dfas, totnst);
805 		fprintf(stderr, _("  %d rules\n"),
806 		    num_rules + num_eof_rules -
807 		    1 /* - 1 for def. rule */ );
808 
809 		if (num_backing_up == 0)
810 			fprintf(stderr, _("  No backing up\n"));
811 		else if (fullspd || fulltbl)
812 			fprintf(stderr,
813 			    _
814 			    ("  %d backing-up (non-accepting) states\n"),
815 			    num_backing_up);
816 		else
817 			fprintf(stderr,
818 			    _
819 			    ("  Compressed tables always back-up\n"));
820 
821 		if (bol_needed)
822 			fprintf(stderr,
823 			    _("  Beginning-of-line patterns used\n"));
824 
825 		fprintf(stderr, _("  %d/%d start conditions\n"), lastsc,
826 		    current_max_scs);
827 		fprintf(stderr,
828 		    _
829 		    ("  %d epsilon states, %d double epsilon states\n"),
830 		    numeps, eps2);
831 
832 		if (lastccl == 0)
833 			fprintf(stderr, _("  no character classes\n"));
834 		else
835 			fprintf(stderr,
836 			    _
837 			    ("  %d/%d character classes needed %d/%d words of storage, %d reused\n"),
838 			    lastccl, current_maxccls,
839 			    cclmap[lastccl] + ccllen[lastccl],
840 			    current_max_ccl_tbl_size, cclreuse);
841 
842 		fprintf(stderr, _("  %d state/nextstate pairs created\n"),
843 		    numsnpairs);
844 		fprintf(stderr,
845 		    _("  %d/%d unique/duplicate transitions\n"),
846 		    numuniq, numdup);
847 
848 		if (fulltbl) {
849 			tblsiz = lastdfa * numecs;
850 			fprintf(stderr, _("  %d table entries\n"),
851 			    tblsiz);
852 		} else {
853 			tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
854 
855 			fprintf(stderr,
856 			    _("  %d/%d base-def entries created\n"),
857 			    lastdfa + numtemps, current_max_dfas);
858 			fprintf(stderr,
859 			    _
860 			    ("  %d/%d (peak %d) nxt-chk entries created\n"),
861 			    tblend, current_max_xpairs, peakpairs);
862 			fprintf(stderr,
863 			    _
864 			    ("  %d/%d (peak %d) template nxt-chk entries created\n"),
865 			    numtemps * nummecs,
866 			    current_max_template_xpairs,
867 			    numtemps * numecs);
868 			fprintf(stderr, _("  %d empty table entries\n"),
869 			    nummt);
870 			fprintf(stderr, _("  %d protos created\n"),
871 			    numprots);
872 			fprintf(stderr,
873 			    _("  %d templates created, %d uses\n"),
874 			    numtemps, tmpuses);
875 		}
876 
877 		if (useecs) {
878 			tblsiz = tblsiz + csize;
879 			fprintf(stderr,
880 			    _
881 			    ("  %d/%d equivalence classes created\n"),
882 			    numecs, csize);
883 		}
884 		if (usemecs) {
885 			tblsiz = tblsiz + numecs;
886 			fprintf(stderr,
887 			    _
888 			    ("  %d/%d meta-equivalence classes created\n"),
889 			    nummecs, csize);
890 		}
891 		fprintf(stderr,
892 		    _
893 		    ("  %d (%d saved) hash collisions, %d DFAs equal\n"),
894 		    hshcol, hshsave, dfaeql);
895 		fprintf(stderr, _("  %d sets of reallocations needed\n"),
896 		    num_reallocs);
897 		fprintf(stderr, _("  %d total table entries needed\n"),
898 		    tblsiz);
899 	}
900 	FLEX_EXIT(exit_status);
901 }
902 
903 
904 /* flexinit - initialize flex */
905 
906 void
907 flexinit(argc, argv)
908 	int argc;
909 	char **argv;
910 {
911 	int i, sawcmpflag, rv, optind;
912 	char *arg;
913 	scanopt_t sopt;
914 
915 	printstats = syntaxerror = trace = spprdflt = false;
916 	lex_compat = posix_compat = C_plus_plus = backing_up_report =
917 	    ddebug = fulltbl = false;
918 	fullspd = long_align = nowarn = yymore_used = continued_action =
919 	    false;
920 	do_yylineno = yytext_is_array = in_rule = reject = do_stdinit =
921 	    false;
922 	yymore_really_used = reject_really_used = unspecified;
923 	interactive = csize = unspecified;
924 	do_yywrap = gen_line_dirs = usemecs = useecs = true;
925 	reentrant = bison_bridge_lval = bison_bridge_lloc = false;
926 	performance_report = 0;
927 	did_outfilename = 0;
928 	prefix = "yy";
929 	yyclass = 0;
930 	use_read = use_stdout = false;
931 	tablesext = tablesverify = false;
932 	gentables = true;
933 	tablesfilename = tablesname = NULL;
934 	ansi_func_defs = ansi_func_protos = true;
935 
936 	sawcmpflag = false;
937 
938 	/* Initialize dynamic array for holding the rule actions. */
939 	action_size = 2048;	/* default size of action array in bytes */
940 	action_array = allocate_character_array(action_size);
941 	defs1_offset = prolog_offset = action_offset = action_index = 0;
942 	action_array[0] = '\0';
943 
944 	/* Initialize any buffers. */
945 	buf_init(&userdef_buf, sizeof(char));	/* one long string */
946 	buf_init(&defs_buf, sizeof(char *));	/* list of strings */
947 	buf_init(&yydmap_buf, sizeof(char));	/* one long string */
948 	buf_init(&top_buf, sizeof(char));	/* one long string */
949 
950 	{
951 		const char *m4defs_init_str[] = {"m4_changequote\n",
952 		"m4_changequote([[, ]])\n"};
953 		buf_init(&m4defs_buf, sizeof(char *));
954 		buf_append(&m4defs_buf, &m4defs_init_str, 2);
955 	}
956 
957 	sf_init();
958 
959 	/* initialize regex lib */
960 	flex_init_regex();
961 
962 	/* Enable C++ if program name ends with '+'. */
963 	program_name = basename2(argv[0], 0);
964 
965 	if (program_name[0] != '\0' &&
966 	    program_name[strlen(program_name) - 1] == '+')
967 		C_plus_plus = true;
968 
969 	/* read flags */
970 	sopt = scanopt_init(flexopts, argc, argv, 0);
971 	if (!sopt) {
972 		/* This will only happen when flexopts array is altered. */
973 		fprintf(stderr,
974 		    _("Internal error. flexopts are malformed.\n"));
975 		FLEX_EXIT(1);
976 	}
977 	while ((rv = scanopt(sopt, &arg, &optind)) != 0) {
978 
979 		if (rv < 0) {
980 			/*
981 			 * Scanopt has already printed an option-specific
982 			 * error message.
983 			 */
984 			fprintf(stderr,
985 			    _
986 			    ("Try `%s --help' for more information.\n"),
987 			    program_name);
988 			FLEX_EXIT(1);
989 		}
990 		switch ((enum flexopt_flag_t) rv) {
991 		case OPT_CPLUSPLUS:
992 			C_plus_plus = true;
993 			break;
994 
995 		case OPT_BATCH:
996 			interactive = false;
997 			break;
998 
999 		case OPT_BACKUP:
1000 			backing_up_report = true;
1001 			break;
1002 
1003 		case OPT_DONOTHING:
1004 			break;
1005 
1006 		case OPT_COMPRESSION:
1007 			if (!sawcmpflag) {
1008 				useecs = false;
1009 				usemecs = false;
1010 				fulltbl = false;
1011 				sawcmpflag = true;
1012 			}
1013 			for (i = 0; arg && arg[i] != '\0'; i++)
1014 				switch (arg[i]) {
1015 				case 'a':
1016 					long_align = true;
1017 					break;
1018 
1019 				case 'e':
1020 					useecs = true;
1021 					break;
1022 
1023 				case 'F':
1024 					fullspd = true;
1025 					break;
1026 
1027 				case 'f':
1028 					fulltbl = true;
1029 					break;
1030 
1031 				case 'm':
1032 					usemecs = true;
1033 					break;
1034 
1035 				case 'r':
1036 					use_read = true;
1037 					break;
1038 
1039 				default:
1040 					lerrif(_
1041 					    ("unknown -C option '%c'"),
1042 					    (int) arg[i]);
1043 					break;
1044 				}
1045 			break;
1046 
1047 		case OPT_DEBUG:
1048 			ddebug = true;
1049 			break;
1050 
1051 		case OPT_NO_DEBUG:
1052 			ddebug = false;
1053 			break;
1054 
1055 		case OPT_FULL:
1056 			useecs = usemecs = false;
1057 			use_read = fulltbl = true;
1058 			break;
1059 
1060 		case OPT_FAST:
1061 			useecs = usemecs = false;
1062 			use_read = fullspd = true;
1063 			break;
1064 
1065 		case OPT_HELP:
1066 			usage();
1067 			FLEX_EXIT(0);
1068 
1069 		case OPT_INTERACTIVE:
1070 			interactive = true;
1071 			break;
1072 
1073 		case OPT_CASE_INSENSITIVE:
1074 			sf_set_case_ins(true);
1075 			break;
1076 
1077 		case OPT_LEX_COMPAT:
1078 			lex_compat = true;
1079 			break;
1080 
1081 		case OPT_POSIX_COMPAT:
1082 			posix_compat = true;
1083 			break;
1084 
1085 		case OPT_PREPROC_LEVEL:
1086 			preproc_level = strtol(arg, NULL, 0);
1087 			break;
1088 
1089 		case OPT_MAIN:
1090 			buf_strdefine(&userdef_buf, "YY_MAIN", "1");
1091 			do_yywrap = false;
1092 			break;
1093 
1094 		case OPT_NO_MAIN:
1095 			buf_strdefine(&userdef_buf, "YY_MAIN", "0");
1096 			break;
1097 
1098 		case OPT_NO_LINE:
1099 			gen_line_dirs = false;
1100 			break;
1101 
1102 		case OPT_OUTFILE:
1103 			outfilename = arg;
1104 			did_outfilename = 1;
1105 			break;
1106 
1107 		case OPT_PREFIX:
1108 			prefix = arg;
1109 			break;
1110 
1111 		case OPT_PERF_REPORT:
1112 			++performance_report;
1113 			break;
1114 
1115 		case OPT_BISON_BRIDGE:
1116 			bison_bridge_lval = true;
1117 			break;
1118 
1119 		case OPT_BISON_BRIDGE_LOCATIONS:
1120 			bison_bridge_lval = bison_bridge_lloc = true;
1121 			break;
1122 
1123 		case OPT_REENTRANT:
1124 			reentrant = true;
1125 			break;
1126 
1127 		case OPT_NO_REENTRANT:
1128 			reentrant = false;
1129 			break;
1130 
1131 		case OPT_SKEL:
1132 			skelname = arg;
1133 			break;
1134 
1135 		case OPT_DEFAULT:
1136 			spprdflt = false;
1137 			break;
1138 
1139 		case OPT_NO_DEFAULT:
1140 			spprdflt = true;
1141 			break;
1142 
1143 		case OPT_STDOUT:
1144 			use_stdout = true;
1145 			break;
1146 
1147 		case OPT_NO_UNISTD_H:
1148 			//buf_strdefine(&userdef_buf, "YY_NO_UNISTD_H", "1");
1149 			buf_m4_define(&m4defs_buf, "M4_YY_NO_UNISTD_H", 0);
1150 			break;
1151 
1152 		case OPT_TABLES_FILE:
1153 			tablesext = true;
1154 			tablesfilename = arg;
1155 			break;
1156 
1157 		case OPT_TABLES_VERIFY:
1158 			tablesverify = true;
1159 			break;
1160 
1161 		case OPT_TRACE:
1162 			trace = true;
1163 			break;
1164 
1165 		case OPT_VERBOSE:
1166 			printstats = true;
1167 			break;
1168 
1169 		case OPT_VERSION:
1170 			printf(_("%s %s\n"), program_name, flex_version);
1171 			FLEX_EXIT(0);
1172 
1173 		case OPT_WARN:
1174 			nowarn = false;
1175 			break;
1176 
1177 		case OPT_NO_WARN:
1178 			nowarn = true;
1179 			break;
1180 
1181 		case OPT_7BIT:
1182 			csize = 128;
1183 			break;
1184 
1185 		case OPT_8BIT:
1186 			csize = CSIZE;
1187 			break;
1188 
1189 		case OPT_ALIGN:
1190 			long_align = true;
1191 			break;
1192 
1193 		case OPT_NO_ALIGN:
1194 			long_align = false;
1195 			break;
1196 
1197 		case OPT_ALWAYS_INTERACTIVE:
1198 			buf_m4_define(&m4defs_buf, "M4_YY_ALWAYS_INTERACTIVE", 0);
1199 			break;
1200 
1201 		case OPT_NEVER_INTERACTIVE:
1202 			buf_m4_define(&m4defs_buf, "M4_YY_NEVER_INTERACTIVE", 0);
1203 			break;
1204 
1205 		case OPT_ARRAY:
1206 			yytext_is_array = true;
1207 			break;
1208 
1209 		case OPT_POINTER:
1210 			yytext_is_array = false;
1211 			break;
1212 
1213 		case OPT_ECS:
1214 			useecs = true;
1215 			break;
1216 
1217 		case OPT_NO_ECS:
1218 			useecs = false;
1219 			break;
1220 
1221 		case OPT_HEADER_FILE:
1222 			headerfilename = arg;
1223 			break;
1224 
1225 		case OPT_META_ECS:
1226 			usemecs = true;
1227 			break;
1228 
1229 		case OPT_NO_META_ECS:
1230 			usemecs = false;
1231 			break;
1232 
1233 		case OPT_PREPROCDEFINE:
1234 			{
1235 				/* arg is "symbol" or "symbol=definition". */
1236 				char *def;
1237 
1238 				for (def = arg;
1239 				    *def != '\0' && *def != '='; ++def);
1240 
1241 				buf_strappend(&userdef_buf, "#define ");
1242 				if (*def == '\0') {
1243 					buf_strappend(&userdef_buf, arg);
1244 					buf_strappend(&userdef_buf,
1245 					    " 1\n");
1246 				} else {
1247 					buf_strnappend(&userdef_buf, arg,
1248 					    def - arg);
1249 					buf_strappend(&userdef_buf, " ");
1250 					buf_strappend(&userdef_buf,
1251 					    def + 1);
1252 					buf_strappend(&userdef_buf, "\n");
1253 				}
1254 			}
1255 			break;
1256 
1257 		case OPT_READ:
1258 			use_read = true;
1259 			break;
1260 
1261 		case OPT_STACK:
1262 			//buf_strdefine(&userdef_buf, "YY_STACK_USED", "1");
1263 			buf_m4_define(&m4defs_buf, "M4_YY_STACK_USED", 0);
1264 			break;
1265 
1266 		case OPT_STDINIT:
1267 			do_stdinit = true;
1268 			break;
1269 
1270 		case OPT_NO_STDINIT:
1271 			do_stdinit = false;
1272 			break;
1273 
1274 		case OPT_YYCLASS:
1275 			yyclass = arg;
1276 			break;
1277 
1278 		case OPT_YYLINENO:
1279 			do_yylineno = true;
1280 			break;
1281 
1282 		case OPT_NO_YYLINENO:
1283 			do_yylineno = false;
1284 			break;
1285 
1286 		case OPT_YYWRAP:
1287 			do_yywrap = true;
1288 			break;
1289 
1290 		case OPT_NO_YYWRAP:
1291 			do_yywrap = false;
1292 			break;
1293 
1294 		case OPT_YYMORE:
1295 			yymore_really_used = true;
1296 			break;
1297 
1298 		case OPT_NO_YYMORE:
1299 			yymore_really_used = false;
1300 			break;
1301 
1302 		case OPT_REJECT:
1303 			reject_really_used = true;
1304 			break;
1305 
1306 		case OPT_NO_REJECT:
1307 			reject_really_used = false;
1308 			break;
1309 
1310 		case OPT_NO_ANSI_FUNC_DEFS:
1311 			ansi_func_defs = false;
1312 			break;
1313 
1314 		case OPT_NO_ANSI_FUNC_PROTOS:
1315 			ansi_func_protos = false;
1316 			break;
1317 
1318 		case OPT_NO_YY_PUSH_STATE:
1319 			//buf_strdefine(&userdef_buf, "YY_NO_PUSH_STATE", "1");
1320 			buf_m4_define(&m4defs_buf, "M4_YY_NO_PUSH_STATE", 0);
1321 			break;
1322 		case OPT_NO_YY_POP_STATE:
1323 			//buf_strdefine(&userdef_buf, "YY_NO_POP_STATE", "1");
1324 			buf_m4_define(&m4defs_buf, "M4_YY_NO_POP_STATE", 0);
1325 			break;
1326 		case OPT_NO_YY_TOP_STATE:
1327 			//buf_strdefine(&userdef_buf, "YY_NO_TOP_STATE", "1");
1328 			buf_m4_define(&m4defs_buf, "M4_YY_NO_TOP_STATE", 0);
1329 			break;
1330 		case OPT_NO_UNPUT:
1331 			//buf_strdefine(&userdef_buf, "YY_NO_UNPUT", "1");
1332 			buf_m4_define(&m4defs_buf, "M4_YY_NO_UNPUT", 0);
1333 			break;
1334 		case OPT_NO_YY_SCAN_BUFFER:
1335 			//buf_strdefine(&userdef_buf, "YY_NO_SCAN_BUFFER", "1");
1336 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SCAN_BUFFER", 0);
1337 			break;
1338 		case OPT_NO_YY_SCAN_BYTES:
1339 			//buf_strdefine(&userdef_buf, "YY_NO_SCAN_BYTES", "1");
1340 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SCAN_BYTES", 0);
1341 			break;
1342 		case OPT_NO_YY_SCAN_STRING:
1343 			//buf_strdefine(&userdef_buf, "YY_NO_SCAN_STRING", "1");
1344 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SCAN_STRING", 0);
1345 			break;
1346 		case OPT_NO_YYGET_EXTRA:
1347 			//buf_strdefine(&userdef_buf, "YY_NO_GET_EXTRA", "1");
1348 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_EXTRA", 0);
1349 			break;
1350 		case OPT_NO_YYSET_EXTRA:
1351 			//buf_strdefine(&userdef_buf, "YY_NO_SET_EXTRA", "1");
1352 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SET_EXTRA", 0);
1353 			break;
1354 		case OPT_NO_YYGET_LENG:
1355 			//buf_strdefine(&userdef_buf, "YY_NO_GET_LENG", "1");
1356 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_LENG", 0);
1357 			break;
1358 		case OPT_NO_YYGET_TEXT:
1359 			//buf_strdefine(&userdef_buf, "YY_NO_GET_TEXT", "1");
1360 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_TEXT", 0);
1361 			break;
1362 		case OPT_NO_YYGET_LINENO:
1363 			//buf_strdefine(&userdef_buf, "YY_NO_GET_LINENO", "1");
1364 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_LINENO", 0);
1365 			break;
1366 		case OPT_NO_YYSET_LINENO:
1367 			//buf_strdefine(&userdef_buf, "YY_NO_SET_LINENO", "1");
1368 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SET_LINENO", 0);
1369 			break;
1370 		case OPT_NO_YYGET_IN:
1371 			//buf_strdefine(&userdef_buf, "YY_NO_GET_IN", "1");
1372 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_IN", 0);
1373 			break;
1374 		case OPT_NO_YYSET_IN:
1375 			//buf_strdefine(&userdef_buf, "YY_NO_SET_IN", "1");
1376 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SET_IN", 0);
1377 			break;
1378 		case OPT_NO_YYGET_OUT:
1379 			//buf_strdefine(&userdef_buf, "YY_NO_GET_OUT", "1");
1380 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_OUT", 0);
1381 			break;
1382 		case OPT_NO_YYSET_OUT:
1383 			//buf_strdefine(&userdef_buf, "YY_NO_SET_OUT", "1");
1384 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SET_OUT", 0);
1385 			break;
1386 		case OPT_NO_YYGET_LVAL:
1387 			//buf_strdefine(&userdef_buf, "YY_NO_GET_LVAL", "1");
1388 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_LVAL", 0);
1389 			break;
1390 		case OPT_NO_YYSET_LVAL:
1391 			//buf_strdefine(&userdef_buf, "YY_NO_SET_LVAL", "1");
1392 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SET_LVAL", 0);
1393 			break;
1394 		case OPT_NO_YYGET_LLOC:
1395 			//buf_strdefine(&userdef_buf, "YY_NO_GET_LLOC", "1");
1396 			buf_m4_define(&m4defs_buf, "M4_YY_NO_GET_LLOC", 0);
1397 			break;
1398 		case OPT_NO_YYSET_LLOC:
1399 			//buf_strdefine(&userdef_buf, "YY_NO_SET_LLOC", "1");
1400 			buf_m4_define(&m4defs_buf, "M4_YY_NO_SET_LLOC", 0);
1401 			break;
1402 
1403 		}		/* switch */
1404 	}			/* while scanopt() */
1405 
1406 	scanopt_destroy(sopt);
1407 
1408 	num_input_files = argc - optind;
1409 	input_files = argv + optind;
1410 	set_input_file(num_input_files > 0 ? input_files[0] : NULL);
1411 
1412 	lastccl = lastsc = lastdfa = lastnfa = 0;
1413 	num_rules = num_eof_rules = default_rule = 0;
1414 	numas = numsnpairs = tmpuses = 0;
1415 	numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst =
1416 	    0;
1417 	numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
1418 	num_backing_up = onesp = numprots = 0;
1419 	variable_trailing_context_rules = bol_needed = false;
1420 
1421 	linenum = sectnum = 1;
1422 	firstprot = NIL;
1423 
1424 	/*
1425 	 * Used in mkprot() so that the first proto goes in slot 1 of the
1426 	 * proto queue.
1427 	 */
1428 	lastprot = 1;
1429 
1430 	set_up_initial_allocations();
1431 }
1432 
1433 
1434 /* readin - read in the rules section of the input file(s) */
1435 
1436 void
1437 readin()
1438 {
1439 	static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;";
1440 	static char yy_nostdinit[] =
1441 	"FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;";
1442 
1443 	line_directive_out((FILE *) 0, 1);
1444 
1445 	if (yyparse()) {
1446 		pinpoint_message(_("fatal parse error"));
1447 		flexend(1);
1448 	}
1449 	if (syntaxerror)
1450 		flexend(1);
1451 
1452 	/*
1453 	 * If the user explicitly requested posix compatibility by specifing
1454 	 * the posix-compat option, then we check for conflicting options.
1455 	 * However, if the POSIXLY_CORRECT variable is set, then we quietly
1456 	 * make flex as posix-compatible as possible.  This is the
1457 	 * recommended behavior according to the GNU Coding Standards.
1458 	 *
1459 	 * Note: The posix option was added to flex to provide the posix
1460 	 * behavior of the repeat operator in regular expressions, e.g.,
1461 	 * `ab{3}'
1462 	 */
1463 	if (posix_compat) {
1464 		/*
1465 		 * TODO: This is where we try to make flex behave according
1466 		 * to posiz, AND check for conflicting options. How far
1467 		 * should we go with this? Should we disable all the neat-o
1468 		 * flex features?
1469 		 */
1470 		/*
1471 		 * Update: Estes says no, since other flex features don't
1472 		 * violate posix.
1473 		 */
1474 	}
1475 	if (getenv("POSIXLY_CORRECT")) {
1476 		posix_compat = true;
1477 	}
1478 	if (backing_up_report) {
1479 		backing_up_file = fopen(backing_name, "w");
1480 		if (backing_up_file == NULL)
1481 			lerrsf(_
1482 			    ("could not create backing-up info file %s"),
1483 			    backing_name);
1484 	} else
1485 		backing_up_file = NULL;
1486 
1487 	if (yymore_really_used == true)
1488 		yymore_used = true;
1489 	else if (yymore_really_used == false)
1490 		yymore_used = false;
1491 
1492 	if (reject_really_used == true)
1493 		reject = true;
1494 	else if (reject_really_used == false)
1495 		reject = false;
1496 
1497 	if (performance_report > 0) {
1498 		if (lex_compat) {
1499 			fprintf(stderr,
1500 			    _
1501 			    ("-l AT&T lex compatibility option entails a large performance penalty\n"));
1502 			fprintf(stderr,
1503 			    _
1504 			    (" and may be the actual source of other reported performance penalties\n"));
1505 		} else if (do_yylineno) {
1506 			fprintf(stderr,
1507 			    _
1508 			    ("%%option yylineno entails a performance penalty ONLY on rules that can match newline characters\n"));
1509 		}
1510 		if (performance_report > 1) {
1511 			if (interactive)
1512 				fprintf(stderr,
1513 				    _
1514 				    ("-I (interactive) entails a minor performance penalty\n"));
1515 
1516 			if (yymore_used)
1517 				fprintf(stderr,
1518 				    _
1519 				    ("yymore() entails a minor performance penalty\n"));
1520 		}
1521 		if (reject)
1522 			fprintf(stderr,
1523 			    _
1524 			    ("REJECT entails a large performance penalty\n"));
1525 
1526 		if (variable_trailing_context_rules)
1527 			fprintf(stderr,
1528 			    _
1529 			    ("Variable trailing context rules entail a large performance penalty\n"));
1530 	}
1531 	if (reject)
1532 		real_reject = true;
1533 
1534 	if (variable_trailing_context_rules)
1535 		reject = true;
1536 
1537 	if ((fulltbl || fullspd) && reject) {
1538 		if (real_reject)
1539 			flexerror(_
1540 			    ("REJECT cannot be used with -f or -F"));
1541 		else if (do_yylineno)
1542 			flexerror(_
1543 			    ("%option yylineno cannot be used with REJECT"));
1544 		else
1545 			flexerror(_
1546 			    ("variable trailing context rules cannot be used with -f or -F"));
1547 	}
1548 	if (reject) {
1549 		out_m4_define("M4_YY_USES_REJECT", NULL);
1550 		//outn("\n#define YY_USES_REJECT");
1551 	}
1552 	if (!do_yywrap) {
1553 		if (!C_plus_plus)
1554 			if (reentrant)
1555 				outn("\n#define yywrap(yyscanner) 1");
1556 			else
1557 				outn("\n#define yywrap() 1");
1558 		outn("#define YY_SKIP_YYWRAP");
1559 	}
1560 	if (ddebug)
1561 		outn("\n#define FLEX_DEBUG");
1562 
1563 	OUT_BEGIN_CODE();
1564 	if (csize == 256)
1565 		outn("typedef unsigned char YY_CHAR;");
1566 	else
1567 		outn("typedef char YY_CHAR;");
1568 	OUT_END_CODE();
1569 
1570 	if (C_plus_plus) {
1571 		outn("#define yytext_ptr yytext");
1572 
1573 		if (interactive)
1574 			outn("#define YY_INTERACTIVE");
1575 	} else {
1576 		OUT_BEGIN_CODE();
1577 		/* In reentrant scanner, stdinit is handled in flex.skl. */
1578 		if (do_stdinit) {
1579 			if (reentrant) {
1580 				outn("#define YY_STDINIT");
1581 			}
1582 			outn(yy_stdinit);
1583 		} else {
1584 			if (!reentrant)
1585 				outn(yy_nostdinit);
1586 		}
1587 		OUT_END_CODE();
1588 	}
1589 
1590 	OUT_BEGIN_CODE();
1591 	if (fullspd)
1592 		outn("typedef yyconst struct yy_trans_info *yy_state_type;");
1593 	else if (!C_plus_plus)
1594 		outn("typedef int yy_state_type;");
1595 	OUT_END_CODE();
1596 
1597 	if (lex_compat)
1598 		outn("#define YY_FLEX_LEX_COMPAT");
1599 
1600 	if (!C_plus_plus && !reentrant) {
1601 		outn("extern int yylineno;");
1602 		OUT_BEGIN_CODE();
1603 		outn("int yylineno = 1;");
1604 		OUT_END_CODE();
1605 	}
1606 	if (C_plus_plus) {
1607 		outn("\n#include <FlexLexer.h>");
1608 
1609 		if (!do_yywrap) {
1610 			outn("\nint yyFlexLexer::yywrap() { return 1; }");
1611 		}
1612 		if (yyclass) {
1613 			outn("int yyFlexLexer::yylex()");
1614 			outn("\t{");
1615 			outn("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );");
1616 			outn("\treturn 0;");
1617 			outn("\t}");
1618 
1619 			out_str("\n#define YY_DECL int %s::yylex()\n",
1620 			    yyclass);
1621 		}
1622 	} else {
1623 
1624 		/*
1625 		 * Watch out: yytext_ptr is a variable when yytext is an
1626 		 * array, but it's a macro when yytext is a pointer.
1627 		 */
1628 		if (yytext_is_array) {
1629 			if (!reentrant)
1630 				outn("extern char yytext[];\n");
1631 		} else {
1632 			if (reentrant) {
1633 				outn("#define yytext_ptr yytext_r");
1634 			} else {
1635 				outn("extern char *yytext;");
1636 				outn("#define yytext_ptr yytext");
1637 			}
1638 		}
1639 
1640 		if (yyclass)
1641 			flexerror(_
1642 			    ("%option yyclass only meaningful for C++ scanners"));
1643 	}
1644 
1645 	if (useecs)
1646 		numecs = cre8ecs(nextecm, ecgroup, csize);
1647 	else
1648 		numecs = csize;
1649 
1650 	/* Now map the equivalence class for NUL to its expected place. */
1651 	ecgroup[0] = ecgroup[csize];
1652 	NUL_ec = ABS(ecgroup[0]);
1653 
1654 	if (useecs)
1655 		ccl2ecl();
1656 }
1657 
1658 
1659 /* set_up_initial_allocations - allocate memory for internal tables */
1660 
1661 void
1662 set_up_initial_allocations()
1663 {
1664 	maximum_mns = (long_align ? MAXIMUM_MNS_LONG : MAXIMUM_MNS);
1665 	current_mns = INITIAL_MNS;
1666 	firstst = allocate_integer_array(current_mns);
1667 	lastst = allocate_integer_array(current_mns);
1668 	finalst = allocate_integer_array(current_mns);
1669 	transchar = allocate_integer_array(current_mns);
1670 	trans1 = allocate_integer_array(current_mns);
1671 	trans2 = allocate_integer_array(current_mns);
1672 	accptnum = allocate_integer_array(current_mns);
1673 	assoc_rule = allocate_integer_array(current_mns);
1674 	state_type = allocate_integer_array(current_mns);
1675 
1676 	current_max_rules = INITIAL_MAX_RULES;
1677 	rule_type = allocate_integer_array(current_max_rules);
1678 	rule_linenum = allocate_integer_array(current_max_rules);
1679 	rule_useful = allocate_integer_array(current_max_rules);
1680 	rule_has_nl = allocate_bool_array(current_max_rules);
1681 
1682 	current_max_scs = INITIAL_MAX_SCS;
1683 	scset = allocate_integer_array(current_max_scs);
1684 	scbol = allocate_integer_array(current_max_scs);
1685 	scxclu = allocate_integer_array(current_max_scs);
1686 	sceof = allocate_integer_array(current_max_scs);
1687 	scname = allocate_char_ptr_array(current_max_scs);
1688 
1689 	current_maxccls = INITIAL_MAX_CCLS;
1690 	cclmap = allocate_integer_array(current_maxccls);
1691 	ccllen = allocate_integer_array(current_maxccls);
1692 	cclng = allocate_integer_array(current_maxccls);
1693 	ccl_has_nl = allocate_bool_array(current_maxccls);
1694 
1695 	current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
1696 	ccltbl = allocate_Character_array(current_max_ccl_tbl_size);
1697 
1698 	current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
1699 
1700 	current_max_xpairs = INITIAL_MAX_XPAIRS;
1701 	nxt = allocate_integer_array(current_max_xpairs);
1702 	chk = allocate_integer_array(current_max_xpairs);
1703 
1704 	current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
1705 	tnxt = allocate_integer_array(current_max_template_xpairs);
1706 
1707 	current_max_dfas = INITIAL_MAX_DFAS;
1708 	base = allocate_integer_array(current_max_dfas);
1709 	def = allocate_integer_array(current_max_dfas);
1710 	dfasiz = allocate_integer_array(current_max_dfas);
1711 	accsiz = allocate_integer_array(current_max_dfas);
1712 	dhash = allocate_integer_array(current_max_dfas);
1713 	dss = allocate_int_ptr_array(current_max_dfas);
1714 	dfaacc = allocate_dfaacc_union(current_max_dfas);
1715 
1716 	nultrans = (int *) 0;
1717 }
1718 
1719 
1720 /* extracts basename from path, optionally stripping the extension "\.*"
1721  * (same concept as /bin/sh `basename`, but different handling of extension). */
1722 static char *
1723 basename2(path, strip_ext)
1724 	char *path;
1725 	int strip_ext;		/* boolean */
1726 {
1727 	char *b, *e = 0;
1728 
1729 	b = path;
1730 	for (b = path; *path; path++)
1731 		if (*path == '/')
1732 			b = path + 1;
1733 		else if (*path == '.')
1734 			e = path;
1735 
1736 	if (strip_ext && e && e > b)
1737 		*e = '\0';
1738 	return b;
1739 }
1740 
1741 void
1742 usage()
1743 {
1744 	FILE *f = stdout;
1745 
1746 	if (!did_outfilename) {
1747 		snprintf(outfile_path, sizeof(outfile_path), outfile_template,
1748 		    prefix, C_plus_plus ? "cc" : "c");
1749 		outfilename = outfile_path;
1750 	}
1751 	fprintf(f, _("Usage: %s [OPTIONS] [FILE]...\n"), program_name);
1752 	fprintf(f,
1753 	    _
1754 	    ("Generates programs that perform pattern-matching on text.\n"
1755 		"\n" "Table Compression:\n"
1756 		"  -Ca, --align      trade off larger tables for better memory alignment\n"
1757 		"  -Ce, --ecs        construct equivalence classes\n"
1758 		"  -Cf               do not compress tables; use -f representation\n"
1759 		"  -CF               do not compress tables; use -F representation\n"
1760 		"  -Cm, --meta-ecs   construct meta-equivalence classes\n"
1761 		"  -Cr, --read       use read() instead of stdio for scanner input\n"
1762 		"  -f, --full        generate fast, large scanner. Same as -Cfr\n"
1763 		"  -F, --fast        use alternate table representation. Same as -CFr\n"
1764 		"  -Cem              default compression (same as --ecs --meta-ecs)\n"
1765 		"\n" "Debugging:\n"
1766 		"  -d, --debug             enable debug mode in scanner\n"
1767 		"  -b, --backup            write backing-up information to %s\n"
1768 		"  -p, --perf-report       write performance report to stderr\n"
1769 		"  -s, --nodefault         suppress default rule to ECHO unmatched text\n"
1770 		"  -T, --trace             %s should run in trace mode\n"
1771 		"  -w, --nowarn            do not generate warnings\n"
1772 		"  -v, --verbose           write summary of scanner statistics to stdout\n"
1773 		"\n" "Files:\n"
1774 		"  -o, --outfile=FILE      specify output filename\n"
1775 		"  -S, --skel=FILE         specify skeleton file\n"
1776 		"  -t, --stdout            write scanner on stdout instead of %s\n"
1777 		"      --yyclass=NAME      name of C++ class\n"
1778 		"      --header-file=FILE   create a C header file in addition to the scanner\n"
1779 		"      --tables-file[=FILE] write tables to FILE\n" "\n"
1780 		"Scanner behavior:\n"
1781 		"  -7, --7bit              generate 7-bit scanner\n"
1782 		"  -8, --8bit              generate 8-bit scanner\n"
1783 		"  -B, --batch             generate batch scanner (opposite of -I)\n"
1784 		"  -i, --case-insensitive  ignore case in patterns\n"
1785 		"  -l, --lex-compat        maximal compatibility with original lex\n"
1786 		"  -X, --posix-compat      maximal compatibility with POSIX lex\n"
1787 		"  -I, --interactive       generate interactive scanner (opposite of -B)\n"
1788 		"      --yylineno          track line count in yylineno\n"
1789 		"\n" "Generated code:\n"
1790 		"  -+,  --c++               generate C++ scanner class\n"
1791 		"  -Dmacro[=defn]           #define macro defn  (default defn is '1')\n"
1792 		"  -L,  --noline            suppress #line directives in scanner\n"
1793 		"  -P,  --prefix=STRING     use STRING as prefix instead of \"yy\"\n"
1794 		"  -R,  --reentrant         generate a reentrant C scanner\n"
1795 		"       --bison-bridge      scanner for bison pure parser.\n"
1796 		"       --bison-locations   include yylloc support.\n"
1797 		"       --stdinit           initialize yyin/yyout to stdin/stdout\n"
1798 		"       --noansi-definitions old-style function definitions\n"
1799 		"       --noansi-prototypes  empty parameter list in prototypes\n"
1800 		"       --nounistd          do not include <unistd.h>\n"
1801 		"       --noFUNCTION        do not generate a particular FUNCTION\n"
1802 		"\n" "Miscellaneous:\n"
1803 		"  -n                      do-nothing POSIX option\n"
1804 		"  -?\n"
1805 		"  -h, --help              produce this help message\n"
1806 		"  -V, --version           report %s version\n"),
1807 	    backing_name, program_name, outfile_path, program_name);
1808 
1809 }
1810