1 /* flex - tool to generate fast lexical analyzers */
4 * Copyright (c) 1990 The Regents of the University of California.
7 * This code is derived from software contributed to Berkeley by
10 * The United States Government has rights in this work pursuant
11 * to contract no. DE-AC03-76SF00098 between the United States
12 * Department of Energy and the University of California.
14 * Redistribution and use in source and binary forms are permitted provided
15 * that: (1) source distributions retain this entire copyright notice and
16 * comment, and (2) distributions including binaries display the following
17 * acknowledgement: ``This product includes software developed by the
18 * University of California, Berkeley and its contributors'' in the
19 * documentation or other materials provided with the distribution and in
20 * all advertising materials mentioning features or use of this software.
21 * Neither the name of the University nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
32 All rights reserved.\n";
37 "@(#) $Id: main.c,v 1.2 1994/06/24 10:57:09 ceriel Exp $ (LBL)";
43 static char flex_version[] = "2.3";
46 /* declare functions that have forward references */
48 void flexinit PROTO((int, char**));
49 void readin PROTO(());
50 void set_up_initial_allocations PROTO(());
53 /* these globals are all defined and commented in flexdef.h */
54 int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
55 int interactive, caseins, useecs, fulltbl, usemecs;
56 int fullspd, gen_line_dirs, performance_report, backtrack_report, csize;
57 int yymore_used, reject, real_reject, continued_action;
58 int yymore_really_used, reject_really_used;
59 int datapos, dataline, linenum;
60 FILE *skelfile = NULL;
61 char *infilename = NULL;
62 int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
63 int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
64 int current_mns, num_rules, current_max_rules, lastnfa;
65 int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
66 int *accptnum, *assoc_rule, *state_type, *rule_type, *rule_linenum;
67 int current_state_type;
68 int variable_trailing_context_rules;
69 int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
70 int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
71 int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
72 int tecbck[CSIZE + 1];
73 int *xlation = (int *) 0;
75 int lastsc, current_max_scs, *scset, *scbol, *scxclu, *sceof, *actvsc;
77 int current_max_dfa_size, current_max_xpairs;
78 int current_max_template_xpairs, current_max_dfas;
79 int lastdfa, *nxt, *chk, *tnxt;
80 int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz;
81 union dfaacc_union *dfaacc;
82 int *accsiz, *dhash, numas;
83 int numsnpairs, jambase, jamstate;
84 int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
85 int current_max_ccl_tbl_size;
87 char *starttime, *endtime, nmstr[MAXLINE];
88 int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
89 int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
90 int num_backtracking, bol_needed;
91 FILE *temp_action_file;
93 int end_of_buffer_state;
94 char *action_file_name = NULL;
99 #ifndef SHORT_FILE_NAMES
100 static char *outfile = "lex.yy.c";
102 static char *outfile = "lexyy.c";
104 static int outfile_created = 0;
105 static int use_stdout;
106 static char *skelname = NULL;
109 int main( argc, argv )
114 flexinit( argc, argv );
121 if ( yymore_really_used == REALLY_USED )
123 else if ( yymore_really_used == REALLY_NOT_USED )
126 if ( reject_really_used == REALLY_USED )
128 else if ( reject_really_used == REALLY_NOT_USED )
131 if ( performance_report )
135 "-I (interactive) entails a minor performance penalty\n" );
138 fprintf( stderr, "yymore() entails a minor performance penalty\n" );
141 fprintf( stderr, "REJECT entails a large performance penalty\n" );
143 if ( variable_trailing_context_rules )
145 "Variable trailing context rules entail a large performance penalty\n" );
151 if ( variable_trailing_context_rules )
154 if ( (fulltbl || fullspd) && reject )
157 flexerror( "REJECT cannot be used with -f or -F" );
160 "variable trailing context rules cannot be used with -f or -F" );
165 /* generate the C state transition tables from the DFA */
168 /* note, flexend does not return. It exits with its argument as status. */
176 /* flexend - terminate flex
182 * status is exit status.
185 * This routine does not return.
188 void flexend( status )
193 char *flex_gettime();
195 if ( skelfile != NULL )
197 if ( ferror( skelfile ) )
198 flexfatal( "error occurred when writing skeleton file" );
200 else if ( fclose( skelfile ) )
201 flexfatal( "error occurred when closing skeleton file" );
204 if ( temp_action_file )
206 if ( ferror( temp_action_file ) )
207 flexfatal( "error occurred when writing temporary action file" );
209 else if ( fclose( temp_action_file ) )
210 flexfatal( "error occurred when closing temporary action file" );
212 else if ( unlink( action_file_name ) )
213 flexfatal( "error occurred when deleting temporary action file" );
216 if ( status != 0 && outfile_created )
218 if ( ferror( stdout ) )
219 flexfatal( "error occurred when writing output file" );
221 else if ( fclose( stdout ) )
222 flexfatal( "error occurred when closing output file" );
224 else if ( unlink( outfile ) )
225 flexfatal( "error occurred when deleting output file" );
228 if ( backtrack_report && backtrack_file )
230 if ( num_backtracking == 0 )
231 fprintf( backtrack_file, "No backtracking.\n" );
232 else if ( fullspd || fulltbl )
233 fprintf( backtrack_file,
234 "%d backtracking (non-accepting) states.\n",
237 fprintf( backtrack_file, "Compressed tables always backtrack.\n" );
239 if ( ferror( backtrack_file ) )
240 flexfatal( "error occurred when writing backtracking file" );
242 else if ( fclose( backtrack_file ) )
243 flexfatal( "error occurred when closing backtracking file" );
248 endtime = flex_gettime();
250 fprintf( stderr, "%s version %s usage statistics:\n", program_name,
252 fprintf( stderr, " started at %s, finished at %s\n",
253 starttime, endtime );
255 fprintf( stderr, " scanner options: -" );
257 if ( backtrack_report )
265 if ( ! gen_line_dirs )
267 if ( performance_report )
276 putc( 'v', stderr ); /* always true! */
280 fprintf( stderr, " -C" );
291 if ( strcmp( skelname, DEFAULT_SKELETON_FILE ) )
292 fprintf( stderr, " -S%s", skelname );
294 putc( '\n', stderr );
296 fprintf( stderr, " %d/%d NFA states\n", lastnfa, current_mns );
297 fprintf( stderr, " %d/%d DFA states (%d words)\n", lastdfa,
298 current_max_dfas, totnst );
300 " %d rules\n", num_rules - 1 /* - 1 for def. rule */ );
302 if ( num_backtracking == 0 )
303 fprintf( stderr, " No backtracking\n" );
304 else if ( fullspd || fulltbl )
305 fprintf( stderr, " %d backtracking (non-accepting) states\n",
308 fprintf( stderr, " compressed tables always backtrack\n" );
311 fprintf( stderr, " Beginning-of-line patterns used\n" );
313 fprintf( stderr, " %d/%d start conditions\n", lastsc,
315 fprintf( stderr, " %d epsilon states, %d double epsilon states\n",
319 fprintf( stderr, " no character classes\n" );
322 " %d/%d character classes needed %d/%d words of storage, %d reused\n",
323 lastccl, current_maxccls,
324 cclmap[lastccl] + ccllen[lastccl],
325 current_max_ccl_tbl_size, cclreuse );
327 fprintf( stderr, " %d state/nextstate pairs created\n", numsnpairs );
328 fprintf( stderr, " %d/%d unique/duplicate transitions\n",
333 tblsiz = lastdfa * numecs;
334 fprintf( stderr, " %d table entries\n", tblsiz );
339 tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
341 fprintf( stderr, " %d/%d base-def entries created\n",
342 lastdfa + numtemps, current_max_dfas );
343 fprintf( stderr, " %d/%d (peak %d) nxt-chk entries created\n",
344 tblend, current_max_xpairs, peakpairs );
346 " %d/%d (peak %d) template nxt-chk entries created\n",
347 numtemps * nummecs, current_max_template_xpairs,
349 fprintf( stderr, " %d empty table entries\n", nummt );
350 fprintf( stderr, " %d protos created\n", numprots );
351 fprintf( stderr, " %d templates created, %d uses\n",
357 tblsiz = tblsiz + csize;
358 fprintf( stderr, " %d/%d equivalence classes created\n",
364 tblsiz = tblsiz + numecs;
365 fprintf( stderr, " %d/%d meta-equivalence classes created\n",
369 fprintf( stderr, " %d (%d saved) hash collisions, %d DFAs equal\n",
370 hshcol, hshsave, dfaeql );
371 fprintf( stderr, " %d sets of reallocations needed\n", num_reallocs );
372 fprintf( stderr, " %d total table entries needed\n", tblsiz );
383 /* flexinit - initialize flex
388 * flexinit( argc, argv );
391 void flexinit( argc, argv )
397 char *arg, *flex_gettime(), *mktemp();
399 printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
400 backtrack_report = performance_report = ddebug = fulltbl = fullspd = false;
401 yymore_used = continued_action = reject = false;
402 yymore_really_used = reject_really_used = false;
403 gen_line_dirs = usemecs = useecs = true;
408 csize = DEFAULT_CSIZE;
410 program_name = argv[0];
413 for ( --argc, ++argv; argc ; --argc, ++argv )
415 if ( argv[0][0] != '-' || argv[0][1] == '\0' )
420 for ( i = 1; arg[i] != '\0'; ++i )
424 backtrack_report = true;
429 "%s: Assuming use of deprecated -c flag is really intended to be -C\n",
436 flexerror( "-C flag must be given separately" );
446 for ( ++i; arg[i] != '\0'; ++i )
466 lerrif( "unknown -C option '%c'",
478 useecs = usemecs = false;
483 useecs = usemecs = false;
496 gen_line_dirs = false;
500 /* stupid do-nothing deprecated option */
504 performance_report = true;
509 flexerror( "-S flag must be given separately" );
511 skelname = arg + i + 1;
535 lerrif( "unknown flag '%c'", (int) arg[i] );
539 get_next_arg: /* used by -C and -S flags in lieu of a "continue 2" control */
543 if ( (fulltbl || fullspd) && usemecs )
544 flexerror( "full table and -Cm don't make sense together" );
546 if ( (fulltbl || fullspd) && interactive )
547 flexerror( "full table and -I are (currently) incompatible" );
549 if ( fulltbl && fullspd )
550 flexerror( "full table and -F are mutually exclusive" );
554 static char skeleton_name_storage[400];
556 skelname = skeleton_name_storage;
557 (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
562 FILE *prev_stdout = freopen( outfile, "w", stdout );
564 if ( prev_stdout == NULL )
565 lerrsf( "could not create %s", outfile );
570 num_input_files = argc;
572 set_input_file( num_input_files > 0 ? input_files[0] : NULL );
574 if ( backtrack_report )
576 #ifndef SHORT_FILE_NAMES
577 backtrack_file = fopen( "lex.backtrack", "w" );
579 backtrack_file = fopen( "lex.bck", "w" );
582 if ( backtrack_file == NULL )
583 flexerror( "could not create lex.backtrack" );
587 backtrack_file = NULL;
593 /* initialize the statistics */
594 starttime = flex_gettime();
596 if ( (skelfile = fopen( skelname, "r" )) == NULL )
597 lerrsf( "can't open skeleton file %s", skelname );
601 action_file_name = tmpnam( NULL );
605 if ( action_file_name == NULL )
607 static char temp_action_file_name[32];
609 #ifndef SHORT_FILE_NAMES
610 (void) strcpy( temp_action_file_name, "/tmp/flexXXXXXX" );
612 (void) strcpy( temp_action_file_name, "flexXXXXXX.tmp" );
614 (void) mktemp( temp_action_file_name );
616 action_file_name = temp_action_file_name;
619 if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
620 lerrsf( "can't open temporary action file %s", action_file_name );
622 lastdfa = lastnfa = num_rules = numas = numsnpairs = tmpuses = 0;
623 numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
624 numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
625 num_backtracking = onesp = numprots = 0;
626 variable_trailing_context_rules = bol_needed = false;
628 linenum = sectnum = 1;
631 /* used in mkprot() so that the first proto goes in slot 1
637 { /* set up doubly-linked equivalence classes */
638 /* We loop all the way up to csize, since ecgroup[csize] is the
639 * position used for NUL characters
643 for ( i = 2; i <= csize; ++i )
649 nextecm[csize] = NIL;
653 { /* put everything in its own equivalence class */
654 for ( i = 1; i <= csize; ++i )
657 nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */
661 set_up_initial_allocations();
665 /* readin - read in the rules section of the input file(s)
677 puts( "#define FLEX_DEBUG" );
680 puts( "#define YY_CHAR unsigned char" );
682 puts( "#define YY_CHAR char" );
684 line_directive_out( stdout );
688 pinpoint_message( "fatal parse error" );
694 numecs = ecs_from_xlation( ecgroup );
699 numecs = cre8ecs( nextecm, ecgroup, csize );
704 /* now map the equivalence class for NUL to its expected place */
705 ecgroup[0] = ecgroup[csize];
706 NUL_ec = abs( ecgroup[0] );
714 /* set_up_initial_allocations - allocate memory for internal tables */
716 void set_up_initial_allocations()
719 current_mns = INITIAL_MNS;
720 firstst = allocate_integer_array( current_mns );
721 lastst = allocate_integer_array( current_mns );
722 finalst = allocate_integer_array( current_mns );
723 transchar = allocate_integer_array( current_mns );
724 trans1 = allocate_integer_array( current_mns );
725 trans2 = allocate_integer_array( current_mns );
726 accptnum = allocate_integer_array( current_mns );
727 assoc_rule = allocate_integer_array( current_mns );
728 state_type = allocate_integer_array( current_mns );
730 current_max_rules = INITIAL_MAX_RULES;
731 rule_type = allocate_integer_array( current_max_rules );
732 rule_linenum = allocate_integer_array( current_max_rules );
734 current_max_scs = INITIAL_MAX_SCS;
735 scset = allocate_integer_array( current_max_scs );
736 scbol = allocate_integer_array( current_max_scs );
737 scxclu = allocate_integer_array( current_max_scs );
738 sceof = allocate_integer_array( current_max_scs );
739 scname = allocate_char_ptr_array( current_max_scs );
740 actvsc = allocate_integer_array( current_max_scs );
742 current_maxccls = INITIAL_MAX_CCLS;
743 cclmap = allocate_integer_array( current_maxccls );
744 ccllen = allocate_integer_array( current_maxccls );
745 cclng = allocate_integer_array( current_maxccls );
747 current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
748 ccltbl = allocate_character_array( current_max_ccl_tbl_size );
750 current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
752 current_max_xpairs = INITIAL_MAX_XPAIRS;
753 nxt = allocate_integer_array( current_max_xpairs );
754 chk = allocate_integer_array( current_max_xpairs );
756 current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
757 tnxt = allocate_integer_array( current_max_template_xpairs );
759 current_max_dfas = INITIAL_MAX_DFAS;
760 base = allocate_integer_array( current_max_dfas );
761 def = allocate_integer_array( current_max_dfas );
762 dfasiz = allocate_integer_array( current_max_dfas );
763 accsiz = allocate_integer_array( current_max_dfas );
764 dhash = allocate_integer_array( current_max_dfas );
765 dss = allocate_int_ptr_array( current_max_dfas );
766 dfaacc = allocate_dfaacc_union( current_max_dfas );
768 nultrans = (int *) 0;