home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / CUG / BAWKACT.C < prev    next >
Text File  |  1993-12-01  |  8KB  |  431 lines

  1. /*
  2.     HEADER:        CUG000.00;
  3.     TITLE:        BAWK Actions Compiler;
  4.     DATE:        05/17/1987;
  5.     VERSION:    1.1;
  6.     FILENAME:    BAWKACT.C;
  7.     SEE-ALSO:    BAWK.C;
  8.     AUTHORS:    W. C. Colley III, B. Brodt;
  9. */
  10.  
  11. /*
  12.  * Bawk C actions compiler
  13.  */
  14. #include <stdio.h>
  15. #include "bawk.h"
  16.  
  17. /* Functions local to this module.    */
  18.  
  19. char *str_compile();
  20. int stmt_compile();
  21.  
  22. int act_compile( actbuf )
  23. char    *actbuf;    /* where tokenized actions are compiled into */
  24. {
  25.     Where = ACTION;
  26.     return stmt_compile( actbuf );
  27. }
  28.  
  29. int pat_compile( actbuf )
  30. char    *actbuf;    /* where tokenized actions are compiled into */
  31. {
  32.     Where = PATTERN;
  33.     return stmt_compile( actbuf );
  34. }
  35.  
  36. int stmt_compile( actbuf )
  37. char    *actbuf;    /* where tokenized actions are compiled into */
  38. {
  39.     /*
  40.      * Read and tokenize C actions from current input file into the
  41.      * action buffer.  Strip out comments and whitespace in the
  42.      * process.
  43.      */
  44.     char    *actptr,    /* actbuf pointer */
  45.         *cp,        /* work pointer */
  46.         buf[MAXLINELEN];/* string buffer */
  47.     int    braces,        /* counts '{}' pairs - return when 0 */
  48.         parens,        /* counts '()' pairs */
  49.         i,        /* temp */
  50.         c;        /* current input character */
  51.  
  52.     braces = parens = 0;
  53.     actptr = actbuf;
  54.     while ( (c = getcharacter()) != -1 )
  55.     {
  56.         /*
  57.          * Skip over spaces, tabs and newlines
  58.          */
  59.         if ( c==' ' || c=='\t' || c=='\n' )
  60.             continue;
  61.         if ( c=='#' )
  62.         {
  63.             /*
  64.              * Skip comments.  Comments start with a '#' and
  65.              * end at the next newline.
  66.              */
  67.             while ( (c = getcharacter()) != -1 && c!='\n' )
  68.                 ;
  69.             continue;
  70.         }
  71.  
  72.         if ( c=='{' )
  73.         {
  74.             if ( Where==PATTERN )
  75.             {
  76.                 /*
  77.                  * We're compiling a pattern. The '{' marks
  78.                  * the beginning of an action statement.
  79.                  * Push the character back and return.
  80.                  */
  81.                 ungetcharacter( '{' );
  82.                 break;
  83.             }
  84.             else
  85.             {
  86.                 /*
  87.                  * We must be compiling an action statement.
  88.                  * '{'s mark beginning of action or compound
  89.                  * statements.
  90.                  */
  91.                 ++braces;
  92.                 *actptr++ = T_LBRACE;
  93.             }
  94.         }
  95.         else if ( c=='}' )
  96.         {
  97.             *actptr++ = T_RBRACE;
  98.             if ( ! --braces )
  99.                 /*
  100.                  * Found the end of the action string
  101.                  */
  102.                 break;
  103.         }
  104.         else if ( c=='(' )
  105.         {
  106.             ++parens;
  107.             *actptr++ = T_LPAREN;
  108.         }
  109.         else if ( c==')' )
  110.         {
  111.             if ( --parens < 0 )
  112.                 error( "mismatched '()'", ACT_ERROR );
  113.             *actptr++ = T_RPAREN;
  114.         }
  115.         else if ( c==',' && !braces && !parens && Where==PATTERN )
  116.         {
  117.             /*
  118.              * found a comma outside of any braces or parens-
  119.              * this must be a regular expression seperator.
  120.              */
  121.             ungetcharacter( ',' );
  122.             break;
  123.         }
  124.  
  125.         /*
  126.          * Check if it's a regular expression:
  127.          */
  128.         else if ( c=='/' )
  129.         {
  130.             /*
  131.              * A '/' inside a pattern string starts a regular
  132.              * expression.    Inside action strings, a '/' is
  133.              * the division operator.
  134.              */
  135.             if ( Where == PATTERN )
  136.                 goto dopattern;
  137.             else
  138.                 *actptr++ = T_DIV;
  139.         }
  140.         else if ( c=='@' )
  141.         {
  142. dopattern:
  143.             /*
  144.              * Within action strings, only the '@' may be used to
  145.              * delimit regular expressions
  146.              */
  147.             *actptr++ = T_REGEXP;
  148.             ungetcharacter( c );
  149.             actptr += re_compile( actptr );
  150.         }
  151.  
  152.         /*
  153.          * symbol, string or constant:
  154.          */
  155.         else if ( alpha( c ) )
  156.         {
  157.             /*
  158.              * It's a symbol reference. Copy the symbol into
  159.              * string buffer.
  160.              */
  161.             cp = buf;
  162.             do
  163.                 *cp++ = c;
  164.             while ( (c=getcharacter()) != -1 && alphanum( c ) );
  165.             ungetcharacter( c );
  166.             *cp = 0;
  167.             /*
  168.              * Check if a keyword, builtin function or variable.
  169.              */
  170.             if ( c = iskeyword( buf ) )
  171.                 *actptr++ = c;
  172.             else if ( i = isfunction( buf ) )
  173.             {
  174.                 *actptr++ = T_FUNCTION;
  175.                 *((int *)actptr)++ = i;
  176.             }
  177.             else
  178.             {
  179.                 /*
  180.                  * It's a symbol name.
  181.                  */
  182.                 *actptr++ = T_VARIABLE;
  183.                 if (!(cp = (char *)findvar(buf)))
  184.                     cp = (char *)addvar(buf);
  185.                 *((char **)actptr)++ = cp;
  186.             }
  187.         }
  188.  
  189.         else if ( c == '"' )
  190.         {
  191.             /*
  192.              * It's a string constant
  193.              */
  194.             *actptr++ = T_STRING;
  195.             actptr = str_compile( actptr, '"' );
  196.         }
  197.         else if ( c == '\'' )
  198.         {
  199.             /*
  200.              * It's a character constant
  201.              */
  202.             *actptr++ = T_CONSTANT;
  203.             str_compile( buf, '\'' );
  204.             *((int *)actptr)++ = *buf;
  205.         }
  206.  
  207.         else if (isdigit(c))
  208.         {
  209.             /*
  210.              * It's a numeric constant
  211.              */
  212.             *actptr++ = T_CONSTANT;
  213.             cp = buf;
  214.             do
  215.                 *cp++ = c;
  216.             while ((c=getcharacter()) != -1 && isdigit(c));
  217.             ungetcharacter( c );
  218.             *cp = 0;
  219.             *((int *)actptr)++ = atoi(buf);
  220.         }
  221.  
  222.         /*
  223.          * unary operator:
  224.          */
  225.         else if ( c == '$' )
  226.             *actptr++ = T_DOLLAR;
  227.  
  228.         /*
  229.          * or binary operator:
  230.          */
  231.         else if ( c == '=' )
  232.         {
  233.             if ( (c=getcharacter()) == '=' )
  234.                 *actptr++ = T_EQ;
  235.             else
  236.             {
  237.                 ungetcharacter( c );
  238.                 *actptr++ = T_ASSIGN;
  239.             }
  240.         }
  241.  
  242.         else if ( c == '!' )
  243.         {
  244.             if ( (c=getcharacter()) == '=' )
  245.                 *actptr++ = T_NE;
  246.             else
  247.             {
  248.                 ungetcharacter( c );
  249.                 *actptr++ = T_LNOT;
  250.             }
  251.         }
  252.  
  253.         else if ( c == '<' )
  254.         {
  255.             if ( (c=getcharacter()) == '<' )
  256.                 *actptr++ = T_SHL;
  257.             else if ( c == '=' )
  258.                 *actptr++ = T_LE;
  259.             else
  260.             {
  261.                 ungetcharacter( c );
  262.                 *actptr++ = T_LT;
  263.             }
  264.         }
  265.  
  266.         else if ( c == '>' )
  267.         {
  268.             if ( (c=getcharacter()) == '>' )
  269.                 *actptr++ = T_SHR;
  270.             else if ( c == '=' )
  271.                 *actptr++ = T_GE;
  272.             else
  273.             {
  274.                 ungetcharacter( c );
  275.                 *actptr++ = T_GT;
  276.             }
  277.         }
  278.  
  279.         else if ( c == '&' )
  280.         {
  281.             if ( (c=getcharacter()) == '&' )
  282.                 *actptr++ = T_LAND;
  283.             else
  284.             {
  285.                 ungetcharacter( c );
  286.                 *actptr++ = T_AND;
  287.             }
  288.         }
  289.  
  290.         else if ( c == '|' )
  291.         {
  292.             if ( (c=getcharacter()) == '|' )
  293.                 *actptr++ = T_LIOR;
  294.             else
  295.             {
  296.                 ungetcharacter( c );
  297.                 *actptr++ = T_IOR;
  298.             }
  299.         }
  300.         else if ( c == '+' )
  301.         {
  302.             if ( (c=getcharacter()) == '+' )
  303.                 *actptr++ = T_INCR;
  304.             else
  305.             {
  306.                 ungetcharacter( c );
  307.                 *actptr++ = T_ADD;
  308.             }
  309.         }
  310.  
  311.         else if ( c == '-' )
  312.         {
  313.             if ( (c=getcharacter()) == '-' )
  314.                 *actptr++ = T_DECR;
  315.             else
  316.             {
  317.                 ungetcharacter( c );
  318.                 *actptr++ = T_SUB;
  319.             }
  320.         }
  321.  
  322.         /*
  323.          * punctuation
  324.          */
  325.         else if ( instr( c, "[](),;*/%+-^~" ) )
  326.             *actptr++ = c;
  327.  
  328.         else
  329.         {
  330.             /*
  331.              * Bad character in input line
  332.              */
  333.             error( "lexical error", ACT_ERROR );
  334.         }
  335.  
  336.         if ( actptr >= Workbuf + MAXWORKBUFLEN )
  337.             error( "action too long", MEM_ERROR );
  338.     }
  339.     if ( braces || parens )
  340.         error( "mismatched '{}' or '()'", ACT_ERROR );
  341.  
  342.     *actptr++ = T_EOF;
  343.  
  344.     return actptr - actbuf;
  345. }
  346.  
  347. char *str_compile( str, delim )
  348. char *str, delim;
  349. {
  350.     /*
  351.      * Compile a string from current input file into the given string
  352.      * buffer.  Stop when input character is the delimiter in "delim".
  353.      * Returns a pointer to the first character after the string.
  354.      */
  355.     int c;
  356.     char buf[ MAXLINELEN ];
  357.  
  358.     while ( (c = getcharacter()) != -1 && c != delim)
  359.     {
  360.         if ( c    == '\\' )
  361.         {
  362.             switch ( c = getcharacter() )
  363.             {
  364.             case -1: goto err;
  365.             case 'b': c = '\b'; break;
  366.             case 'n': c = '\n'; break;
  367.             case 't': c = '\t'; break;
  368.             case 'f': c = '\f'; break;
  369.             case 'r': c = '\r'; break;
  370.             case '0':
  371.             case '1':
  372.             case '2':
  373.             case '3':
  374.                 *buf = c;
  375.                 for ( c=1; c<3; ++c )
  376.                 {
  377.                     if ( (buf[c]=getcharacter()) == -1 )
  378.                         goto err;
  379.                 }
  380.                 buf[c] = 0;
  381.                 sscanf( buf, "%o", &c );
  382.                 break;
  383.             case '\n':
  384.                 if ( getcharacter() == -1 )
  385.                     goto err;
  386.             default:
  387.                 if ( (c = getcharacter()) == -1 )
  388.                     goto err;
  389.             }
  390.         }
  391.         *str++ = c;
  392.     }
  393.     *str++ = 0;
  394.  
  395.     return str;
  396. err:
  397.     sprintf( buf, "missing %c delimiter", delim );
  398.     error( buf, 4 );
  399. }
  400.  
  401. int getoken()
  402. {
  403.     switch ( Token = *Actptr++ )
  404.     {
  405.     case T_STRING:
  406.     case T_REGEXP:
  407.         Value.dptr = Actptr;
  408.         Actptr += strlen( Actptr ) + 1;
  409.         break;
  410.     case T_VARIABLE:
  411.         Value.dptr = *((char **)Actptr)++;
  412.         break;
  413.     case T_FUNCTION:
  414.     case T_CONSTANT:
  415.         Value.ival = *((int *)Actptr)++;
  416.         break;
  417.     case T_EOF:
  418.         --Actptr;
  419.     default:
  420.         Value.dptr = 0;
  421.     }
  422.  
  423. #ifdef DEBUG
  424.     if ( Debug > 1 )
  425.         printf( "Token='%c' (0x%x), Value=%d\n",
  426.             Token,Token,Value.ival );
  427. #endif
  428.  
  429.     return Token;
  430. }
  431.