Fixed an error I made a long while back which caused us to link against
[unix-history] / usr.bin / lex / main.c
CommitLineData
7d684d5e
NW
1/* flex - tool to generate fast lexical analyzers */
2
15637ed4
RG
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
7d684d5e 8 * Vern Paxson.
15637ed4 9 *
7d684d5e 10 * The United States Government has rights in this work pursuant
15637ed4
RG
11 * to contract no. DE-AC03-76SF00098 between the United States
12 * Department of Energy and the University of California.
13 *
7d684d5e
NW
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.
15637ed4
RG
27 */
28
29#ifndef lint
30char copyright[] =
31"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
32 All rights reserved.\n";
33#endif /* not lint */
34
35#ifndef lint
7d684d5e
NW
36static char rcsid[] =
37 "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/main.c,v 2.9 90/06/27 23:48:24 vern Exp $ (LBL)";
38#endif
15637ed4 39
15637ed4
RG
40
41#include "flexdef.h"
42#include "pathnames.h"
43
44static char flex_version[] = "2.3";
45
46
47/* declare functions that have forward references */
48
49void flexinit PROTO((int, char**));
50void readin PROTO(());
51void set_up_initial_allocations PROTO(());
52
53
54/* these globals are all defined and commented in flexdef.h */
55int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
56int interactive, caseins, useecs, fulltbl, usemecs;
57int fullspd, gen_line_dirs, performance_report, backtrack_report, csize;
58int yymore_used, reject, real_reject, continued_action;
59int yymore_really_used, reject_really_used;
60int datapos, dataline, linenum;
61FILE *skelfile = NULL;
62char *infilename = NULL;
63int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
64int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
65int current_mns, num_rules, current_max_rules, lastnfa;
66int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
67int *accptnum, *assoc_rule, *state_type, *rule_type, *rule_linenum;
68int current_state_type;
69int variable_trailing_context_rules;
70int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
71int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
72int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
73int tecbck[CSIZE + 1];
74int *xlation = (int *) 0;
75int num_xlations;
76int lastsc, current_max_scs, *scset, *scbol, *scxclu, *sceof, *actvsc;
77char **scname;
78int current_max_dfa_size, current_max_xpairs;
79int current_max_template_xpairs, current_max_dfas;
80int lastdfa, *nxt, *chk, *tnxt;
81int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz;
82union dfaacc_union *dfaacc;
83int *accsiz, *dhash, numas;
84int numsnpairs, jambase, jamstate;
85int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
86int current_max_ccl_tbl_size;
87Char *ccltbl;
88char *starttime, *endtime, nmstr[MAXLINE];
89int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
90int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
91int num_backtracking, bol_needed;
92FILE *temp_action_file;
93FILE *backtrack_file;
94int end_of_buffer_state;
95char *action_file_name = NULL;
96char **input_files;
97int num_input_files;
98char *program_name;
99
100#ifndef SHORT_FILE_NAMES
101static char *outfile = "lex.yy.c";
102#else
103static char *outfile = "lexyy.c";
104#endif
105static int outfile_created = 0;
106static int use_stdout;
107static char *skelname = NULL;
108
109
110int main( argc, argv )
111int argc;
112char **argv;
113
114 {
115 flexinit( argc, argv );
116
117 readin();
118
119 if ( syntaxerror )
120 flexend( 1 );
121
122 if ( yymore_really_used == REALLY_USED )
123 yymore_used = true;
124 else if ( yymore_really_used == REALLY_NOT_USED )
125 yymore_used = false;
126
127 if ( reject_really_used == REALLY_USED )
128 reject = true;
129 else if ( reject_really_used == REALLY_NOT_USED )
130 reject = false;
131
132 if ( performance_report )
133 {
134 if ( interactive )
135 fprintf( stderr,
136 "-I (interactive) entails a minor performance penalty\n" );
137
138 if ( yymore_used )
139 fprintf( stderr, "yymore() entails a minor performance penalty\n" );
140
141 if ( reject )
142 fprintf( stderr, "REJECT entails a large performance penalty\n" );
143
144 if ( variable_trailing_context_rules )
145 fprintf( stderr,
146"Variable trailing context rules entail a large performance penalty\n" );
147 }
148
149 if ( reject )
150 real_reject = true;
151
152 if ( variable_trailing_context_rules )
153 reject = true;
154
155 if ( (fulltbl || fullspd) && reject )
156 {
157 if ( real_reject )
158 flexerror( "REJECT cannot be used with -f or -F" );
159 else
160 flexerror(
161 "variable trailing context rules cannot be used with -f or -F" );
162 }
163
164 ntod();
165
166 /* generate the C state transition tables from the DFA */
167 make_tables();
168
169 /* note, flexend does not return. It exits with its argument as status. */
170
171 flexend( 0 );
172
173 /*NOTREACHED*/
174 }
175
176
177/* flexend - terminate flex
178 *
179 * synopsis
180 * int status;
181 * flexend( status );
182 *
183 * status is exit status.
184 *
185 * note
186 * This routine does not return.
187 */
188
189void flexend( status )
190int status;
191
192 {
193 int tblsiz;
194 char *flex_gettime();
195
196 if ( skelfile != NULL )
197 {
198 if ( ferror( skelfile ) )
199 flexfatal( "error occurred when writing skeleton file" );
200
201 else if ( fclose( skelfile ) )
202 flexfatal( "error occurred when closing skeleton file" );
203 }
204
205 if ( temp_action_file )
206 {
207 if ( ferror( temp_action_file ) )
208 flexfatal( "error occurred when writing temporary action file" );
209
210 else if ( fclose( temp_action_file ) )
211 flexfatal( "error occurred when closing temporary action file" );
212
213 else if ( unlink( action_file_name ) )
214 flexfatal( "error occurred when deleting temporary action file" );
215 }
216
217 if ( status != 0 && outfile_created )
218 {
219 if ( ferror( stdout ) )
220 flexfatal( "error occurred when writing output file" );
221
222 else if ( fclose( stdout ) )
223 flexfatal( "error occurred when closing output file" );
224
225 else if ( unlink( outfile ) )
226 flexfatal( "error occurred when deleting output file" );
227 }
228
229 if ( backtrack_report && backtrack_file )
230 {
231 if ( num_backtracking == 0 )
232 fprintf( backtrack_file, "No backtracking.\n" );
233 else if ( fullspd || fulltbl )
234 fprintf( backtrack_file,
235 "%d backtracking (non-accepting) states.\n",
236 num_backtracking );
237 else
238 fprintf( backtrack_file, "Compressed tables always backtrack.\n" );
239
240 if ( ferror( backtrack_file ) )
241 flexfatal( "error occurred when writing backtracking file" );
242
243 else if ( fclose( backtrack_file ) )
244 flexfatal( "error occurred when closing backtracking file" );
245 }
246
247 if ( printstats )
248 {
249 endtime = flex_gettime();
250
251 fprintf( stderr, "%s version %s usage statistics:\n", program_name,
252 flex_version );
253 fprintf( stderr, " started at %s, finished at %s\n",
254 starttime, endtime );
255
256 fprintf( stderr, " scanner options: -" );
257
258 if ( backtrack_report )
259 putc( 'b', stderr );
260 if ( ddebug )
261 putc( 'd', stderr );
262 if ( interactive )
263 putc( 'I', stderr );
264 if ( caseins )
265 putc( 'i', stderr );
266 if ( ! gen_line_dirs )
267 putc( 'L', stderr );
268 if ( performance_report )
269 putc( 'p', stderr );
270 if ( spprdflt )
271 putc( 's', stderr );
272 if ( use_stdout )
273 putc( 't', stderr );
274 if ( trace )
275 putc( 'T', stderr );
276 if ( printstats )
277 putc( 'v', stderr ); /* always true! */
278 if ( csize == 256 )
279 putc( '8', stderr );
280
281 fprintf( stderr, " -C" );
282
283 if ( fulltbl )
284 putc( 'f', stderr );
285 if ( fullspd )
286 putc( 'F', stderr );
287 if ( useecs )
288 putc( 'e', stderr );
289 if ( usemecs )
290 putc( 'm', stderr );
291
7d684d5e 292 if ( skelname && strcmp( skelname, _PATH_SKELETONFILE ) )
15637ed4
RG
293 fprintf( stderr, " -S%s", skelname );
294
295 putc( '\n', stderr );
296
297 fprintf( stderr, " %d/%d NFA states\n", lastnfa, current_mns );
298 fprintf( stderr, " %d/%d DFA states (%d words)\n", lastdfa,
299 current_max_dfas, totnst );
300 fprintf( stderr,
301 " %d rules\n", num_rules - 1 /* - 1 for def. rule */ );
302
303 if ( num_backtracking == 0 )
304 fprintf( stderr, " No backtracking\n" );
305 else if ( fullspd || fulltbl )
306 fprintf( stderr, " %d backtracking (non-accepting) states\n",
307 num_backtracking );
308 else
309 fprintf( stderr, " compressed tables always backtrack\n" );
310
311 if ( bol_needed )
312 fprintf( stderr, " Beginning-of-line patterns used\n" );
313
314 fprintf( stderr, " %d/%d start conditions\n", lastsc,
315 current_max_scs );
316 fprintf( stderr, " %d epsilon states, %d double epsilon states\n",
317 numeps, eps2 );
318
319 if ( lastccl == 0 )
320 fprintf( stderr, " no character classes\n" );
321 else
322 fprintf( stderr,
323 " %d/%d character classes needed %d/%d words of storage, %d reused\n",
324 lastccl, current_maxccls,
325 cclmap[lastccl] + ccllen[lastccl],
326 current_max_ccl_tbl_size, cclreuse );
327
328 fprintf( stderr, " %d state/nextstate pairs created\n", numsnpairs );
329 fprintf( stderr, " %d/%d unique/duplicate transitions\n",
330 numuniq, numdup );
331
332 if ( fulltbl )
333 {
334 tblsiz = lastdfa * numecs;
335 fprintf( stderr, " %d table entries\n", tblsiz );
336 }
337
338 else
339 {
340 tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
341
342 fprintf( stderr, " %d/%d base-def entries created\n",
343 lastdfa + numtemps, current_max_dfas );
344 fprintf( stderr, " %d/%d (peak %d) nxt-chk entries created\n",
345 tblend, current_max_xpairs, peakpairs );
346 fprintf( stderr,
347 " %d/%d (peak %d) template nxt-chk entries created\n",
348 numtemps * nummecs, current_max_template_xpairs,
349 numtemps * numecs );
350 fprintf( stderr, " %d empty table entries\n", nummt );
351 fprintf( stderr, " %d protos created\n", numprots );
352 fprintf( stderr, " %d templates created, %d uses\n",
353 numtemps, tmpuses );
354 }
355
356 if ( useecs )
357 {
358 tblsiz = tblsiz + csize;
359 fprintf( stderr, " %d/%d equivalence classes created\n",
360 numecs, csize );
361 }
362
363 if ( usemecs )
364 {
365 tblsiz = tblsiz + numecs;
366 fprintf( stderr, " %d/%d meta-equivalence classes created\n",
367 nummecs, csize );
368 }
369
370 fprintf( stderr, " %d (%d saved) hash collisions, %d DFAs equal\n",
371 hshcol, hshsave, dfaeql );
372 fprintf( stderr, " %d sets of reallocations needed\n", num_reallocs );
373 fprintf( stderr, " %d total table entries needed\n", tblsiz );
374 }
375
376#ifndef VMS
377 exit( status );
378#else
379 exit( status + 1 );
380#endif
381 }
382
383
384/* flexinit - initialize flex
385 *
386 * synopsis
387 * int argc;
388 * char **argv;
389 * flexinit( argc, argv );
390 */
391
392void flexinit( argc, argv )
393int argc;
394char **argv;
395
396 {
397 int i, sawcmpflag;
398 char *arg, *flex_gettime(), *mktemp();
399
400 printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
401 backtrack_report = performance_report = ddebug = fulltbl = fullspd = false;
402 yymore_used = continued_action = reject = false;
403 yymore_really_used = reject_really_used = false;
404 gen_line_dirs = usemecs = useecs = true;
405
406 sawcmpflag = false;
407 use_stdout = false;
408
409 csize = DEFAULT_CSIZE;
410
7d684d5e
NW
411 starttime = flex_gettime();
412
15637ed4
RG
413 program_name = argv[0];
414
415 /* read flags */
416 for ( --argc, ++argv; argc ; --argc, ++argv )
417 {
418 if ( argv[0][0] != '-' || argv[0][1] == '\0' )
419 break;
420
421 arg = argv[0];
422
423 for ( i = 1; arg[i] != '\0'; ++i )
424 switch ( arg[i] )
425 {
426 case 'b':
427 backtrack_report = true;
428 break;
429
430 case 'c':
431 fprintf( stderr,
432 "%s: Assuming use of deprecated -c flag is really intended to be -C\n",
433 program_name );
434
435 /* fall through */
436
437 case 'C':
438 if ( i != 1 )
439 flexerror( "-C flag must be given separately" );
440
441 if ( ! sawcmpflag )
442 {
443 useecs = false;
444 usemecs = false;
445 fulltbl = false;
446 sawcmpflag = true;
447 }
448
449 for ( ++i; arg[i] != '\0'; ++i )
450 switch ( arg[i] )
451 {
452 case 'e':
453 useecs = true;
454 break;
455
456 case 'F':
457 fullspd = true;
458 break;
459
460 case 'f':
461 fulltbl = true;
462 break;
463
464 case 'm':
465 usemecs = true;
466 break;
467
468 default:
469 lerrif( "unknown -C option '%c'",
470 (int) arg[i] );
471 break;
472 }
473
474 goto get_next_arg;
475
476 case 'd':
477 ddebug = true;
478 break;
479
480 case 'f':
481 useecs = usemecs = false;
482 fulltbl = true;
483 break;
484
485 case 'F':
486 useecs = usemecs = false;
487 fullspd = true;
488 break;
489
490 case 'I':
491 interactive = true;
492 break;
493
494 case 'i':
495 caseins = true;
496 break;
497
498 case 'L':
499 gen_line_dirs = false;
500 break;
501
502 case 'n':
503 /* stupid do-nothing deprecated option */
504 break;
505
506 case 'p':
507 performance_report = true;
508 break;
509
510 case 'S':
511 if ( i != 1 )
512 flexerror( "-S flag must be given separately" );
513
514 skelname = arg + i + 1;
515 goto get_next_arg;
516
517 case 's':
518 spprdflt = true;
519 break;
520
521 case 't':
522 use_stdout = true;
523 break;
524
525 case 'T':
526 trace = true;
527 break;
528
529 case 'v':
530 printstats = true;
531 break;
532
533 case '8':
534 csize = CSIZE;
535 break;
536
537 default:
538 lerrif( "unknown flag '%c'", (int) arg[i] );
539 break;
540 }
541
542get_next_arg: /* used by -C and -S flags in lieu of a "continue 2" control */
543 ;
544 }
545
546 if ( (fulltbl || fullspd) && usemecs )
547 flexerror( "full table and -Cm don't make sense together" );
548
549 if ( (fulltbl || fullspd) && interactive )
550 flexerror( "full table and -I are (currently) incompatible" );
551
552 if ( fulltbl && fullspd )
553 flexerror( "full table and -F are mutually exclusive" );
554
555 if ( ! skelname )
556 {
557 static char skeleton_name_storage[400];
558
559 skelname = skeleton_name_storage;
560 (void) strcpy( skelname, _PATH_SKELETONFILE );
561 }
562
563 if ( ! use_stdout )
564 {
565 FILE *prev_stdout = freopen( outfile, "w", stdout );
566
567 if ( prev_stdout == NULL )
568 lerrsf( "could not create %s", outfile );
569
570 outfile_created = 1;
571 }
572
573 num_input_files = argc;
574 input_files = argv;
575 set_input_file( num_input_files > 0 ? input_files[0] : NULL );
576
577 if ( backtrack_report )
578 {
579#ifndef SHORT_FILE_NAMES
580 backtrack_file = fopen( "lex.backtrack", "w" );
581#else
582 backtrack_file = fopen( "lex.bck", "w" );
583#endif
584
585 if ( backtrack_file == NULL )
586 flexerror( "could not create lex.backtrack" );
587 }
588
589 else
590 backtrack_file = NULL;
591
592
593 lastccl = 0;
594 lastsc = 0;
595
596 /* initialize the statistics */
15637ed4
RG
597
598 if ( (skelfile = fopen( skelname, "r" )) == NULL )
599 lerrsf( "can't open skeleton file %s", skelname );
600
601#ifdef SYS_V
602 action_file_name = tmpnam( NULL );
603#endif
604
605 if ( action_file_name == NULL )
606 {
607 static char temp_action_file_name[32];
608
609#ifndef SHORT_FILE_NAMES
610 (void) strcpy( temp_action_file_name, "/tmp/flexXXXXXX" );
611#else
612 (void) strcpy( temp_action_file_name, "flexXXXXXX.tmp" );
613#endif
614 (void) mktemp( temp_action_file_name );
615
616 action_file_name = temp_action_file_name;
617 }
618
619 if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
620 lerrsf( "can't open temporary action file %s", action_file_name );
621
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;
627
628 linenum = sectnum = 1;
629 firstprot = NIL;
630
631 /* used in mkprot() so that the first proto goes in slot 1
632 * of the proto queue
633 */
634 lastprot = 1;
635
636 if ( useecs )
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
640 */
641 ecgroup[1] = NIL;
642
643 for ( i = 2; i <= csize; ++i )
644 {
645 ecgroup[i] = i - 1;
646 nextecm[i - 1] = i;
647 }
648
649 nextecm[csize] = NIL;
650 }
651
652 else
653 { /* put everything in its own equivalence class */
654 for ( i = 1; i <= csize; ++i )
655 {
656 ecgroup[i] = i;
657 nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */
658 }
659 }
660
661 set_up_initial_allocations();
662 }
663
664
665/* readin - read in the rules section of the input file(s)
666 *
667 * synopsis
668 * readin();
669 */
670
671void readin()
672
673 {
674 skelout();
675
676 if ( ddebug )
677 puts( "#define FLEX_DEBUG" );
678
679 if ( csize == 256 )
680 puts( "#define YY_CHAR unsigned char" );
681 else
682 puts( "#define YY_CHAR char" );
683
684 line_directive_out( stdout );
685
686 if ( yyparse() )
687 {
688 pinpoint_message( "fatal parse error" );
689 flexend( 1 );
690 }
691
692 if ( xlation )
693 {
694 numecs = ecs_from_xlation( ecgroup );
695 useecs = true;
696 }
697
698 else if ( useecs )
699 numecs = cre8ecs( nextecm, ecgroup, csize );
700
701 else
702 numecs = csize;
703
704 /* now map the equivalence class for NUL to its expected place */
705 ecgroup[0] = ecgroup[csize];
706 NUL_ec = abs( ecgroup[0] );
707
708 if ( useecs )
709 ccl2ecl();
710 }
711
712
713
714/* set_up_initial_allocations - allocate memory for internal tables */
715
716void set_up_initial_allocations()
717
718 {
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 );
729
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 );
733
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 );
741
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 );
746
747 current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
748 ccltbl = allocate_character_array( current_max_ccl_tbl_size );
749
750 current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
751
752 current_max_xpairs = INITIAL_MAX_XPAIRS;
753 nxt = allocate_integer_array( current_max_xpairs );
754 chk = allocate_integer_array( current_max_xpairs );
755
756 current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
757 tnxt = allocate_integer_array( current_max_template_xpairs );
758
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 );
767
768 nultrans = (int *) 0;
769 }