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

  1. /*
  2.  * Bawk C actions builtin functions, variable declaration, and
  3.  * stack management routines.
  4.  */
  5. #include <stdio.h>
  6. #include "bawk.h"
  7.  
  8. #define MAXARGS        10    /* max # of arguments to a builtin func */
  9. #define F_PRINTF    1
  10. #define F_GETLINE    2
  11. #define F_STRLEN    3
  12. #define F_STRCPY    4
  13. #define F_STRCMP    5
  14. #define F_TOUPPER    6
  15. #define F_TOLOWER    7
  16. #define F_MATCH        8
  17. #define F_NEXTFILE    9
  18.  
  19. int isfunction( s )
  20. register char *s;
  21. {
  22.     /*
  23.      * Compare the string "s" to a list of builtin functions
  24.      * and return its (non-zero) token number.
  25.      * Return zero if "s" is not a function.
  26.      */
  27.     DBUG_ENTER("isfunction");
  28.     switch(*s) {
  29.         case 'g':
  30.         if ( !strcmp( s, "getline" ) )
  31.             DBUG_RETURN(F_GETLINE);
  32.         break;
  33.         case 'm':
  34.         if ( !strcmp( s, "match" ) )
  35.             DBUG_RETURN(F_MATCH);
  36.         break;
  37.         case 'n':
  38.         if ( !strcmp( s, "nextfile" ) )
  39.             DBUG_RETURN(F_NEXTFILE);
  40.         break;
  41.         case 'p':
  42.         if ( !strcmp( s, "printf" ) )
  43.             DBUG_RETURN(F_PRINTF);
  44.         break;
  45.         case 's':
  46.         if ( !strcmp( s, "strlen" ) )
  47.             DBUG_RETURN(F_STRLEN);
  48.         if ( !strcmp( s, "strcpy" ) )
  49.             DBUG_RETURN(F_STRCPY);
  50.         if ( !strcmp( s, "strcmp" ) )
  51.             DBUG_RETURN(F_STRCMP);
  52.         break;
  53.         case 't':
  54.         if ( !strcmp( s, "toupper" ) )
  55.             DBUG_RETURN(F_TOUPPER);
  56.         if ( !strcmp( s, "tolower" ) )
  57.             DBUG_RETURN(F_TOLOWER);
  58.         break;
  59.         default:;
  60.     }
  61.     DBUG_RETURN(0);
  62. }
  63.  
  64. int iskeyword( s )
  65. register char *s;
  66. {
  67.     /*
  68.      * Compare the string "s" to a list of keywords and return its
  69.      * (non-zero) token number.  Return zero if "s" is not a keyword.
  70.      */
  71.     DBUG_ENTER("iskeyword");
  72.     switch(*s) {
  73.         case 'b':
  74.         if ( !strcmp( s, "break" ) )
  75.             DBUG_RETURN(T_BREAK);
  76.         break;
  77.         case 'c':
  78.         if ( !strcmp( s, "char" ) )
  79.             DBUG_RETURN(T_CHAR);
  80.         break;
  81.         case 'e':
  82.         if ( !strcmp( s, "else" ) )
  83.             DBUG_RETURN(T_ELSE);
  84.         break;
  85.         case 'i':
  86.         if ( !strcmp( s, "int" ) )
  87.             DBUG_RETURN(T_INT);
  88.         if ( !strcmp( s, "if" ) )
  89.             DBUG_RETURN(T_IF);
  90.         break;
  91.         case 'w':
  92.         if ( !strcmp( s, "while" ) )
  93.             DBUG_RETURN(T_WHILE);
  94.         break;
  95.         case 'B':
  96.         if ( !strcmp( s, "BEGIN" ) )
  97.             DBUG_RETURN(T_BEGIN);
  98.         break;
  99.         case 'E':
  100.         if ( !strcmp( s, "END" ) )
  101.             DBUG_RETURN(T_END);
  102.         break;
  103.         case 'F':
  104.         if ( !strcmp( s, "FS" ) )
  105.             DBUG_RETURN(T_FS);
  106.         if ( !strcmp( s, "FILENAME" ) )
  107.             DBUG_RETURN(T_FILENAME);
  108.         break;
  109.         case 'N':
  110.         if ( !strcmp( s, "NF" ) )
  111.             DBUG_RETURN(T_NF);
  112.         if ( !strcmp( s, "NR" ) )
  113.             DBUG_RETURN(T_NR);
  114.         break;
  115.         case 'R':
  116.         if ( !strcmp( s, "RS" ) )
  117.             DBUG_RETURN(T_RS);
  118.         break;
  119.         default:;
  120.     }
  121.     DBUG_RETURN(0);
  122. }
  123.  
  124. void function( funcnum, arg_root )
  125. register int funcnum;
  126. register EXPR_NODE *arg_root;
  127. {
  128.     register int argc, args[ MAXARGS ];
  129.  
  130.     DBUG_ENTER("function");
  131.     argc = 0;
  132.     /*
  133.      * If there are any arguments, evaluate them and copy their values
  134.      * to a local array.
  135.      */
  136.     for(; argc < MAXARGS && arg_root; arg_root = arg_root->right)
  137.     {
  138.         walk_tree(arg_root->left);
  139.         args[ argc++ ] = popint();
  140.     }
  141.     switch ( funcnum )
  142.     {
  143.     case F_PRINTF:    /* just like the real printf() function */
  144.         pushint( printf( (char *) args[0], args[1], args[2], args[3],
  145.              args[4], args[5], args[6], args[7], args[8],
  146.              args[9] ) );
  147.         break;
  148.     case F_GETLINE:
  149.         /*
  150.          * Get the next line of input from the current input file
  151.          * and parse according to the current field seperator.
  152.          * Don't forget to free up the previous line's words first...
  153.          */
  154.         while ( Fieldcount )
  155.             free( Fields[ --Fieldcount ] );
  156.         pushint( getline() );
  157.         Fieldcount = parse( Linebuf, Fields, Fieldsep );
  158.         break;
  159.     case F_STRLEN:    /* calculate length of string argument */
  160.         pushint( strlen( args[0] ) );
  161.         break;
  162.     case F_STRCPY:    /* copy second string argument to first string */
  163.         pushint( strcpy( args[0], args[1] ) );
  164.         break;
  165.     case F_STRCMP:    /* compare two strings */
  166.         pushint( strcmp( args[0], args[1] ) );
  167.         break;
  168.     case F_TOUPPER:    /* convert the character argument to upper case */
  169.         pushint( toupper( args[0] ) );
  170.         break;
  171.     case F_TOLOWER:    /* convert the character argument to lower case */
  172.         pushint( tolower( args[0] ) );
  173.         break;
  174.     case F_MATCH:    /* match a string argument to a regular expression */
  175.         pushint( match( (char *) args[0], (char *) args[1] ) );
  176.         break;
  177.     case F_NEXTFILE:/* close current input file and process next file */
  178.         endfile();
  179.         pushint( 1 ); /* is this a correct value? jw */
  180.         break;
  181.     default:    /* oops! */
  182.         error( "bad function call", ACT_ERROR );
  183.     }
  184.     DBUG_VOID_RETURN;
  185. }
  186.  
  187. VARIABLE *
  188. findvar( s )
  189. register char *s;
  190. {
  191.     /*
  192.      * Search the symbol table for a variable whose name is "s".
  193.      */
  194.     register VARIABLE *pvar;
  195.     register int i;
  196.     register char name[ MAXVARLEN ];
  197.  
  198.     DBUG_ENTER("findvar");
  199.     i = 0;
  200.     while ( i < MAXVARLEN && (isalnum( *s ) || (*s == '_')))
  201.         name[i++] = *s++;
  202.     if ( i<MAXVARLEN )
  203.         name[i] = 0;
  204.  
  205.     for ( pvar = Vartab; pvar<Nextvar; ++pvar )
  206.     {
  207.         if ( !strncmp( pvar->vname, name, MAXVARLEN ) )
  208.             DBUG_RETURN(pvar);
  209.     }
  210.     DBUG_RETURN(NULL);
  211. }
  212.  
  213. VARIABLE *
  214. addvar( name )
  215. register char *name;
  216. {
  217.     /*
  218.      * Add a new variable to symbol table and assign it default
  219.      * attributes (int name;)
  220.      */
  221.     register int i;
  222.  
  223.     DBUG_ENTER("addvar");
  224.     if ( Nextvar <= Vartab + MAXVARTABSZ )
  225.     {
  226.         i = 0;
  227.         while ( i<MAXVARLEN && (isalnum( *name ) || (*name == '_')))
  228.             Nextvar->vname[i++] = *name++;
  229.         if ( i<MAXVARLEN )
  230.             Nextvar->vname[i] = 0;
  231.  
  232.         Nextvar->vclass = 0;
  233.         Nextvar->vsize = WORD;
  234.         Nextvar->vlen = 0;
  235.         /*
  236.          * Allocate some new room
  237.          */
  238.         Nextvar->vptr = get_clear_memory( WORD );
  239.     }
  240.     else
  241.         error( "symbol table overflow", MEM_ERROR );
  242.  
  243.     DBUG_RETURN(Nextvar++);
  244. }
  245.  
  246. EXPR_NODE *declist_parse()
  247. {
  248.     /*
  249.      * Parse a "char" or "int" statement.
  250.      */
  251.     register char type;
  252.     register EXPR_NODE *root, *end_pointer;
  253.  
  254.     DBUG_ENTER("declist_parse");
  255.     type = Token;
  256.     getoken();
  257.     root = end_pointer = decl_parse( type );
  258.     while ( Token==T_COMMA )
  259.     {
  260.         getoken();
  261.         end_pointer->right = decl_parse( type );
  262.         end_pointer = end_pointer->right;
  263.     }
  264.     if ( Token==T_SEMICOLON )
  265.         getoken();
  266.     DBUG_RETURN(root);
  267. }
  268.  
  269. EXPR_NODE *decl_parse( type )
  270. register int type;
  271. {
  272.     /*
  273.      * Parse an element of a "char" or "int" declaration list.
  274.      * The function stmt_compile() has already entered the variable
  275.      * into the symbol table as an integer, this routine simply changes
  276.      * the symbol's class, size or length according to the declaraction.
  277.      * WARNING: The interpreter depends on the fact that pointers are
  278.      * the same length as int's.  If your machine uses long's for
  279.      * pointers either change the code or #define int long (or whatever).
  280.      */
  281.     register char class, size;
  282.     register VARIABLE *pvar;
  283.     register VARDECL *pdecl;
  284.     register EXPR_NODE *node;
  285.     EXPR_NODE *action;
  286.  
  287.     DBUG_ENTER("decl_parse");
  288.     if ( Token==T_MUL )
  289.     {
  290.         /*
  291.          * it's a pointer
  292.          */
  293.         getoken();
  294.         node = decl_parse( type );
  295.         if(node->operator == T_DECLARE)
  296.             ((VARDECL *) (node->right))->vclass += 1;
  297.         else
  298.             ((VARDECL *) (node->right->right))->vclass += 1;
  299.     }
  300.     else if ( Token==T_VARIABLE )
  301.     {
  302.         /*
  303.          * Simple variable so far.  The token value (in the global
  304.          * "Value" variable) is a pointer to the variable's symbol
  305.          * table entry.
  306.          */
  307.         pdecl = (VARDECL *) getmemory(sizeof(VARDECL));
  308.         pvar = (VARIABLE *) Value.dptr;
  309.         getoken();
  310.         class = 0;
  311.         /*
  312.          * Compute its length
  313.          */
  314.         if ( Token==T_LBRACKET )
  315.         {
  316.             /*
  317.              * It's an array.
  318.              */
  319.             node = get_expr_node((char) T_ARRAY_DECLARE);
  320.             node->left = action =
  321.                 get_expr_node((char) T_ARRAY_DECLARE);
  322.             action->left = (EXPR_NODE *) pdecl;
  323.             getoken();
  324.             ++class;
  325.             /*
  326.              * Parse the dimension expression
  327.              */
  328.             action->right = expr_parse();
  329.             if ( Token!=T_RBRACKET )
  330.                 error( "missing ']'", ACT_ERROR );
  331.             getoken();
  332.         }
  333.         else
  334.         {
  335.             /*
  336.              * It's a simple variable.
  337.              */
  338.             node = get_expr_node((char) T_DECLARE);
  339.             node->left = (EXPR_NODE *) pdecl;
  340.         }
  341.         size = (type==T_CHAR) ? BYTE : WORD;
  342.         pdecl->variable = pvar;
  343.         pdecl->vclass = class;
  344.         pdecl->vsize = size;
  345.     }
  346.     else
  347.         syntaxerror();
  348.  
  349.     DBUG_RETURN(node);
  350. }
  351.  
  352. void assignment()
  353. {
  354.     /*
  355.      * Perform an assignment
  356.      */
  357.     int ival;
  358.  
  359.     DBUG_ENTER("assignment");
  360.     ival = popint();
  361.     /*
  362.      * make sure we've got an lvalue
  363.      */
  364.     if ( Stackptr->lvalue )
  365.     {
  366.         if ( Stackptr->class )
  367.             movmem((char *) &ival, Stackptr->value.dptr, WORD );
  368.         else
  369.             movmem((char *) &ival, Stackptr->value.dptr,
  370.                    Stackptr->size);
  371.         pop();
  372.         pushint( ival );
  373.     }
  374.     else
  375.         error( "'=' needs an lvalue", ACT_ERROR );
  376.     DBUG_VOID_RETURN;
  377. }
  378.  
  379. int pop()
  380. {
  381.     /*
  382.      * Pop the stack and return the integer value
  383.      */
  384.     DBUG_ENTER("pop");
  385.     if ( Stackptr >= Stackbtm )
  386.         DBUG_RETURN((Stackptr--)->value.ival);
  387.     DBUG_RETURN(error( "stack underflow", ACT_ERROR ));
  388. }
  389.  
  390. void push( pclass, plvalue, psize, pdatum )
  391. register char pclass, plvalue, psize;
  392. register DATUM *pdatum;
  393. {
  394.     /*
  395.      * Push item parts onto the stack
  396.      */
  397.     DBUG_ENTER("push");
  398.     if ( ++Stackptr <= Stacktop )
  399.     {
  400.         Stackptr->lvalue = plvalue;
  401.         Stackptr->size = psize;
  402.         if ( !(Stackptr->class = pclass)  &&  !plvalue )
  403.             Stackptr->value.ival = pdatum->ival;
  404.         else
  405.             Stackptr->value.dptr = pdatum->dptr;
  406.     }
  407.     else
  408.         error( "stack overflow", MEM_ERROR );
  409.     DBUG_VOID_RETURN;
  410. }
  411.  
  412. void pushint( intvalue )
  413. register int intvalue;
  414. {
  415.     /*
  416.      * push an integer onto the stack
  417.      */
  418.     DBUG_ENTER("pushint");
  419.     if ( ++Stackptr <= Stacktop )
  420.     {
  421.         Stackptr->lvalue =
  422.         Stackptr->class = 0;
  423.         Stackptr->size = WORD;
  424.         Stackptr->value.ival = intvalue;
  425.     }
  426.     else
  427.         error( "stack overflow", MEM_ERROR );
  428.     DBUG_VOID_RETURN;
  429. }
  430.  
  431. int popint()
  432. {
  433.     /*
  434.      * Resolve the item on the top of the stack and return it
  435.      */
  436.     register int intvalue;
  437.  
  438.     DBUG_ENTER("popint");
  439.     if ( Stackptr->lvalue )
  440.     {
  441.         /*
  442.          * if it's a byte indirect, sign extend it
  443.          */
  444.         if ( Stackptr->size == BYTE && !Stackptr->class )
  445.             intvalue = *Stackptr->value.dptr;
  446.         else
  447.         {
  448.             /*
  449.              * otherwise, it's an unsigned int
  450.              */
  451.             intvalue = (int) (*Stackptr->value.ptrptr);
  452.         }
  453.         pop();
  454.         DBUG_RETURN(intvalue);
  455.     }
  456.     else
  457.     {
  458.         /*
  459.          * else it's an ACTUAL, just pop it
  460.          */
  461.         DBUG_RETURN(pop());
  462.     }
  463. }
  464.  
  465.