GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/lex/main.c Lines: 297 771 38.5 %
Date: 2017-11-07 Branches: 122 504 24.2 %

Line Branch Exec Source
1
/*	$OpenBSD: main.c,v 1.27 2017/01/21 08:33:07 krw 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
70
	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
40
	exit_status = setjmp(flex_main_jmp_buf);
155
40
	if (exit_status) {
156


30
		if (stdout && !_stdout_closed && !ferror(stdout)) {
157
10
			fflush(stdout);
158
10
			fclose(stdout);
159
10
		}
160
40
		while (wait(&child_status) > 0) {
161
60
			if (!WIFEXITED(child_status)
162
60
			    || WEXITSTATUS(child_status) != 0) {
163
				/*
164
				 * report an error of a child
165
				 */
166
30
				if (exit_status <= 1)
167
					exit_status = 2;
168
169
			}
170
		}
171
10
		return exit_status - 1;
172
	}
173
30
	flexinit(argc, argv);
174
175
30
	readin();
176
177
30
	skelout();
178
	/* %% [1.5] DFA */
179
30
	ntod();
180
181
1160
	for (i = 1; i <= num_rules; ++i)
182

564
		if (!rule_useful[i] && i != default_rule)
183
			line_warning(_("rule cannot be matched"),
184
			    rule_linenum[i]);
185
186

10
	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
10
	make_tables();
193
194
	/*
195
	 * Note, flexend does not return.  It exits with its argument as
196
	 * status.
197
	 */
198
10
	flexend(0);
199
200
10
	return 0;		/* keep compilers/lint happy */
201
10
}
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
60
	if (pledge("stdio rpath wpath cpath proc exec flock", NULL) == -1) {
219
		fprintf(stderr, _("%s: pledge\n"),
220
		    program_name);
221
		exit(1);
222
	}
223
30
	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
60
	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
30
	if (csize == unspecified) {
256
30
		if ((fulltbl || fullspd) && !useecs)
257
			csize = DEFAULT_CSIZE;
258
		else
259
			csize = CSIZE;
260
30
	}
261
30
	if (interactive == unspecified) {
262
18
		if (fulltbl || fullspd)
263
			interactive = false;
264
		else
265
			interactive = true;
266
18
	}
267
30
	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
30
	if (C_plus_plus && fullspd)
285
		flexerror(_("Can't use -+ with -CF option"));
286
287
30
	if (C_plus_plus && yytext_is_array) {
288
		warn(_("%array incompatible with -+ option"));
289
		yytext_is_array = false;
290
	}
291
30
	if (C_plus_plus && (reentrant))
292
		flexerror(_("Options -+ and --reentrant are mutually exclusive."));
293
294
30
	if (C_plus_plus && bison_bridge_lval)
295
		flexerror(_("bison bridge not supported for the C++ scanner."));
296
297
298
30
	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
24
		ecgroup[1] = NIL;
305
306
12288
		for (i = 2; i <= csize; ++i) {
307
6120
			ecgroup[i] = i - 1;
308
6120
			nextecm[i - 1] = i;
309
		}
310
311
24
		nextecm[csize] = NIL;
312
24
	} else {
313
		/* Put everything in its own equivalence class. */
314
3084
		for (i = 1; i <= csize; ++i) {
315
1536
			ecgroup[i] = i;
316
1536
			nextecm[i] = BAD_SUBSCRIPT;	/* to catch errors */
317
		}
318
	}
319
320
30
	if (!ansi_func_defs)
321
		buf_m4_define(&m4defs_buf, "M4_YY_NO_ANSI_FUNC_DEFS", NULL);
322
323
30
	if (!ansi_func_protos)
324
		buf_m4_define(&m4defs_buf, "M4_YY_NO_ANSI_FUNC_PROTOS", NULL);
325
326
30
	if (extra_type)
327
		buf_m4_define(&m4defs_buf, "M4_EXTRA_TYPE_DEFS", extra_type);
328
329
30
	if (!use_stdout) {
330
		FILE *prev_stdout;
331
332
21
		if (!did_outfilename) {
333
			char *suffix;
334
335
9
			if (C_plus_plus)
336
				suffix = "cc";
337
			else
338
				suffix = "c";
339
340
18
			snprintf(outfile_path, sizeof(outfile_path), outfile_template,
341
9
			    prefix, suffix);
342
343
9
			outfilename = outfile_path;
344
9
		}
345
21
		prev_stdout = freopen(outfilename, "w+", stdout);
346
347
21
		if (prev_stdout == NULL)
348
			lerrsf(_("could not create %s"), outfilename);
349
350
21
		outfile_created = 1;
351
21
	}
