Category : C Source Code
Archive   : CUG236A.ZIP
Filename : BAWKSYM.C

 
Output of file : BAWKSYM.C contained in archive : CUG236A.ZIP

/*
HEADER: CUG236;
TITLE: BAWK Support Module;
DATE: 05/17/1987;
VERSION: 1.1;
FILENAME: BAWKSYM.C;
SEE-ALSO: BAWK.C;
AUTHORS: W. C. Colley III, B. Brodt;
*/

/*
* Bawk C actions builtin functions, variable declaration, and
* stack management routines.
*/
#include
#include "bawk.h"

#define MAXARGS 10 /* max # of arguments to a builtin func */
#define F_PRINTF 1
#define F_GETLINE 2
#define F_STRLEN 3
#define F_STRCPY 4
#define F_STRCMP 5
#define F_TOUPPER 6
#define F_TOLOWER 7
#define F_MATCH 8
#define F_NEXTFILE 9

/* Functions that are local to this module. */

VARIABLE *decl();

int isfunction( s )
char *s;
{
/*
* Compare the string "s" to a list of builtin functions
* and return its (non-zero) token number.
* Return zero if "s" is not a function.
*/
if ( !strcmp( s, "printf" ) )
return F_PRINTF;
if ( !strcmp( s, "getline" ) )
return F_GETLINE;
if ( !strcmp( s, "strlen" ) )
return F_STRLEN;
if ( !strcmp( s, "strcpy" ) )
return F_STRCPY;
if ( !strcmp( s, "strcmp" ) )
return F_STRCMP;
if ( !strcmp( s, "toupper" ) )
return F_TOUPPER;
if ( !strcmp( s, "tolower" ) )
return F_TOLOWER;
if ( !strcmp( s, "match" ) )
return F_MATCH;
if ( !strcmp( s, "nextfile" ) )
return F_NEXTFILE;
return 0;
}

int iskeyword( s )
char *s;
{
/*
* Compare the string "s" to a list of keywords and return its
* (non-zero) token number. Return zero if "s" is not a keyword.
*/
if ( !strcmp( s, "char" ) )
return T_CHAR;
if ( !strcmp( s, "int" ) )
return T_INT;
if ( !strcmp( s, "if" ) )
return T_IF;
if ( !strcmp( s, "else" ) )
return T_ELSE;
if ( !strcmp( s, "while" ) )
return T_WHILE;
if ( !strcmp( s, "break" ) )
return T_BREAK;

if ( !strcmp( s, "NF" ) )
return T_NF;
if ( !strcmp( s, "NR" ) )
return T_NR;
if ( !strcmp( s, "FS" ) )
return T_FS;
if ( !strcmp( s, "RS" ) )
return T_RS;
if ( !strcmp( s, "FILENAME" ) )
return T_FILENAME;
if ( !strcmp( s, "BEGIN" ) )
return T_BEGIN;
if ( !strcmp( s, "END" ) )
return T_END;
return 0;
}

void function(funcnum)
int funcnum;
{
int argc;
char lpar;
DATUM args[MAXARGS];

argc = 0;
if (Token == T_LPAREN) {
lpar = 1; getoken();
}
else lpar = 0;
/*
* If there are any arguments, evaluate them and copy their values
* to a local array.
*/
if (Token != T_RPAREN && Token != T_EOF) {
for (;;) {
expression();
if (argc < MAXARGS) args[argc++].ival = popint();
else popint();
if (Token == T_COMMA) getoken();
else break;
}
}
if (lpar && Token != T_RPAREN) error( "missing ')'", ACT_ERROR );
else if (Token == T_RPAREN) getoken();

switch (funcnum) {
case F_PRINTF: /* just like the real printf() function */
pushint(printf(args[0].dptr,args[1].ival,args[2].ival,
args[3].ival,args[4].ival,args[5].ival, args[6].ival,
args[7].ival,args[8].ival,args[9].ival));
break;
case F_GETLINE:
/*
* Get the next line of input from the current input file
* and parse according to the current field seperator.
* Don't forget to free up the previous line's words first...
*/
while (Fieldcount) free(Fields[--Fieldcount]);
pushint(getline());
Fieldcount = parse(Linebuf,Fields,Fldsep);
break;
case F_STRLEN: /* calculate length of string argument */
pushint(strlen(args[0].dptr));
break;
case F_STRCPY: /* copy second string to first string */
pushint((int)strcpy(args[0].dptr,args[1].dptr));
break;
case F_STRCMP: /* compare two strings */
pushint(strcmp(args[0].dptr,args[1].dptr));
break;
case F_TOUPPER: /* convert character argument to upper case */
pushint(toupper(args[0].ival));
break;
case F_TOLOWER: /* convert character argument to lower case */
pushint(tolower(args[0].ival));
break;
case F_MATCH: /* match string argument to regular expr. */
pushint(match(args[0].dptr,args[1].dptr));
break;
case F_NEXTFILE:/* close current input file, process next */
endfile(); pushint(0);
break;
default: /* oops! */
error("bad function call",ACT_ERROR);
}
}

