Category : BASIC Source Code
Archive   : BWB110S.ZIP
Filename : BWB_ELX.C

 
Output of file : BWB_ELX.C contained in archive : BWB110S.ZIP
/****************************************************************

bwb_elx.c Parse Elements of Expressions
for Bywater BASIC Interpreter

Copyright (c) 1992, Ted A. Campbell

Bywater Software
P. O. Box 4023
Duke Station
Durham, NC 27706

email: [email protected]

Copyright and Permissions Information:

All U.S. and international copyrights are claimed by the
author. The author grants permission to use this code
and software based on it under the following conditions:
(a) in general, the code and software based upon it may be
used by individuals and by non-profit organizations; (b) it
may also be utilized by governmental agencies in any country,
with the exception of military agencies; (c) the code and/or
software based upon it may not be sold for a profit without
an explicit and specific permission from the author, except
that a minimal fee may be charged for media on which it is
copied, and for copying and handling; (d) the code must be
distributed in the form in which it has been released by the
author; and (e) the code and software based upon it may not
be used for illegal activities.

****************************************************************/

#include
#include
#include
#include
#include

#include "bwbasic.h"
#include "bwb_mes.h"

/***************************************************************

FUNCTION: exp_paren()

DESCRIPTION: This function interprets a parenthetical
expression, calling bwb_exp() (recursively) to resolve
the internal expression.

***************************************************************/

int
exp_paren( char *expression )
{
struct exp_ese *e;
register int c;
int s_pos; /* position in build buffer */
int loop;
int paren_level;

/* find a string enclosed by parentheses */

exp_es[ exp_esc ].pos_adv = 1; /* start beyond open paren */
s_pos = 0;
loop = TRUE;
paren_level = 1;
exp_es[ exp_esc ].string[ 0 ] = '\0';

while( loop == TRUE )
{

/* check the current character */

switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{

case '(':
++paren_level;
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
break;

case ')':

--paren_level;
if ( paren_level == 0 )
{
loop = FALSE;
}
else
{
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
}
break;

case '\"': /* embedded string constant */
++exp_es[ exp_esc ].pos_adv;
while ( ( expression[ exp_es[ exp_esc ].pos_adv ] != '\"' )
&& ( expression[ exp_es[ exp_esc ].pos_adv ] != '\0' ) )
{
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
++exp_es[ exp_esc ].pos_adv;
}
break;

default:
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
break;
}

/* advance the counter */

++exp_es[ exp_esc ].pos_adv;

}

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_paren() found internal string <%s>",
exp_es[ exp_esc ].string );
bwb_debug( bwb_ebuf );
#endif

/* call bwb_exp() recursively to interpret this expression */

exp_es[ exp_esc ].rec_pos = 0;
e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
&( exp_es[ exp_esc ].rec_pos ) );

/* assign operation and value at this level */

exp_es[ exp_esc ].type = e->type;

switch ( e->type )
{
case STRING:
exp_es[ exp_esc ].operation = CONST_STRING;
str_btob( exp_getsval( &( exp_es[ exp_esc ] )), exp_getsval( e ) );
break;
case INTEGER:
exp_es[ exp_esc ].operation = NUMBER;
exp_es[ exp_esc ].ival = exp_getival( e );
break;
case DOUBLE:
exp_es[ exp_esc ].operation = NUMBER;
exp_es[ exp_esc ].dval = exp_getdval( e );
break;
default:
exp_es[ exp_esc ].operation = NUMBER;
exp_es[ exp_esc ].fval = exp_getfval( e );
break;
}

return TRUE;

}

/***************************************************************

FUNCTION: exp_strconst()

DESCRIPTION: This function interprets a string
constant.

***************************************************************/