352
	/* Setup the filter chain. */
353
30
	output_chain = filter_create_int(NULL, filter_tee_header, headerfilename);
354
30
	filter_create_ext(output_chain, M4, "-P", 0);
355
30
	filter_create_int(output_chain, filter_fix_linedirs, NULL);
356
357
	/* For debugging, only run the requested number of filters. */
358
30
	if (preproc_level > 0) {
359
30
		filter_truncate(output_chain, preproc_level);
360
30
		filter_apply_chain(output_chain);
361
30
	}
362
10
	yyout = stdout;
363
364
365
	/* always generate the tablesverify flag. */
366
10
	buf_m4_define(&m4defs_buf, "M4_YY_TABLES_VERIFY", tablesverify ? "1" : "0");
367
10
	if (tablesext)
368
		gentables = false;
369
370
10
	if (tablesverify)
371
		/* force generation of C tables. */
372
		gentables = true;
373
374
375
10
	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

10
	if (skelname && (skelfile = fopen(skelname, "r")) == NULL)
404
		lerrsf(_("can't open skeleton file %s"), skelname);
405
406
10
	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
10
	if (bison_bridge_lval)
412
		buf_m4_define(&m4defs_buf, "M4_YY_BISON_LVAL", NULL);
413
414
10
	if (bison_bridge_lloc)
415
		buf_m4_define(&m4defs_buf, "<M4_YY_BISON_LLOC>", NULL);
416
417
10
	buf_m4_define(&m4defs_buf, "M4_YY_PREFIX", prefix);
418
419
10
	if (did_outfilename)
420
4
		line_directive_out(stdout, 0);
421
422
10
	if (do_yylineno)
423
2
		buf_m4_define(&m4defs_buf, "M4_YY_USE_LINENO", NULL);
424
425
	/* Create the alignment type. */
426
10
	buf_strdefine(&userdef_buf, "YY_INT_ALIGNED",
427
10
	    long_align ? "long int" : "short int");
428
429
	/* Define the start condition macros. */
430
	{
431
10
		struct Buf tmpbuf;
432
10
		buf_init(&tmpbuf, sizeof(char));
433
84
		for (i = 1; i <= lastsc; i++) {
434
			char *str, *fmt = "#define %s %d\n";
435
			size_t strsz;
436
437
32
			str = (char *) malloc(strsz = strlen(fmt) + strlen(scname[i]) + (int) (1 + log10(i)) + 2);
438
32
			if (!str)
439
				flexfatal(_("allocation of macro definition failed"));
440
32
			snprintf(str, strsz, fmt, scname[i], i - 1);
441
32
			buf_strappend(&tmpbuf, str);
442
32
			free(str);
443
		}
444
10
		buf_m4_define(&m4defs_buf, "M4_YY_SC_DEFS", tmpbuf.elts);
445
10
		buf_destroy(&tmpbuf);
446
10
	}
447
448
	/* This is where we begin writing to the file. */
449
450
	/* Dump the %top code. */
451
10
	if (top_buf.elts)
452
		outn((char *) top_buf.elts);
453
454
	/* Dump the m4 definitions. */
455
10
	buf_print_strings(&m4defs_buf, stdout);
456
10
	m4defs_buf.nelts = 0;	/* memory leak here. */
457
458
	/* Place a bogus line directive, it will be fixed in the filter. */
459
10
	outn("#line 0 \"M4_YY_OUTFILE_NAME\"\n");
460
461
	/* Dump the user defined preproc directives. */
462
10
	if (userdef_buf.elts)
463
10
		outn((char *) (userdef_buf.elts));
464
465
10
	skelout();
466
	/* %% [1.0] */
467
10
}
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
20
	if (++called_before)
484
		FLEX_EXIT(exit_status);
485
486
10
	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
10
	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
10
	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
10
	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
60
	int i, sawcmpflag, rv, optind;
912
30
	char *arg;
913
	scanopt_t sopt;
914
915
30
	printstats = syntaxerror = trace = spprdflt = false;
916
30
	lex_compat = posix_compat = C_plus_plus = backing_up_report =
917
30
	    ddebug = fulltbl = false;
