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