int
exp_strconst( char *expression )
{
int e_pos, s_pos;

/* assign values to structure */

exp_es[ exp_esc ].type = STRING;
exp_es[ exp_esc ].operation = CONST_STRING;

/* set counters */

s_pos = 0;
exp_es[ exp_esc ].pos_adv = e_pos = 1;
exp_es[ exp_esc ].string[ 0 ] = '\0';

/* read the string up until the next double quotation mark */

while( expression[ e_pos ] != '\"' )
{
exp_es[ exp_esc ].string[ s_pos ] = expression[ e_pos ];
++e_pos;
++s_pos;
++exp_es[ exp_esc ].pos_adv;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
if ( s_pos >= ( MAXSTRINGSIZE - 1 ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
expression, MAXSTRINGSIZE );
bwb_error( bwb_ebuf );
#else
bwb_error( err_overflow );
#endif
return OP_NULL;
}
}

/* now write string over to bstring */

str_ctob( &( exp_es[ exp_esc ].sval ), exp_es[ exp_esc ].string );

/* advance past last double quotation mark */

++exp_es[ exp_esc ].pos_adv;

/* return */

return TRUE;

}

/***************************************************************

FUNCTION: exp_numconst()

DESCRIPTION: This function interprets a numerical
constant.

***************************************************************/

int
exp_numconst( char *expression )
{
int base; /* numerical base for the constant */
static struct bwb_variable mantissa; /* mantissa of floating-point number */
static int init = FALSE; /* is mantissa variable initialized? */
int exponent; /* exponent for floating point number */
int man_start; /* starting point of mantissa */
int s_pos; /* position in build string */
int build_loop;
int need_pm;
int i;
double d;
#if CHECK_RECURSION
static int in_use = FALSE; /* boolean: is function in use? */

/* check recursion status */

if ( in_use == TRUE )
{
sprintf( bwb_ebuf, "Recursion error in bwb_exp.c:exp_findop(): recursion violation." );
bwb_error( bwb_ebuf );
}

/* reset recursion status indicator */

else
{
in_use = TRUE;
}
#endif

/* initialize the variable if necessary */

#if INTENSIVE_DEBUG
strcpy( mantissa.name, "(mantissa)" );
#endif

if ( init == FALSE )
{
init = TRUE;
var_make( &mantissa, DOUBLE );
}

/* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
this is necessary because mantissa might be used before dim_base
is set */

mantissa.array_pos[ 0 ] = dim_base;

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_numconst(): received <%s>, eval <%c>",
expression, expression[ 0 ] );
bwb_debug( bwb_ebuf );
#endif

need_pm = FALSE;
exp_es[ exp_esc ].ival = 0;

/* check the first character(s) to determine numerical base
and starting point of the mantissa */

switch( expression[ 0 ] )
{
case '-':
case '+':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
base = 10; /* decimal constant */
man_start = 0; /* starts at position 0 */
need_pm = FALSE;
break;
case '&': /* hex or octal constant */
if ( ( expression[ 1 ] == 'H' ) || ( expression[ 1 ] == 'h' ))
{
base = 16; /* hexadecimal constant */
man_start = 2; /* starts at position 2 */
}
else
{
base = 8; /* octal constant */
if ( ( expression[ 1 ] == 'O' ) || ( expression[ 1 ] == 'o' ))
{
man_start = 2; /* starts at position 2 */
}
else
{
man_start = 1; /* starts at position 1 */
}
}
break;
default:

#if PROG_ERRORS
sprintf( bwb_ebuf, "expression <%s> is not a numerical constant.",
expression );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return OP_NULL;
}

/* now build the mantissa according to the numerical base */

switch( base )
{

case 10: /* decimal constant */

/* initialize counters */

exp_es[ exp_esc ].pos_adv = man_start;
exp_es[ exp_esc ].type = INTEGER;
exp_es[ exp_esc ].string[ 0 ] = '\0';
s_pos = 0;
exponent = OP_NULL;
build_loop = TRUE;

/* loop to build the string */

while ( build_loop == TRUE )
{
switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{
case '-': /* prefixed plus or minus */
case '+':

/* in the first position, a plus or minus sign can
be added to the beginning of the string to be
scanned */

if ( exp_es[ exp_esc ].pos_adv == man_start )
{
exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
}

/* but in any other position, the plus or minus sign
must be taken as an operator and thus as terminating
the string to be scanned */

else
{
build_loop = FALSE;
}
break;
case '.': /* note at least single precision */
if ( exp_es[ exp_esc ].type == INTEGER )
{
exp_es[ exp_esc ].type = SINGLE;
} /* fall through (no break) */
case '0': /* or ordinary digit */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
break;

case 'E': /* exponential, single precision */
case 'e':
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
exp_es[ exp_esc ].type = SINGLE;
exponent = TRUE;
build_loop = FALSE;
break;


case 'D': /* exponential, double precision */
case 'd':
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
exp_es[ exp_esc ].type = DOUBLE;
exponent = TRUE;
build_loop = FALSE;
break;

case SINGLE: /* single precision termination */
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
exp_es[ exp_esc ].type = SINGLE;
build_loop = FALSE;
break;

case DOUBLE: /* double precision termination */
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
exp_es[ exp_esc ].type = DOUBLE;
build_loop = FALSE;
break;

case INTEGER: /* integer precision termination */
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
exp_es[ exp_esc ].type = INTEGER;
build_loop = FALSE;
break;

default: /* anything else, terminate */
build_loop = FALSE;
break;
}

}

/* assign the value to the mantissa variable */

sscanf( exp_es[ exp_esc ].string, "%lf",
var_finddval( &mantissa, mantissa.array_pos ));

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_numconst(): read mantissa, string <%s> val <%lf>",
exp_es[ exp_esc ].string, var_getdval( &mantissa ) );
bwb_debug( bwb_ebuf );
#endif

