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