918
30
	fullspd = long_align = nowarn = yymore_used = continued_action =
919
	    false;
920
30
	do_yylineno = yytext_is_array = in_rule = reject = do_stdinit =
921
	    false;
922
30
	yymore_really_used = reject_really_used = unspecified;
923
30
	interactive = csize = unspecified;
924
30
	do_yywrap = gen_line_dirs = usemecs = useecs = true;
925
30
	reentrant = bison_bridge_lval = bison_bridge_lloc = false;
926
30
	performance_report = 0;
927
30
	did_outfilename = 0;
928
30
	prefix = "yy";
929
30
	yyclass = 0;
930
30
	use_read = use_stdout = false;
931
30
	tablesext = tablesverify = false;
932
30
	gentables = true;
933
30
	tablesfilename = tablesname = NULL;
934
30
	ansi_func_defs = ansi_func_protos = true;
935
936
	sawcmpflag = false;
937
938
	/* Initialize dynamic array for holding the rule actions. */
939
30
	action_size = 2048;	/* default size of action array in bytes */
940
30
	action_array = allocate_character_array(action_size);
941
30
	defs1_offset = prolog_offset = action_offset = action_index = 0;
942
30
	action_array[0] = '\0';
943
944
	/* Initialize any buffers. */
945
30
	buf_init(&userdef_buf, sizeof(char));	/* one long string */
946
30
	buf_init(&defs_buf, sizeof(char *));	/* list of strings */
947
30
	buf_init(&yydmap_buf, sizeof(char));	/* one long string */
948
30
	buf_init(&top_buf, sizeof(char));	/* one long string */
949
950
	{
951
30
		const char *m4defs_init_str[] = {"m4_changequote\n",
952
		"m4_changequote([[, ]])\n"};
953
30
		buf_init(&m4defs_buf, sizeof(char *));
954
30
		buf_append(&m4defs_buf, &m4defs_init_str, 2);
955
30
	}
956
957
30
	sf_init();
958
959
	/* initialize regex lib */
960
30
	flex_init_regex();
961
962
	/* Enable C++ if program name ends with '+'. */
963
30
	program_name = basename2(argv[0], 0);
964
965

60
	if (program_name[0] != '\0' &&
966
30
	    program_name[strlen(program_name) - 1] == '+')
967
		C_plus_plus = true;
968
969
	/* read flags */
970
30
	sopt = scanopt_init(flexopts, argc, argv, 0);
971
30
	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
90
	while ((rv = scanopt(sopt, &arg, &optind)) != 0) {
978
979
60
		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





















114
		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
6
			if (!sawcmpflag) {
1008
6
				useecs = false;
1009
6
				usemecs = false;
1010
6
				fulltbl = false;
1011
				sawcmpflag = true;
1012
6
			}
1013

36
			for (i = 0; arg && arg[i] != '\0'; i++)
1014

6
				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
6
					use_read = true;
1037
6
					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
15
			sf_set_case_ins(true);
1075
15
			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
12
			outfilename = arg;
1104
12
			did_outfilename = 1;
1105
12
			break;
1106
1107
		case OPT_PREFIX:
1108
12
			prefix = arg;
1109
12
			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
6
			spprdflt = true;
1141
6
			break;
1142
1143
		case OPT_STDOUT:
1144
9
			use_stdout = true;
1145
9
			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
30
	scanopt_destroy(sopt);
1407
1408
30
	num_input_files = argc - optind;
1409
30
	input_files = argv + optind;
1410
90
	set_input_file(num_input_files > 0 ? input_files[0] : NULL);
1411
1412
30
	lastccl = lastsc = lastdfa = lastnfa = 0;
1413
30
	num_rules = num_eof_rules = default_rule = 0;
1414
30
	numas = numsnpairs = tmpuses = 0;
1415
30
	numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst =
1416
	    0;
1417
30
	numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
1418
30
	num_backing_up = onesp = numprots = 0;
1419
30
	variable_trailing_context_rules = bol_needed = false;
1420
1421
30
	linenum = sectnum = 1;
1422
30
	firstprot = NIL;
1423
1424
	/*
1425
	 * Used in mkprot() so that the first proto goes in slot 1 of the
1426
	 * proto queue.
1427
	 */
1428
30
	lastprot = 1;
1429
1430
30
	set_up_initial_allocations();
1431
30
}
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
40
	line_directive_out((FILE *) 0, 1);