/* test if integer bounds have been exceeded */

if ( exp_es[ exp_esc ].type == INTEGER )
{
i = (int) var_getdval( &mantissa );
d = (double) i;
if ( d != var_getdval( &mantissa ))
{
exp_es[ exp_esc ].type = DOUBLE;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_numconst(): integer bounds violated, promote to DOUBLE" );
bwb_debug( bwb_ebuf );
#endif

}
}

/* read the exponent if there is one */

if ( exponent == TRUE )
{

/* allow a plus or minus once at the beginning */

need_pm = TRUE;

/* initialize counters */

exp_es[ exp_esc ].string[ 0 ] = '\0';
s_pos = 0;
build_loop = TRUE;

/* loop to build the string */

while ( build_loop == TRUE )
{
switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{
case '-': /* prefixed plus or minus */
case '+':

if ( need_pm == TRUE ) /* only allow once */
{
exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
}
else
{
build_loop = FALSE;
}
break;

case '0': /* or ordinary digit */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':

exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
need_pm = FALSE;
break;

default: /* anything else, terminate */
build_loop = FALSE;
break;
}

} /* end of build loop for exponent */

/* assign the value to the user variable */

sscanf( exp_es[ exp_esc ].string, "%d",
&( exp_es[ exp_esc ].ival ) );

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_numconst(): exponent is <%d>",
exp_es[ exp_esc ].ival );
bwb_debug( bwb_ebuf );
#endif

} /* end of exponent search */

if ( exp_es[ exp_esc ].ival == 0 )
{
exp_es[ exp_esc ].dval = var_getdval( &mantissa );
}
else
{
exp_es[ exp_esc ].dval = var_getdval( &mantissa )
* pow( (double) 10.0, (double) exp_es[ exp_esc ].ival );
}

exp_es[ exp_esc ].fval = (float) exp_es[ exp_esc ].dval;
exp_es[ exp_esc ].ival = (int) exp_es[ exp_esc ].dval;

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_numconst(): val double <%lf> single <%f> int <%d>",
exp_es[ exp_esc ].dval, exp_es[ exp_esc ].fval, exp_es[ exp_esc ].ival );
bwb_debug( bwb_ebuf );
#endif

break;

case 8: /* octal constant */

/* initialize counters */

exp_es[ exp_esc ].pos_adv = man_start;
exp_es[ exp_esc ].type = INTEGER;
exp_es[ exp_esc ].string[ 0 ] = '\0';
s_pos = 0;
exponent = OP_NULL;
build_loop = TRUE;

/* loop to build the string */

while ( build_loop == TRUE )
{
switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{
case '0': /* or ordinary digit */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
++exp_es[ exp_esc ].pos_adv; /* advance to next character */
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
break;

default: /* anything else, terminate */
build_loop = FALSE;
break;
}

}

/* now scan the string to determine the number */

sscanf( exp_es[ exp_esc ].string, "%o",
&( exp_es[ exp_esc ].ival ));

break;

case 16: /* hexadecimal constant */

/* initialize counters */