VARIABLE *findvar( s )
char *s;
{
/*
* Search the symbol table for a variable whose name is "s".
*/
VARIABLE *pvar;
int i;
char name[ MAXVARLEN ];

i = 0;
while ( i < MAXVARLEN && alphanum( *s ) )
name[i++] = *s++;
if ( i name[i] = 0;

for ( pvar = Vartab; pvar {
if ( !strncmp( pvar->vname, name, MAXVARLEN ) )
return pvar;
}
return NULL;
}

VARIABLE *addvar( name )
char *name;
{
/*
* Add a new variable to symbol table and assign it default
* attributes (int name;)
*/
int i;

if ( Nextvar <= Vartab + MAXVARTABSZ )
{
i = 0;
while ( i Nextvar->vname[i++] = *name++;
if ( i Nextvar->vname[i] = 0;

Nextvar->vclass = 0;
Nextvar->vsize = WORD;
Nextvar->vlen = 0;
/*
* Allocate some new room
*/
Nextvar->vptr = getmem( WORD );
fillmem( Nextvar->vptr, WORD, 0 );
}
else
error( "symbol table overflow", MEM_ERROR );

return Nextvar++;
}

void declist()
{
/*
* Parse a "char" or "int" statement.
*/
char type;

type = Token;
getoken();
decl( type );
while ( Token==T_COMMA )
{
getoken();
decl( type );
}
if ( Token==T_SEMICOLON )
getoken();
}

VARIABLE *decl( type )
int type;
{
/*
* Parse an element of a "char" or "int" declaration list.
* The function stmt_compile() has already entered the variable
* into the symbol table as an integer, this routine simply changes
* the symbol's class, size or length according to the declaraction.
* WARNING: The interpreter depends on the fact that pointers are
* the same length as int's. If your machine uses long's for
* pointers either change the code or #define int long (or whatever).
*/
char class, size;
int len;
unsigned oldsize, newsize;
VARIABLE *pvar;

if ( Token==T_MUL )
{
/*
* it's a pointer
*/
getoken();
pvar = decl( type );
++pvar->vclass;
}
else if ( Token==T_VARIABLE )
{
/*
* Simple variable so far. The token value (in the global
* "Value" variable) is a pointer to the variable's symbol
* table entry.
*/
pvar = (VARIABLE *)Value.dptr;
getoken();
class = 0;
/*
* Compute its length
*/
if ( Token==T_LBRACKET )
{
/*
* It's an array.
*/
getoken();
++class;
/*
* Compute the dimension
*/
expression();
if ( Token!=T_RBRACKET )
error( "missing ']'", ACT_ERROR );
getoken();
len = popint();
}
else
/*
* It's a simple variable - array length is zero.
*/
len = 0;

size = (type==T_CHAR) ? BYTE : WORD;

newsize = (len ? len : 1) * size;
oldsize = (pvar->vlen ? pvar->vlen : 1) * pvar->vsize;
if ( newsize != oldsize )
{
/*
* The amount of storage needed for the variable
* has changed - free up memory allocated initially
* and reallocate for new size.
*/
free( pvar->vptr );
pvar->vptr = getmem( newsize );
}
/*
* Now change the variable's attributes.
*/
pvar->vclass = class;
pvar->vsize = size;
pvar->vlen = len;
}
else
syntaxerror();

return pvar;
}

void assignment()
{
/*
* Perform an assignment
*/
int ival;

ival = popint();
/*
* make sure we've got an lvalue
*/
if ( Stackptr->lvalue )
{
if ( Stackptr->class )
movemem( &ival, Stackptr->value.dptr, WORD );
else
movemem(&ival, Stackptr->value.dptr, Stackptr->size);
pop();
pushint( ival );
}
else
error( "'=' needs an lvalue", ACT_ERROR );
}

int pop()
{
/*
* Pop the stack and return the integer value
*/
if ( Stackptr >= Stackbtm )
return (Stackptr--)->value.ival;
error( "stack underflow", ACT_ERROR );
return 0;
}

void push( pclass, plvalue, psize, pdatum )
char pclass, plvalue, psize;
DATUM *pdatum;
{
/*
* Push item parts onto the stack
*/
if ( ++Stackptr <= Stacktop )
{
Stackptr->lvalue = plvalue;
Stackptr->size = psize;
if ( !(Stackptr->class = pclass) && !plvalue )
Stackptr->value.ival = pdatum->ival;
else
Stackptr->value.dptr = pdatum->dptr;
}
else
error( "stack overflow", MEM_ERROR );
}

void pushint( intvalue )
int intvalue;
{
/*
* push an integer onto the stack
*/
if ( ++Stackptr <= Stacktop )
{
Stackptr->lvalue =
Stackptr->class = 0;
Stackptr->size = WORD;
Stackptr->value.ival = intvalue;
}
else
error( "stack overflow", MEM_ERROR );
}

int popint()
{
/*
* Resolve the item on the top of the stack and return it
*/
int intvalue;

if ( Stackptr->lvalue )
{
/*
* if it's a byte indirect, sign extend it
*/
if ( Stackptr->size == BYTE && !Stackptr->class )
intvalue = *Stackptr->value.dptr;
else
{
/*
* otherwise, it's an unsigned int
*/
intvalue = *(int *)Stackptr->value.dptr;
}
pop();
return intvalue;
}
else
{
/*
* else it's an ACTUAL, just pop it
*/
return pop();
}
}