1 /* $Id: main.c,v 1.26 2021/08/06 23:47:40 Boris.Kolpackov Exp $ */
2 /* flex - tool to generate fast lexical analyzers */
3 
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  * Redistribution and use in source and binary forms with or without
16  * modification are permitted provided that: (1) source distributions retain
17  * this entire copyright notice and comment, and (2) distributions including
18  * binaries display the following acknowledgement:  ``This product includes
19  * software developed by the University of California, Berkeley and its
20  * contributors'' in the documentation or other materials provided with the
21  * distribution and in all advertising materials mentioning features or use
22  * of this software.  Neither the name of the University nor the names of
23  * its contributors may be used to endorse or promote products derived from
24  * this software without specific prior written permission.
25  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
26  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
27  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28  */
29 
30 #ifndef lint
31 char copyright[] =
32 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
33  All rights reserved.\n";
34 #endif /* not lint */
35 
36 /* @Header: /home/daffy/u0/vern/flex/RCS/main.c,v 2.64 96/05/25 20:42:42 vern Exp @ */
37 
38 #include "flexdef.h"
39 #include "version.h"
40 
41 #ifdef LOCALE
42 #include <locale.h>
43 #endif
44 
45 static char flex_version[] = FLEX_VERSION;
46 static char flex_patched[] = FLEX_PATCHED;
47 
48 /* declare functions that have forward references */
49 
50 void flexinit(int, char **);
51 void readin(void);
52 void set_up_initial_allocations(void);
53 
54 #ifdef NEED_ARGV_FIXUP
55 extern void argv_fixup(int *, char ***);
56 #endif
57 
58 /* these globals are all defined and commented in flexdef.h */
59 int printstats, syntaxerror, eofseen, ddebug, trace, nowarn, spprdflt;
60 int interactive, caseins, lex_compat, do_yylineno, useecs, fulltbl, usemecs;
61 int fullspd, gen_line_dirs, performance_report, backing_up_report;
62 int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap, csize;
63 int yymore_used, reject, real_reject, continued_action, in_rule;
64 int fallthru_action;
65 int yymore_really_used, reject_really_used;
66 int datapos, dataline, linenum, out_linenum;
67 FILE *skelfile = NULL;
68 int skel_ind = 0;
69 char *action_array;
70 int action_size, defs1_offset, prolog_offset, action_offset, action_index;
71 char *infilename = NULL;
72 const char *outfilename = NULL;
73 int did_outfilename;
74 const char *prefix;
75 char *yyclass;
76 int do_stdinit, use_stdout;
77 int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
78 int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
79 int current_mns, current_max_rules;
80 int num_rules, num_eof_rules, default_rule, lastnfa;
81 int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
82 int *accptnum, *assoc_rule, *state_type;
83 int *rule_type, *rule_linenum, *rule_useful;
84 int current_state_type;
85 int variable_trailing_context_rules;
86 int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
87 int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
88 int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
89 int tecbck[CSIZE + 1];
90 int lastsc, *scset, *scbol, *scxclu, *sceof;
91 int current_max_scs;
92 char **scname;
93 int current_max_dfa_size, current_max_xpairs;
94 int current_max_template_xpairs, current_max_dfas;
95 int lastdfa, *nxt, *chk, *tnxt;
96 int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz;
97 union dfaacc_union *dfaacc;
98 int *accsiz, *dhash, numas;
99 int numsnpairs, jambase, jamstate;
100 int lastccl, *cclmap, *ccllen, *cclng, cclreuse;
101 int current_maxccls, current_max_ccl_tbl_size;
102 CCLTBL *ccltbl;
103 char nmstr[MAXLINE];
104 int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
105 int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
106 int num_backing_up, bol_needed;
107 FILE *backing_up_file;
108 int end_of_buffer_state;
109 char **input_files;
110 int num_input_files;
111 
112 /* Make sure program_name is initialized so we don't crash if writing
113  * out an error message before getting the program name from argv[0].
114  */
115 const char *program_name = "flex";
116 
117 #ifndef SHORT_FILE_NAMES
118 static const char *outfile_template = "lex.%s.%s";
119 static const char *backing_name = "lex.backup";
120 #else
121 static const char *outfile_template = "lex%s.%s";
122 static const char *backing_name = "lex.bck";
123 #endif
124 
125 #ifdef THINK_C
126 #include <console.h>
127 #endif
128 
129 #ifdef MS_DOS
130 extern unsigned _stklen = 16384;
131 #endif
132 
133 static char outfile_path[MAXLINE];
134 static int outfile_created = 0;
135 static const char *skelname = NULL;
136 
137 int
main(int argc,char ** argv)138 main(int argc, char **argv)
139 {
140     int i;
141 
142 #ifdef THINK_C
143     argc = ccommand(&argv);
144 #endif
145 #ifdef NEED_ARGV_FIXUP
146     argv_fixup(&argc, &argv);
147 #endif
148 
149 #ifdef LOCALE
150     setlocale(LC_ALL, "");
151 #endif
152 
153     flexinit(argc, argv);
154 
155     readin();
156 
157     ntod();
158 
159     for (i = 1; i <= num_rules; ++i)
160 	if (!rule_useful[i] && i != default_rule)
161 	    line_warning(_("rule cannot be matched"),
162 			 rule_linenum[i]);
163 
164     if (spprdflt && !reject && rule_useful[default_rule])
165 	line_warning(
166 			_("-s option given but default rule can be matched"),
167 			rule_linenum[default_rule]);
168 
169     /* Generate the C state transition tables from the DFA. */
170     make_tables();
171 
172     /* Note, flexend does not return.  It exits with its argument
173      * as status.
174      */
175     flexend(0);
176 
177     return EXIT_SUCCESS;	/* keep compilers/lint happy */
178 }
179 
180 /* check_options - check user-specified options */
181 void
check_options(void)182 check_options(void)
183 {
184     int i;
185 
186     if (lex_compat) {
187 	if (C_plus_plus)
188 	    flexerror(_("Can't use -+ with -l option"));
189 
190 	if (fulltbl || fullspd)
191 	    flexerror(_("Can't use -f or -F with -l option"));
192 
193 	/* Don't rely on detecting use of yymore() and REJECT,
194 	 * just assume they'll be used.
195 	 */
196 	yymore_really_used = reject_really_used = true;
197 
198 	yytext_is_array = true;
199 	do_yylineno = true;
200 	use_read = false;
201     }
202 
203     if (do_yylineno)
204 	/* This should really be "maintain_backup_tables = true" */
205 	reject_really_used = true;
206 
207     if (csize == unspecified) {
208 	if ((fulltbl || fullspd) && !useecs)
209 	    csize = DEFAULT_CSIZE;
210 	else
211 	    csize = CSIZE;
212     }
213 
214     if (interactive == unspecified) {
215 	if (fulltbl || fullspd)
216 	    interactive = false;
217 	else
218 	    interactive = true;
219     }
220 
221     if (fulltbl || fullspd) {
222 	if (usemecs)
223 	    flexerror(
224 			 _("-Cf/-CF and -Cm don't make sense together"));
225 
226 	if (interactive)
227 	    flexerror(_("-Cf/-CF and -I are incompatible"));
228 
229 	if (lex_compat)
230 	    flexerror(
231 			 _("-Cf/-CF are incompatible with lex-compatibility mode"));
232 
233 	if (do_yylineno)
234 	    flexerror(
235 			 _("-Cf/-CF and %%option yylineno are incompatible"));
236 
237 	if (fulltbl && fullspd)
238 	    flexerror(_("-Cf and -CF are mutually exclusive"));
239     }
240 
241     if (C_plus_plus && fullspd)
242 	flexerror(_("Can't use -+ with -CF option"));
243 
244     if (C_plus_plus && yytext_is_array) {
245 	warn(_("%array incompatible with -+ option"));
246 	yytext_is_array = false;
247     }
248 
249     if (useecs) {		/* Set up doubly-linked equivalence classes. */
250 
251 	/* We loop all the way up to csize, since ecgroup[csize] is
252 	 * the position used for NUL characters.
253 	 */
254 	ecgroup[1] = NIL;
255 
256 	for (i = 2; i <= csize; ++i) {
257 	    ecgroup[i] = i - 1;
258 	    nextecm[i - 1] = i;
259 	}
260 
261 	nextecm[csize] = NIL;
262     }
263 
264     else {
265 	/* Put everything in its own equivalence class. */
266 	for (i = 1; i <= csize; ++i) {
267 	    ecgroup[i] = i;
268 	    nextecm[i] = BAD_SUBSCRIPT;		/* to catch errors */
269 	}
270     }
271 
272     if (!use_stdout) {
273 	FILE *prev_stdout;
274 
275 	if (!did_outfilename) {
276 	    const char *suffix;
277 
278 	    if (C_plus_plus)
279 		suffix = "cc";
280 	    else
281 		suffix = "c";
282 
283 	    sprintf(outfile_path, outfile_template,
284 		    prefix, suffix);
285 
286 	    outfilename = outfile_path;
287 	}
288 
289 	prev_stdout = freopen(outfilename, "w", stdout);
290 
291 	if (prev_stdout == NULL)
292 	    lerrsf(_("could not create %s"), outfilename);
293 
294 	outfile_created = 1;
295     }
296 
297     if (skelname && (skelfile = fopen(skelname, "r")) == NULL)
298 	lerrsf(_("can't open skeleton file %s"), skelname);
299 
300     if (strcmp(prefix, "yy")) {
301 #define GEN_PREFIX(name) out_str3( "#define yy%s %s%s\n", name, prefix, name )
302 	if (C_plus_plus)
303 	    GEN_PREFIX("FlexLexer");
304 	else {
305 	    GEN_PREFIX("_create_buffer");
306 	    GEN_PREFIX("_delete_buffer");
307 	    GEN_PREFIX("_scan_buffer");
308 	    GEN_PREFIX("_scan_string");
309 	    GEN_PREFIX("_scan_bytes");
310 	    GEN_PREFIX("_flex_debug");
311 	    GEN_PREFIX("_init_buffer");
312 	    GEN_PREFIX("_flush_buffer");
313 	    GEN_PREFIX("_load_buffer_state");
314 	    GEN_PREFIX("_switch_to_buffer");
315 	    GEN_PREFIX("in");
316 	    GEN_PREFIX("leng");
317 	    GEN_PREFIX("lex");
318 	    GEN_PREFIX("lex_destroy");
319 	    GEN_PREFIX("out");
320 	    GEN_PREFIX("restart");
321 	    GEN_PREFIX("text");
322 
323 	    if (do_yylineno)
324 		GEN_PREFIX("lineno");
325 	}
326 
327 	if (do_yywrap)
328 	    GEN_PREFIX("wrap");
329 
330 	outc('\n');
331     }
332 
333     if (did_outfilename)
334 	line_directive_out(stdout, 0);
335 
336     skelout();
337 }
338 
339 /* flexend - terminate flex
340  *
341  * note
342  *    This routine does not return.
343  */
344 void
flexend(int exit_status)345 flexend(int exit_status)
346 {
347     if (skelfile != NULL) {
348 	if (ferror(skelfile))
349 	    lerrsf(_("input error reading skeleton file %s"),
350 		   skelname);
351 
352 	else if (fclose(skelfile))
353 	    lerrsf(_("error closing skeleton file %s"),
354 		   skelname);
355     }
356 
357     if (exit_status != 0 && outfile_created) {
358 	if (ferror(stdout))
359 	    lerrsf(_("error writing output file %s"),
360 		   outfilename);
361 
362 	else if (fclose(stdout))
363 	    lerrsf(_("error closing output file %s"),
364 		   outfilename);
365 
366 	else if (unlink(outfilename))
367 	    lerrsf(_("error deleting output file %s"),
368 		   outfilename);
369     }
370 
371     if (backing_up_report && backing_up_file) {
372 	if (num_backing_up == 0)
373 	    fprintf(backing_up_file, _("No backing up.\n"));
374 	else if (fullspd || fulltbl)
375 	    fprintf(backing_up_file,
376 		    _("%d backing up (non-accepting) states.\n"),
377 		    num_backing_up);
378 	else
379 	    fprintf(backing_up_file,
380 		    _("Compressed tables always back up.\n"));
381 
382 	if (ferror(backing_up_file))
383 	    lerrsf(_("error writing backup file %s"),
384 		   backing_name);
385 
386 	else if (fclose(backing_up_file))
387 	    lerrsf(_("error closing backup file %s"),
388 		   backing_name);
389     }
390 
391     if (printstats) {
392 	int tblsiz;
393 
394 	fprintf(stderr, _("%s version %s (%s) usage statistics:\n"),
395 		program_name, flex_version, flex_patched);
396 
397 	fprintf(stderr, _("  scanner options: -"));
398 
399 	if (C_plus_plus)
400 	    putc('+', stderr);
401 	if (backing_up_report)
402 	    putc('b', stderr);
403 	if (ddebug)
404 	    putc('d', stderr);
405 	if (caseins)
406 	    putc('i', stderr);
407 	if (lex_compat)
408 	    putc('l', stderr);
409 	if (performance_report > 0)
410 	    putc('p', stderr);
411 	if (performance_report > 1)
412 	    putc('p', stderr);
413 	if (spprdflt)
414 	    putc('s', stderr);
415 	if (use_stdout)
416 	    putc('t', stderr);
417 	if (printstats)
418 	    putc('v', stderr);	/* always true! */
419 	if (nowarn)
420 	    putc('w', stderr);
421 	if (interactive == false)
422 	    putc('B', stderr);
423 	if (interactive == true)
424 	    putc('I', stderr);
425 	if (!gen_line_dirs)
426 	    putc('L', stderr);
427 	if (trace)
428 	    putc('T', stderr);
429 
430 	if (csize == unspecified)
431 	    /* We encountered an error fairly early on, so csize
432 	     * never got specified.  Define it now, to prevent
433 	     * bogus table sizes being written out below.
434 	     */
435 	    csize = 256;
436 
437 	if (csize == 128)
438 	    putc('7', stderr);
439 	else
440 	    putc('8', stderr);
441 
442 	fprintf(stderr, " -C");
443 
444 	if (long_align)
445 	    putc('a', stderr);
446 	if (fulltbl)
447 	    putc('f', stderr);
448 	if (fullspd)
449 	    putc('F', stderr);
450 	if (useecs)
451 	    putc('e', stderr);
452 	if (usemecs)
453 	    putc('m', stderr);
454 	if (use_read)
455 	    putc('r', stderr);
456 
457 	if (did_outfilename)
458 	    fprintf(stderr, " -o%s", outfilename);
459 
460 	if (skelname)
461 	    fprintf(stderr, " -S%s", skelname);
462 
463 	if (strcmp(prefix, "yy"))
464 	    fprintf(stderr, " -P%s", prefix);
465 
466 	putc('\n', stderr);
467 
468 	fprintf(stderr, _("  %d/%d NFA states\n"),
469 		lastnfa, current_mns);
470 	fprintf(stderr, _("  %d/%d DFA states (%d words)\n"),
471 		lastdfa, current_max_dfas, totnst);
472 	fprintf(stderr, _("  %d rules\n"),
473 		num_rules + num_eof_rules - 1 /* - 1 for def. rule */ );
474 
475 	if (num_backing_up == 0)
476 	    fprintf(stderr, _("  No backing up\n"));
477 	else if (fullspd || fulltbl)
478 	    fprintf(stderr,
479 		    _("  %d backing-up (non-accepting) states\n"),
480 		    num_backing_up);
481 	else
482 	    fprintf(stderr,
483 		    _("  Compressed tables always back-up\n"));
484 
485 	if (bol_needed)
486 	    fprintf(stderr,
487 		    _("  Beginning-of-line patterns used\n"));
488 
489 	fprintf(stderr, _("  %d/%d start conditions\n"), lastsc,
490 		current_max_scs);
491 	fprintf(stderr,
492 		_("  %d epsilon states, %d double epsilon states\n"),
493 		numeps, eps2);
494 
495 	if (lastccl == 0)
496 	    fprintf(stderr, _("  no character classes\n"));
497 	else
498 	    fprintf(stderr,
499 		    _("  %d/%d character classes needed %d/%d words of storage, %d reused\n"),
500 		    lastccl, current_maxccls,
501 		    cclmap[lastccl] + ccllen[lastccl],
502 		    current_max_ccl_tbl_size, cclreuse);
503 
504 	fprintf(stderr, _("  %d state/nextstate pairs created\n"),
505 		numsnpairs);
506 	fprintf(stderr, _("  %d/%d unique/duplicate transitions\n"),
507 		numuniq, numdup);
508 
509 	if (fulltbl) {
510 	    tblsiz = lastdfa * numecs;
511 	    fprintf(stderr, _("  %d table entries\n"), tblsiz);
512 	}
513 
514 	else {
515 	    tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
516 
517 	    fprintf(stderr,
518 		    _("  %d/%d base-def entries created\n"),
519 		    lastdfa + numtemps, current_max_dfas);
520 	    fprintf(stderr,
521 		    _("  %d/%d (peak %d) nxt-chk entries created\n"),
522 		    tblend, current_max_xpairs, peakpairs);
523 	    fprintf(stderr,
524 		    _("  %d/%d (peak %d) template nxt-chk entries created\n"),
525 		    numtemps * nummecs,
526 		    current_max_template_xpairs,
527 		    numtemps * numecs);
528 	    fprintf(stderr, _("  %d empty table entries\n"),
529 		    nummt);
530 	    fprintf(stderr, _("  %d protos created\n"),
531 		    numprots);
532 	    fprintf(stderr,
533 		    _("  %d templates created, %d uses\n"),
534 		    numtemps, tmpuses);
535 	}
536 
537 	if (useecs) {
538 	    tblsiz = tblsiz + csize;
539 	    fprintf(stderr,
540 		    _("  %d/%d equivalence classes created\n"),
541 		    numecs, csize);
542 	}
543 
544 	if (usemecs) {
545 	    tblsiz = tblsiz + numecs;
546 	    fprintf(stderr,
547 		    _("  %d/%d meta-equivalence classes created\n"),
548 		    nummecs, csize);
549 	}
550 
551 	fprintf(stderr,
552 		_("  %d (%d saved) hash collisions, %d DFAs equal\n"),
553 		hshcol, hshsave, dfaeql);
554 	fprintf(stderr, _("  %d sets of reallocations needed\n"),
555 		num_reallocs);
556 	fprintf(stderr, _("  %d total table entries needed\n"),
557 		tblsiz);
558     }
559 
560     exit(exit_status);
561 }
562 
563 #define SIZEOF(v) (sizeof(v) / sizeof((v)[0]))
564 
565 /*
566  * Long options are provided only as a compatibility aid for scripters.
567  */
568 /* *INDENT-OFF* */
569 static const struct {
570     const char fake_opt[16];
571     const char yacc_arg;
572     const char real_opt;
573 } long_opts[] = {
574     { "7bit",             0, '7' },
575     { "8bit",             0, '8' },
576     { "backup",           0, 'b' },
577     { "batch",            0, 'B' },
578     { "case-insensitive", 0, 'i' },
579     { "debug",            0, 'd' },
580     { "help",             0, 'h' },
581     { "interactive",      0, 'I' },
582     { "lex-compat",       0, 'l' },
583     { "nodefault",        0, 's' },
584     { "noline",           0, 'L' },
585     { "nowarn",           0, 'w' },
586     { "outfile",          0, 'o' },
587     { "perf-report",      0, 'p' },
588     { "prefix",           0, 'P' },
589     { "skel",             0, 'S' },
590     { "stdout",           0, 't' },
591     { "trace",            0, 'T' },
592     { "version",          0, 'V' },
593 };
594 
595 static const struct {
596     const char option;
597     const char param_type;	/* 0=none, 1=string, 2=file */
598     const char is_program;	/* 0=none, 1=program */
599     const char help_text[80];
600 } normal_opts[] = {
601     { '+', 0, 0,  _("generate C++ scanner class") },
602     { '?', 0, 0,  _("produce this help message") },
603     { '7', 0, 0,  _("generate 7-bit scanner") },
604     { '8', 0, 0,  _("generate 8-bit scanner") },
605     { 'B', 0, 0,  _("generate batch scanner (opposite of -I)") },
606     { 'b', 0, 3,  _("generate backing-up information to %s") },
607     { 'c', 0, 0,  _("do-nothing POSIX option") },
608     { 'C',-1, 0,  _("specify degree of table compression (default is -Cem)") },
609     { 'd', 0, 0,  _("turn on debug mode in generated scanner") },
610     { 'f', 0, 0,  _("generate fast, large scanner") },
611     { 'F', 0, 0,  _("use alternative fast scanner representation") },
612     { 'h', 0, 0,  _("produce this help message") },
613     { 'i', 0, 0,  _("generate case-insensitive scanner") },
614     { 'I', 0, 0,  _("generate interactive scanner (opposite of -B)") },
615     { 'l', 0, 0,  _("maximal compatibility with original lex") },
616     { 'L', 0, 0,  _("suppress #line directives in scanner") },
617     { 'n', 0, 0,  _("do-nothing POSIX option") },
618     { 'o', 2, 0,  _("specify output filename") },
619     { 'p', 0, 0,  _("generate performance report to stderr") },
620     { 'P', 1, 0,  _("specify scanner prefix other than \"yy\"") },
621     { 's', 0, 0,  _("suppress default rule to ECHO unmatched text") },
622     { 'S', 2, 0,  _("specify skeleton file") },
623     { 'T', 0, 1,  _("%s should run in trace mode") },
624     { 't', 0, 2,  _("write generated scanner on stdout instead of %s") },
625     { 'v', 0, 0,  _("write summary of scanner statistics to stderr") },
626     { 'V', 0, 1,  _("report %s version") },
627     { 'w', 0, 0,  _("do not generate warnings") },
628 };
629 
630 static const struct {
631     const char option;
632     const char help_text[80];
633 } compress_opts[] = {
634     { 'a', _("trade off larger tables for better memory alignment") },
635     { 'e', _("construct equivalence classes") },
636     { 'f', _("do not compress scanner tables; use -f representation") },
637     { 'F', _("do not compress scanner tables; use -F representation") },
638     { 'm', _("construct meta-equivalence classes") },
639     { 'r', _("use read() instead of stdio for scanner input") },
640 };
641 /* *INDENT-ON* */
642 
643 static void
invalid_option(const char * arg)644 invalid_option(const char *arg)
645 {
646     fprintf(stderr, _("invalid option: %s"), arg);
647     usage();
648     exit(EXIT_FAILURE);
649 }
650 
651 /* flexinit - initialize flex */
652 void
flexinit(int argc,char ** argv)653 flexinit(int argc, char **argv)
654 {
655     int i, sawcmpflag;
656     char *arg;
657 
658     printstats = syntaxerror = trace = spprdflt = caseins = false;
659     lex_compat = C_plus_plus = backing_up_report = ddebug = fulltbl = false;
660     fullspd = long_align = nowarn = yymore_used = continued_action = false;
661     do_yylineno = yytext_is_array = in_rule = reject = do_stdinit = false;
662     yymore_really_used = reject_really_used = unspecified;
663     interactive = csize = unspecified;
664     do_yywrap = gen_line_dirs = usemecs = useecs = true;
665     performance_report = 0;
666     did_outfilename = 0;
667     prefix = copy_string("yy");
668     yyclass = 0;
669     use_read = use_stdout = false;
670 
671     sawcmpflag = false;
672 
673     /* Initialize dynamic array for holding the rule actions. */
674     action_size = 2048;		/* default size of action array in bytes */
675     action_array = allocate_character_array(action_size);
676     defs1_offset = prolog_offset = action_offset = action_index = 0;
677     action_array[0] = '\0';
678 
679     program_name = argv[0];
680 
681     if (program_name[0] != '\0' &&
682 	program_name[strlen(program_name) - 1] == '+')
683 	C_plus_plus = true;
684 
685     /* read flags */
686     for (--argc, ++argv; argc > 0; --argc, ++argv) {
687 	arg = argv[0];
688 
689 	if (arg[0] != '-' || arg[1] == '\0')
690 	    break;
691 
692 	if (!strncmp(arg, "--", 2)) {
693 	    char *eqls;
694 	    size_t lc;
695 	    size_t len;
696 
697 	    if ((len = strlen(arg)) == 2) {
698 		--argc;
699 		++argv;
700 		break;
701 	    }
702 
703 	    if ((eqls = strchr(arg, '=')) != NULL) {
704 		len = (size_t) (eqls - arg);
705 		if (len == 0 || eqls[1] == '\0')
706 		    invalid_option(arg);
707 	    }
708 
709 	    for (lc = 0; lc < SIZEOF(long_opts); ++lc) {
710 		if (!strncmp(long_opts[lc].fake_opt, arg + 2, len - 2)) {
711 		    if (eqls != NULL && !long_opts[lc].yacc_arg)
712 			invalid_option(arg);
713 		    *arg++ = '-';
714 		    *arg++ = long_opts[lc].real_opt;
715 		    *arg = '\0';
716 		    if (eqls) {
717 			while ((*arg++ = *++eqls) != '\0') /* empty */ ;
718 		    }
719 		    break;
720 		}
721 	    }
722 	    arg = argv[0];
723 	    if (!strncmp(arg, "--", 2))
724 		invalid_option(arg);
725 	}
726 
727 	for (i = 1; arg[i] != '\0'; ++i) {
728 	    int ch = arg[i];
729 	    size_t j;
730 	    const char *option_value = NULL;
731 
732 	    for (j = 0; j < SIZEOF(normal_opts); ++j) {
733 		if (normal_opts[j].option == ch) {
734 		    if (normal_opts[j].param_type < 0) {
735 			option_value = arg + i + 1;
736 		    } else if (normal_opts[j].param_type != 0) {
737 			if (i != 1) {
738 			    flexerror(_("-%c flag must be given separately"),
739 				      ch);
740 			}
741 			if (arg[i + 1] != '\0') {
742 			    option_value = arg + i + 1;
743 			} else {
744 			    --argc;
745 			    option_value = arg = *++argv;
746 			}
747 			if (option_value == NULL)
748 			    flexerror(_("-%c flag has no value"), ch);
749 		    }
750 		    i = (int) strlen(arg) - 1;
751 		    break;
752 		}
753 	    }
754 
755 	    switch (ch) {
756 	    case '+':
757 		C_plus_plus = true;
758 		break;
759 
760 	    case 'B':
761 		interactive = false;
762 		break;
763 
764 	    case 'b':
765 		backing_up_report = true;
766 		break;
767 
768 	    case 'c':
769 		break;
770 
771 	    case 'C':
772 		if (!sawcmpflag) {
773 		    useecs = false;
774 		    usemecs = false;
775 		    fulltbl = false;
776 		    sawcmpflag = true;
777 		}
778 
779 		if (option_value != NULL) {
780 		    for (j = 0; option_value[j] != '\0'; ++j) {
781 			switch (option_value[j]) {
782 			case 'a':
783 			    long_align =
784 				true;
785 			    break;
786 
787 			case 'e':
788 			    useecs = true;
789 			    break;
790 
791 			case 'F':
792 			    fullspd = true;
793 			    break;
794 
795 			case 'f':
796 			    fulltbl = true;
797 			    break;
798 
799 			case 'm':
800 			    usemecs = true;
801 			    break;
802 
803 			case 'r':
804 			    use_read = true;
805 			    break;
806 
807 			default:
808 			    lerrif(
809 				      _("unknown -C option '%c'"),
810 				      (int) option_value[j]);
811 			    break;
812 			}
813 		    }
814 		}
815 		break;
816 
817 	    case 'd':
818 		ddebug = true;
819 		break;
820 
821 	    case 'f':
822 		useecs = usemecs = false;
823 		use_read = fulltbl = true;
824 		break;
825 
826 	    case 'F':
827 		useecs = usemecs = false;
828 		use_read = fullspd = true;
829 		break;
830 
831 	    case '?':
832 	    case 'h':
833 		usage();
834 		exit(EXIT_SUCCESS);
835 
836 	    case 'I':
837 		interactive = true;
838 		break;
839 
840 	    case 'i':
841 		caseins = true;
842 		break;
843 
844 	    case 'l':
845 		lex_compat = true;
846 		break;
847 
848 	    case 'L':
849 		gen_line_dirs = false;
850 		break;
851 
852 	    case 'n':
853 		/* Stupid do-nothing deprecated
854 		 * option.
855 		 */
856 		break;
857 
858 	    case 'o':
859 		outfilename = option_value;
860 		did_outfilename = 1;
861 		break;
862 
863 	    case 'P':
864 		prefix = option_value;
865 		break;
866 
867 	    case 'p':
868 		++performance_report;
869 		break;
870 
871 	    case 'S':
872 		skelname = option_value;
873 		break;
874 
875 	    case 's':
876 		spprdflt = true;
877 		break;
878 
879 	    case 't':
880 		use_stdout = true;
881 		break;
882 
883 	    case 'T':
884 		trace = true;
885 		break;
886 
887 	    case 'v':
888 		printstats = true;
889 		break;
890 
891 	    case 'V':
892 		printf(_("%s version %s (%s)\n"),
893 		       program_name, flex_version, flex_patched);
894 		exit(EXIT_SUCCESS);
895 
896 	    case 'w':
897 		nowarn = true;
898 		break;
899 
900 	    case '7':
901 		csize = 128;
902 		break;
903 
904 	    case '8':
905 		csize = CSIZE;
906 		break;
907 
908 	    default:
909 		fprintf(stderr,
910 			_("%s: unknown flag '%c'.  For usage, try\n\t%s --help\n"),
911 			program_name, ch,
912 			program_name);
913 		exit(EXIT_FAILURE);
914 	    }
915 	}
916     }
917 
918     /*
919      * At this point, argv points to the first input-file, and argc has been
920      * adjusted to the length of the input-file list in argv.
921      */
922     num_input_files = argc;
923     input_files = argv;
924     set_input_file(num_input_files > 0 ? input_files[0] : NULL);
925 
926     lastccl = lastsc = lastdfa = lastnfa = 0;
927     num_rules = num_eof_rules = default_rule = 0;
928     numas = numsnpairs = tmpuses = 0;
929     numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
930     numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
931     num_backing_up = onesp = numprots = 0;
932     variable_trailing_context_rules = bol_needed = false;
933 
934     out_linenum = linenum = sectnum = 1;
935     firstprot = NIL;
936 
937     /* Used in mkprot() so that the first proto goes in slot 1
938      * of the proto queue.
939      */
940     lastprot = 1;
941 
942     set_up_initial_allocations();
943 }
944 
945 /* readin - read in the rules section of the input file(s) */
946 
947 void
readin(void)948 readin(void)
949 {
950     static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;";
951     static char yy_nostdinit[] =
952     "FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;";
953 #ifndef FLEXLEXER_HDR
954 #define FLEXLEXER_HDR "FlexLexer.h"
955 #endif
956     if (C_plus_plus) {
957 	outn("\n#include <" FLEXLEXER_HDR ">");
958     }
959 
960     line_directive_out((FILE *) 0, 1);
961 
962     if (yyparse()) {
963 	pinpoint_message(_("fatal parse error"));
964 	flexend(1);
965     }
966 
967     if (syntaxerror)
968 	flexend(1);
969 
970     if (backing_up_report) {
971 	backing_up_file = fopen(backing_name, "w");
972 	if (backing_up_file == NULL)
973 	    lerrsf(
974 		      _("could not create backing-up info file %s"),
975 		      backing_name);
976     }
977 
978     else
979 	backing_up_file = NULL;
980 
981     if (yymore_really_used == true)
982 	yymore_used = true;
983     else if (yymore_really_used == false)
984 	yymore_used = false;
985 
986     if (reject_really_used == true)
987 	reject = true;
988     else if (reject_really_used == false)
989 	reject = false;
990 
991     if (performance_report > 0) {
992 	if (lex_compat) {
993 	    fprintf(stderr,
994 		    _("-l AT&T lex compatibility option entails a large performance penalty\n"));
995 	    fprintf(stderr,
996 		    _(" and may be the actual source of other reported performance penalties\n"));
997 	}
998 
999 	else if (do_yylineno) {
1000 	    fprintf(stderr,
1001 		    _("%%option yylineno entails a large performance penalty\n"));
1002 	}
1003 
1004 	if (performance_report > 1) {
1005 	    if (interactive)
1006 		fprintf(stderr,
1007 			_("-I (interactive) entails a minor performance penalty\n"));
1008 
1009 	    if (yymore_used)
1010 		fprintf(stderr,
1011 			_("yymore() entails a minor performance penalty\n"));
1012 	}
1013 
1014 	if (reject)
1015 	    fprintf(stderr,
1016 		    _("REJECT entails a large performance penalty\n"));
1017 
1018 	if (variable_trailing_context_rules)
1019 	    fprintf(stderr,
1020 		    _("Variable trailing context rules entail a large performance penalty\n"));
1021     }
1022 
1023     if (reject)
1024 	real_reject = true;
1025 
1026     if (variable_trailing_context_rules)
1027 	reject = true;
1028 
1029     if ((fulltbl || fullspd) && reject) {
1030 	if (real_reject)
1031 	    flexerror(
1032 			 _("REJECT cannot be used with -f or -F"));
1033 	else if (do_yylineno)
1034 	    flexerror(
1035 			 _("%%option yylineno cannot be used with -f or -F"));
1036 	else
1037 	    flexerror(
1038 			 _("variable trailing context rules cannot be used with -f or -F"));
1039     }
1040 
1041     if (reject)
1042 	outn("\n#define YY_USES_REJECT");
1043 
1044     if (!do_yywrap) {
1045 	outn("\n#define yywrap() 1");
1046 	outn("#define YY_SKIP_YYWRAP");
1047     }
1048 
1049     if (ddebug)
1050 	outn("\n#define FLEX_DEBUG");
1051 
1052     if (csize == 256)
1053 	outn("typedef unsigned char YY_CHAR;");
1054     else
1055 	outn("typedef char YY_CHAR;");
1056 
1057     if (C_plus_plus) {
1058 	outn("#define yytext_ptr yytext");
1059 
1060 	if (interactive)
1061 	    outn("#define YY_INTERACTIVE");
1062     }
1063 
1064     else {
1065 	if (do_stdinit) {
1066 	    outn("#ifdef VMS");
1067 	    outn("#ifndef __VMS_POSIX");
1068 	    outn(yy_nostdinit);
1069 	    outn("#else");
1070 	    outn(yy_stdinit);
1071 	    outn("#endif");
1072 	    outn("#else");
1073 	    outn(yy_stdinit);
1074 	    outn("#endif");
1075 	}
1076 
1077 	else
1078 	    outn(yy_nostdinit);
1079     }
1080 
1081     if (fullspd)
1082 	outn("typedef yyconst struct yy_trans_info *yy_state_type;");
1083     else if (!C_plus_plus)
1084 	outn("typedef int yy_state_type;");
1085 
1086     if (ddebug)
1087 	outn("\n#define FLEX_DEBUG");
1088 
1089     if (lex_compat)
1090 	outn("#define YY_FLEX_LEX_COMPAT");
1091 
1092     if (do_yylineno && !C_plus_plus) {
1093 	outn("extern int yylineno;");
1094 	outn("int yylineno = 1;");
1095     }
1096     if (C_plus_plus) {
1097 	if (yyclass) {
1098 	    outn("int yyFlexLexer::yylex()");
1099 	    outn("\t{");
1100 	    outn(
1101 		    "\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );");
1102 	    outn("\treturn 0;");
1103 	    outn("\t}");
1104 
1105 	    out_str("\n#define YY_DECL int %s::yylex()\n",
1106 		    yyclass);
1107 	}
1108     }
1109 
1110     else {
1111 	if (yytext_is_array)
1112 	    outn("extern char yytext[];\n");
1113 
1114 	else {
1115 	    outn("extern char *yytext;");
1116 	    outn("#define yytext_ptr yytext");
1117 	}
1118 
1119 	if (yyclass)
1120 	    flexerror(
1121 			 _("%%option yyclass only meaningful for C++ scanners"));
1122     }
1123 
1124     if (useecs)
1125 	numecs = cre8ecs(nextecm, ecgroup, csize);
1126     else
1127 	numecs = csize;
1128 
1129     /* Now map the equivalence class for NUL to its expected place. */
1130     ecgroup[0] = ecgroup[csize];
1131     NUL_ec = ABS(ecgroup[0]);
1132 
1133     if (useecs)
1134 	ccl2ecl();
1135 }
1136 
1137 /* set_up_initial_allocations - allocate memory for internal tables */
1138 
1139 void
set_up_initial_allocations(void)1140 set_up_initial_allocations(void)
1141 {
1142     current_mns = INITIAL_MNS;
1143     firstst = allocate_integer_array(current_mns);
1144     lastst = allocate_integer_array(current_mns);
1145     finalst = allocate_integer_array(current_mns);
1146     transchar = allocate_integer_array(current_mns);
1147     trans1 = allocate_integer_array(current_mns);
1148     trans2 = allocate_integer_array(current_mns);
1149     accptnum = allocate_integer_array(current_mns);
1150     assoc_rule = allocate_integer_array(current_mns);
1151     state_type = allocate_integer_array(current_mns);
1152 
1153     current_max_rules = INITIAL_MAX_RULES;
1154     rule_type = allocate_integer_array(current_max_rules);
1155     rule_linenum = allocate_integer_array(current_max_rules);
1156     rule_useful = allocate_integer_array(current_max_rules);
1157 
1158     current_max_scs = INITIAL_MAX_SCS;
1159     scset = allocate_integer_array(current_max_scs);
1160     scbol = allocate_integer_array(current_max_scs);
1161     scxclu = allocate_integer_array(current_max_scs);
1162     sceof = allocate_integer_array(current_max_scs);
1163     scname = allocate_char_ptr_array(current_max_scs);
1164 
1165     current_maxccls = INITIAL_MAX_CCLS;
1166     cclmap = allocate_integer_array(current_maxccls);
1167     ccllen = allocate_integer_array(current_maxccls);
1168     cclng = allocate_integer_array(current_maxccls);
1169 
1170     current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
1171     ccltbl = allocate_CCLTBL_array(current_max_ccl_tbl_size);
1172 
1173     current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
1174 
1175     current_max_xpairs = INITIAL_MAX_XPAIRS;
1176     nxt = allocate_integer_array(current_max_xpairs);
1177     chk = allocate_integer_array(current_max_xpairs);
1178 
1179     current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
1180     tnxt = allocate_integer_array(current_max_template_xpairs);
1181 
1182     current_max_dfas = INITIAL_MAX_DFAS;
1183     base = allocate_integer_array(current_max_dfas);
1184     def = allocate_integer_array(current_max_dfas);
1185     dfasiz = allocate_integer_array(current_max_dfas);
1186     accsiz = allocate_integer_array(current_max_dfas);
1187     dhash = allocate_integer_array(current_max_dfas);
1188     dss = allocate_int_ptr_array(current_max_dfas);
1189     dfaacc = allocate_dfaacc_union(current_max_dfas);
1190 
1191     nultrans = (int *) 0;
1192 }
1193 
1194 void
usage(void)1195 usage(void)
1196 {
1197     FILE *f = stdout;
1198     size_t n;
1199     const char *extra_param = NULL;
1200 
1201     if (!did_outfilename) {
1202 	sprintf(outfile_path, outfile_template,
1203 		prefix, C_plus_plus ? "cc" : "c");
1204 	outfilename = outfile_path;
1205     }
1206 
1207     fprintf(f, _("%s [options] [file ...]\n"), program_name);
1208 
1209     fprintf(f, "\n");
1210     fprintf(f, _("Options:\n"));
1211     for (n = 0; n < SIZEOF(normal_opts); ++n) {
1212 	const char *param = "";
1213 	switch (normal_opts[n].param_type) {
1214 	case -1:
1215 	    param = "[STRING]";
1216 	    break;
1217 	case 1:
1218 	    param = " STRING";
1219 	    break;
1220 	case 2:
1221 	    param = " FILE";
1222 	    break;
1223 	}
1224 
1225 	fprintf(f, "  -%c%-9s ", normal_opts[n].option, param);
1226 	switch (normal_opts[n].is_program) {
1227 	case 1:
1228 	    extra_param = program_name;
1229 	    break;
1230 	case 2:
1231 	    extra_param = outfilename;
1232 	    break;
1233 	case 3:
1234 	    extra_param = backing_name;
1235 	    break;
1236 	}
1237 	if (extra_param) {
1238 	    fprintf(f, normal_opts[n].help_text, extra_param);
1239 	} else {
1240 	    fputs(normal_opts[n].help_text, f);
1241 	}
1242 	fputc('\n', f);
1243     }
1244 
1245     fprintf(f, "\n");
1246     fprintf(f, _("Compression options:\n"));
1247     for (n = 0; n < SIZEOF(compress_opts); ++n) {
1248 	fprintf(f, "  -C%c %7s %s\n",
1249 		compress_opts[n].option,
1250 		"",
1251 		compress_opts[n].help_text);
1252     }
1253 
1254     fprintf(f, "\n");
1255     fprintf(f, _("Long options:\n"));
1256     for (n = 0; n < SIZEOF(long_opts); ++n) {
1257 	fprintf(f, "  --%-20s-%c\n",
1258 		long_opts[n].fake_opt,
1259 		long_opts[n].real_opt);
1260     }
1261 }
1262