exp_es[ exp_esc ].pos_adv = man_start;
exp_es[ exp_esc ].type = INTEGER;
exp_es[ exp_esc ].string[ 0 ] = '\0';
s_pos = 0;
exponent = OP_NULL;
build_loop = TRUE;

/* loop to build the string */

while ( build_loop == TRUE )
{
switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{
case '0': /* or ordinary digit */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
case 'D':
case 'd':
case 'E':
case 'e':
exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];

++exp_es[ exp_esc ].pos_adv; /* advance to next character */
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
break;

default: /* anything else, terminate */
build_loop = FALSE;
break;
}

}

/* now scan the string to determine the number */

sscanf( exp_es[ exp_esc ].string, "%x",
&( exp_es[ exp_esc ].ival ));

break;
}

/* note that the operation at this level is now a determined NUMBER */

exp_es[ exp_esc ].operation = NUMBER;

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_numconst(): exit level <%d> precision <%c> value <%lf>",
exp_esc, exp_es[ exp_esc ].type, exp_getdval( &( exp_es[ exp_esc ] ) ) );
bwb_debug( bwb_ebuf );
#endif

#if CHECK_RECURSION
in_use = FALSE;
#endif

return TRUE;

}

/***************************************************************

FUNCTION: exp_function()

DESCRIPTION: This function interprets a function,
calling bwb_exp() (recursively) to resolve any
arguments to the function.

***************************************************************/

int
exp_function( char *expression )
{
struct exp_ese *e;
register int c;
int s_pos; /* position in build buffer */
int loop;
int paren_level;
int n_args;
struct bwb_variable *v;
struct bwb_variable argv[ MAX_FARGS ];
bstring *b;
#if INTENSIVE_DEBUG
char tbuf[ MAXSTRINGSIZE + 1 ];

sprintf( bwb_ebuf, "in exp_function(): entered function, expression <%s>",
expression );
bwb_debug( bwb_ebuf );
#endif

/* assign pointers to argument stack */

/* get the function name */

exp_getvfname( expression, exp_es[ exp_esc ].string );

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): name is <%s>.",
exp_es[ exp_esc ].string );
bwb_debug( bwb_ebuf );
#endif

/* now find the function itself */

exp_es[ exp_esc ].function = fnc_find( exp_es[ exp_esc ].string );

/* check to see if it is valid */

if ( exp_es[ exp_esc ].function == NULL )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Failed to find function <%s>.",
exp_es[ exp_esc ].string );
bwb_error( bwb_ebuf );
#else
bwb_error( err_uf );
#endif
return OP_ERROR;
}

/* note that this level is a function */

exp_es[ exp_esc ].operation = FUNCTION;
exp_es[ exp_esc ].pos_adv = strlen( exp_es[ exp_esc ].string );

/* check for begin parenthesis */

loop = TRUE;
while( loop == TRUE )
{
switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{

case ' ': /* whitespace */
case '\t':
++exp_es[ exp_esc ].pos_adv; /* advance */
break;

case '(': /* begin paren */

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): found begin parenthesis." );
bwb_debug( bwb_ebuf );
#endif

++exp_es[ exp_esc ].pos_adv; /* advance beyond it */
paren_level = 1; /* set paren_level */
loop = FALSE; /* and break out */
break;

default: /* anything else */
loop = FALSE;
paren_level = 0; /* do not look for arguments */
break;
}
}

/* find arguments within parentheses */
/* for each argument, find a string ending with ',' or with end parenthesis */

n_args = 0;
s_pos = 0;
exp_es[ exp_esc ].string[ 0 ] = '\0';

while( paren_level > 0 )
{

/* check the current character */

switch( expression[ exp_es[ exp_esc ].pos_adv ] )
{

case ',': /* end of an argument */

if ( paren_level == 1 ) /* ignore ',' within parentheses */
{

/* call bwb_exp() recursively to resolve the argument */

if ( exp_validarg( exp_es[ exp_esc ].string ) == TRUE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf,
"in exp_function(): valid argument (not last)." );
bwb_debug( bwb_ebuf );
#endif

exp_es[ exp_esc ].rec_pos = 0;
e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
&( exp_es[ exp_esc ].rec_pos ) );

/* assign operation and value at this level */

var_make( &( argv[ n_args ] ), e->type );

switch( argv[ n_args ].type )
{
case DOUBLE:
* var_finddval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
= exp_getdval( e );
break;
case SINGLE:
* var_findfval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
= exp_getfval( e );
break;
case INTEGER:
* var_findival( &( argv[ n_args ] ), argv[ n_args ].array_pos )
= exp_getival( e );
break;
case STRING:
str_btob( var_findsval( &( argv[ n_args ] ),
argv[ n_args ].array_pos ), exp_getsval( e ) );
break;
}

++n_args; /* increment number of arguments */

}

s_pos = 0; /* reset counter */
exp_es[ exp_esc ].string[ 0 ] = '\0';
}