1444
1445
10
	if (yyparse()) {
1446
		pinpoint_message(_("fatal parse error"));
1447
		flexend(1);
1448
	}
1449
10
	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
10
	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
10
	if (getenv("POSIXLY_CORRECT")) {
1476
		posix_compat = true;
1477
	}
1478
10
	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
10
		backing_up_file = NULL;
1486
1487
10
	if (yymore_really_used == true)
1488
		yymore_used = true;
1489
10
	else if (yymore_really_used == false)
1490
		yymore_used = false;
1491
1492
10
	if (reject_really_used == true)
1493
		reject = true;
1494
10
	else if (reject_really_used == false)
1495
		reject = false;
1496
1497
10
	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
10
	if (reject)
1532
3
		real_reject = true;
1533
1534
10
	if (variable_trailing_context_rules)
1535
		reject = true;
1536
1537
10
	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
10
	if (reject) {
1549
3
		out_m4_define("M4_YY_USES_REJECT", NULL);
1550
		//outn("\n#define YY_USES_REJECT");
1551
3
	}
1552
10
	if (!do_yywrap) {
1553
2
		if (!C_plus_plus) {
1554
2
			if (reentrant)
1555
				outn("\n#define yywrap(yyscanner) 1");
1556
			else
1557
2
				outn("\n#define yywrap() 1");
1558
		}
1559
2
		outn("#define YY_SKIP_YYWRAP");
1560
2
	}
1561
10
	if (ddebug)
1562
		outn("\n#define FLEX_DEBUG");
1563
1564
10
	OUT_BEGIN_CODE();
1565
10
	if (csize == 256)
1566
10
		outn("typedef unsigned char YY_CHAR;");
1567
	else
1568
		outn("typedef char YY_CHAR;");
1569
10
	OUT_END_CODE();
1570
1571
10
	if (C_plus_plus) {
1572
		outn("#define yytext_ptr yytext");
1573
1574
		if (interactive)
1575
			outn("#define YY_INTERACTIVE");
1576
	} else {
1577
10
		OUT_BEGIN_CODE();
1578
		/* In reentrant scanner, stdinit is handled in flex.skl. */
1579
10
		if (do_stdinit) {
1580
			if (reentrant) {
1581
				outn("#define YY_STDINIT");
1582
			}
1583
			outn(yy_stdinit);
1584
		} else {
1585
10
			if (!reentrant)
1586
10
				outn(yy_nostdinit);
1587
		}
1588
10
		OUT_END_CODE();
1589
	}
1590
1591
10
	OUT_BEGIN_CODE();
1592
10
	if (fullspd)
1593
		outn("typedef yyconst struct yy_trans_info *yy_state_type;");
1594
10
	else if (!C_plus_plus)
1595
10
		outn("typedef int yy_state_type;");
1596
10
	OUT_END_CODE();
1597
1598
10
	if (lex_compat)
1599
		outn("#define YY_FLEX_LEX_COMPAT");
1600
1601
10
	if (!C_plus_plus && !reentrant) {
1602
10
		outn("extern int yylineno;");
1603
10
		OUT_BEGIN_CODE();
1604
10
		outn("int yylineno = 1;");
1605
10
		OUT_END_CODE();
1606
10
	}
1607
10
	if (C_plus_plus) {
1608
		outn("\n#include <FlexLexer.h>");
1609
1610
		if (!do_yywrap) {
1611
			outn("\nint yyFlexLexer::yywrap() { return 1; }");
1612
		}
1613
		if (yyclass) {
1614
			outn("int yyFlexLexer::yylex()");
1615
			outn("\t{");
1616
			outn("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );");
1617
			outn("\treturn 0;");
1618
			outn("\t}");
1619
1620
			out_str("\n#define YY_DECL int %s::yylex()\n",
1621
			    yyclass);
1622
		}
1623
	} else {
1624
1625
		/*
1626
		 * Watch out: yytext_ptr is a variable when yytext is an
1627
		 * array, but it's a macro when yytext is a pointer.
1628
		 */
1629
10
		if (yytext_is_array) {
1630
			if (!reentrant)
1631
				outn("extern char yytext[];\n");
1632
		} else {
1633
10
			if (reentrant) {
1634
				outn("#define yytext_ptr yytext_r");
1635
			} else {
1636
10
				outn("extern char *yytext;");
1637
10
				outn("#define yytext_ptr yytext");
1638
			}
1639
		}
1640
1641
10
		if (yyclass)
1642
			flexerror(_
1643
			    ("%option yyclass only meaningful for C++ scanners"));
1644
	}
