home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d0xx / d092 / bawk.lha / Bawk / bawkact.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-22  |  9.5 KB  |  528 lines

  1. /*
  2.  * Bawk C actions compiler
  3.  */
  4. #include <stdio.h>
  5. #include "bawk.h"
  6.  
  7. EXPR_NODE *act_compile( actbuf )
  8. register char    *actbuf;/* where tokenized actions are compiled into */
  9. {
  10.     DBUG_ENTER("act_compile");
  11.     Where = ACTION;
  12.     stmt_lex( actbuf );
  13.     Actptr = actbuf;
  14.     getoken();
  15.     DBUG_RETURN(stmt_parse());
  16. }
  17.  
  18. EXPR_NODE *pat_compile( actbuf )
  19. register char    *actbuf;/* where tokenized actions are compiled into */
  20. {
  21.     DBUG_ENTER("pat_compile");
  22.     Where = PATTERN;
  23.     stmt_lex( actbuf );
  24.     Actptr = actbuf;
  25.     getoken();
  26.     DBUG_RETURN(stmt_parse());
  27. }
  28.  
  29. void stmt_lex( actbuf )
  30. register char    *actbuf;/* where tokenized actions are compiled into */
  31. {
  32.     /*
  33.      * Read and tokenize C actions from current input file into the
  34.      * action buffer.  Strip out comments and whitespace in the
  35.      * process.
  36.      */
  37.     register char *actptr,    /* actbuf pointer */
  38.         *cp;        /* work pointer */
  39.     char    buf[MAXLINELEN+1];/* string buffer */
  40.     register int braces = 0,/* counts '{}' pairs - return when 0 */
  41.         parens = 0,    /* counts '()' pairs */
  42.         i,        /* temp */
  43.         c,        /* current input character */
  44.         finished = 0;
  45.  
  46.     DBUG_ENTER("stmt_lex");
  47.     actptr = actbuf;
  48.     while ( !finished && ((c = getcharacter()) != -1) )
  49.     {
  50.         switch(c) {
  51.         case ' ':
  52.         case '\t':
  53.         case '\n':
  54.             /*
  55.              * Skip over spaces, tabs and newlines
  56.              */
  57.             break;
  58.         case '#':
  59.             /*
  60.              * Skip comments.  Comments start with a '#' and
  61.              * end at the next newline.
  62.              */
  63.             while ( (c = getcharacter()) != -1 && c!='\n' )
  64.                 ;
  65.             break;
  66.         case '{':
  67.             if ( Where==PATTERN )
  68.             {
  69.                 /*
  70.                  * We're compiling a pattern. The '{' marks
  71.                  * the beginning of an action statement.
  72.                  * Push the character back and return.
  73.                  */
  74.                 ungetcharacter( (char) '{' );
  75.                 finished = 1;
  76.             }
  77.             else
  78.             {
  79.                 /*
  80.                  * We must be compiling an action statement.
  81.                  * '{'s mark beginning of action or compound
  82.                  * statements.
  83.                  */
  84.                 ++braces;
  85.                 *actptr++ = T_LBRACE;
  86.             }
  87.             break;
  88.         case '}':
  89.             *actptr++ = T_RBRACE;
  90.             finished = (! --braces );
  91.             break;
  92.         case '(':
  93.             ++parens;
  94.             *actptr++ = T_LPAREN;
  95.             break;
  96.         case ')':
  97.             if ( --parens < 0 )
  98.                 error( "mismatched '()'", ACT_ERROR );
  99.             *actptr++ = T_RPAREN;
  100.             break;
  101.         case ',':
  102.             if ( !braces && !parens )
  103.             {
  104.                 /*
  105.                  * found a comma outside of any braces or 
  106.                 * parens - this must be a regular
  107.                 * expression seperator.
  108.                 */
  109.                 ungetcharacter( (char) ',' );
  110.                 finished = 1;
  111.             } else
  112.                 *actptr++ = T_COMMA;
  113.             break;
  114.         case '/':
  115.             *actptr++ = T_DIV;
  116.             break;
  117.         case '@':
  118.             *actptr++ = T_REGEXP;
  119.             ungetcharacter( (char) c );
  120.             actptr += re_compile( actptr );
  121.             break;
  122.         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  123.         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
  124.         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
  125.         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
  126.         case 'y': case 'z':
  127.         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  128.         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
  129.         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
  130.         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
  131.         case 'Y': case 'Z':
  132.         case '_':
  133.             /*
  134.              * It's a symbol reference. Copy the symbol into
  135.              * string buffer.
  136.              */
  137.             cp = buf;
  138.             do
  139.                 *cp++ = c;
  140.             while ( (c=getcharacter()) != -1 &&
  141.                 (isalnum( c ) || (c == '_')));
  142.             ungetcharacter( (char) c );
  143.             *cp = 0;
  144.             /*
  145.              * Check if a keyword, builtin function or variable.
  146.              */
  147.             if ( c = iskeyword( buf ) )
  148.                 *actptr++ = c;
  149.             else if ( i = isfunction( buf ) )
  150.             {
  151.                 *actptr++ = T_FUNCTION;
  152.                 storeint( actptr, i );
  153.                 actptr += sizeof( i );
  154.             }
  155.             else
  156.             {
  157.                 /*
  158.                  * It's a symbol name.
  159.                  */
  160.                 *actptr++ = T_VARIABLE;
  161.                 if ( !(cp = (char *) findvar( buf )) )
  162.                     cp = (char *) addvar( buf );
  163.                 storeptr( actptr, cp );
  164.                 actptr += sizeof( cp );
  165.             }
  166.             break;
  167. #ifdef QUOTE_STRING_HACK
  168.         case '`':
  169. #endif
  170.         case '"':
  171.             /*
  172.              * It's a string constant
  173.              */
  174.             *actptr++ = T_STRING;
  175.             actptr = str_compile( actptr, c );
  176.             break;
  177.         case '\'':
  178.             /*
  179.              * It's a character constant
  180.              */
  181.             *actptr++ = T_CONSTANT;
  182.             str_compile( buf, (char) '\'' );
  183.             storeint( actptr, *buf );
  184.             actptr += sizeof( i );
  185.             break;
  186.         case '0': case '1': case '2': case '3': case '4': case '5':
  187.         case '6': case '7': case '8': case '9':
  188.             /*
  189.              * It's a numeric constant
  190.              */
  191.             *actptr++ = T_CONSTANT;
  192.             cp = buf;
  193.             do
  194.                 *cp++ = c;
  195.             while ( (c=getcharacter()) != -1 && isdigit(c) );
  196.             ungetcharacter( (char) c );
  197.             *cp = 0;
  198.             storeint( actptr, atoi( buf ) );
  199.             actptr += sizeof( i );
  200.             break;
  201.         case '$':
  202.             *actptr++ = T_DOLLAR;
  203.             break;
  204.         case '=':
  205.             if ( (c=getcharacter()) == '=' )
  206.                 *actptr++ = T_EQ;
  207.             else
  208.             {
  209.                 ungetcharacter( (char) c );
  210.                 *actptr++ = T_ASSIGN;
  211.             }
  212.             break;
  213.         case '!':
  214.             if ( (c=getcharacter()) == '=' )
  215.                 *actptr++ = T_NE;
  216.             else
  217.             {
  218.                 ungetcharacter( (char) c );
  219.                 *actptr++ = T_LNOT;
  220.             }
  221.             break;
  222.         case '<':
  223.             if ( (c=getcharacter()) == '<' )
  224.                 *actptr++ = T_SHL;
  225.             else if ( c == '=' )
  226.                 *actptr++ = T_LE;
  227.             else
  228.             {
  229.                 ungetcharacter( (char) c );
  230.                 *actptr++ = T_LT;
  231.             }
  232.             break;
  233.         case '>':
  234.             if ( (c=getcharacter()) == '>' )
  235.                 *actptr++ = T_SHR;
  236.             else if ( c == '=' )
  237.                 *actptr++ = T_GE;
  238.             else
  239.             {
  240.                 ungetcharacter( (char) c );
  241.                 *actptr++ = T_GT;
  242.             }
  243.             break;
  244.         case '&':
  245.             if ( (c=getcharacter()) == '&' )
  246.                 *actptr++ = T_LAND;
  247.             else
  248.             {
  249.                 ungetcharacter( (char) c );
  250.                 *actptr++ = T_AND;
  251.             }
  252.             break;
  253.         case '|':
  254.             if ( (c=getcharacter()) == '|' )
  255.                 *actptr++ = T_LOR;
  256.             else
  257.             {
  258.                 ungetcharacter( (char) c );
  259.                 *actptr++ = T_OR;
  260.             }
  261.             break;
  262.         case '+':
  263.             if ( (c=getcharacter()) == '+' )
  264.                 *actptr++ = T_INCR;
  265.             else
  266.             {
  267.                 ungetcharacter( (char) c );
  268.                 *actptr++ = T_ADD;
  269.             }
  270.             break;
  271.         case '-':
  272.             if ( (c=getcharacter()) == '-' )
  273.                 *actptr++ = T_DECR;
  274.             else
  275.             {
  276.                 ungetcharacter( (char) c );
  277.                 *actptr++ = T_SUB;
  278.             }
  279.             break;
  280.         case '[':
  281.             *actptr++ = T_LBRACKET;
  282.             break;
  283.         case ']':
  284.             *actptr++ = T_RBRACKET;
  285.             break;
  286.         case ';':
  287.             *actptr++ = T_SEMICOLON;
  288.             break;
  289.         case '*':
  290.             *actptr++ = T_MUL;
  291.             break;
  292.         case '%':
  293.             *actptr++ = T_MOD;
  294.             break;
  295.         case '^':
  296.             *actptr++ = T_XOR;
  297.             break;
  298.         case '~':
  299.             *actptr++ = T_NOT;
  300.             break;
  301.         default:
  302.             /*
  303.              * Bad character in input line
  304.              */
  305.             error( "lexical error", ACT_ERROR );
  306.         }
  307.         if ( actptr >= Workbuf + MAXWORKBUFLEN )
  308.         error( "action too long", MEM_ERROR );
  309.     }
  310.     if ( braces || parens )
  311.         error( "mismatched '{}' or '()'", ACT_ERROR );
  312.  
  313.     *actptr++ = T_EOF;
  314.  
  315.     DBUG_VOID_RETURN;
  316. }
  317.  
  318. char *
  319. str_compile( str, delim )
  320. register char *str, delim;
  321. {
  322.     /*
  323.      * Compile a string from current input file into the given string
  324.      * buffer.  Stop when input character is the delimiter in "delim".
  325.      * Returns a pointer to the first character after the string.
  326.      */
  327.     int tmpc;    /* can not be a register variable */
  328.     register int c;
  329.     register char buf[4];
  330.  
  331.     DBUG_ENTER("str_compile");
  332.     while ( (c = getcharacter()) != -1 && c != delim)
  333.     {
  334.         if ( c  == '\\' )
  335.         {
  336.             switch ( c = getcharacter() )
  337.             {
  338.             case -1: goto err;
  339.             case 'b': c = '\b'; break;
  340.             case 'n': c = '\n'; break;
  341.             case 't': c = '\t'; break;
  342.             case 'f': c = '\f'; break;
  343.             case 'r': c = '\r'; break;
  344.             case '0':
  345.             case '1':
  346.             case '2':
  347.             case '3':
  348.                 *buf = c;
  349.                 for ( c=1; c<3; c++ )
  350.                 {
  351.                     if ( (buf[c]=getcharacter()) == -1 )
  352.                         goto err;
  353.                 }
  354.                 buf[c] = 0;
  355.                 sscanf( buf, "%o", &tmpc );
  356.                 c = tmpc;
  357.                 break;
  358.             case '\n':
  359.                 if ( getcharacter() == -1 )
  360.                     goto err;
  361.             default:
  362.                 if ( (c = getcharacter()) == -1 )
  363.                     goto err;
  364.             }
  365.         }
  366.         *str++ = c;
  367.     }
  368.     *str++ = 0;
  369.  
  370.     DBUG_RETURN(str);
  371. err:
  372.     sprintf( buf, "missing %c delimiter", delim );
  373.     error( buf, 4 );
  374.     DBUG_RETURN(NULL);
  375. }
  376.  
  377. void storeint( ip, i )
  378. char *ip;
  379. int i;
  380. {
  381.     DBUG_ENTER("storeint");
  382.     movmem((char *) &i, ip, sizeof(i));
  383.     DBUG_VOID_RETURN;
  384. }
  385.  
  386. void storeptr( pp, p )
  387. char *pp, *p;
  388. {
  389.     DBUG_ENTER("storeptr");
  390.     movmem((char *) &p, pp, sizeof(p));
  391.     DBUG_VOID_RETURN;
  392. }
  393.  
  394. int fetchint( ip )
  395. register char *ip;
  396. {
  397.     int i;
  398.  
  399.     DBUG_ENTER("fetchint");
  400.     movmem(ip, (char *) &i, sizeof(i));
  401.     DBUG_RETURN(i);
  402. }
  403.  
  404. char *
  405. fetchptr( pp )
  406. register char *pp;
  407. {
  408.     char *p;
  409.  
  410.     DBUG_ENTER("fetchptr");
  411.     movmem(pp, (char *) &p, sizeof(p));
  412.     DBUG_RETURN(p);
  413. }
  414.  
  415. #ifndef DBUG_OFF
  416. char *token_name[] = {
  417. 0,
  418. "CHAR",
  419. "BOL",
  420. "EOL",
  421. "ANY",
  422. "CLASS",
  423. "NCLASS",
  424. "STAR",
  425. "PLUS",
  426. "MINUS",
  427. "ALPHA",
  428. "DIGIT",
  429. "NALPHA",
  430. "PUNCT",
  431. "RANGE",
  432. "ENDPAT",
  433. "T_STRING",
  434. "T_DOLLAR",
  435. "T_REGEXP",
  436. "T_REGEXP_ARG",
  437. "T_CONSTANT",
  438. "T_VARIABLE",
  439. "T_FUNCTION",
  440. "T_SEMICOLON",
  441. "T_EOF",
  442. "T_LBRACE",
  443. "T_RBRACE",
  444. "T_LPAREN",
  445. "T_RPAREN",
  446. "T_LBRACKET",
  447. "T_RBRACKET",
  448. "T_COMMA",
  449. "T_ASSIGN",
  450. "T_STAR",
  451. "T_MUL",
  452. "T_DIV",
  453. "T_MOD",
  454. "T_ADD",
  455. "T_UMINUS",
  456. "T_SUB",
  457. "T_SHL",
  458. "T_SHR",
  459. "T_LT",
  460. "T_LE",
  461. "T_GT",
  462. "T_GE",
  463. "T_EQ",
  464. "T_NE",
  465. "T_NOT",
  466. "T_ADDROF",
  467. "T_AND",
  468. "T_XOR",
  469. "T_OR",
  470. "T_LNOT",
  471. "T_LAND",
  472. "T_LOR",
  473. "T_INCR",
  474. "T_DECR",
  475. "T_POSTINCR",
  476. "T_POSTDECR",
  477. "T_IF",
  478. "T_ELSE",
  479. "T_WHILE",
  480. "T_BREAK",
  481. "T_CHAR",
  482. "T_INT",
  483. "T_BEGIN",
  484. "T_END",
  485. "T_NF",
  486. "T_NR",
  487. "T_FS",
  488. "T_RS",
  489. "T_FILENAME",
  490. "T_STATEMENT",
  491. "T_DECLARE",
  492. "T_ARRAY_DECLARE"
  493. };
  494. #endif
  495.  
  496. char getoken()
  497. {
  498.     register char *cp;
  499.     register int i;
  500.  
  501.     DBUG_ENTER("getoken");
  502.     switch ( Token = *Actptr++ )
  503.     {
  504.     case T_STRING:
  505.     case T_REGEXP:
  506.         Value.dptr = Actptr;
  507.         Actptr += strlen( Actptr ) + 1;
  508.         break;
  509.     case T_VARIABLE:
  510.         Value.dptr = fetchptr( Actptr );
  511.         Actptr += sizeof( cp );
  512.         break;
  513.     case T_FUNCTION:
  514.     case T_CONSTANT:
  515.         Value.ival = fetchint( Actptr );
  516.         Actptr += sizeof( i );
  517.         break;
  518.     case T_EOF:
  519.         --Actptr;
  520.     default:
  521.         Value.dptr = 0;
  522.     }
  523.  
  524.     DBUG_PRINT("getoken",
  525.        ("Token='%s' (%d), Value=%d",token_name[Token],Token,Value.ival));
  526.     DBUG_RETURN(Token);
  527. }
  528.