1 /* flex - tool to generate fast lexical analyzers */
3 /* Copyright (c) 1990 The Regents of the University of California. */
4 /* All rights reserved. */
6 /* This code is derived from software contributed to Berkeley by */
9 /* The United States Government has rights in this work pursuant */
10 /* to contract no. DE-AC03-76SF00098 between the United States */
11 /* Department of Energy and the University of California. */
13 /* This file is part of flex. */
15 /* Redistribution and use in source and binary forms, with or without */
16 /* modification, are permitted provided that the following conditions */
19 /* 1. Redistributions of source code must retain the above copyright */
20 /* notice, this list of conditions and the following disclaimer. */
21 /* 2. Redistributions in binary form must reproduce the above copyright */
22 /* notice, this list of conditions and the following disclaimer in the */
23 /* documentation and/or other materials provided with the distribution. */
25 /* Neither the name of the University nor the names of its contributors */
26 /* may be used to endorse or promote products derived from this software */
27 /* without specific prior written permission. */
29 /* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
30 /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
31 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
40 static char flex_version
[] = FLEX_VERSION
;
42 /* declare functions that have forward references */
44 void flexinit
PROTO ((int, char **));
45 void readin
PROTO ((void));
46 void set_up_initial_allocations
PROTO ((void));
47 static char *basename2
PROTO ((char *path
, int should_strip_ext
));
50 /* these globals are all defined and commented in flexdef.h */
51 int printstats
, syntaxerror
, eofseen
, ddebug
, trace
, nowarn
, spprdflt
;
52 int interactive
, lex_compat
, posix_compat
, do_yylineno
,
53 useecs
, fulltbl
, usemecs
;
54 int fullspd
, gen_line_dirs
, performance_report
, backing_up_report
;
55 int C_plus_plus
, long_align
, use_read
, yytext_is_array
, do_yywrap
,
57 int reentrant
, bison_bridge_lval
, bison_bridge_lloc
;
58 int yymore_used
, reject
, real_reject
, continued_action
, in_rule
;
59 int yymore_really_used
, reject_really_used
;
60 int datapos
, dataline
, linenum
;
61 FILE *skelfile
= NULL
;
64 int action_size
, defs1_offset
, prolog_offset
, action_offset
,
66 char *infilename
= NULL
, *outfilename
= NULL
, *headerfilename
= NULL
;
68 char *prefix
, *yyclass
, *extra_type
= NULL
;
69 int do_stdinit
, use_stdout
;
70 int onestate
[ONE_STACK_SIZE
], onesym
[ONE_STACK_SIZE
];
71 int onenext
[ONE_STACK_SIZE
], onedef
[ONE_STACK_SIZE
], onesp
;
72 int maximum_mns
, current_mns
, current_max_rules
;
73 int num_rules
, num_eof_rules
, default_rule
, lastnfa
;
74 int *firstst
, *lastst
, *finalst
, *transchar
, *trans1
, *trans2
;
75 int *accptnum
, *assoc_rule
, *state_type
;
76 int *rule_type
, *rule_linenum
, *rule_useful
;
77 int current_state_type
;
78 int variable_trailing_context_rules
;
79 int numtemps
, numprots
, protprev
[MSP
], protnext
[MSP
], prottbl
[MSP
];
80 int protcomst
[MSP
], firstprot
, lastprot
, protsave
[PROT_SAVE_SIZE
];
81 int numecs
, nextecm
[CSIZE
+ 1], ecgroup
[CSIZE
+ 1], nummecs
,
83 int tecbck
[CSIZE
+ 1];
84 int lastsc
, *scset
, *scbol
, *scxclu
, *sceof
;
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
;
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
;
105 jmp_buf flex_main_jmp_buf
;
106 bool *rule_has_nl
, *ccl_has_nl
;
108 bool ansi_func_defs
, ansi_func_protos
;
110 bool tablesext
, tablesverify
, gentables
;
111 char *tablesfilename
=0,*tablesname
=0;
112 struct yytbl_writer tableswr
;
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].
117 char *program_name
= "flex";
119 #ifndef SHORT_FILE_NAMES
120 static char *outfile_template
= "lex.%s.%s";
121 static char *backing_name
= "lex.backup";
122 static char *tablesfile_template
= "lex.%s.tables";
124 static char *outfile_template
= "lex%s.%s";
125 static char *backing_name
= "lex.bck";
126 static char *tablesfile_template
= "lex%s.tbl";
130 extern unsigned _stklen
= 16384;
136 static char outfile_path
[MAXLINE
];
137 static int outfile_created
= 0;
138 static char *skelname
= NULL
;
139 static int _stdout_closed
= 0; /* flag to prevent double-fclose() on stdout. */
140 const char *escaped_qstart
= "[[]]M4_YY_NOOP[M4_YY_NOOP[M4_YY_NOOP[[]]";
141 const char *escaped_qend
= "[[]]M4_YY_NOOP]M4_YY_NOOP]M4_YY_NOOP[[]]";
143 /* For debugging. The max number of filters to apply to skeleton. */
144 static int preproc_level
= 1000;
146 int flex_main
PROTO ((int argc
, char *argv
[]));
147 int main
PROTO ((int argc
, char *argv
[]));
149 int flex_main (argc
, argv
)
153 int i
, exit_status
, child_status
;
155 /* Set a longjmp target. Yes, I know it's a hack, but it gets worse: The
156 * return value of setjmp, if non-zero, is the desired exit code PLUS ONE.
157 * For example, if you want 'main' to return with code '2', then call
158 * longjmp() with an argument of 3. This is because it is invalid to
159 * specify a value of 0 to longjmp. FLEX_EXIT(n) should be used instead of
162 exit_status
= setjmp (flex_main_jmp_buf
);
164 if (stdout
&& !_stdout_closed
&& !ferror(stdout
)){
168 while (wait(&child_status
) > 0){
169 if (!WIFEXITED (child_status
)
170 || WEXITSTATUS (child_status
) != 0){
171 /* report an error of a child
173 if( exit_status
<= 1 )
178 return exit_status
- 1;
181 flexinit (argc
, argv
);
187 for (i
= 1; i
<= num_rules
; ++i
)
188 if (!rule_useful
[i
] && i
!= default_rule
)
189 line_warning (_("rule cannot be matched"),
192 if (spprdflt
&& !reject
&& rule_useful
[default_rule
])
194 ("-s option given but default rule can be matched"),
195 rule_linenum
[default_rule
]);
197 /* Generate the C state transition tables from the DFA. */
200 /* Note, flexend does not return. It exits with its argument
205 return 0; /* keep compilers/lint happy */
208 /* Wrapper around flex_main, so flex_main can be built as a library. */
209 int main (argc
, argv
)
215 setlocale (LC_MESSAGES
, "");
216 setlocale (LC_CTYPE
, "");
217 textdomain (PACKAGE
);
218 bindtextdomain (PACKAGE
, LOCALEDIR
);
222 return flex_main (argc
, argv
);
225 /* check_options - check user-specified options */
227 void check_options ()
230 const char * m4
= NULL
;
234 flexerror (_("Can't use -+ with -l option"));
236 if (fulltbl
|| fullspd
)
237 flexerror (_("Can't use -f or -F with -l option"));
239 if (reentrant
|| bison_bridge_lval
)
241 ("Can't use --reentrant or --bison-bridge with -l option"));
243 /* Don't rely on detecting use of yymore() and REJECT,
244 * just assume they'll be used.
246 yymore_really_used
= reject_really_used
= true;
248 yytext_is_array
= true;
255 /* This makes no sense whatsoever. I'm removing it. */
257 /* This should really be "maintain_backup_tables = true" */
258 reject_really_used
= true;
261 if (csize
== unspecified
) {
262 if ((fulltbl
|| fullspd
) && !useecs
)
263 csize
= DEFAULT_CSIZE
;
268 if (interactive
== unspecified
) {
269 if (fulltbl
|| fullspd
)
275 if (fulltbl
|| fullspd
) {
278 ("-Cf/-CF and -Cm don't make sense together"));
281 flexerror (_("-Cf/-CF and -I are incompatible"));
285 ("-Cf/-CF are incompatible with lex-compatibility mode"));
288 if (fulltbl
&& fullspd
)
290 ("-Cf and -CF are mutually exclusive"));
293 if (C_plus_plus
&& fullspd
)
294 flexerror (_("Can't use -+ with -CF option"));
296 if (C_plus_plus
&& yytext_is_array
) {
297 warn (_("%array incompatible with -+ option"));
298 yytext_is_array
= false;
301 if (C_plus_plus
&& (reentrant
))
302 flexerror (_("Options -+ and --reentrant are mutually exclusive."));
304 if (C_plus_plus
&& bison_bridge_lval
)
305 flexerror (_("bison bridge not supported for the C++ scanner."));
308 if (useecs
) { /* Set up doubly-linked equivalence classes. */
310 /* We loop all the way up to csize, since ecgroup[csize] is
311 * the position used for NUL characters.
315 for (i
= 2; i
<= csize
; ++i
) {
320 nextecm
[csize
] = NIL
;
324 /* Put everything in its own equivalence class. */
325 for (i
= 1; i
<= csize
; ++i
) {
327 nextecm
[i
] = BAD_SUBSCRIPT
; /* to catch errors */
332 buf_m4_define( &m4defs_buf
, "M4_YY_NO_ANSI_FUNC_DEFS", NULL
);
334 if (!ansi_func_protos
)
335 buf_m4_define( &m4defs_buf
, "M4_YY_NO_ANSI_FUNC_PROTOS", NULL
);
338 buf_m4_define( &m4defs_buf
, "M4_EXTRA_TYPE_DEFS", extra_type
);
343 if (!did_outfilename
) {
351 snprintf (outfile_path
, sizeof(outfile_path
), outfile_template
,
354 outfilename
= outfile_path
;
357 prev_stdout
= freopen (outfilename
, "w+", stdout
);
359 if (prev_stdout
== NULL
)
360 lerrsf (_("could not create %s"), outfilename
);
366 /* Setup the filter chain. */
367 output_chain
= filter_create_int(NULL
, filter_tee_header
, headerfilename
);
368 if ( !(m4
= getenv("M4")))
370 filter_create_ext(output_chain
, m4
, "-P", 0);
371 filter_create_int(output_chain
, filter_fix_linedirs
, NULL
);
373 /* For debugging, only run the requested number of filters. */
374 if (preproc_level
> 0) {
375 filter_truncate(output_chain
, preproc_level
);
376 filter_apply_chain(output_chain
);
381 /* always generate the tablesverify flag. */
382 buf_m4_define (&m4defs_buf
, "M4_YY_TABLES_VERIFY", tablesverify
? "1" : "0");
387 /* force generation of C tables. */
393 struct yytbl_hdr hdr
;
397 buf_m4_define (&m4defs_buf
, "M4_YY_TABLES_EXTERNAL", NULL
);
399 if (!tablesfilename
) {
400 nbytes
= strlen (prefix
) + strlen (tablesfile_template
) + 2;
401 tablesfilename
= pname
= (char *) calloc (nbytes
, 1);
402 snprintf (pname
, nbytes
, tablesfile_template
, prefix
);
405 if ((tablesout
= fopen (tablesfilename
, "w")) == NULL
)
406 lerrsf (_("could not create %s"), tablesfilename
);
411 yytbl_writer_init (&tableswr
, tablesout
);
413 nbytes
= strlen (prefix
) + strlen ("tables") + 2;
414 tablesname
= (char *) calloc (nbytes
, 1);
415 snprintf (tablesname
, nbytes
, "%stables", prefix
);
416 yytbl_hdr_init (&hdr
, flex_version
, tablesname
);
418 if (yytbl_hdr_fwrite (&tableswr
, &hdr
) <= 0)
419 flexerror (_("could not write tables header"));
422 if (skelname
&& (skelfile
= fopen (skelname
, "r")) == NULL
)
423 lerrsf (_("can't open skeleton file %s"), skelname
);
426 buf_m4_define (&m4defs_buf
, "M4_YY_REENTRANT", NULL
);
428 buf_m4_define (&m4defs_buf
, "M4_YY_TEXT_IS_ARRAY", NULL
);
431 if ( bison_bridge_lval
)
432 buf_m4_define (&m4defs_buf
, "M4_YY_BISON_LVAL", NULL
);
434 if ( bison_bridge_lloc
)
435 buf_m4_define (&m4defs_buf
, "<M4_YY_BISON_LLOC>", NULL
);
437 buf_m4_define(&m4defs_buf
, "M4_YY_PREFIX", prefix
);
440 line_directive_out (stdout
, 0);
443 buf_m4_define (&m4defs_buf
, "M4_YY_USE_LINENO", NULL
);
445 /* Create the alignment type. */
446 buf_strdefine (&userdef_buf
, "YY_INT_ALIGNED",
447 long_align
? "long int" : "short int");
449 /* Define the start condition macros. */
452 buf_init(&tmpbuf
, sizeof(char));
453 for (i
= 1; i
<= lastsc
; i
++) {
454 char *str
, *fmt
= "#define %s %d\n";
457 str
= (char*)flex_alloc(strsz
= strlen(fmt
) + strlen(scname
[i
]) + (int)(1 + log10(i
)) + 2);
459 flexfatal(_("allocation of macro definition failed"));
460 snprintf(str
, strsz
, fmt
, scname
[i
], i
- 1);
461 buf_strappend(&tmpbuf
, str
);
464 buf_m4_define(&m4defs_buf
, "M4_YY_SC_DEFS", tmpbuf
.elts
);
465 buf_destroy(&tmpbuf
);
468 /* This is where we begin writing to the file. */
470 /* Dump the %top code. */
472 outn((char*) top_buf
.elts
);
474 /* Dump the m4 definitions. */
475 buf_print_strings(&m4defs_buf
, stdout
);
476 m4defs_buf
.nelts
= 0; /* memory leak here. */
478 /* Place a bogus line directive, it will be fixed in the filter. */
479 outn("#line 0 \"M4_YY_OUTFILE_NAME\"\n");
481 /* Dump the user defined preproc directives. */
482 if (userdef_buf
.elts
)
483 outn ((char *) (userdef_buf
.elts
));
489 /* flexend - terminate flex
492 * This routine does not return.
495 void flexend (exit_status
)
499 static int called_before
= -1; /* prevent infinite recursion. */
503 FLEX_EXIT (exit_status
);
505 if (skelfile
!= NULL
) {
506 if (ferror (skelfile
))
507 lerrsf (_("input error reading skeleton file %s"),
510 else if (fclose (skelfile
))
511 lerrsf (_("error closing skeleton file %s"),
517 "#ifdef YY_HEADER_EXPORT_START_CONDITIONS\n");
519 "/* Beware! Start conditions are not prefixed. */\n");
521 /* Special case for "INITIAL" */
523 "#undef INITIAL\n#define INITIAL 0\n");
524 for (i
= 2; i
<= lastsc
; i
++)
525 fprintf (header_out
, "#define %s %d\n", scname
[i
], i
- 1);
527 "#endif /* YY_HEADER_EXPORT_START_CONDITIONS */\n\n");
529 /* Kill ALL flex-related macros. This is so the user
530 * can #include more than one generated header file. */
531 fprintf (header_out
, "#ifndef YY_HEADER_NO_UNDEFS\n");
533 "/* Undefine all internal macros, etc., that do no belong in the header. */\n\n");
536 const char * undef_list
[] = {
540 "EOB_ACT_CONTINUE_SCAN",
541 "EOB_ACT_END_OF_FILE",
542 "EOB_ACT_LAST_MATCH",
554 "YY_BUFFER_EOF_PENDING",
558 "M4_YY_CALL_LAST_ARG",
559 "M4_YY_CALL_ONLY_ARG",
562 "M4_YY_DECL_LAST_ARG",
563 "M4_YY_DEF_LAST_ARG",
564 "M4_YY_DEF_ONLY_ARG",
565 "YY_DO_BEFORE_ACTION",
567 "YY_END_OF_BUFFER_CHAR",
571 "YY_FLEX_DEFINED_ECHO",
572 "YY_FLEX_LEX_COMPAT",
573 "YY_FLEX_MAJOR_VERSION",
574 "YY_FLEX_MINOR_VERSION",
575 "YY_FLEX_SUBMINOR_VERSION",
584 "YY_LEX_DECLARATION",
595 "M4_YY_PROTO_LAST_ARG",
596 "M4_YY_PROTO_ONLY_ARG void",
599 "YY_RESTORE_YY_MORE_OFFSET",
604 "YY_START_STACK_INCR",
607 "YY_TRAILING_HEAD_MASK",
619 "yy_load_buffer_state",
625 "yy_set_interactive",
626 "yy_switch_to_buffer",
627 "yypush_buffer_state",
628 "yypop_buffer_state",
629 "yyensure_buffer_stack",
671 /* must be null-terminated */
675 for (i
=0; undef_list
[i
] != NULL
; i
++)
676 fprintf (header_out
, "#undef %s\n", undef_list
[i
]);
679 /* undef any of the auto-generated symbols. */
680 for (i
= 0; i
< defs_buf
.nelts
; i
++) {
682 /* don't undef start conditions */
683 if (sclookup (((char **) defs_buf
.elts
)[i
]) > 0)
685 fprintf (header_out
, "#undef %s\n",
686 ((char **) defs_buf
.elts
)[i
]);
690 "#endif /* !YY_HEADER_NO_UNDEFS */\n");
691 fprintf (header_out
, "\n");
692 fprintf (header_out
, "#undef %sIN_HEADER\n", prefix
);
693 fprintf (header_out
, "#endif /* %sHEADER_H */\n", prefix
);
695 if (ferror (header_out
))
696 lerrsf (_("error creating header file %s"),
702 if (exit_status
!= 0 && outfile_created
) {
704 lerrsf (_("error writing output file %s"),
707 else if ((_stdout_closed
= 1) && fclose (stdout
))
708 lerrsf (_("error closing output file %s"),
711 else if (unlink (outfilename
))
712 lerrsf (_("error deleting output file %s"),
717 if (backing_up_report
&& backing_up_file
) {
718 if (num_backing_up
== 0)
719 fprintf (backing_up_file
, _("No backing up.\n"));
720 else if (fullspd
|| fulltbl
)
721 fprintf (backing_up_file
,
723 ("%d backing up (non-accepting) states.\n"),
726 fprintf (backing_up_file
,
727 _("Compressed tables always back up.\n"));
729 if (ferror (backing_up_file
))
730 lerrsf (_("error writing backup file %s"),
733 else if (fclose (backing_up_file
))
734 lerrsf (_("error closing backup file %s"),
739 fprintf (stderr
, _("%s version %s usage statistics:\n"),
740 program_name
, flex_version
);
742 fprintf (stderr
, _(" scanner options: -"));
746 if (backing_up_report
)
756 if (performance_report
> 0)
758 if (performance_report
> 1)
763 fputs ("--reentrant", stderr
);
764 if (bison_bridge_lval
)
765 fputs ("--bison-bridge", stderr
);
766 if (bison_bridge_lloc
)
767 fputs ("--bison-locations", stderr
);
771 putc ('v', stderr
); /* always true! */
774 if (interactive
== false)
776 if (interactive
== true)
783 if (csize
== unspecified
)
784 /* We encountered an error fairly early on, so csize
785 * never got specified. Define it now, to prevent
786 * bogus table sizes being written out below.
795 fprintf (stderr
, " -C");
811 fprintf (stderr
, " -o%s", outfilename
);
814 fprintf (stderr
, " -S%s", skelname
);
816 if (strcmp (prefix
, "yy"))
817 fprintf (stderr
, " -P%s", prefix
);
821 fprintf (stderr
, _(" %d/%d NFA states\n"),
822 lastnfa
, current_mns
);
823 fprintf (stderr
, _(" %d/%d DFA states (%d words)\n"),
824 lastdfa
, current_max_dfas
, totnst
);
825 fprintf (stderr
, _(" %d rules\n"),
826 num_rules
+ num_eof_rules
-
827 1 /* - 1 for def. rule */ );
829 if (num_backing_up
== 0)
830 fprintf (stderr
, _(" No backing up\n"));
831 else if (fullspd
|| fulltbl
)
834 (" %d backing-up (non-accepting) states\n"),
839 (" Compressed tables always back-up\n"));
843 _(" Beginning-of-line patterns used\n"));
845 fprintf (stderr
, _(" %d/%d start conditions\n"), lastsc
,
849 (" %d epsilon states, %d double epsilon states\n"),
853 fprintf (stderr
, _(" no character classes\n"));
857 (" %d/%d character classes needed %d/%d words of storage, %d reused\n"),
858 lastccl
, current_maxccls
,
859 cclmap
[lastccl
] + ccllen
[lastccl
],
860 current_max_ccl_tbl_size
, cclreuse
);
862 fprintf (stderr
, _(" %d state/nextstate pairs created\n"),
865 _(" %d/%d unique/duplicate transitions\n"),
869 tblsiz
= lastdfa
* numecs
;
870 fprintf (stderr
, _(" %d table entries\n"),
875 tblsiz
= 2 * (lastdfa
+ numtemps
) + 2 * tblend
;
878 _(" %d/%d base-def entries created\n"),
879 lastdfa
+ numtemps
, current_max_dfas
);
882 (" %d/%d (peak %d) nxt-chk entries created\n"),
883 tblend
, current_max_xpairs
, peakpairs
);
886 (" %d/%d (peak %d) template nxt-chk entries created\n"),
888 current_max_template_xpairs
,
890 fprintf (stderr
, _(" %d empty table entries\n"),
892 fprintf (stderr
, _(" %d protos created\n"),
895 _(" %d templates created, %d uses\n"),
900 tblsiz
= tblsiz
+ csize
;
903 (" %d/%d equivalence classes created\n"),
908 tblsiz
= tblsiz
+ numecs
;
911 (" %d/%d meta-equivalence classes created\n"),
917 (" %d (%d saved) hash collisions, %d DFAs equal\n"),
918 hshcol
, hshsave
, dfaeql
);
919 fprintf (stderr
, _(" %d sets of reallocations needed\n"),
921 fprintf (stderr
, _(" %d total table entries needed\n"),
925 FLEX_EXIT (exit_status
);
929 /* flexinit - initialize flex */
931 void flexinit (argc
, argv
)
935 int i
, sawcmpflag
, rv
, optind
;
939 printstats
= syntaxerror
= trace
= spprdflt
= false;
940 lex_compat
= posix_compat
= C_plus_plus
= backing_up_report
=
941 ddebug
= fulltbl
= false;
942 fullspd
= long_align
= nowarn
= yymore_used
= continued_action
=
944 do_yylineno
= yytext_is_array
= in_rule
= reject
= do_stdinit
=
946 yymore_really_used
= reject_really_used
= unspecified
;
947 interactive
= csize
= unspecified
;
948 do_yywrap
= gen_line_dirs
= usemecs
= useecs
= true;
949 reentrant
= bison_bridge_lval
= bison_bridge_lloc
= false;
950 performance_report
= 0;
954 use_read
= use_stdout
= false;
955 tablesext
= tablesverify
= false;
957 tablesfilename
= tablesname
= NULL
;
958 ansi_func_defs
= ansi_func_protos
= true;
962 /* Initialize dynamic array for holding the rule actions. */
963 action_size
= 2048; /* default size of action array in bytes */
964 action_array
= allocate_character_array (action_size
);
965 defs1_offset
= prolog_offset
= action_offset
= action_index
= 0;
966 action_array
[0] = '\0';
968 /* Initialize any buffers. */
969 buf_init (&userdef_buf
, sizeof (char)); /* one long string */
970 buf_init (&defs_buf
, sizeof (char *)); /* list of strings */
971 buf_init (&yydmap_buf
, sizeof (char)); /* one long string */
972 buf_init (&top_buf
, sizeof (char)); /* one long string */
975 const char * m4defs_init_str
[] = {"m4_changequote\n",
976 "m4_changequote([[, ]])\n"};
977 buf_init (&m4defs_buf
, sizeof (char *));
978 buf_append (&m4defs_buf
, &m4defs_init_str
, 2);
983 /* initialize regex lib */
986 /* Enable C++ if program name ends with '+'. */
987 program_name
= basename2 (argv
[0], 0);
989 if (program_name
[0] != '\0' &&
990 program_name
[strlen (program_name
) - 1] == '+')
994 sopt
= scanopt_init (flexopts
, argc
, argv
, 0);
996 /* This will only happen when flexopts array is altered. */
998 _("Internal error. flexopts are malformed.\n"));
1002 while ((rv
= scanopt (sopt
, &arg
, &optind
)) != 0) {
1005 /* Scanopt has already printed an option-specific error message. */
1008 ("Try `%s --help' for more information.\n"),
1013 switch ((enum flexopt_flag_t
) rv
) {
1019 interactive
= false;
1023 backing_up_report
= true;
1029 case OPT_COMPRESSION
:
1037 for (i
= 0; arg
&& arg
[i
] != '\0'; i
++)
1065 ("unknown -C option '%c'"),
1080 useecs
= usemecs
= false;
1081 use_read
= fulltbl
= true;
1085 useecs
= usemecs
= false;
1086 use_read
= fullspd
= true;
1093 case OPT_INTERACTIVE
:
1097 case OPT_CASE_INSENSITIVE
:
1098 sf_set_case_ins(true);
1101 case OPT_LEX_COMPAT
:
1105 case OPT_POSIX_COMPAT
:
1106 posix_compat
= true;
1109 case OPT_PREPROC_LEVEL
:
1110 preproc_level
= strtol(arg
,NULL
,0);
1114 buf_strdefine (&userdef_buf
, "YY_MAIN", "1");
1119 buf_strdefine (&userdef_buf
, "YY_MAIN", "0");
1123 gen_line_dirs
= false;
1128 did_outfilename
= 1;
1135 case OPT_PERF_REPORT
:
1136 ++performance_report
;
1139 case OPT_BISON_BRIDGE
:
1140 bison_bridge_lval
= true;
1143 case OPT_BISON_BRIDGE_LOCATIONS
:
1144 bison_bridge_lval
= bison_bridge_lloc
= true;
1151 case OPT_NO_REENTRANT
:
1163 case OPT_NO_DEFAULT
:
1171 case OPT_NO_UNISTD_H
:
1172 //buf_strdefine (&userdef_buf, "YY_NO_UNISTD_H", "1");
1173 buf_m4_define( &m4defs_buf
, "M4_YY_NO_UNISTD_H",0);
1176 case OPT_TABLES_FILE
:
1178 tablesfilename
= arg
;
1181 case OPT_TABLES_VERIFY
:
1182 tablesverify
= true;
1194 printf (_("%s %s\n"), program_name
, flex_version
);
1221 case OPT_ALWAYS_INTERACTIVE
:
1222 buf_m4_define (&m4defs_buf
, "M4_YY_ALWAYS_INTERACTIVE", 0);
1225 case OPT_NEVER_INTERACTIVE
:
1226 buf_m4_define( &m4defs_buf
, "M4_YY_NEVER_INTERACTIVE", 0);
1230 yytext_is_array
= true;
1234 yytext_is_array
= false;
1245 case OPT_HEADER_FILE
:
1246 headerfilename
= arg
;
1253 case OPT_NO_META_ECS
:
1257 case OPT_PREPROCDEFINE
:
1259 /* arg is "symbol" or "symbol=definition". */
1263 *def
!= '\0' && *def
!= '='; ++def
) ;
1265 buf_strappend (&userdef_buf
, "#define ");
1267 buf_strappend (&userdef_buf
, arg
);
1268 buf_strappend (&userdef_buf
,
1272 buf_strnappend (&userdef_buf
, arg
,
1274 buf_strappend (&userdef_buf
, " ");
1275 buf_strappend (&userdef_buf
,
1277 buf_strappend (&userdef_buf
, "\n");
1287 //buf_strdefine (&userdef_buf, "YY_STACK_USED", "1");
1288 buf_m4_define( &m4defs_buf
, "M4_YY_STACK_USED",0);
1295 case OPT_NO_STDINIT
:
1307 case OPT_NO_YYLINENO
:
1308 do_yylineno
= false;
1320 yymore_really_used
= true;
1324 yymore_really_used
= false;
1328 reject_really_used
= true;
1332 reject_really_used
= false;
1335 case OPT_NO_ANSI_FUNC_DEFS
:
1336 ansi_func_defs
= false;
1339 case OPT_NO_ANSI_FUNC_PROTOS
:
1340 ansi_func_protos
= false;
1343 case OPT_NO_YY_PUSH_STATE
:
1344 //buf_strdefine (&userdef_buf, "YY_NO_PUSH_STATE", "1");
1345 buf_m4_define( &m4defs_buf
, "M4_YY_NO_PUSH_STATE",0);
1347 case OPT_NO_YY_POP_STATE
:
1348 //buf_strdefine (&userdef_buf, "YY_NO_POP_STATE", "1");
1349 buf_m4_define( &m4defs_buf
, "M4_YY_NO_POP_STATE",0);
1351 case OPT_NO_YY_TOP_STATE
:
1352 //buf_strdefine (&userdef_buf, "YY_NO_TOP_STATE", "1");
1353 buf_m4_define( &m4defs_buf
, "M4_YY_NO_TOP_STATE",0);
1356 //buf_strdefine (&userdef_buf, "YY_NO_UNPUT", "1");
1357 buf_m4_define( &m4defs_buf
, "M4_YY_NO_UNPUT",0);
1359 case OPT_NO_YY_SCAN_BUFFER
:
1360 //buf_strdefine (&userdef_buf, "YY_NO_SCAN_BUFFER", "1");
1361 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SCAN_BUFFER",0);
1363 case OPT_NO_YY_SCAN_BYTES
:
1364 //buf_strdefine (&userdef_buf, "YY_NO_SCAN_BYTES", "1");
1365 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SCAN_BYTES",0);
1367 case OPT_NO_YY_SCAN_STRING
:
1368 //buf_strdefine (&userdef_buf, "YY_NO_SCAN_STRING", "1");
1369 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SCAN_STRING",0);
1371 case OPT_NO_YYGET_EXTRA
:
1372 //buf_strdefine (&userdef_buf, "YY_NO_GET_EXTRA", "1");
1373 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_EXTRA",0);
1375 case OPT_NO_YYSET_EXTRA
:
1376 //buf_strdefine (&userdef_buf, "YY_NO_SET_EXTRA", "1");
1377 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SET_EXTRA",0);
1379 case OPT_NO_YYGET_LENG
:
1380 //buf_strdefine (&userdef_buf, "YY_NO_GET_LENG", "1");
1381 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_LENG",0);
1383 case OPT_NO_YYGET_TEXT
:
1384 //buf_strdefine (&userdef_buf, "YY_NO_GET_TEXT", "1");
1385 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_TEXT",0);
1387 case OPT_NO_YYGET_LINENO
:
1388 //buf_strdefine (&userdef_buf, "YY_NO_GET_LINENO", "1");
1389 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_LINENO",0);
1391 case OPT_NO_YYSET_LINENO
:
1392 //buf_strdefine (&userdef_buf, "YY_NO_SET_LINENO", "1");
1393 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SET_LINENO",0);
1395 case OPT_NO_YYGET_IN
:
1396 //buf_strdefine (&userdef_buf, "YY_NO_GET_IN", "1");
1397 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_IN",0);
1399 case OPT_NO_YYSET_IN
:
1400 //buf_strdefine (&userdef_buf, "YY_NO_SET_IN", "1");
1401 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SET_IN",0);
1403 case OPT_NO_YYGET_OUT
:
1404 //buf_strdefine (&userdef_buf, "YY_NO_GET_OUT", "1");
1405 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_OUT",0);
1407 case OPT_NO_YYSET_OUT
:
1408 //buf_strdefine (&userdef_buf, "YY_NO_SET_OUT", "1");
1409 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SET_OUT",0);
1411 case OPT_NO_YYGET_LVAL
:
1412 //buf_strdefine (&userdef_buf, "YY_NO_GET_LVAL", "1");
1413 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_LVAL",0);
1415 case OPT_NO_YYSET_LVAL
:
1416 //buf_strdefine (&userdef_buf, "YY_NO_SET_LVAL", "1");
1417 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SET_LVAL",0);
1419 case OPT_NO_YYGET_LLOC
:
1420 //buf_strdefine (&userdef_buf, "YY_NO_GET_LLOC", "1");
1421 buf_m4_define( &m4defs_buf
, "M4_YY_NO_GET_LLOC",0);
1423 case OPT_NO_YYSET_LLOC
:
1424 //buf_strdefine (&userdef_buf, "YY_NO_SET_LLOC", "1");
1425 buf_m4_define( &m4defs_buf
, "M4_YY_NO_SET_LLOC",0);
1429 } /* while scanopt() */
1431 scanopt_destroy (sopt
);
1433 num_input_files
= argc
- optind
;
1434 input_files
= argv
+ optind
;
1435 set_input_file (num_input_files
> 0 ? input_files
[0] : NULL
);
1437 lastccl
= lastsc
= lastdfa
= lastnfa
= 0;
1438 num_rules
= num_eof_rules
= default_rule
= 0;
1439 numas
= numsnpairs
= tmpuses
= 0;
1440 numecs
= numeps
= eps2
= num_reallocs
= hshcol
= dfaeql
= totnst
=
1442 numuniq
= numdup
= hshsave
= eofseen
= datapos
= dataline
= 0;
1443 num_backing_up
= onesp
= numprots
= 0;
1444 variable_trailing_context_rules
= bol_needed
= false;
1446 linenum
= sectnum
= 1;
1449 /* Used in mkprot() so that the first proto goes in slot 1
1450 * of the proto queue.
1454 set_up_initial_allocations ();
1458 /* readin - read in the rules section of the input file(s) */
1462 static char yy_stdinit
[] = "FILE *yyin = stdin, *yyout = stdout;";
1463 static char yy_nostdinit
[] =
1464 "FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;";
1466 line_directive_out ((FILE *) 0, 1);
1469 pinpoint_message (_("fatal parse error"));
1476 /* If the user explicitly requested posix compatibility by specifing the
1477 * posix-compat option, then we check for conflicting options. However, if
1478 * the POSIXLY_CORRECT variable is set, then we quietly make flex as
1479 * posix-compatible as possible. This is the recommended behavior
1480 * according to the GNU Coding Standards.
1482 * Note: The posix option was added to flex to provide the posix behavior
1483 * of the repeat operator in regular expressions, e.g., `ab{3}'
1486 /* TODO: This is where we try to make flex behave according to
1487 * posiz, AND check for conflicting options. How far should we go
1488 * with this? Should we disable all the neat-o flex features?
1490 /* Update: Estes says no, since other flex features don't violate posix. */
1493 if (getenv ("POSIXLY_CORRECT")) {
1494 posix_compat
= true;
1497 if (backing_up_report
) {
1498 backing_up_file
= fopen (backing_name
, "w");
1499 if (backing_up_file
== NULL
)
1501 ("could not create backing-up info file %s"),
1506 backing_up_file
= NULL
;
1508 if (yymore_really_used
== true)
1510 else if (yymore_really_used
== false)
1511 yymore_used
= false;
1513 if (reject_really_used
== true)
1515 else if (reject_really_used
== false)
1518 if (performance_report
> 0) {
1522 ("-l AT&T lex compatibility option entails a large performance penalty\n"));
1525 (" and may be the actual source of other reported performance penalties\n"));
1528 else if (do_yylineno
) {
1531 ("%%option yylineno entails a performance penalty ONLY on rules that can match newline characters\n"));
1534 if (performance_report
> 1) {
1538 ("-I (interactive) entails a minor performance penalty\n"));
1543 ("yymore() entails a minor performance penalty\n"));
1549 ("REJECT entails a large performance penalty\n"));
1551 if (variable_trailing_context_rules
)
1554 ("Variable trailing context rules entail a large performance penalty\n"));
1560 if (variable_trailing_context_rules
)
1563 if ((fulltbl
|| fullspd
) && reject
) {
1566 ("REJECT cannot be used with -f or -F"));
1567 else if (do_yylineno
)
1569 ("%option yylineno cannot be used with REJECT"));
1572 ("variable trailing context rules cannot be used with -f or -F"));
1576 out_m4_define( "M4_YY_USES_REJECT", NULL
);
1577 //outn ("\n#define YY_USES_REJECT");
1583 outn ("\n#define yywrap(yyscanner) 1");
1585 outn ("\n#define yywrap() 1");
1587 outn ("#define YY_SKIP_YYWRAP");
1591 outn ("\n#define FLEX_DEBUG");
1595 outn ("typedef unsigned char YY_CHAR;");
1597 outn ("typedef char YY_CHAR;");
1601 outn ("#define yytext_ptr yytext");
1604 outn ("#define YY_INTERACTIVE");
1609 /* In reentrant scanner, stdinit is handled in flex.skl. */
1612 outn ("#ifdef VMS");
1613 outn ("#ifdef __VMS_POSIX");
1614 outn ("#define YY_STDINIT");
1617 outn ("#define YY_STDINIT");
1621 outn ("#ifdef VMS");
1622 outn ("#ifndef __VMS_POSIX");
1623 outn (yy_nostdinit
);
1634 outn (yy_nostdinit
);
1641 outn ("typedef yyconst struct yy_trans_info *yy_state_type;");
1642 else if (!C_plus_plus
)
1643 outn ("typedef int yy_state_type;");
1647 outn ("#define YY_FLEX_LEX_COMPAT");
1649 if (!C_plus_plus
&& !reentrant
) {
1650 outn ("extern int yylineno;");
1652 outn ("int yylineno = 1;");
1657 outn ("\n#include <FlexLexer.h>");
1660 outn("\nint yyFlexLexer::yywrap() { return 1; }");
1664 outn ("int yyFlexLexer::yylex()");
1666 outn ("\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );");
1667 outn ("\treturn 0;");
1670 out_str ("\n#define YY_DECL int %s::yylex()\n",
1677 /* Watch out: yytext_ptr is a variable when yytext is an array,
1678 * but it's a macro when yytext is a pointer.
1680 if (yytext_is_array
) {
1682 outn ("extern char yytext[];\n");
1686 outn ("#define yytext_ptr yytext_r");
1689 outn ("extern char *yytext;");
1690 outn ("#define yytext_ptr yytext");
1696 ("%option yyclass only meaningful for C++ scanners"));
1700 numecs
= cre8ecs (nextecm
, ecgroup
, csize
);
1704 /* Now map the equivalence class for NUL to its expected place. */
1705 ecgroup
[0] = ecgroup
[csize
];
1706 NUL_ec
= ABS (ecgroup
[0]);
1713 /* set_up_initial_allocations - allocate memory for internal tables */
1715 void set_up_initial_allocations ()
1717 maximum_mns
= (long_align
? MAXIMUM_MNS_LONG
: MAXIMUM_MNS
);
1718 current_mns
= INITIAL_MNS
;
1719 firstst
= allocate_integer_array (current_mns
);
1720 lastst
= allocate_integer_array (current_mns
);
1721 finalst
= allocate_integer_array (current_mns
);
1722 transchar
= allocate_integer_array (current_mns
);
1723 trans1
= allocate_integer_array (current_mns
);
1724 trans2
= allocate_integer_array (current_mns
);
1725 accptnum
= allocate_integer_array (current_mns
);
1726 assoc_rule
= allocate_integer_array (current_mns
);
1727 state_type
= allocate_integer_array (current_mns
);
1729 current_max_rules
= INITIAL_MAX_RULES
;
1730 rule_type
= allocate_integer_array (current_max_rules
);
1731 rule_linenum
= allocate_integer_array (current_max_rules
);
1732 rule_useful
= allocate_integer_array (current_max_rules
);
1733 rule_has_nl
= allocate_bool_array (current_max_rules
);
1735 current_max_scs
= INITIAL_MAX_SCS
;
1736 scset
= allocate_integer_array (current_max_scs
);
1737 scbol
= allocate_integer_array (current_max_scs
);
1738 scxclu
= allocate_integer_array (current_max_scs
);
1739 sceof
= allocate_integer_array (current_max_scs
);
1740 scname
= allocate_char_ptr_array (current_max_scs
);
1742 current_maxccls
= INITIAL_MAX_CCLS
;
1743 cclmap
= allocate_integer_array (current_maxccls
);
1744 ccllen
= allocate_integer_array (current_maxccls
);
1745 cclng
= allocate_integer_array (current_maxccls
);
1746 ccl_has_nl
= allocate_bool_array (current_maxccls
);
1748 current_max_ccl_tbl_size
= INITIAL_MAX_CCL_TBL_SIZE
;
1749 ccltbl
= allocate_Character_array (current_max_ccl_tbl_size
);
1751 current_max_dfa_size
= INITIAL_MAX_DFA_SIZE
;
1753 current_max_xpairs
= INITIAL_MAX_XPAIRS
;
1754 nxt
= allocate_integer_array (current_max_xpairs
);
1755 chk
= allocate_integer_array (current_max_xpairs
);
1757 current_max_template_xpairs
= INITIAL_MAX_TEMPLATE_XPAIRS
;
1758 tnxt
= allocate_integer_array (current_max_template_xpairs
);
1760 current_max_dfas
= INITIAL_MAX_DFAS
;
1761 base
= allocate_integer_array (current_max_dfas
);
1762 def
= allocate_integer_array (current_max_dfas
);
1763 dfasiz
= allocate_integer_array (current_max_dfas
);
1764 accsiz
= allocate_integer_array (current_max_dfas
);
1765 dhash
= allocate_integer_array (current_max_dfas
);
1766 dss
= allocate_int_ptr_array (current_max_dfas
);
1767 dfaacc
= allocate_dfaacc_union (current_max_dfas
);
1769 nultrans
= (int *) 0;
1773 /* extracts basename from path, optionally stripping the extension "\.*"
1774 * (same concept as /bin/sh `basename`, but different handling of extension). */
1775 static char *basename2 (path
, strip_ext
)
1777 int strip_ext
; /* boolean */
1782 for (b
= path
; *path
; path
++)
1785 else if (*path
== '.')
1788 if (strip_ext
&& e
&& e
> b
)
1797 if (!did_outfilename
) {
1798 snprintf (outfile_path
, sizeof(outfile_path
), outfile_template
,
1799 prefix
, C_plus_plus
? "cc" : "c");
1800 outfilename
= outfile_path
;
1803 fprintf (f
, _("Usage: %s [OPTIONS] [FILE]...\n"), program_name
);
1806 ("Generates programs that perform pattern-matching on text.\n"
1807 "\n" "Table Compression:\n"
1808 " -Ca, --align trade off larger tables for better memory alignment\n"
1809 " -Ce, --ecs construct equivalence classes\n"
1810 " -Cf do not compress tables; use -f representation\n"
1811 " -CF do not compress tables; use -F representation\n"
1812 " -Cm, --meta-ecs construct meta-equivalence classes\n"
1813 " -Cr, --read use read() instead of stdio for scanner input\n"
1814 " -f, --full generate fast, large scanner. Same as -Cfr\n"
1815 " -F, --fast use alternate table representation. Same as -CFr\n"
1816 " -Cem default compression (same as --ecs --meta-ecs)\n"
1818 " -d, --debug enable debug mode in scanner\n"
1819 " -b, --backup write backing-up information to %s\n"
1820 " -p, --perf-report write performance report to stderr\n"
1821 " -s, --nodefault suppress default rule to ECHO unmatched text\n"
1822 " -T, --trace %s should run in trace mode\n"
1823 " -w, --nowarn do not generate warnings\n"
1824 " -v, --verbose write summary of scanner statistics to stdout\n"
1826 " -o, --outfile=FILE specify output filename\n"
1827 " -S, --skel=FILE specify skeleton file\n"
1828 " -t, --stdout write scanner on stdout instead of %s\n"
1829 " --yyclass=NAME name of C++ class\n"
1830 " --header-file=FILE create a C header file in addition to the scanner\n"
1831 " --tables-file[=FILE] write tables to FILE\n" "\n"
1832 "Scanner behavior:\n"
1833 " -7, --7bit generate 7-bit scanner\n"
1834 " -8, --8bit generate 8-bit scanner\n"
1835 " -B, --batch generate batch scanner (opposite of -I)\n"
1836 " -i, --case-insensitive ignore case in patterns\n"
1837 " -l, --lex-compat maximal compatibility with original lex\n"
1838 " -X, --posix-compat maximal compatibility with POSIX lex\n"
1839 " -I, --interactive generate interactive scanner (opposite of -B)\n"
1840 " --yylineno track line count in yylineno\n"
1841 "\n" "Generated code:\n"
1842 " -+, --c++ generate C++ scanner class\n"
1843 " -Dmacro[=defn] #define macro defn (default defn is '1')\n"
1844 " -L, --noline suppress #line directives in scanner\n"
1845 " -P, --prefix=STRING use STRING as prefix instead of \"yy\"\n"
1846 " -R, --reentrant generate a reentrant C scanner\n"
1847 " --bison-bridge scanner for bison pure parser.\n"
1848 " --bison-locations include yylloc support.\n"
1849 " --stdinit initialize yyin/yyout to stdin/stdout\n"
1850 " --noansi-definitions old-style function definitions\n"
1851 " --noansi-prototypes empty parameter list in prototypes\n"
1852 " --nounistd do not include <unistd.h>\n"
1853 " --noFUNCTION do not generate a particular FUNCTION\n"
1854 "\n" "Miscellaneous:\n"
1855 " -c do-nothing POSIX option\n"
1856 " -n do-nothing POSIX option\n"
1858 " -h, --help produce this help message\n"
1859 " -V, --version report %s version\n"),
1860 backing_name
, program_name
, outfile_path
, program_name
);