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