home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 213b.lha / Flex / Flex1 / main.c < prev    next >
C/C++ Source or Header  |  1996-02-14  |  15KB  |  529 lines

  1. /* flex - tool to generate fast lexical analyzers
  2.  *
  3.  *
  4.  * Copyright (c) 1987, the University of California
  5.  *
  6.  * The United States Government has rights in this work pursuant to
  7.  * contract no. DE-AC03-76SF00098 between the United States Department of
  8.  * Energy and the University of California.
  9.  *
  10.  * This program may be redistributed.  Enhancements and derivative works
  11.  * may be created provided the new works, if made available to the general
  12.  * public, are made available for use by anyone.
  13.  *
  14.  *
  15.  * ver   date  who    remarks
  16.  * ---   ----  ------ -------------------------------------------------------
  17.  * 04b 30sep87 kg, vp .implemented (part of) Van Jacobson's fast scanner design
  18.  * 04a 27jun86 vp     .translated from Ratfor into C
  19.  * 01a 22aug83 vp     .written.  Original version by Jef Poskanzer.
  20.  */
  21.  
  22. #include "flexdef.h"
  23.  
  24.  
  25. /* these globals are all defined and commented in flexdef.h */
  26. int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
  27. int interactive, caseins, useecs, fulltbl, usemecs, reject;
  28. int fullspd, gen_line_dirs;
  29. int datapos, dataline, linenum;
  30. FILE *skelfile = NULL;
  31. char *infilename = NULL;
  32. int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
  33. int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
  34. int current_mns;
  35. int accnum, *firstst, *lastst, *finalst, *transchar;
  36. int *trans1, *trans2, *accptnum, lastnfa;
  37. int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
  38. int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
  39. int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
  40. int tecbck[CSIZE + 1];
  41. int lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
  42. int current_max_dfa_size, current_max_xpairs;
  43. int current_max_template_xpairs, current_max_dfas;
  44. int lastdfa, *nxt, *chk, *tnxt;
  45. int *base, *def, tblend, firstfree, **dss, *dfasiz;
  46. union dfaacc_union *dfaacc;
  47. int *accsiz, *dhash, *todo, todo_head, todo_next, numas;
  48. int numsnpairs, jambase, jamstate;
  49. int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
  50. int current_max_ccl_tbl_size;
  51. char *ccltbl;
  52. char *starttime, *endtime, nmstr[MAXLINE];
  53. int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
  54. int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
  55. FILE *temp_action_file;
  56. int end_of_buffer_state;
  57. char *action_file_name = "t:flex.tmp";
  58.  
  59.  
  60. /* flex - main program
  61.  *
  62.  * synopsis (from the shell)
  63.  *    flex [-v] [file ...]
  64.  */
  65.  
  66. main( argc, argv )
  67. int argc;
  68. char **argv;
  69.  
  70.     {
  71.     flexinit( argc, argv );
  72.  
  73.     readin();
  74.  
  75.     if ( ! syntaxerror )
  76.         {
  77.         /* convert the ndfa to a dfa */
  78.         ntod();
  79.  
  80.         /* generate the C state transition tables from the DFA */
  81.         make_tables();
  82.         }
  83.  
  84.     /* note, flexend does not return.  It exits with its argument as status. */
  85.  
  86.     flexend( 0 );
  87.     }
  88.  
  89.  
  90. /* flexend - terminate flex
  91.  *
  92.  * synopsis
  93.  *    int status;
  94.  *    flexend( status );
  95.  *
  96.  *    status is exit status.
  97.  *
  98.  * note
  99.  *    This routine does not return.
  100.  */
  101.  
  102. flexend( status )
  103. int status;
  104.  
  105.     {
  106.     int tblsiz;
  107.     char *gettime();
  108.  
  109.     if ( skelfile != NULL )
  110.         (void) fclose( skelfile );
  111.  
  112.     if ( temp_action_file )
  113.         {
  114.         (void) fclose( temp_action_file );
  115.         (void) unlink( action_file_name );
  116.         }
  117.  
  118.     if ( printstats )
  119.         {
  120.         endtime = gettime();
  121.  
  122.         fprintf( stderr, "flex usage statistics:\n" );
  123.         fprintf( stderr, "  started at %s, finished at %s\n",
  124.                  starttime, endtime );
  125.  
  126.         fprintf( stderr, "  %d/%d NFA states\n", lastnfa, current_mns );
  127.         fprintf( stderr, "  %d/%d DFA states (%d words)\n", lastdfa,
  128.                          current_max_dfas, totnst );
  129.         fprintf( stderr, "  %d rules\n", accnum );
  130.         fprintf( stderr, "  %d/%d start conditions\n", lastsc,
  131.                          current_max_scs );
  132.         fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
  133.                  numeps, eps2 );
  134.  
  135.         if ( lastccl == 0 )
  136.             fprintf( stderr, "  no character classes\n" );
  137.         else
  138.             fprintf( stderr,
  139.         "  %d/%d character classes needed %d/%d words of storage, %d reused\n",
  140.                      lastccl, current_maxccls,
  141.                      cclmap[lastccl] + ccllen[lastccl] - 1,
  142.                      current_max_ccl_tbl_size, cclreuse );
  143.  
  144.         fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
  145.         fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
  146.                  numuniq, numdup );
  147.  
  148.         if ( fulltbl )
  149.             {
  150.             tblsiz = lastdfa * numecs;
  151.             fprintf( stderr, "  %d table entries\n", tblsiz );
  152.             }
  153.  
  154.         else
  155.             {
  156.             tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
  157.  
  158.             fprintf( stderr, "  %d/%d base/def entries created\n",
  159.                      lastdfa + numtemps, current_max_dfas );
  160.             fprintf( stderr, "  %d/%d (peak %d) nxt/chk entries created\n",
  161.                      tblend, current_max_xpairs, peakpairs );
  162.             fprintf( stderr,
  163.                      "  %d/%d (peak %d) template nxt/chk entries created\n",
  164.                      numtemps * nummecs, current_max_template_xpairs,
  165.                      numtemps * numecs );
  166.             fprintf( stderr, "  %d empty table entries\n", nummt );
  167.             fprintf( stderr, "  %d protos created\n", numprots );
  168.             fprintf( stderr, "  %d templates created, %d uses\n",
  169.                      numtemps, tmpuses );
  170.             }
  171.  
  172.         if ( useecs )
  173.             {
  174.             tblsiz = tblsiz + CSIZE;
  175.             fprintf( stderr, "  %d/%d equivalence classes created\n",
  176.                      numecs, CSIZE );
  177.             }
  178.  
  179.         if ( usemecs )
  180.             {
  181.             tblsiz = tblsiz + numecs;
  182.             fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
  183.                      nummecs, CSIZE );
  184.             }
  185.  
  186.         fprintf( stderr, "  %d (%d saved) hash collisions, %d DFAs equal\n",
  187.                  hshcol, hshsave, dfaeql );
  188.         fprintf( stderr, "  %d sets of reallocations needed\n", num_reallocs );
  189.         fprintf( stderr, "  %d total table entries needed\n", tblsiz );
  190.         }
  191.  
  192.     exit( status );
  193.     }
  194.  
  195.  
  196. /* flexinit - initialize flex
  197.  *
  198.  * synopsis
  199.  *    int argc;
  200.  *    char **argv;
  201.  *    flexinit( argc, argv );
  202.  */
  203.  
  204. flexinit( argc, argv )
  205. int argc;
  206. char **argv;
  207.  
  208.     {
  209.     int i, sawcmpflag, use_stdout;
  210.     char *arg, *skelname = NULL, *gettime(), clower()/* , *mktemp() */;
  211.  
  212.     printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
  213.     ddebug = fulltbl = reject = fullspd = false;
  214.     gen_line_dirs = usemecs = useecs = true;
  215.  
  216.     sawcmpflag = false;
  217.     use_stdout = false;
  218.  
  219.     /* read flags */
  220.     for ( --argc, ++argv; argc ; --argc, ++argv )
  221.         {
  222.         if ( argv[0][0] != '-' || argv[0][1] == '\0' )
  223.             break;
  224.  
  225.         arg = argv[0];
  226.  
  227.         for ( i = 1; arg[i] != '\0'; ++i )
  228.             switch ( arg[i] )
  229.                 {
  230.                 case 'c':
  231.                     if ( i != 1 )
  232.                         flexerror( "-c flag must be given separately" );
  233.  
  234.                     if ( ! sawcmpflag )
  235.                         {
  236.                         useecs = false;
  237.                         usemecs = false;
  238.                         fulltbl = false;
  239.                         sawcmpflag = true;
  240.                         }
  241.  
  242.                     for ( ++i; arg[i] != '\0'; ++i )
  243.                         switch ( clower( arg[i] ) )
  244.                             {
  245.                             case 'e':
  246.                                 useecs = true;
  247.                                 break;
  248.  
  249.                             case 'F':
  250.                                 fullspd = true;
  251.                                 break;
  252.  
  253.                             case 'f':
  254.                                 fulltbl = true;
  255.                                 break;
  256.  
  257.                             case 'm':
  258.                                 usemecs = true;
  259.                                 break;
  260.  
  261.                             default:
  262.                                 lerrif( "unknown -c option %c",
  263.                                         (int) arg[i] );
  264.                                 break;
  265.                             }
  266.  
  267.                     goto get_next_arg;
  268.  
  269.                 case 'd':
  270.                     ddebug = true;
  271.                     break;
  272.  
  273.                 case 'f':
  274.                     useecs = usemecs = false;
  275.                     fulltbl = true;
  276.                     break;
  277.  
  278.                 case 'I':
  279.                     interactive = true;
  280.                     break;
  281.  
  282.                 case 'i':
  283.                     caseins = true;
  284.                     break;
  285.  
  286.                 case 'L':
  287.                     gen_line_dirs = false;
  288.                     break;
  289.  
  290.                 case 'r':
  291.                     reject = true;
  292.                     break;
  293.  
  294.                 case 'F':
  295.                     useecs = usemecs = false;
  296.                     fullspd = true;
  297.                     break;
  298.  
  299.                 case 'S':
  300.                     if ( i != 1 )
  301.                         flexerror( "-S flag must be given separately" );
  302.  
  303.                     skelname = arg + i + 1;
  304.                     goto get_next_arg;
  305.  
  306.                 case 's':
  307.                     spprdflt = true;
  308.                     break;
  309.  
  310.                 case 't':
  311.                     use_stdout = true;
  312.                     break;
  313.  
  314.                 case 'T':
  315.                     trace = true;
  316.                     break;
  317.  
  318.                 case 'v':
  319.                     printstats = true;
  320.                     break;
  321.  
  322.                 default:
  323.                     lerrif( "unknown flag %c", (int) arg[i] );
  324.                     break;
  325.                 }
  326.  
  327. get_next_arg: /* used by -c and -S flags in lieu of a "continue 2" control */
  328.         ;
  329.         }
  330.  
  331.     if ( (fulltbl || fullspd) && usemecs )
  332.         flexerror( "full table and -cm don't make sense together" );
  333.  
  334.     if ( (fulltbl || fullspd) && interactive )
  335.         flexerror( "full table and -I are (currently) incompatible" );
  336.  
  337.     if ( (fulltbl || fullspd) && reject )
  338.         flexerror( "reject (-r) cannot be used with -f or -F" );
  339.  
  340.     if ( fulltbl && fullspd )
  341.         flexerror( "full table and -F are mutually exclusive" );
  342.  
  343.     if ( ! skelname )
  344.         {
  345.         static char skeleton_name_storage[400];
  346.  
  347.         skelname = skeleton_name_storage;
  348.  
  349.         if ( fullspd || fulltbl )
  350.             (void) strcpy( skelname, FAST_SKELETON_FILE );
  351.         else
  352.             (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
  353.         }
  354.  
  355.     if ( ! use_stdout )
  356.         {
  357.         FILE *prev_stdout = freopen( "lex.yy.c", "w", stdout );
  358.  
  359.         if ( prev_stdout == NULL )
  360.             flexerror( "could not create lex.yy.c" );
  361.         }
  362.  
  363.     if ( argc )
  364.         {
  365.         if ( argc > 1 )
  366.             flexerror( "extraneous argument(s) given" );
  367.  
  368.         yyin = fopen( infilename = argv[0], "r" );
  369.  
  370.         if ( yyin == NULL )
  371.             lerrsf( "can't open %s", argv[0] );
  372.         }
  373.  
  374.     else
  375.         yyin = stdin;
  376.  
  377.     lastccl = 0;
  378.     lastsc = 0;
  379.  
  380.     /* initialize the statistics */
  381.     starttime = gettime();
  382.  
  383.     if ((skelfile = fopen( skelname, "r" )) == NULL )
  384.         lerrsf( "can't open skeleton file %s", skelname );
  385.  
  386.     /* (void) mktemp( &action_file_name ); */
  387.  
  388.     if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
  389.         lerrsf( "can't open temporary action file %s", action_file_name );
  390.  
  391.     lastdfa = lastnfa = accnum = numas = numsnpairs = tmpuses = 0;
  392.     numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
  393.     numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
  394.     onesp = numprots = 0;
  395.  
  396.     linenum = sectnum = 1;
  397.     firstprot = NIL;
  398.  
  399.     /* used in mkprot() so that the first proto goes in slot 1
  400.      * of the proto queue
  401.      */
  402.     lastprot = 1;
  403.  
  404.     if ( useecs )
  405.         {
  406.         /* set up doubly-linked equivalence classes */
  407.         ecgroup[1] = NIL;
  408.  
  409.         for ( i = 2; i <= CSIZE; ++i )
  410.             {
  411.             ecgroup[i] = i - 1;
  412.             nextecm[i - 1] = i;
  413.             }
  414.  
  415.         nextecm[CSIZE] = NIL;
  416.         }
  417.  
  418.     else
  419.         { /* put everything in its own equivalence class */
  420.         for ( i = 1; i <= CSIZE; ++i )
  421.             {
  422.             ecgroup[i] = i;
  423.             nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */
  424.             }
  425.         }
  426.  
  427.     set_up_initial_allocations();
  428.     }
  429.  
  430.  
  431. /* readin - read in the rules section of the input file(s)
  432.  *
  433.  * synopsis
  434.  *    readin();
  435.  */
  436.  
  437. readin()
  438.  
  439.     {
  440.     fputs( "#define YY_DEFAULT_ACTION ", stdout );
  441.  
  442.     if ( spprdflt )
  443.         fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", stdout );
  444.     else
  445.         fputs( "ECHO", stdout );
  446.  
  447.     fputs( ";\n", stdout );
  448.  
  449.     if ( ddebug )
  450.         puts( "#define FLEX_DEBUG" );
  451.     if ( useecs )
  452.         puts( "#define FLEX_USE_ECS" );
  453.     if ( usemecs )
  454.         puts( "#define FLEX_USE_MECS" );
  455.     if ( interactive )
  456.         puts( "#define FLEX_INTERACTIVE_SCANNER" );
  457.     if ( reject )
  458.         puts( "#define FLEX_REJECT_ENABLED" );
  459.     if ( fulltbl )
  460.         puts( "#define FLEX_FULL_TABLE" );
  461.  
  462.     skelout();
  463.  
  464.     line_directive_out( stdout );
  465.  
  466.     if ( yyparse() )
  467.         lerrif( "fatal parse error at line %d", linenum );
  468.  
  469.     if ( useecs )
  470.         {
  471.         numecs = cre8ecs( nextecm, ecgroup, CSIZE );
  472.         ccl2ecl();
  473.         }
  474.  
  475.     else
  476.         numecs = CSIZE;
  477.  
  478.     }
  479.  
  480.  
  481.  
  482. /* set_up_initial_allocations - allocate memory for internal tables */
  483.  
  484. set_up_initial_allocations()
  485.  
  486.     {
  487.     current_mns = INITIAL_MNS;
  488.     firstst = allocate_integer_array( current_mns );
  489.     lastst = allocate_integer_array( current_mns );
  490.     finalst = allocate_integer_array( current_mns );
  491.     transchar = allocate_integer_array( current_mns );
  492.     trans1 = allocate_integer_array( current_mns );
  493.     trans2 = allocate_integer_array( current_mns );
  494.     accptnum = allocate_integer_array( current_mns );
  495.  
  496.     current_max_scs = INITIAL_MAX_SCS;
  497.     scset = allocate_integer_array( current_max_scs );
  498.     scbol = allocate_integer_array( current_max_scs );
  499.     scxclu = allocate_integer_array( current_max_scs );
  500.     actvsc = allocate_integer_array( current_max_scs );
  501.  
  502.     current_maxccls = INITIAL_MAXCCLS;
  503.     cclmap = allocate_integer_array( current_maxccls );
  504.     ccllen = allocate_integer_array( current_maxccls );
  505.     cclng = allocate_integer_array( current_maxccls );
  506.  
  507.     current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
  508.     ccltbl = allocate_character_array( current_max_ccl_tbl_size );
  509.  
  510.     current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
  511.  
  512.     current_max_xpairs = INITIAL_MAX_XPAIRS;
  513.     nxt = allocate_integer_array( current_max_xpairs );
  514.     chk = allocate_integer_array( current_max_xpairs );
  515.  
  516.     current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
  517.     tnxt = allocate_integer_array( current_max_template_xpairs );
  518.  
  519.     current_max_dfas = INITIAL_MAX_DFAS;
  520.     base = allocate_integer_array( current_max_dfas );
  521.     def = allocate_integer_array( current_max_dfas );
  522.     dfasiz = allocate_integer_array( current_max_dfas );
  523.     accsiz = allocate_integer_array( current_max_dfas );
  524.     dhash = allocate_integer_array( current_max_dfas );
  525.     todo = allocate_integer_array( current_max_dfas );
  526.     dss = allocate_integer_pointer_array( current_max_dfas );
  527.     dfaacc = allocate_dfaacc_union( current_max_dfas );
  528.     }
  529.