Pristine Ack-5.5
[Ack-5.5.git] / util / flex / main.c
1 /* flex - tool to generate fast lexical analyzers */
2
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
8  * Vern Paxson.
9  * 
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.
13  *
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.
27  */
28
29 #ifndef lint
30 char 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
36 static char rcsid[] =
37     "@(#) $Id: main.c,v 1.2 1994/06/24 10:57:09 ceriel Exp $ (LBL)";
38 #endif
39
40
41 #include "flexdef.h"
42
43 static char flex_version[] = "2.3";
44
45
46 /* declare functions that have forward references */
47
48 void flexinit PROTO((int, char**));
49 void readin PROTO(());
50 void set_up_initial_allocations PROTO(());
51
52
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;
74 int num_xlations;
75 int lastsc, current_max_scs, *scset, *scbol, *scxclu, *sceof, *actvsc;
76 char **scname;
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;
86 Char *ccltbl;
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;
92 FILE *backtrack_file;
93 int end_of_buffer_state;
94 char *action_file_name = NULL;
95 char **input_files;
96 int num_input_files;
97 char *program_name;
98
99 #ifndef SHORT_FILE_NAMES
100 static char *outfile = "lex.yy.c";
101 #else
102 static char *outfile = "lexyy.c";
103 #endif
104 static int outfile_created = 0;
105 static int use_stdout;
106 static char *skelname = NULL;
107
108
109 int main( argc, argv )
110 int argc;
111 char **argv;
112
113     {
114     flexinit( argc, argv );
115
116     readin();
117
118     if ( syntaxerror )
119         flexend( 1 );
120
121     if ( yymore_really_used == REALLY_USED )
122         yymore_used = true;
123     else if ( yymore_really_used == REALLY_NOT_USED )
124         yymore_used = false;
125
126     if ( reject_really_used == REALLY_USED )
127         reject = true;
128     else if ( reject_really_used == REALLY_NOT_USED )
129         reject = false;
130
131     if ( performance_report )
132         {
133         if ( interactive )
134             fprintf( stderr,
135                      "-I (interactive) entails a minor performance penalty\n" );
136
137         if ( yymore_used )
138             fprintf( stderr, "yymore() entails a minor performance penalty\n" );
139
140         if ( reject )
141             fprintf( stderr, "REJECT entails a large performance penalty\n" );
142
143         if ( variable_trailing_context_rules )
144             fprintf( stderr,
145 "Variable trailing context rules entail a large performance penalty\n" );
146         }
147
148     if ( reject )
149         real_reject = true;
150
151     if ( variable_trailing_context_rules )
152         reject = true;
153
154     if ( (fulltbl || fullspd) && reject )
155         {
156         if ( real_reject )
157             flexerror( "REJECT cannot be used with -f or -F" );
158         else
159             flexerror(
160         "variable trailing context rules cannot be used with -f or -F" );
161         }
162
163     ntod();
164
165     /* generate the C state transition tables from the DFA */
166     make_tables();
167
168     /* note, flexend does not return.  It exits with its argument as status. */
169
170     flexend( 0 );
171
172     /*NOTREACHED*/
173     }
174
175
176 /* flexend - terminate flex
177  *
178  * synopsis
179  *    int status;
180  *    flexend( status );
181  *
182  *    status is exit status.
183  *
184  * note
185  *    This routine does not return.
186  */
187
188 void flexend( status )
189 int status;
190
191     {
192     int tblsiz;
193     char *flex_gettime();
194
195     if ( skelfile != NULL )
196         {
197         if ( ferror( skelfile ) )
198             flexfatal( "error occurred when writing skeleton file" );
199
200         else if ( fclose( skelfile ) )
201             flexfatal( "error occurred when closing skeleton file" );
202         }
203
204     if ( temp_action_file )
205         {
206         if ( ferror( temp_action_file ) )
207             flexfatal( "error occurred when writing temporary action file" );
208
209         else if ( fclose( temp_action_file ) )
210             flexfatal( "error occurred when closing temporary action file" );
211
212         else if ( unlink( action_file_name ) )
213             flexfatal( "error occurred when deleting temporary action file" );
214         }
215
216     if ( status != 0 && outfile_created )
217         {
218         if ( ferror( stdout ) )
219             flexfatal( "error occurred when writing output file" );
220
221         else if ( fclose( stdout ) )
222             flexfatal( "error occurred when closing output file" );
223
224         else if ( unlink( outfile ) )
225             flexfatal( "error occurred when deleting output file" );
226         }
227
228     if ( backtrack_report && backtrack_file )
229         {
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",
235                      num_backtracking );
236         else
237             fprintf( backtrack_file, "Compressed tables always backtrack.\n" );
238
239         if ( ferror( backtrack_file ) )
240             flexfatal( "error occurred when writing backtracking file" );
241
242         else if ( fclose( backtrack_file ) )
243             flexfatal( "error occurred when closing backtracking file" );
244         }
245
246     if ( printstats )
247         {
248         endtime = flex_gettime();
249
250         fprintf( stderr, "%s version %s usage statistics:\n", program_name,
251                  flex_version );
252         fprintf( stderr, "  started at %s, finished at %s\n",
253                  starttime, endtime );
254
255         fprintf( stderr, "  scanner options: -" );
256
257         if ( backtrack_report )
258             putc( 'b', stderr );
259         if ( ddebug )
260             putc( 'd', stderr );
261         if ( interactive )
262             putc( 'I', stderr );
263         if ( caseins )
264             putc( 'i', stderr );
265         if ( ! gen_line_dirs )
266             putc( 'L', stderr );
267         if ( performance_report )
268             putc( 'p', stderr );
269         if ( spprdflt )
270             putc( 's', stderr );
271         if ( use_stdout )
272             putc( 't', stderr );
273         if ( trace )
274             putc( 'T', stderr );
275         if ( printstats )
276             putc( 'v', stderr );        /* always true! */
277         if ( csize == 256 )
278             putc( '8', stderr );
279
280         fprintf( stderr, " -C" );
281
282         if ( fulltbl )
283             putc( 'f', stderr );
284         if ( fullspd )
285             putc( 'F', stderr );
286         if ( useecs )
287             putc( 'e', stderr );
288         if ( usemecs )
289             putc( 'm', stderr );
290
291         if ( strcmp( skelname, DEFAULT_SKELETON_FILE ) )
292             fprintf( stderr, " -S%s", skelname );
293
294         putc( '\n', stderr );
295
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 );
299         fprintf( stderr,
300                  "  %d rules\n", num_rules - 1 /* - 1 for def. rule */ );
301
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",
306                      num_backtracking );
307         else
308             fprintf( stderr, "  compressed tables always backtrack\n" );
309
310         if ( bol_needed )
311             fprintf( stderr, "  Beginning-of-line patterns used\n" );
312
313         fprintf( stderr, "  %d/%d start conditions\n", lastsc,
314                  current_max_scs );
315         fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
316                  numeps, eps2 );
317
318         if ( lastccl == 0 )
319             fprintf( stderr, "  no character classes\n" );
320         else
321             fprintf( stderr,
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 );
326
327         fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
328         fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
329                  numuniq, numdup );
330
331         if ( fulltbl )
332             {
333             tblsiz = lastdfa * numecs;
334             fprintf( stderr, "  %d table entries\n", tblsiz );
335             }
336
337         else
338             {
339             tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
340
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 );
345             fprintf( stderr,
346                      "  %d/%d (peak %d) template nxt-chk entries created\n",
347                      numtemps * nummecs, current_max_template_xpairs,
348                      numtemps * numecs );
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",
352                      numtemps, tmpuses );
353             }
354
355         if ( useecs )
356             {
357             tblsiz = tblsiz + csize;
358             fprintf( stderr, "  %d/%d equivalence classes created\n",
359                      numecs, csize );
360             }
361
362         if ( usemecs )
363             {
364             tblsiz = tblsiz + numecs;
365             fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
366                      nummecs, csize );
367             }
368
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 );
373         }
374
375 #ifndef VMS
376     exit( status );
377 #else
378     exit( status + 1 );
379 #endif
380     }
381
382
383 /* flexinit - initialize flex
384  *
385  * synopsis
386  *    int argc;
387  *    char **argv;
388  *    flexinit( argc, argv );
389  */
390
391 void flexinit( argc, argv )
392 int argc;
393 char **argv;
394
395     {
396     int i, sawcmpflag;
397     char *arg, *flex_gettime(), *mktemp();
398
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;
404
405     sawcmpflag = false;
406     use_stdout = false;
407
408     csize = DEFAULT_CSIZE;
409
410     program_name = argv[0];
411
412     /* read flags */
413     for ( --argc, ++argv; argc ; --argc, ++argv )
414         {
415         if ( argv[0][0] != '-' || argv[0][1] == '\0' )
416             break;
417
418         arg = argv[0];
419
420         for ( i = 1; arg[i] != '\0'; ++i )
421             switch ( arg[i] )
422                 {
423                 case 'b':
424                     backtrack_report = true;
425                     break;
426
427                 case 'c':
428                     fprintf( stderr,
429         "%s: Assuming use of deprecated -c flag is really intended to be -C\n",
430                              program_name );
431
432                     /* fall through */
433
434                 case 'C':
435                     if ( i != 1 )
436                         flexerror( "-C flag must be given separately" );
437
438                     if ( ! sawcmpflag )
439                         {
440                         useecs = false;
441                         usemecs = false;
442                         fulltbl = false;
443                         sawcmpflag = true;
444                         }
445
446                     for ( ++i; arg[i] != '\0'; ++i )
447                         switch ( arg[i] )
448                             {
449                             case 'e':
450                                 useecs = true;
451                                 break;
452
453                             case 'F':
454                                 fullspd = true;
455                                 break;
456
457                             case 'f':
458                                 fulltbl = true;
459                                 break;
460
461                             case 'm':
462                                 usemecs = true;
463                                 break;
464
465                             default:
466                                 lerrif( "unknown -C option '%c'",
467                                         (int) arg[i] );
468                                 break;
469                             }
470
471                     goto get_next_arg;
472
473                 case 'd':
474                     ddebug = true;
475                     break;
476
477                 case 'f':
478                     useecs = usemecs = false;
479                     fulltbl = true;
480                     break;
481
482                 case 'F':
483                     useecs = usemecs = false;
484                     fullspd = true;
485                     break;
486
487                 case 'I':
488                     interactive = true;
489                     break;
490
491                 case 'i':
492                     caseins = true;
493                     break;
494
495                 case 'L':
496                     gen_line_dirs = false;
497                     break;
498
499                 case 'n':
500                     /* stupid do-nothing deprecated option */
501                     break;
502
503                 case 'p':
504                     performance_report = true;
505                     break;
506
507                 case 'S':
508                     if ( i != 1 )
509                         flexerror( "-S flag must be given separately" );
510
511                     skelname = arg + i + 1;
512                     goto get_next_arg;
513
514                 case 's':
515                     spprdflt = true;
516                     break;
517
518                 case 't':
519                     use_stdout = true;
520                     break;
521
522                 case 'T':
523                     trace = true;
524                     break;
525
526                 case 'v':
527                     printstats = true;
528                     break;
529
530                 case '8':
531                     csize = CSIZE;
532                     break;
533
534                 default:
535                     lerrif( "unknown flag '%c'", (int) arg[i] );
536                     break;
537                 }
538
539 get_next_arg: /* used by -C and -S flags in lieu of a "continue 2" control */
540         ;
541         }
542
543     if ( (fulltbl || fullspd) && usemecs )
544         flexerror( "full table and -Cm don't make sense together" );
545
546     if ( (fulltbl || fullspd) && interactive )
547         flexerror( "full table and -I are (currently) incompatible" );
548
549     if ( fulltbl && fullspd )
550         flexerror( "full table and -F are mutually exclusive" );
551
552     if ( ! skelname )
553         {
554         static char skeleton_name_storage[400];
555
556         skelname = skeleton_name_storage;
557         (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
558         }
559
560     if ( ! use_stdout )
561         {
562         FILE *prev_stdout = freopen( outfile, "w", stdout );
563
564         if ( prev_stdout == NULL )
565             lerrsf( "could not create %s", outfile );
566
567         outfile_created = 1;
568         }
569
570     num_input_files = argc;
571     input_files = argv;
572     set_input_file( num_input_files > 0 ? input_files[0] : NULL );
573
574     if ( backtrack_report )
575         {
576 #ifndef SHORT_FILE_NAMES
577         backtrack_file = fopen( "lex.backtrack", "w" );
578 #else
579         backtrack_file = fopen( "lex.bck", "w" );
580 #endif
581
582         if ( backtrack_file == NULL )
583             flexerror( "could not create lex.backtrack" );
584         }
585
586     else
587         backtrack_file = NULL;
588
589
590     lastccl = 0;
591     lastsc = 0;
592
593     /* initialize the statistics */
594     starttime = flex_gettime();
595
596     if ( (skelfile = fopen( skelname, "r" )) == NULL )
597         lerrsf( "can't open skeleton file %s", skelname );
598
599 #ifndef ACK_MOD
600 #ifdef SYS_V
601     action_file_name = tmpnam( NULL );
602 #endif
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
671 void 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
716 void 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     }