else
{
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
}
break;

case '(':
++paren_level;
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
break;

case ')':
--paren_level;

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf,
"in exp_function(): hit close parenthesis." );
bwb_debug( bwb_ebuf );
#endif

if ( paren_level == 0 )
{

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf,
"in exp_function(): paren level 0." );
bwb_debug( bwb_ebuf );
#endif

/* call bwb_exp() recursively to resolve the argument */

if ( exp_validarg( exp_es[ exp_esc ].string ) == TRUE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf,
"in exp_function(): valid argument (last)." );
bwb_debug( bwb_ebuf );
#endif

exp_es[ exp_esc ].rec_pos = 0;
e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
&( exp_es[ exp_esc ].rec_pos ) );

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf,
"in exp_function(): return from bwb_exp(), last arg, type <%c> op <%d>",
e->type, e->operation );
bwb_debug( bwb_ebuf );
#endif

/* assign operation and value at this level */

var_make( &( argv[ n_args ] ), e->type );

switch( argv[ n_args ].type )
{
case DOUBLE:
* var_finddval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
= exp_getdval( e );
break;
case SINGLE:
* var_findfval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
= exp_getfval( e );
break;
case INTEGER:
* var_findival( &( argv[ n_args ] ), argv[ n_args ].array_pos )
= exp_getival( e );
break;
case STRING:
str_btob( var_findsval( &( argv[ n_args ] ),
argv[ n_args ].array_pos ), exp_getsval( e ) );
break;
}

++n_args; /* increment number of arguments */

}

s_pos = 0; /* reset counter */
exp_es[ exp_esc ].string[ 0 ] = '\0';
}

else
{
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
}
break;

case '\"': /* embedded string constant */

/* add the initial quotation mark */

exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
++exp_es[ exp_esc ].pos_adv;

/* add intervening characters */

while ( ( expression[ exp_es[ exp_esc ].pos_adv ] != '\"' )
&& ( expression[ exp_es[ exp_esc ].pos_adv ] != '\0' ) )
{
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
++exp_es[ exp_esc ].pos_adv;
}

/* add the concluding quotation mark */

exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
/* the following bracketed out 14 July 1992; since this counter */
/* incremented at the end of the switch statement, this may */
/* increment it past the next character needed */
/* ++exp_es[ exp_esc ].pos_adv; */
break;

default:
exp_es[ exp_esc ].string[ s_pos ]
= expression[ exp_es[ exp_esc ].pos_adv ];
++s_pos;
exp_es[ exp_esc ].string[ s_pos ] = '\0';
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): new char <%d>=<%c>",
expression[ exp_es[ exp_esc ].pos_adv ],
expression[ exp_es[ exp_esc ].pos_adv ] );
bwb_debug( bwb_ebuf );
sprintf( bwb_ebuf, "in exp_function(): building <%s>.",
exp_es[ exp_esc ].string );
bwb_debug( bwb_ebuf );
#endif
break;
}

/* advance the counter */

++exp_es[ exp_esc ].pos_adv;

}

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): ready to call function vector" );
bwb_debug( bwb_ebuf );
#endif

/* call the function vector */

if ( exp_es[ exp_esc ].function->ufnc != NULL )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): calling fnc_intufnc()" );
bwb_debug( bwb_ebuf );
#endif
v = fnc_intufnc( n_args, &( argv[ 0 ] ), exp_es[ exp_esc ].function );
}
else
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): calling preset function" );
bwb_debug( bwb_ebuf );
#endif
v = exp_es[ exp_esc ].function->vector ( n_args, &( argv[ 0 ] ) );
}

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): return from function vector, type <%c>",
v->type );
bwb_debug( bwb_ebuf );
#endif

