]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/lex/main.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.bin / lex / 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 /* $Header: /home/daffy/u0/vern/flex/RCS/main.c,v 2.64 96/05/25 20:42:42 vern Exp $ */
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39
40 #include "flexdef.h"
41 #include "version.h"
42
43 static char flex_version[] = FLEX_VERSION;
44
45
46 /* declare functions that have forward references */
47
48 void flexinit PROTO((int, char**));
49 void readin PROTO((void));
50 void set_up_initial_allocations PROTO((void));
51
52 #ifdef NEED_ARGV_FIXUP
53 extern void argv_fixup PROTO((int *, char ***));
54 #endif
55
56
57 /* these globals are all defined and commented in flexdef.h */
58 int printstats, syntaxerror, eofseen, ddebug, trace, nowarn, spprdflt;
59 int interactive, caseins, lex_compat, do_yylineno, useecs, fulltbl, usemecs;
60 int fullspd, gen_line_dirs, performance_report, backing_up_report;
61 int C_plus_plus, long_align, use_read, yytext_is_array, do_yywrap, csize;
62 int yymore_used, reject, real_reject, continued_action, in_rule;
63 int yymore_really_used, reject_really_used;
64 int datapos, dataline, linenum, out_linenum;
65 FILE *skelfile = NULL;
66 int skel_ind = 0;
67 char *action_array;
68 int action_size, defs1_offset, prolog_offset, action_offset, action_index;
69 char *infilename = NULL, *outfilename = NULL;
70 int did_outfilename;
71 char *prefix, *yyclass;
72 int do_stdinit, use_stdout;
73 int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
74 int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
75 int current_mns, current_max_rules;
76 int num_rules, num_eof_rules, default_rule, lastnfa;
77 int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
78 int *accptnum, *assoc_rule, *state_type;
79 int *rule_type, *rule_linenum, *rule_useful;
80 int current_state_type;
81 int variable_trailing_context_rules;
82 int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
83 int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
84 int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
85 int tecbck[CSIZE + 1];
86 int lastsc, *scset, *scbol, *scxclu, *sceof;
87 int current_max_scs;
88 char **scname;
89 int current_max_dfa_size, current_max_xpairs;
90 int current_max_template_xpairs, current_max_dfas;
91 int lastdfa, *nxt, *chk, *tnxt;
92 int *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz;
93 union dfaacc_union *dfaacc;
94 int *accsiz, *dhash, numas;
95 int numsnpairs, jambase, jamstate;
96 int lastccl, *cclmap, *ccllen, *cclng, cclreuse;
97 int current_maxccls, current_max_ccl_tbl_size;
98 Char *ccltbl;
99 char nmstr[MAXLINE];
100 int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
101 int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
102 int num_backing_up, bol_needed;
103 FILE *backing_up_file;
104 int end_of_buffer_state;
105 char **input_files;
106 int num_input_files;
107
108 /* Make sure program_name is initialized so we don't crash if writing
109  * out an error message before getting the program name from argv[0].
110  */
111 char *program_name = "flex";
112
113 #ifndef SHORT_FILE_NAMES
114 static char *outfile_template = "lex.%s.%s";
115 static char *backing_name = "lex.backup";
116 #else
117 static char *outfile_template = "lex%s.%s";
118 static char *backing_name = "lex.bck";
119 #endif
120
121 #ifdef THINK_C
122 #include <console.h>
123 #endif
124
125 #ifdef MS_DOS
126 extern unsigned _stklen = 16384;
127 #endif
128
129 static char outfile_path[MAXLINE];
130 static int outfile_created = 0;
131 static char *skelname = NULL;
132
133
134 int main( argc, argv )
135 int argc;
136 char **argv;
137         {
138         int i;
139
140 #ifdef THINK_C
141         argc = ccommand( &argv );
142 #endif
143 #ifdef NEED_ARGV_FIXUP
144         argv_fixup( &argc, &argv );
145 #endif
146
147         flexinit( argc, argv );
148
149         readin();
150
151         ntod();
152
153         for ( i = 1; i <= num_rules; ++i )
154                 if ( ! rule_useful[i] && i != default_rule )
155                         line_warning( _( "rule cannot be matched" ),
156                                         rule_linenum[i] );
157
158         if ( spprdflt && ! reject && rule_useful[default_rule] )
159                 line_warning(
160                         _( "-s option given but default rule can be matched" ),
161                         rule_linenum[default_rule] );
162
163         /* Generate the C state transition tables from the DFA. */
164         make_tables();
165
166         /* Note, flexend does not return.  It exits with its argument
167          * as status.
168          */
169         flexend( 0 );
170
171         return 0;       /* keep compilers/lint happy */
172         }
173
174
175 /* check_options - check user-specified options */
176
177 void check_options()
178         {
179         int i;
180
181         if ( lex_compat )
182                 {
183                 if ( C_plus_plus )
184                         flexerror( _( "Can't use -+ with -l option" ) );
185
186                 if ( fulltbl || fullspd )
187                         flexerror( _( "Can't use -f or -F with -l option" ) );
188
189                 /* Don't rely on detecting use of yymore() and REJECT,
190                  * just assume they'll be used.
191                  */
192                 yymore_really_used = reject_really_used = true;
193
194                 yytext_is_array = true;
195                 do_yylineno = true;
196                 use_read = false;
197                 }
198
199         if ( do_yylineno )
200                 /* This should really be "maintain_backup_tables = true" */
201                 reject_really_used = true;
202
203         if ( csize == unspecified )
204                 {
205                 if ( (fulltbl || fullspd) && ! useecs )
206                         csize = DEFAULT_CSIZE;
207                 else
208                         csize = CSIZE;
209                 }
210
211         if ( interactive == unspecified )
212                 {
213                 if ( fulltbl || fullspd )
214                         interactive = false;
215                 else
216                         interactive = true;
217                 }
218
219         if ( fulltbl || fullspd )
220                 {
221                 if ( usemecs )
222                         flexerror(
223                         _( "-Cf/-CF and -Cm don't make sense together" ) );
224
225                 if ( interactive )
226                         flexerror( _( "-Cf/-CF and -I are incompatible" ) );
227
228                 if ( lex_compat )
229                         flexerror(
230                 _( "-Cf/-CF are incompatible with lex-compatibility mode" ) );
231
232                 if ( do_yylineno )
233                         flexerror(
234                         _( "-Cf/-CF and %option yylineno are incompatible" ) );
235
236                 if ( fulltbl && fullspd )
237                         flexerror( _( "-Cf and -CF are mutually exclusive" ) );
238                 }
239
240         if ( C_plus_plus && fullspd )
241                 flexerror( _( "Can't use -+ with -CF option" ) );
242
243         if ( C_plus_plus && yytext_is_array )
244                 {
245                 warn( _( "%array incompatible with -+ option" ) );
246                 yytext_is_array = false;
247                 }
248
249         if ( useecs )
250                 { /* Set up doubly-linked equivalence classes. */
251
252                 /* We loop all the way up to csize, since ecgroup[csize] is
253                  * the position used for NUL characters.
254                  */
255                 ecgroup[1] = NIL;
256
257                 for ( i = 2; i <= csize; ++i )
258                         {
259                         ecgroup[i] = i - 1;
260                         nextecm[i - 1] = i;
261                         }
262
263                 nextecm[csize] = NIL;
264                 }
265
266         else
267                 {
268                 /* Put everything in its own equivalence class. */
269                 for ( i = 1; i <= csize; ++i )
270                         {
271                         ecgroup[i] = i;
272                         nextecm[i] = BAD_SUBSCRIPT;     /* to catch errors */
273                         }
274                 }
275
276         if ( ! use_stdout )
277                 {
278                 FILE *prev_stdout;
279
280                 if ( ! did_outfilename )
281                         {
282                         char *suffix;
283
284                         if ( C_plus_plus )
285                                 suffix = "cc";
286                         else
287                                 suffix = "c";
288
289                         sprintf( outfile_path, outfile_template,
290                                 prefix, suffix );
291
292                         outfilename = outfile_path;
293                         }
294
295                 prev_stdout = freopen( outfilename, "w", stdout );
296
297                 if ( prev_stdout == NULL )
298                         lerrsf( _( "could not create %s" ), outfilename );
299
300                 outfile_created = 1;
301                 }
302
303         if ( skelname && (skelfile = fopen( skelname, "r" )) == NULL )
304                 lerrsf( _( "can't open skeleton file %s" ), skelname );
305
306         if ( strcmp( prefix, "yy" ) )
307                 {
308 #define GEN_PREFIX(name) out_str3( "#define yy%s %s%s\n", name, prefix, name )
309                 if ( C_plus_plus )
310                         GEN_PREFIX( "FlexLexer" );
311                 else
312                         {
313                         GEN_PREFIX( "_create_buffer" );
314                         GEN_PREFIX( "_delete_buffer" );
315                         GEN_PREFIX( "_scan_buffer" );
316                         GEN_PREFIX( "_scan_string" );
317                         GEN_PREFIX( "_scan_bytes" );
318                         GEN_PREFIX( "_flex_debug" );
319                         GEN_PREFIX( "_init_buffer" );
320                         GEN_PREFIX( "_flush_buffer" );
321                         GEN_PREFIX( "_load_buffer_state" );
322                         GEN_PREFIX( "_switch_to_buffer" );
323                         GEN_PREFIX( "in" );
324                         GEN_PREFIX( "leng" );
325                         GEN_PREFIX( "lex" );
326                         GEN_PREFIX( "out" );
327                         GEN_PREFIX( "restart" );
328                         GEN_PREFIX( "text" );
329
330                         if ( do_yylineno )
331                                 GEN_PREFIX( "lineno" );
332                         }
333
334                 if ( do_yywrap )
335                         GEN_PREFIX( "wrap" );
336
337                 outn( "" );
338                 }
339
340         if ( did_outfilename )
341                 line_directive_out( stdout, 0 );
342
343         skelout();
344         }
345
346
347 /* flexend - terminate flex
348  *
349  * note
350  *    This routine does not return.
351  */
352
353 void flexend( exit_status )
354 int exit_status;
355
356         {
357         int tblsiz;
358         int unlink();
359
360         if ( skelfile != NULL )
361                 {
362                 if ( ferror( skelfile ) )
363                         lerrsf( _( "input error reading skeleton file %s" ),
364                                 skelname );
365
366                 else if ( fclose( skelfile ) )
367                         lerrsf( _( "error closing skeleton file %s" ),
368                                 skelname );
369                 }
370
371         if ( exit_status != 0 && outfile_created )
372                 {
373                 if ( ferror( stdout ) )
374                         lerrsf( _( "error writing output file %s" ),
375                                 outfilename );
376
377                 else if ( fclose( stdout ) )
378                         lerrsf( _( "error closing output file %s" ),
379                                 outfilename );
380
381                 else if ( unlink( outfilename ) )
382                         lerrsf( _( "error deleting output file %s" ),
383                                 outfilename );
384                 }
385
386         if ( backing_up_report && backing_up_file )
387                 {
388                 if ( num_backing_up == 0 )
389                         fprintf( backing_up_file, _( "No backing up.\n" ) );
390                 else if ( fullspd || fulltbl )
391                         fprintf( backing_up_file,
392                                 _( "%d backing up (non-accepting) states.\n" ),
393                                 num_backing_up );
394                 else
395                         fprintf( backing_up_file,
396                                 _( "Compressed tables always back up.\n" ) );
397
398                 if ( ferror( backing_up_file ) )
399                         lerrsf( _( "error writing backup file %s" ),
400                                 backing_name );
401
402                 else if ( fclose( backing_up_file ) )
403                         lerrsf( _( "error closing backup file %s" ),
404                                 backing_name );
405                 }
406
407         if ( printstats )
408                 {
409                 fprintf( stderr, _( "%s version %s usage statistics:\n" ),
410                         program_name, flex_version );
411
412                 fprintf( stderr, _( "  scanner options: -" ) );
413
414                 if ( C_plus_plus )
415                         putc( '+', stderr );
416                 if ( backing_up_report )
417                         putc( 'b', stderr );
418                 if ( ddebug )
419                         putc( 'd', stderr );
420                 if ( caseins )
421                         putc( 'i', stderr );
422                 if ( lex_compat )
423                         putc( 'l', stderr );
424                 if ( performance_report > 0 )
425                         putc( 'p', stderr );
426                 if ( performance_report > 1 )
427                         putc( 'p', stderr );
428                 if ( spprdflt )
429                         putc( 's', stderr );
430                 if ( use_stdout )
431                         putc( 't', stderr );
432                 if ( printstats )
433                         putc( 'v', stderr );    /* always true! */
434                 if ( nowarn )
435                         putc( 'w', stderr );
436                 if ( interactive == false )
437                         putc( 'B', stderr );
438                 if ( interactive == true )
439                         putc( 'I', stderr );
440                 if ( ! gen_line_dirs )
441                         putc( 'L', stderr );
442                 if ( trace )
443                         putc( 'T', stderr );
444
445                 if ( csize == unspecified )
446                         /* We encountered an error fairly early on, so csize
447                          * never got specified.  Define it now, to prevent
448                          * bogus table sizes being written out below.
449                          */
450                         csize = 256;
451
452                 if ( csize == 128 )
453                         putc( '7', stderr );
454                 else
455                         putc( '8', stderr );
456
457                 fprintf( stderr, " -C" );
458
459                 if ( long_align )
460                         putc( 'a', stderr );
461                 if ( fulltbl )
462                         putc( 'f', stderr );
463                 if ( fullspd )
464                         putc( 'F', stderr );
465                 if ( useecs )
466                         putc( 'e', stderr );
467                 if ( usemecs )
468                         putc( 'm', stderr );
469                 if ( use_read )
470                         putc( 'r', stderr );
471
472                 if ( did_outfilename )
473                         fprintf( stderr, " -o%s", outfilename );
474
475                 if ( skelname )
476                         fprintf( stderr, " -S%s", skelname );
477
478                 if ( strcmp( prefix, "yy" ) )
479                         fprintf( stderr, " -P%s", prefix );
480
481                 putc( '\n', stderr );
482
483                 fprintf( stderr, _( "  %d/%d NFA states\n" ),
484                         lastnfa, current_mns );
485                 fprintf( stderr, _( "  %d/%d DFA states (%d words)\n" ),
486                         lastdfa, current_max_dfas, totnst );
487                 fprintf( stderr, _( "  %d rules\n" ),
488                 num_rules + num_eof_rules - 1 /* - 1 for def. rule */ );
489
490                 if ( num_backing_up == 0 )
491                         fprintf( stderr, _( "  No backing up\n" ) );
492                 else if ( fullspd || fulltbl )
493                         fprintf( stderr,
494                         _( "  %d backing-up (non-accepting) states\n" ),
495                                 num_backing_up );
496                 else
497                         fprintf( stderr,
498                                 _( "  Compressed tables always back-up\n" ) );
499
500                 if ( bol_needed )
501                         fprintf( stderr,
502                                 _( "  Beginning-of-line patterns used\n" ) );
503
504                 fprintf( stderr, _( "  %d/%d start conditions\n" ), lastsc,
505                         current_max_scs );
506                 fprintf( stderr,
507                         _( "  %d epsilon states, %d double epsilon states\n" ),
508                         numeps, eps2 );
509
510                 if ( lastccl == 0 )
511                         fprintf( stderr, _( "  no character classes\n" ) );
512                 else
513                         fprintf( stderr,
514 _( "  %d/%d character classes needed %d/%d words of storage, %d reused\n" ),
515                                 lastccl, current_maxccls,
516                                 cclmap[lastccl] + ccllen[lastccl],
517                                 current_max_ccl_tbl_size, cclreuse );
518
519                 fprintf( stderr, _( "  %d state/nextstate pairs created\n" ),
520                         numsnpairs );
521                 fprintf( stderr, _( "  %d/%d unique/duplicate transitions\n" ),
522                         numuniq, numdup );
523
524                 if ( fulltbl )
525                         {
526                         tblsiz = lastdfa * numecs;
527                         fprintf( stderr, _( "  %d table entries\n" ), tblsiz );
528                         }
529
530                 else
531                         {
532                         tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
533
534                         fprintf( stderr,
535                                 _( "  %d/%d base-def entries created\n" ),
536                                 lastdfa + numtemps, current_max_dfas );
537                         fprintf( stderr,
538                         _( "  %d/%d (peak %d) nxt-chk entries created\n" ),
539                                 tblend, current_max_xpairs, peakpairs );
540                         fprintf( stderr,
541                 _( "  %d/%d (peak %d) template nxt-chk entries created\n" ),
542                                 numtemps * nummecs,
543                                 current_max_template_xpairs,
544                                 numtemps * numecs );
545                         fprintf( stderr, _( "  %d empty table entries\n" ),
546                                 nummt );
547                         fprintf( stderr, _( "  %d protos created\n" ),
548                                 numprots );
549                         fprintf( stderr,
550                                 _( "  %d templates created, %d uses\n" ),
551                                 numtemps, tmpuses );
552                         }
553
554                 if ( useecs )
555                         {
556                         tblsiz = tblsiz + csize;
557                         fprintf( stderr,
558                                 _( "  %d/%d equivalence classes created\n" ),
559                                 numecs, csize );
560                         }
561
562                 if ( usemecs )
563                         {
564                         tblsiz = tblsiz + numecs;
565                         fprintf( stderr,
566                         _( "  %d/%d meta-equivalence classes created\n" ),
567                                 nummecs, csize );
568                         }
569
570                 fprintf( stderr,
571                 _( "  %d (%d saved) hash collisions, %d DFAs equal\n" ),
572                         hshcol, hshsave, dfaeql );
573                 fprintf( stderr, _( "  %d sets of reallocations needed\n" ),
574                         num_reallocs );
575                 fprintf( stderr, _( "  %d total table entries needed\n" ),
576                         tblsiz );
577                 }
578
579         exit( exit_status );
580         }
581
582
583 /* flexinit - initialize flex */
584
585 void flexinit( argc, argv )
586 int argc;
587 char **argv;
588         {
589         int i, sawcmpflag;
590         char *arg;
591
592         printstats = syntaxerror = trace = spprdflt = caseins = false;
593         lex_compat = C_plus_plus = backing_up_report = ddebug = fulltbl = false;
594         fullspd = long_align = nowarn = yymore_used = continued_action = false;
595         do_yylineno = yytext_is_array = in_rule = reject = do_stdinit = false;
596         yymore_really_used = reject_really_used = unspecified;
597         interactive = csize = unspecified;
598         do_yywrap = gen_line_dirs = usemecs = useecs = true;
599         performance_report = 0;
600         did_outfilename = 0;
601         prefix = "yy";
602         yyclass = 0;
603         use_read = use_stdout = false;
604
605         sawcmpflag = false;
606
607         /* Initialize dynamic array for holding the rule actions. */
608         action_size = 2048;     /* default size of action array in bytes */
609         action_array = allocate_character_array( action_size );
610         defs1_offset = prolog_offset = action_offset = action_index = 0;
611         action_array[0] = '\0';
612
613         program_name = argv[0];
614
615         if ( program_name[0] != '\0' &&
616              program_name[strlen( program_name ) - 1] == '+' )
617                 C_plus_plus = true;
618
619         /* read flags */
620         for ( --argc, ++argv; argc ; --argc, ++argv )
621                 {
622                 arg = argv[0];
623
624                 if ( arg[0] != '-' || arg[1] == '\0' )
625                         break;
626
627                 if ( arg[1] == '-' )
628                         { /* --option */
629                         if ( ! strcmp( arg, "--help" ) )
630                                 arg = "-h";
631
632                         else if ( ! strcmp( arg, "--version" ) )
633                                 arg = "-V";
634
635                         else if ( ! strcmp( arg, "--" ) )
636                                 { /* end of options */
637                                 --argc;
638                                 ++argv;
639                                 break;
640                                 }
641                         }
642
643                 for ( i = 1; arg[i] != '\0'; ++i )
644                         switch ( arg[i] )
645                                 {
646                                 case '+':
647                                         C_plus_plus = true;
648                                         break;
649
650                                 case 'B':
651                                         interactive = false;
652                                         break;
653
654                                 case 'b':
655                                         backing_up_report = true;
656                                         break;
657
658                                 case 'c':
659                                         break;
660
661                                 case 'C':
662                                         if ( i != 1 )
663                                                 flexerror(
664                                 _( "-C flag must be given separately" ) );
665
666                                         if ( ! sawcmpflag )
667                                                 {
668                                                 useecs = false;
669                                                 usemecs = false;
670                                                 fulltbl = false;
671                                                 sawcmpflag = true;
672                                                 }
673
674                                         for ( ++i; arg[i] != '\0'; ++i )
675                                                 switch ( arg[i] )
676                                                         {
677                                                         case 'a':
678                                                                 long_align =
679                                                                         true;
680                                                                 break;
681
682                                                         case 'e':
683                                                                 useecs = true;
684                                                                 break;
685
686                                                         case 'F':
687                                                                 fullspd = true;
688                                                                 break;
689
690                                                         case 'f':
691                                                                 fulltbl = true;
692                                                                 break;
693
694                                                         case 'm':
695                                                                 usemecs = true;
696                                                                 break;
697
698                                                         case 'r':
699                                                                 use_read = true;
700                                                                 break;
701
702                                                         default:
703                                                                 lerrif(
704                                                 _( "unknown -C option '%c'" ),
705                                                                 (int) arg[i] );
706                                                                 break;
707                                                         }
708
709                                         goto get_next_arg;
710
711                                 case 'd':
712                                         ddebug = true;
713                                         break;
714
715                                 case 'f':
716                                         useecs = usemecs = false;
717                                         use_read = fulltbl = true;
718                                         break;
719
720                                 case 'F':
721                                         useecs = usemecs = false;
722                                         use_read = fullspd = true;
723                                         break;
724
725                                 case '?':
726                                 case 'h':
727                                         usage();
728                                         exit( 0 );
729
730                                 case 'I':
731                                         interactive = true;
732                                         break;
733
734                                 case 'i':
735                                         caseins = true;
736                                         break;
737
738                                 case 'l':
739                                         lex_compat = true;
740                                         break;
741
742                                 case 'L':
743                                         gen_line_dirs = false;
744                                         break;
745
746                                 case 'n':
747                                         /* Stupid do-nothing deprecated
748                                          * option.
749                                          */
750                                         break;
751
752                                 case 'o':
753                                         if ( i != 1 )
754                                                 flexerror(
755                                 _( "-o flag must be given separately" ) );
756
757                                         outfilename = arg + i + 1;
758                                         did_outfilename = 1;
759                                         goto get_next_arg;
760
761                                 case 'P':
762                                         if ( i != 1 )
763                                                 flexerror(
764                                 _( "-P flag must be given separately" ) );
765
766                                         prefix = arg + i + 1;
767                                         goto get_next_arg;
768
769                                 case 'p':
770                                         ++performance_report;
771                                         break;
772
773                                 case 'S':
774                                         if ( i != 1 )
775                                                 flexerror(
776                                 _( "-S flag must be given separately" ) );
777
778                                         skelname = arg + i + 1;
779                                         goto get_next_arg;
780
781                                 case 's':
782                                         spprdflt = true;
783                                         break;
784
785                                 case 't':
786                                         use_stdout = true;
787                                         break;
788
789                                 case 'T':
790                                         trace = true;
791                                         break;
792
793                                 case 'v':
794                                         printstats = true;
795                                         break;
796
797                                 case 'V':
798                                         printf( _( "%s version %s\n" ),
799                                                 program_name, flex_version );
800                                         exit( 0 );
801
802                                 case 'w':
803                                         nowarn = true;
804                                         break;
805
806                                 case '7':
807                                         csize = 128;
808                                         break;
809
810                                 case '8':
811                                         csize = CSIZE;
812                                         break;
813
814                                 default:
815                                         fprintf( stderr,
816                 _( "%s: unknown flag '%c'.  For usage, try\n\t%s --help\n" ),
817                                                 program_name, (int) arg[i],
818                                                 program_name );
819                                         exit( 1 );
820                                 }
821
822                 /* Used by -C, -S, -o, and -P flags in lieu of a "continue 2"
823                  * control.
824                  */
825                 get_next_arg: ;
826                 }
827
828         num_input_files = argc;
829         input_files = argv;
830         set_input_file( num_input_files > 0 ? input_files[0] : NULL );
831
832         lastccl = lastsc = lastdfa = lastnfa = 0;
833         num_rules = num_eof_rules = default_rule = 0;
834         numas = numsnpairs = tmpuses = 0;
835         numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
836         numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
837         num_backing_up = onesp = numprots = 0;
838         variable_trailing_context_rules = bol_needed = false;
839
840         out_linenum = linenum = sectnum = 1;
841         firstprot = NIL;
842
843         /* Used in mkprot() so that the first proto goes in slot 1
844          * of the proto queue.
845          */
846         lastprot = 1;
847
848         set_up_initial_allocations();
849         }
850
851
852 /* readin - read in the rules section of the input file(s) */
853
854 void readin()
855         {
856         static char yy_stdinit[] = "FILE *yyin = stdin, *yyout = stdout;";
857         static char yy_nostdinit[] =
858                 "FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;";
859
860         line_directive_out( (FILE *) 0, 1 );
861
862         if ( yyparse() )
863                 {
864                 pinpoint_message( _( "fatal parse error" ) );
865                 flexend( 1 );
866                 }
867
868         if ( syntaxerror )
869                 flexend( 1 );
870
871         if ( backing_up_report )
872                 {
873                 backing_up_file = fopen( backing_name, "w" );
874                 if ( backing_up_file == NULL )
875                         lerrsf(
876                         _( "could not create backing-up info file %s" ),
877                                 backing_name );
878                 }
879
880         else
881                 backing_up_file = NULL;
882
883         if ( yymore_really_used == true )
884                 yymore_used = true;
885         else if ( yymore_really_used == false )
886                 yymore_used = false;
887
888         if ( reject_really_used == true )
889                 reject = true;
890         else if ( reject_really_used == false )
891                 reject = false;
892
893         if ( performance_report > 0 )
894                 {
895                 if ( lex_compat )
896                         {
897                         fprintf( stderr,
898 _( "-l AT&T lex compatibility option entails a large performance penalty\n" ) );
899                         fprintf( stderr,
900 _( " and may be the actual source of other reported performance penalties\n" ) );
901                         }
902
903                 else if ( do_yylineno )
904                         {
905                         fprintf( stderr,
906         _( "%%option yylineno entails a large performance penalty\n" ) );
907                         }
908
909                 if ( performance_report > 1 )
910                         {
911                         if ( interactive )
912                                 fprintf( stderr,
913         _( "-I (interactive) entails a minor performance penalty\n" ) );
914
915                         if ( yymore_used )
916                                 fprintf( stderr,
917                 _( "yymore() entails a minor performance penalty\n" ) );
918                         }
919
920                 if ( reject )
921                         fprintf( stderr,
922                         _( "REJECT entails a large performance penalty\n" ) );
923
924                 if ( variable_trailing_context_rules )
925                         fprintf( stderr,
926 _( "Variable trailing context rules entail a large performance penalty\n" ) );
927                 }
928
929         if ( reject )
930                 real_reject = true;
931
932         if ( variable_trailing_context_rules )
933                 reject = true;
934
935         if ( (fulltbl || fullspd) && reject )
936                 {
937                 if ( real_reject )
938                         flexerror(
939                                 _( "REJECT cannot be used with -f or -F" ) );
940                 else if ( do_yylineno )
941                         flexerror(
942                         _( "%option yylineno cannot be used with -f or -F" ) );
943                 else
944                         flexerror(
945         _( "variable trailing context rules cannot be used with -f or -F" ) );
946                 }
947
948         if ( reject )
949                 outn( "\n#define YY_USES_REJECT" );
950
951         if ( ! do_yywrap )
952                 {
953                 outn( "\n#define yywrap() 1" );
954                 outn( "#define YY_SKIP_YYWRAP" );
955                 }
956
957         if ( ddebug )
958                 outn( "\n#define FLEX_DEBUG" );
959
960         if ( csize == 256 )
961                 outn( "typedef unsigned char YY_CHAR;" );
962         else
963                 outn( "typedef char YY_CHAR;" );
964
965         if ( C_plus_plus )
966                 {
967                 outn( "#define yytext_ptr yytext" );
968
969                 if ( interactive )
970                         outn( "#define YY_INTERACTIVE" );
971                 }
972
973         else
974                 {
975                 if ( do_stdinit )
976                         {
977                         outn( "#ifdef VMS" );
978                         outn( "#ifndef __VMS_POSIX" );
979                         outn( yy_nostdinit );
980                         outn( "#else" );
981                         outn( yy_stdinit );
982                         outn( "#endif" );
983                         outn( "#else" );
984                         outn( yy_stdinit );
985                         outn( "#endif" );
986                         }
987
988                 else
989                         outn( yy_nostdinit );
990                 }
991
992         if ( fullspd )
993                 outn( "typedef yyconst struct yy_trans_info *yy_state_type;" );
994         else if ( ! C_plus_plus )
995                 outn( "typedef int yy_state_type;" );
996
997         if ( ddebug )
998                 outn( "\n#define FLEX_DEBUG" );
999
1000         if ( lex_compat )
1001                 outn( "#define YY_FLEX_LEX_COMPAT" );
1002
1003         if ( do_yylineno && ! C_plus_plus )
1004                 {
1005                 outn( "extern int yylineno;" );
1006                 outn( "int yylineno = 1;" );
1007                 }
1008
1009         if ( C_plus_plus )
1010                 {
1011                 outn( "\n#include <FlexLexer.h>" );
1012
1013                 if ( yyclass )
1014                         {
1015                         outn( "int yyFlexLexer::yylex()" );
1016                         outn( "\t{" );
1017                         outn(
1018 "\tLexerError( \"yyFlexLexer::yylex invoked but %option yyclass used\" );" );
1019                         outn( "\treturn 0;" );
1020                         outn( "\t}" );
1021         
1022                         out_str( "\n#define YY_DECL int %s::yylex()\n",
1023                                 yyclass );
1024                         }
1025                 }
1026
1027         else
1028                 {
1029                 if ( yytext_is_array )
1030                         outn( "extern char yytext[];\n" );
1031
1032                 else
1033                         {
1034                         outn( "extern char *yytext;" );
1035                         outn( "#define yytext_ptr yytext" );
1036                         }
1037
1038                 if ( yyclass )
1039                         flexerror(
1040                 _( "%option yyclass only meaningful for C++ scanners" ) );
1041                 }
1042
1043         if ( useecs )
1044                 numecs = cre8ecs( nextecm, ecgroup, csize );
1045         else
1046                 numecs = csize;
1047
1048         /* Now map the equivalence class for NUL to its expected place. */
1049         ecgroup[0] = ecgroup[csize];
1050         NUL_ec = ABS( ecgroup[0] );
1051
1052         if ( useecs )
1053                 ccl2ecl();
1054         }
1055
1056
1057 /* set_up_initial_allocations - allocate memory for internal tables */
1058
1059 void set_up_initial_allocations()
1060         {
1061         current_mns = INITIAL_MNS;
1062         firstst = allocate_integer_array( current_mns );
1063         lastst = allocate_integer_array( current_mns );
1064         finalst = allocate_integer_array( current_mns );
1065         transchar = allocate_integer_array( current_mns );
1066         trans1 = allocate_integer_array( current_mns );
1067         trans2 = allocate_integer_array( current_mns );
1068         accptnum = allocate_integer_array( current_mns );
1069         assoc_rule = allocate_integer_array( current_mns );
1070         state_type = allocate_integer_array( current_mns );
1071
1072         current_max_rules = INITIAL_MAX_RULES;
1073         rule_type = allocate_integer_array( current_max_rules );
1074         rule_linenum = allocate_integer_array( current_max_rules );
1075         rule_useful = allocate_integer_array( current_max_rules );
1076
1077         current_max_scs = INITIAL_MAX_SCS;
1078         scset = allocate_integer_array( current_max_scs );
1079         scbol = allocate_integer_array( current_max_scs );
1080         scxclu = allocate_integer_array( current_max_scs );
1081         sceof = allocate_integer_array( current_max_scs );
1082         scname = allocate_char_ptr_array( current_max_scs );
1083
1084         current_maxccls = INITIAL_MAX_CCLS;
1085         cclmap = allocate_integer_array( current_maxccls );
1086         ccllen = allocate_integer_array( current_maxccls );
1087         cclng = allocate_integer_array( current_maxccls );
1088
1089         current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
1090         ccltbl = allocate_Character_array( current_max_ccl_tbl_size );
1091
1092         current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
1093
1094         current_max_xpairs = INITIAL_MAX_XPAIRS;
1095         nxt = allocate_integer_array( current_max_xpairs );
1096         chk = allocate_integer_array( current_max_xpairs );
1097
1098         current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
1099         tnxt = allocate_integer_array( current_max_template_xpairs );
1100
1101         current_max_dfas = INITIAL_MAX_DFAS;
1102         base = allocate_integer_array( current_max_dfas );
1103         def = allocate_integer_array( current_max_dfas );
1104         dfasiz = allocate_integer_array( current_max_dfas );
1105         accsiz = allocate_integer_array( current_max_dfas );
1106         dhash = allocate_integer_array( current_max_dfas );
1107         dss = allocate_int_ptr_array( current_max_dfas );
1108         dfaacc = allocate_dfaacc_union( current_max_dfas );
1109
1110         nultrans = (int *) 0;
1111         }
1112
1113
1114 void usage()
1115         {
1116         FILE *f = stdout;
1117
1118         fprintf( f,
1119 _( "%s [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -ooutput -Pprefix -Sskeleton]\n" ),
1120                 program_name );
1121         fprintf( f, _( "\t[--help --version] [file ...]\n" ) );
1122
1123         fprintf( f, _( "\t-b  generate backing-up information to %s\n" ),
1124                 backing_name );
1125         fprintf( f, _( "\t-c  do-nothing POSIX option\n" ) );
1126         fprintf( f, _( "\t-d  turn on debug mode in generated scanner\n" ) );
1127         fprintf( f, _( "\t-f  generate fast, large scanner\n" ) );
1128         fprintf( f, _( "\t-h  produce this help message\n" ) );
1129         fprintf( f, _( "\t-i  generate case-insensitive scanner\n" ) );
1130         fprintf( f, _( "\t-l  maximal compatibility with original lex\n" ) );
1131         fprintf( f, _( "\t-n  do-nothing POSIX option\n" ) );
1132         fprintf( f, _( "\t-p  generate performance report to stderr\n" ) );
1133         fprintf( f,
1134                 _( "\t-s  suppress default rule to ECHO unmatched text\n" ) );
1135
1136         if ( ! did_outfilename )
1137                 {
1138                 sprintf( outfile_path, outfile_template,
1139                         prefix, C_plus_plus ? "cc" : "c" );
1140                 outfilename = outfile_path;
1141                 }
1142
1143         fprintf( f,
1144                 _( "\t-t  write generated scanner on stdout instead of %s\n" ),
1145                 outfilename );
1146
1147         fprintf( f,
1148                 _( "\t-v  write summary of scanner statistics to f\n" ) );
1149         fprintf( f, _( "\t-w  do not generate warnings\n" ) );
1150         fprintf( f, _( "\t-B  generate batch scanner (opposite of -I)\n" ) );
1151         fprintf( f,
1152                 _( "\t-F  use alternative fast scanner representation\n" ) );
1153         fprintf( f,
1154                 _( "\t-I  generate interactive scanner (opposite of -B)\n" ) );
1155         fprintf( f, _( "\t-L  suppress #line directives in scanner\n" ) );
1156         fprintf( f, _( "\t-T  %s should run in trace mode\n" ), program_name );
1157         fprintf( f, _( "\t-V  report %s version\n" ), program_name );
1158         fprintf( f, _( "\t-7  generate 7-bit scanner\n" ) );
1159         fprintf( f, _( "\t-8  generate 8-bit scanner\n" ) );
1160         fprintf( f, _( "\t-+  generate C++ scanner class\n" ) );
1161         fprintf( f, _( "\t-?  produce this help message\n" ) );
1162         fprintf( f,
1163 _( "\t-C  specify degree of table compression (default is -Cem):\n" ) );
1164         fprintf( f,
1165 _( "\t\t-Ca  trade off larger tables for better memory alignment\n" ) );
1166         fprintf( f, _( "\t\t-Ce  construct equivalence classes\n" ) );
1167         fprintf( f,
1168 _( "\t\t-Cf  do not compress scanner tables; use -f representation\n" ) );
1169         fprintf( f,
1170 _( "\t\t-CF  do not compress scanner tables; use -F representation\n" ) );
1171         fprintf( f, _( "\t\t-Cm  construct meta-equivalence classes\n" ) );
1172         fprintf( f,
1173         _( "\t\t-Cr  use read() instead of stdio for scanner input\n" ) );
1174         fprintf( f, _( "\t-o  specify output filename\n" ) );
1175         fprintf( f, _( "\t-P  specify scanner prefix other than \"yy\"\n" ) );
1176         fprintf( f, _( "\t-S  specify skeleton file\n" ) );
1177         fprintf( f, _( "\t--help     produce this help message\n" ) );
1178         fprintf( f, _( "\t--version  report %s version\n" ), program_name );
1179         }