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