1645
1646
10
	if (useecs)
1647
8
		numecs = cre8ecs(nextecm, ecgroup, csize);
1648
	else
1649
		numecs = csize;
1650
1651
	/* Now map the equivalence class for NUL to its expected place. */
1652
10
	ecgroup[0] = ecgroup[csize];
1653
10
	NUL_ec = ABS(ecgroup[0]);
1654
1655
10
	if (useecs)
1656
8
		ccl2ecl();
1657
10
}
1658
1659
1660
/* set_up_initial_allocations - allocate memory for internal tables */
1661
1662
void
1663
set_up_initial_allocations()
1664
{
1665
60
	maximum_mns = (long_align ? MAXIMUM_MNS_LONG : MAXIMUM_MNS);
1666
30
	current_mns = INITIAL_MNS;
1667
30
	firstst = allocate_integer_array(current_mns);
1668
30
	lastst = allocate_integer_array(current_mns);
1669
30
	finalst = allocate_integer_array(current_mns);
1670
30
	transchar = allocate_integer_array(current_mns);
1671
30
	trans1 = allocate_integer_array(current_mns);
1672
30
	trans2 = allocate_integer_array(current_mns);
1673
30
	accptnum = allocate_integer_array(current_mns);
1674
30
	assoc_rule = allocate_integer_array(current_mns);
1675
30
	state_type = allocate_integer_array(current_mns);
1676
1677
30
	current_max_rules = INITIAL_MAX_RULES;
1678
30
	rule_type = allocate_integer_array(current_max_rules);
1679
30
	rule_linenum = allocate_integer_array(current_max_rules);
1680
30
	rule_useful = allocate_integer_array(current_max_rules);
1681
30
	rule_has_nl = allocate_bool_array(current_max_rules);
1682
1683
30
	current_max_scs = INITIAL_MAX_SCS;
1684
30
	scset = allocate_integer_array(current_max_scs);
1685
30
	scbol = allocate_integer_array(current_max_scs);
1686
30
	scxclu = allocate_integer_array(current_max_scs);
1687
30
	sceof = allocate_integer_array(current_max_scs);
1688
30
	scname = allocate_char_ptr_array(current_max_scs);
1689
1690
30
	current_maxccls = INITIAL_MAX_CCLS;
1691
30
	cclmap = allocate_integer_array(current_maxccls);
1692
30
	ccllen = allocate_integer_array(current_maxccls);
1693
30
	cclng = allocate_integer_array(current_maxccls);
1694
30
	ccl_has_nl = allocate_bool_array(current_maxccls);
1695
1696
30
	current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
1697
30
	ccltbl = allocate_Character_array(current_max_ccl_tbl_size);
1698
1699
30
	current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
1700
1701
30
	current_max_xpairs = INITIAL_MAX_XPAIRS;
1702
30
	nxt = allocate_integer_array(current_max_xpairs);
1703
30
	chk = allocate_integer_array(current_max_xpairs);
1704
1705
30
	current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
1706
30
	tnxt = allocate_integer_array(current_max_template_xpairs);
1707
1708
30
	current_max_dfas = INITIAL_MAX_DFAS;
1709
30
	base = allocate_integer_array(current_max_dfas);
1710
30
	def = allocate_integer_array(current_max_dfas);
1711
30
	dfasiz = allocate_integer_array(current_max_dfas);
1712
30
	accsiz = allocate_integer_array(current_max_dfas);
1713
30
	dhash = allocate_integer_array(current_max_dfas);
1714
30
	dss = allocate_int_ptr_array(current_max_dfas);
1715
30
	dfaacc = allocate_dfaacc_union(current_max_dfas);
1716
1717
30
	nultrans = (int *) 0;
1718
30
}
1719
1720
1721
/* extracts basename from path, optionally stripping the extension "\.*"
1722
 * (same concept as /bin/sh `basename`, but different handling of extension). */
1723
static char *
1724
basename2(path, strip_ext)
1725
	char *path;
1726
	int strip_ext;		/* boolean */
