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