/* assign the value at this level */

exp_es[ exp_esc ].type = (char) v->type;

switch( v->type )
{
case STRING:
exp_es[ exp_esc ].operation = CONST_STRING;

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): ready to assign STRING" );
bwb_debug( bwb_ebuf );
#endif

b = var_findsval( v, v->array_pos );
str_btob( exp_getsval( &( exp_es[ exp_esc ] )), b );

#if INTENSIVE_DEBUG
str_btoc( tbuf, b );
sprintf( bwb_ebuf, "in exp_function(): string assigned <%s>", tbuf );
bwb_debug( bwb_ebuf );
#endif

break;

case DOUBLE:
exp_es[ exp_esc ].operation = NUMBER;
exp_es[ exp_esc ].dval = var_getdval( v );
break;
case INTEGER:
exp_es[ exp_esc ].operation = NUMBER;
exp_es[ exp_esc ].ival = var_getival( v );
break;
default:
exp_es[ exp_esc ].operation = NUMBER;
exp_es[ exp_esc ].fval = var_getfval( v );
break;
}

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_function(): end of function" );
bwb_debug( bwb_ebuf );
#endif

/* return */

return TRUE;

}

/***************************************************************

FUNCTION: exp_variable()

DESCRIPTION: This function interprets a variable.

***************************************************************/

int
exp_variable( char *expression )
{
int pos;
int *pp;
int n_params;
register int n;
struct bwb_variable *v;
bstring *b;
int p;

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_variable(): entered function." );
bwb_debug( bwb_ebuf );
#endif

/* get the variable name */

exp_getvfname( expression, exp_es[ exp_esc ].string );

/* now find the variable itself */

v = exp_es[ exp_esc ].xvar = var_find( exp_es[ exp_esc ].string );

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_variable(): level <%d>, found variable name <%s>",
exp_esc, exp_es[ exp_esc ].xvar->name );
bwb_debug( bwb_ebuf );
#endif

/* note that this level is a variable */

exp_es[ exp_esc ].operation = VARIABLE;

/* read subscripts */

pos = strlen( exp_es[ exp_esc ].string );
if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has 1 dimension",
exp_es[ exp_esc ].xvar->name );
bwb_debug( bwb_ebuf );
#endif
pos = strlen( v->name );
n_params = 1;
pp = &p;
pp[ 0 ] = dim_base;
}
else
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has > 1 dimensions",
exp_es[ exp_esc ].xvar->name );
bwb_debug( bwb_ebuf );
#endif
dim_getparams( expression, &pos, &n_params, &pp );
}

exp_es[ exp_esc ].pos_adv = pos;
for ( n = 0; n < v->dimensions; ++n )
{
exp_es[ exp_esc ].array_pos[ n ] = v->array_pos[ n ] = pp[ n ];
}

#if INTENSIVE_DEBUG
for ( n = 0; n < v->dimensions; ++ n )
{
sprintf( bwb_ebuf, "in exp_variable(): var <%s> array_pos element <%d> is <%d>.",
v->name, n, v->array_pos[ n ] );
bwb_debug( bwb_ebuf );
}
#endif

/* assign the type and value at this level */

exp_es[ exp_esc ].type = (char) v->type;

switch( v->type )
{
case STRING:
b = var_findsval( v, v->array_pos );
#if TEST_BSTRING
sprintf( bwb_ebuf, "in exp_variable(): b string name is <%s>",
b->name );
bwb_debug( bwb_ebuf );
#endif
exp_es[ exp_esc ].sval.length = b->length;
exp_es[ exp_esc ].sval.buffer = b->buffer;
break;
case DOUBLE:
exp_es[ exp_esc ].dval = var_getdval( v );
break;
case INTEGER:
exp_es[ exp_esc ].ival = var_getival( v );
break;
default:
exp_es[ exp_esc ].fval = var_getfval( v );
break;
}

#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_variable(): exit, name <%s>, level <%d>, op <%d>",
v->name, exp_esc, exp_es[ exp_esc ].operation );
bwb_debug( bwb_ebuf );
#endif

/* return */

return TRUE;

}




  3 Responses to “Category : BASIC Source Code
Archive   : BWB110S.ZIP
Filename : BWB_ELX.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/