1727
{
1728
	char *b, *e = 0;
1729
1730
	b = path;
1731
294
	for (b = path; *path; path++)
1732
102
		if (*path == '/')
1733
			b = path + 1;
1734
102
		else if (*path == '.')
1735
			e = path;
1736
1737

30
	if (strip_ext && e && e > b)
1738
		*e = '\0';
1739
30
	return b;
1740
}
1741
1742
void
1743
usage()
1744
{
1745
	FILE *f = stdout;
1746
1747
	if (!did_outfilename) {
1748
		snprintf(outfile_path, sizeof(outfile_path), outfile_template,
1749
		    prefix, C_plus_plus ? "cc" : "c");
1750
		outfilename = outfile_path;
1751
	}
1752
	fprintf(f, _("Usage: %s [OPTIONS] [FILE]...\n"), program_name);
1753
	fprintf(f,
1754
	    _
1755
	    ("Generates programs that perform pattern-matching on text.\n"
1756
		"\n" "Table Compression:\n"
1757
		"  -Ca, --align      trade off larger tables for better memory alignment\n"
1758
		"  -Ce, --ecs        construct equivalence classes\n"
1759
		"  -Cf               do not compress tables; use -f representation\n"
1760
		"  -CF               do not compress tables; use -F representation\n"
1761
		"  -Cm, --meta-ecs   construct meta-equivalence classes\n"
1762
		"  -Cr, --read       use read() instead of stdio for scanner input\n"
1763
		"  -f, --full        generate fast, large scanner. Same as -Cfr\n"
1764
		"  -F, --fast        use alternate table representation. Same as -CFr\n"
1765
		"  -Cem              default compression (same as --ecs --meta-ecs)\n"
1766
		"\n" "Debugging:\n"
1767
		"  -d, --debug             enable debug mode in scanner\n"
1768
		"  -b, --backup            write backing-up information to %s\n"
1769
		"  -p, --perf-report       write performance report to stderr\n"
1770
		"  -s, --nodefault         suppress default rule to ECHO unmatched text\n"
1771
		"  -T, --trace             %s should run in trace mode\n"
1772
		"  -w, --nowarn            do not generate warnings\n"
1773
		"  -v, --verbose           write summary of scanner statistics to stdout\n"
1774
		"\n" "Files:\n"
1775
		"  -o, --outfile=FILE      specify output filename\n"
1776
		"  -S, --skel=FILE         specify skeleton file\n"
1777
		"  -t, --stdout            write scanner on stdout instead of %s\n"
1778
		"      --yyclass=NAME      name of C++ class\n"
1779
		"      --header-file=FILE   create a C header file in addition to the scanner\n"
1780
		"      --tables-file[=FILE] write tables to FILE\n" "\n"
1781
		"Scanner behavior:\n"
1782
		"  -7, --7bit              generate 7-bit scanner\n"
1783
		"  -8, --8bit              generate 8-bit scanner\n"
1784
		"  -B, --batch             generate batch scanner (opposite of -I)\n"
1785
		"  -i, --case-insensitive  ignore case in patterns\n"
1786
		"  -l, --lex-compat        maximal compatibility with original lex\n"
1787
		"  -X, --posix-compat      maximal compatibility with POSIX lex\n"
1788
		"  -I, --interactive       generate interactive scanner (opposite of -B)\n"
1789
		"      --yylineno          track line count in yylineno\n"
1790
		"\n" "Generated code:\n"
1791
		"  -+,  --c++               generate C++ scanner class\n"
1792
		"  -Dmacro[=defn]           #define macro defn  (default defn is '1')\n"
1793
		"  -L,  --noline            suppress #line directives in scanner\n"
1794
		"  -P,  --prefix=STRING     use STRING as prefix instead of \"yy\"\n"
1795
		"  -R,  --reentrant         generate a reentrant C scanner\n"
1796
		"       --bison-bridge      scanner for bison pure parser.\n"
1797
		"       --bison-locations   include yylloc support.\n"
1798
		"       --stdinit           initialize yyin/yyout to stdin/stdout\n"
1799
		"       --noansi-definitions old-style function definitions\n"
1800
		"       --noansi-prototypes  empty parameter list in prototypes\n"
1801
		"       --nounistd          do not include <unistd.h>\n"
1802
		"       --noFUNCTION        do not generate a particular FUNCTION\n"
1803
		"\n" "Miscellaneous:\n"
1804
		"  -n                      do-nothing POSIX option\n"
1805
		"  -?\n"
1806
		"  -h, --help              produce this help message\n"
1807
		"  -V, --version           report %s version\n"),
1808
	    backing_name, program_name, outfile_path, program_name);
1809
1810
}