|
- /****************************************************************
-
- bwb_exp.c Expression Parser
- for Bywater BASIC Interpreter
-
- Copyright (c) 1993, Ted A. Campbell
- Bywater Software
-
- email: tcamp@delphi.com
-
- Copyright and Permissions Information:
-
- All U.S. and international rights are claimed by the author,
- Ted A. Campbell.
-
- This software is released under the terms of the GNU General
- Public License (GPL), which is distributed with this software
- in the file "COPYING". The GPL specifies the terms under
- which users may copy and use the software in this distribution.
-
- A separate license is available for commercial distribution,
- for information on which you should contact the author.
-
- ***************************************************************/
-
- /*---------------------------------------------------------------*/
- /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
- /* 11/1995 (eidetics@cerf.net). */
- /* */
- /* Those additionally marked with "DD" were at the suggestion of */
- /* Dale DePriest (daled@cadence.com). */
- /* */
- /* Version 3.00 by Howard Wulf, AF5NE */
- /* */
- /*---------------------------------------------------------------*/
-
-
-
- #include "bwbasic.h"
-
-
-
-
- /***************************************************************
-
- FUNCTION: bwb_exp()
-
- DESCRIPTION: This is the function by which the expression
- parser is called.
-
- ***************************************************************/
-
- struct exp_ese *
- bwb_exp(char *expression, int assignment, int *position)
- {
- struct exp_ese *rval; /* return value */
- int entry_level, main_loop, err_condition;
- int r; /* return value from functions */
- register int c; /* quick counter */
-
- bwx_DEBUG(__FUNCTION__);
-
-
- /* save the entry level of the expression stack in order to check it
- * at the end of this function */
-
- entry_level = CURTASK expsc;
- err_condition = FALSE;
-
- /* advance past whitespace */
-
- adv_ws(expression, position);
-
- /* increment the expression stack counter to get a new level */
-
- inc_esc();
-
- /* check to be sure there is a legitimate expression and set initial
- * parameters for the main loop */
-
- if (is_eol(expression, position) == TRUE)
- {
- main_loop = FALSE; /* break out of loop */
- }
- else
- {
- main_loop = TRUE;
- CURTASK exps[CURTASK expsc].pos_adv = 0;
- }
-
-
-
-
- /* main parsing loop */
-
- while (main_loop == TRUE)
- {
- char *e; /* pointer to current string */
-
- /* set variable <e> to the start of the expression */
-
- e = &(expression[*position]);
-
-
- /* detect the operation required at this level */
-
- CURTASK exps[CURTASK expsc].operation = exp_findop(e);
-
- /* perform actions specific to the operation */
-
- switch (CURTASK exps[CURTASK expsc].operation)
- {
- case OP_ERROR:
- main_loop = FALSE;
- err_condition = TRUE;
- break;
-
- case OP_TERMINATE: /* terminate at THEN, ELSE, TO */
- case OP_STRJOIN: /* string join or tab */
- case OP_STRTAB:
- main_loop = FALSE;
- err_condition = FALSE;
- dec_esc();
- break;
-
- case OP_ADD: /* in the case of any numerical operation, */
- case OP_SUBTRACT:
- case OP_MULTIPLY:
- case OP_DIVIDE:
- case OP_MODULUS:
- case OP_EXPONENT:
- case OP_INTDIVISION:
- case OP_GREATERTHAN:
- case OP_LESSTHAN:
- case OP_GTEQ:
- case OP_LTEQ:
- case OP_NOTEQUAL:
- case OP_NOT:
- case OP_AND:
- case OP_OR:
- case OP_XOR:
- case OP_IMPLIES:
- case OP_EQUIV:
- case OP_NEGATION: /* JBV */
- case OP_POSATION:
-
-
- CURTASK exps[CURTASK expsc].pos_adv = -1; /* set to strange number */
-
- /* cycle through operator table to find match */
-
- for (c = 0; c < NUM_OPERATORS; ++c)
- {
- if (exp_ops[c].operation == CURTASK exps[CURTASK expsc].operation)
- {
- CURTASK exps[CURTASK expsc].pos_adv = strlen(exp_ops[c].symbol);
- }
- }
-
- if (CURTASK exps[CURTASK expsc].pos_adv == -1) /* was a match found? */
- {
- CURTASK exps[CURTASK expsc].pos_adv = 0; /* no -- set to 0 */
- }
- break; /* and move on */
-
- case OP_EQUALS:
-
-
- if (assignment == TRUE)
- {
- CURTASK exps[CURTASK expsc].operation = OP_ASSIGN;
- }
- CURTASK exps[CURTASK expsc].pos_adv = 1;
- break;
-
- case PARENTHESIS:
- r = exp_paren(e);
- break;
-
- case CONST_STRING:
- r = exp_strconst(e);
- break;
-
- case CONST_NUMERICAL:
- r = exp_numconst(e);
- break;
-
- case FUNCTION:
-
-
- r = exp_function(e);
- break;
-
-
- case VARIABLE:
- r = exp_variable(e);
- break;
-
- default:
- err_condition = TRUE;
- main_loop = FALSE;
- sprintf(bwb_ebuf, "in bwb_exp.c:bwb_exp(): unidentified operation (%d).",
- CURTASK exps[CURTASK expsc].operation);
- bwb_error(bwb_ebuf);
- break;
- }
-
- /* increment *position counter based on previous actions */
-
- *position += CURTASK exps[CURTASK expsc].pos_adv;
- CURTASK exps[CURTASK expsc].pos_adv = 0; /* reset advance counter */
-
-
- /* check for end of string */
-
- if (is_eol(expression, position) == TRUE)
- {
- main_loop = FALSE; /* break out of loop */
- }
- /* get a new stack level before looping */
-
- if (main_loop == TRUE)
- {
- r = inc_esc();
- }
- /* check for error return */
-
- if (r == OP_ERROR)
- {
- main_loop = FALSE;
- err_condition = TRUE;
- }
- else
- {
- r = TRUE;
- }
-
- } /* end of main parsing loop */
-
-
- /* check error condition */
-
- if (err_condition == TRUE)
- {
-
-
- /* decrement the expression stack counter until it matches
- * entry_level */
-
- while (CURTASK expsc > entry_level)
- {
- dec_esc();
- }
-
- bwb_error(err_syntax);
- return NULL;
- }
- /* no error; normal exit from function */
-
- else
- {
-
- /* are any more operations needed? if we are still at entry
- * level, then they are not */
-
- /* try operations */
-
- exp_operation(entry_level);
-
- /* see what is on top of the stack */
-
- if (CURTASK expsc > (entry_level + 1))
- {
- switch (CURTASK exps[CURTASK expsc].operation)
- {
- case OP_STRJOIN:
- if (CURTASK expsc != (entry_level + 2))
- {
- sprintf(bwb_ebuf, "in bwb_exp(): OP_STRJOIN in wrong position.");
- bwb_error(bwb_ebuf);
- }
- break;
- default:
- sprintf(bwb_ebuf, "in bwb_exp(): incomplete expression.");
- bwb_error(bwb_ebuf);
- break;
- }
-
- /* decrement the expression stack counter */
-
-
- dec_esc();
-
- }
- /* assign rvar to the variable for the current level */
-
- rval = &(CURTASK exps[CURTASK expsc]);
-
- /* decrement the expression stack counter */
-
- dec_esc();
-
- /* check the current level before exit */
- if (entry_level != CURTASK expsc)
- {
- sprintf(bwb_ebuf, "in bwb_exp(): exit stack level (%d) does not match entry stack level (%d)",
- CURTASK expsc, entry_level);
- bwb_error(bwb_ebuf);
- }
- }
-
- /* return a pointer to the last stack level */
-
- return rval;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_findop()
-
- DESCRIPTION: This function reads the expression to find
- what operation is required at its stack level.
-
- ***************************************************************/
-
- int
- exp_findop(char *expression)
- {
- register int c; /* character counter */
- int rval; /* return value */
- char cbuf[BasicStringLengthMax + 1]; /* capitalized
- * expression */
- char nbuf[BasicStringLengthMax + 1]; /* non-capitalized
- * expression */
- int position; /* position in the expression */
- int adv_loop; /* control loop to build expression */
- int LastPosition;
-
-
- bwx_DEBUG(__FUNCTION__);
-
-
- /* set return value to OP_NULL initially */
-
- rval = OP_NULL;
-
- /* assign local pointer to expression to begin reading */
-
- position = 0;
-
- /* advance to the first significant character */
-
- adv_ws(expression, &position);
-
-
- /* we now have the first significant character and can begin parsing */
-
- /* check the first character for an indication of a parenthetical
- * expression, a string constant, or a numerical constant that begins
- * with a digit (numerical constants beginning with a plus or minus
- * sign or hex/octal/binary constants will have to be detected by
- * exp_isnc() */
-
- switch (expression[position])
- {
- case '=':
- /* look-ahead one character */
- switch( expression[position + 1] )
- {
- case '>':
- /* => */
- rval = OP_GTEQ;
- break;
- case '<':
- /* =< */
- rval = OP_LTEQ;
- break;
- default:
- rval = OP_EQUALS;
- break;
- }
- break;
- case '<':
- /* look-ahead one character */
- switch( expression[position + 1] )
- {
- case '>':
- /* <> */
- rval = OP_NOTEQUAL;
- break;
- case '=':
- /* <= */
- rval = OP_LTEQ;
- break;
- default:
- rval = OP_LESSTHAN;
- break;
- }
- break;
- case '>':
- /* look-ahead one character */
- switch( expression[position + 1] )
- {
- case '=':
- /* >= */
- rval = OP_GTEQ;
- break;
- case '<':
- /* >< */
- rval = OP_NOTEQUAL;
- break;
- default:
- rval = OP_GREATERTHAN;
- break;
- }
- break;
- case '\"': /* this should indicate a string constant */
- rval = CONST_STRING;
- break;
- case '(': /* this will indicate a simple parenthetical
- * expression */
- rval = PARENTHESIS;
- break;
- case ')': /* end of argument list? */
- rval = OP_TERMINATE;
- break;
-
- case '0': /* these will indicate a numerical constant */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '.':
- case '&': /* designator for hex or octal constant */
- rval = CONST_NUMERICAL;
- break;
- }
-
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- /* String constants, numerical constants, open parentheses, and the
- * plus and minus operators have been checked at this point; but if
- * the return value is still OP_NULL, other possibilities must be
- * checked, namely, other operators, function names, and variable
- * names. The function adv_element cannot be used here because it
- * will stop, e.g., with certain operators and not include them in
- * the returned element. */
-
- /* get a character string to be interpreted */
-
- adv_loop = TRUE;
- cbuf[0] = '\0';
- nbuf[0] = '\0';
- c = 0;
- while (adv_loop == TRUE)
- {
-
-
- switch (expression[position])
- {
- case ' ': /* whitespace */
- case '\0': /* end of string */
- case '(': /* parenthesis terminating function name */
- adv_loop = FALSE;
- break;
- default:
- nbuf[c] = cbuf[c] = expression[position];
- ++c;
- nbuf[c] = cbuf[c] = '\0';
- ++position;
- break;
- }
-
-
- LastPosition = position;
-
-
- if (c > BasicStringLengthMax)
- {
- adv_loop = FALSE;
- }
- }
-
-
- /* check for numerical constant */
-
- rval = exp_isnc(cbuf);
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- /* check for other operators */
-
- rval = exp_isop(cbuf);
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- exp_getvfname(cbuf, nbuf);
- if (strlen(nbuf) == 0)
- {
- return OP_ERROR;
- }
- strcpy(CURTASK exps[CURTASK expsc].string, nbuf);
-
-
- /* User definedfunctions are now processed by fnc_deffn */
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- /* check for function name */
-
- rval = exp_isfn(nbuf);
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- /* check for a BASIC command, esp. to catch THEN or ELSE */
-
- rval = exp_iscmd(nbuf);
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- /* last: check for variable name, and assign it if there is not
- * already one */
-
- /* OPTION STRICT OFF to disables Implicit DIM */
- /* This is only for ECMA-55. ECMA-116 requires arrays to be
- * dimensioned prior to being used. */
- if (strlen(nbuf) == strlen(cbuf))
- {
- if (bwb_isvar(nbuf) == FALSE)
- {
- /* not an existing variable */
- while (expression[LastPosition] == ' ')
- {
- LastPosition++;
- }
- if (expression[LastPosition] == '(')
- {
- /* MUST be a dynamically created array, LET
- * ... A(10) ... ' variable "A" has NOT been
- * dimensioned */
- int NumDimensions;
-
- NumDimensions = DetermineNumberOfDimensions(expression, LastPosition);
- if (NumDimensions < 1)
- {
- bwb_error(err_incomplete);
- return OP_ERROR;
- }
- if (ImplicitDim(nbuf, NumDimensions) != TRUE)
- {
- bwb_error(err_syntax);
- return OP_ERROR;
- }
- } /* if( expression[ LastPosition ] == '(' ) */
- } /* if( bwb_isvar( nbuf ) == FALSE ) */
- } /* if( strlen( nbuf ) == strlen( cbuf ) ) */
- rval = exp_isvn(nbuf);
-
- if (rval != OP_NULL)
- {
- return rval;
- }
- /* return the value assigned (or OP_ERROR if none assigned) */
-
- return OP_ERROR;
-
- }
-
-
- /***************************************************************
-
- FUNCTION: exp_isnc()
-
- DESCRIPTION: This function reads the expression to find
- if a numerical constant is present at this
- point.
-
- ***************************************************************/
-
- int
- exp_isnc(char *expression)
- {
-
- bwx_DEBUG(__FUNCTION__);
-
- switch (expression[0])
- {
- case '0': /* these will indicate a numerical constant */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '&': /* indicator for hex or octal constant */
- return CONST_NUMERICAL;
-
-
-
- case '-':
- switch (CURTASK exps[CURTASK expsc - 1].operation)
- {
- case VARIABLE: /* external variable pointed to by xvar */
- if (TRUE)
- {
- struct bwb_variable *v;
- v = CURTASK exps[CURTASK expsc - 1].xvar;
- if (v->IsInDim > 0)
- {
- return OP_NEGATION;
- }
- }
- case NUMBER: /* number held as internal variable in uvar */
- case CONST_STRING: /* string constant */
- case CONST_NUMERICAL: /* numerical constant */
- /* might be subtraction */
- return OP_NULL;
- }
- /* any arithmetic operator: +, -, *, /, \, MOD */
- /* any logical operator: AND, OR, XOR, IMP, EQV, NOT */
- /* any comparison operator: <, <=, =, >=, > */
- /* assignment: LET A = - .... */
- /* parenthesis: LET A = ... (- .... */
- /* command: PRINT - .... */
- return OP_NEGATION;
-
- case '+':
- case BasicFileNumberPrefix: /* EOF( #1 ) */
- switch (CURTASK exps[CURTASK expsc - 1].operation)
- {
- case VARIABLE: /* external variable pointed to by xvar */
- if (TRUE)
- {
- struct bwb_variable *v;
- v = CURTASK exps[CURTASK expsc - 1].xvar;
- if (v->IsInDim > 0)
- {
- return OP_POSATION;
- }
- }
- case NUMBER: /* number held as internal variable in uvar */
- case CONST_STRING: /* string constant */
- case CONST_NUMERICAL: /* numerical constant */
- /* might be addition */
- return OP_NULL;
- }
- /* any arithmetic operator: +, -, *, /, \, MOD */
- /* any logical operator: AND, OR, XOR, IMP, EQV, NOT */
- /* any comparison operator: <, <=, =, >=, > */
- /* assignment: LET A = + .... */
- /* parenthesis: LET A = ... (+ .... */
- /* command: PRINT + .... */
- return OP_POSATION;
-
-
- default:
- return OP_NULL;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_isop()
-
- DESCRIPTION: This function reads the expression to find
- if a logical or mathematical operation is
- required at this point.
-
- This function presupposes that a numerical constant with
- affixed plus or minus sign has been ruled out.
-
- ***************************************************************/
-
- int
- exp_isop(char *expression)
- {
-
- /* Problem: The following lines are valid BASIC: LET note = 0 LET
- * not1 = 0 LET andy = 0 LET and2 = 0 LET oreo = 0 LET or3 = 0 LET
- * xorigin = 0 LET xor4 = 0 LET imply = 0 LET impl5 = 0 LET equality
- * = 0 LET equ6 = 0 LET mode = 0 LET mod7 = 0 However, the
- * interpreter displays the message: ERROR: in exp_getnval():
- * operation <0> is not a number */
- /* Reference: ECMA-116, Page 15, Section 4.1.2, Last Paragraph All
- * keywords in a program, when used as such, shall be preceded and
- * followed by some character other than a letter, digit, underline
- * or dollar-sign. A keyword may also be followed by an end-of-line */
- int i;
- int j;
- int k;
- int Found;
-
- register int c; /* counter */
-
- bwx_DEBUG(__FUNCTION__);
-
- /* compare the initial characters of the string with the table of
- * operators */
-
- for (c = 0; c < NUM_OPERATORS; ++c)
- {
- if (OptionVersion & exp_ops[c].OptionVersionBitmask)
- if (strncasecmp(expression, exp_ops[c].symbol,
- (size_t) strlen(exp_ops[c].symbol)) == 0)
- {
- /* Problem: The following lines are valid
- * BASIC: LET note = 0 LET not1 = 0 LET andy
- * = 0 LET and2 = 0 LET oreo = 0 LET or3 = 0
- * LET xorigin = 0 LET xor4 = 0 LET imply = 0
- * LET impl5 = 0 LET equality = 0 LET equ6 =
- * 0 LET mode = 0 LET mod7 = 0
- *
- * However, the interpreter displays the
- * message: ERROR: in exp_getnval():
- * operation <0> is not a number */
- /* Reference: ECMA-116, Page 15, Section
- * 4.1.2, Last Paragraph All keywords in a
- * program, when used as such, shall be
- * preceded and followed by some character
- * other than a letter, digit, underline or
- * dollar-sign. A keyword may also be
- * followed by an end-of-line */
- Found = TRUE;
- if (isalpha(exp_ops[c].symbol[0]))
- {
- /* NOT, AND, OR, XOR, IMP, EQV, MOD */
- i = strlen(exp_ops[c].symbol);
- j = strlen(expression);
- if (j > i)
- {
- /* the expression does not
- * end with the end of the
- * operator */
- k = expression[i];
- /* character AFTER the
- * operator */
- if (isalpha(k))
- {
- /* NOTe, ANDy, OReo,
- * XORe, IMPly,
- * EQUals, MODe */
- Found = FALSE;
- }
- else
- if (isdigit(k))
- {
- /* NOT1, AND2, OR3,
- * XOR4, IMP5, EQU6,
- * MOD7 */
- Found = FALSE;
- }
- else
- if (k == BasicStringSuffix)
- {
- /* N O T $ ,
- *
- * AN D $ ,
- *
- * OR $ ,
- *
- * XO R $ ,
- *
- * IM P $ ,
- *
- * EQ U $ ,
- *
- * MO D $ */
- Found = FALSE;
- }
- else
- if( OptionFlags & OPTION_BUGS_ON )
- {
- if (k == '_' || k == '.' )
- {
- /* NOT _, AND _, OR_
- * , XOR _, IMP _,
- * EQU _, MOD _ */
- Found = FALSE;
- }
- }
- else
- {
- /* N O T ,
- *
- * AN D ,
- *
- * OR ,
- *
- * XO R ,
- *
- * IM P ,
- *
- * EQ U ,
- *
- * MO D */
- }
- }
- }
- if (Found == TRUE)
- {
- return exp_ops[c].operation;
- }
- }
- }
-
- /* search failed; return OP_NULL */
-
- return OP_NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_iscmd()
-
- DESCRIPTION: This function reads the expression to find
- if a BASIC command name is present; if so,
- it returns OP_TERMINATE to terminate expression
- parsing. This is critical, for example, in
- parsing a conditional following IF where THEN,
- ELSE, and other BASIC commands may follow.
-
- ***************************************************************/
-
- int
- exp_iscmd(char *expression)
- {
- register int n;
-
- bwx_DEBUG(__FUNCTION__);
-
- /* FIXME: extract the expression before calling bwb_exp() - no COMMANDS should be there */
- /* This should be a Syntax Error */
-
- /* first check for likely statements */
- if (strcasecmp(expression, "THEN") == 0)
- {
- /* IF ... THEN */
- return OP_TERMINATE;
- }
- if (strcasecmp(expression, "TO") == 0)
- {
- /* FOR X =... TO ... STEP */
- return OP_TERMINATE;
- }
- if (strcasecmp(expression, "STEP") == 0)
- {
- /* FOR X =... TO ... STEP */
- return OP_TERMINATE;
- }
- if (strcasecmp(expression, "GO") == 0)
- {
- /* ON ... GO */
- return OP_TERMINATE;
- }
- if (strcasecmp(expression, "GOTO") == 0)
- {
- /* ON ... GOTO */
- return OP_TERMINATE;
- }
- if (strcasecmp(expression, "GOSUB") == 0)
- {
- /* ON ... GOSUB */
- return OP_TERMINATE;
- }
- /* run through the command table and search for a match */
-
-
-
-
- n = is_cmd(expression);
- if (n > 0)
- {
- /* FIXME: this should return OP_ERROR, since we found an
- * UNEXPECTED command */
-
- return OP_TERMINATE;
- }
- /* search failed, return NULL */
-
- return OP_NULL;
-
- }
-
-
- /***************************************************************
-
- FUNCTION: exp_isfn()
-
- DESCRIPTION: This function reads the expression to find
- if a function name is present at this point.
-
- ***************************************************************/
-
- int
- exp_isfn(char *expression)
- {
- /* if we are in a USER DEFINED FUNCTION - END FUNCTION block, the
- * function name is a local variable */
- int i;
-
-
- bwx_DEBUG(__FUNCTION__);
-
- for (i = CURTASK exsc; i >= 0; i--)
- {
- if (CURTASK excs[i].LoopTopLine != NULL)
- {
- if (CURTASK excs[i].LoopTopLine->cmdnum == C_FUNCTION)
- {
- if (CURTASK excs[i].local_variable != NULL)
- {
- if (strcasecmp(CURTASK excs[i].local_variable->name, expression) == 0)
- {
- return VARIABLE;
- }
- }
- }
- }
- }
-
- if (fnc_find(expression) != NULL)
- {
- return FUNCTION;
- }
- return OP_NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_isvn()
-
- DESCRIPTION: This function reads the expression to find
- if a variable name at this point.
-
- ***************************************************************/
-
- int
- exp_isvn(char *expression)
- {
- bwx_DEBUG(__FUNCTION__);
-
-
- if (var_find(expression) != NULL)
- {
- return VARIABLE;
- }
- return OP_NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getvfname()
-
- DESCRIPTION: This function reads the expression to find
- a variable or function name at this point.
-
- ***************************************************************/
-
- int
- exp_getvfname(char *source, char *destination)
- {
- #if 0
- int s_pos, d_pos; /* source, destination positions */
-
- bwx_DEBUG(__FUNCTION__);
-
- s_pos = d_pos = 0;
- destination[0] = '\0';
- while (source[s_pos] != '\0')
- {
-
- /* all alphabetical characters are acceptable */
-
- if (isalpha(source[s_pos]) != 0)
-
- {
- destination[d_pos] = source[s_pos];
-
- ++d_pos;
- ++s_pos;
- destination[d_pos] = '\0';
- }
- /* numerical characters are acceptable but not in the first
- * position */
-
- else
- if ((isdigit(source[s_pos]) != 0) && (d_pos != 0))
- {
- destination[d_pos] = source[s_pos];
- ++d_pos;
- ++s_pos;
- destination[d_pos] = '\0';
- }
- /* other characters will have to be tried on their own merits */
-
- else
- {
- switch (source[s_pos])
- {
-
- case '.': /* tolerated non-alphabetical
- * characters */
- case '_':
- destination[d_pos] = source[s_pos];
- ++d_pos;
- ++s_pos;
- destination[d_pos] = '\0';
- break;
-
- case STRING: /* terminating characters */
- case BasicDoubleSuffix: /* Microsoft-type
- * precision indicator;
- * ignored but
- * terminates */
- case BasicSingleSuffix: /* Microsoft-type
- * precision indicator;
- * ignored but
- * terminates */
- case BasicCurrencySuffix: /* Microsoft-type
- * precision indicator;
- * ignored but
- * terminates */
- case BasicLongSuffix: /* Microsoft-type precision
- * indicator; ignored but
- * terminates */
- case BasicIntegerSuffix: /* Microsoft-type
- * precision indicator;
- * ignored but
- * terminates */
-
- destination[d_pos] = source[s_pos];
- ++d_pos;
- ++s_pos;
- destination[d_pos] = '\0';
-
- return TRUE;
-
- case '(': /* begin function/sub name */
- return TRUE;
-
- default: /* anything else is non-tolerated */
- return FALSE;
- }
- }
- }
-
-
- return TRUE; /* exit after coming to the end */
- #endif
- int position = 0;
-
- bwb_getvarname( source, destination, &position);
- return TRUE; /* exit after coming to the end */
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_validarg()
-
- DESCRIPTION: This function reads the expression to
- determine whether it is a valid argument (to be
- read recursively by bwb_exp() and passed to a
- function.
-
- ***************************************************************/
-
- int
- exp_validarg(char *expression)
- {
- register int c;
-
- bwx_DEBUG(__FUNCTION__);
-
- c = 0;
- while (TRUE)
- {
- switch (expression[c])
- {
- case ' ':
- ++c;
- break;
- case '\0':
- return FALSE;
- default:
- return TRUE;
- }
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getnval()
-
- DESCRIPTION: This function returns the numerical value
- contain in the expression-stack element
- pointed to by 'e'.
-
- ***************************************************************/
-
- double
- exp_getnval(struct exp_ese * e)
- {
- BasicNumberType Value;
-
- bwx_DEBUG(__FUNCTION__);
-
- Value = 0;
-
- if (e->type == NUMBER)
- {
- switch (e->operation)
- {
- case VARIABLE:
- Value = (*var_findnval(e->xvar, e->array_pos));
- break;
- case NUMBER:
- Value = e->nval;
- break;
- default:
- bwb_error(err_syntax);
- }
- }
- else
- {
- bwb_error(err_mismatch);
- }
- Value = VerifyNumeric(Value);
- return Value;
-
- }
-
- int
- exp_getival(struct exp_ese * e)
- {
- double XR;
- XR = rint(exp_getnval(e));
- if (XR < INT_MIN)
- {
- bwb_Warning_Overflow("*** Arithmetic Overflow ***");
- XR = INT_MIN;
- }
- else
- if (XR > INT_MAX)
- {
- bwb_Warning_Overflow("*** Arithmetic Overflow ***");
- XR = INT_MAX;
- }
- return (int) XR;
- }
-
- /***************************************************************
-
- FUNCTION: exp_getsval()
-
- DESCRIPTION: This function returns a pointer to the
- BASIC string structure pointed to by
- expression-stack element 'e'.
-
- ***************************************************************/
-
- bstring *
- exp_getsval(struct exp_ese * e)
- {
- static bstring b;
-
- bwx_DEBUG(__FUNCTION__);
-
- b.rab = FALSE;
-
- /* return based on operation type */
-
- switch (e->operation)
- {
- case CONST_STRING:
- case OP_STRJOIN:
- return &(e->sval);
- case VARIABLE:
- switch (e->type)
- {
- case STRING:
- return var_findsval(e->xvar, e->array_pos);
- case NUMBER:
- sprintf(bwb_ebuf, BasicNumberPrintFormat " ", exp_getnval(e));
- str_ctob(&b, bwb_ebuf);
- return &b;
- default:
- sprintf(bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
- e->type);
- bwb_error(bwb_ebuf);
- return NULL;
- }
- break;
-
- case NUMBER:
- switch (e->type)
- {
- case NUMBER:
- sprintf(bwb_ebuf, BasicNumberPrintFormat " ", exp_getnval(e));
- str_ctob(&b, bwb_ebuf);
- return &b;
- default:
- sprintf(bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
- e->type);
- bwb_error(bwb_ebuf);
- return NULL;
- }
- break;
- default:
- sprintf(bwb_ebuf, "in exp_getsval(): operation <%d> inappropriate",
- e->operation);
- bwb_error(bwb_ebuf);
- return NULL;
- }
-
- /* this point may not be reached */
-
- return NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: inc_esc()
-
- DESCRIPTION: This function increments the expression
- stack counter.
-
- ***************************************************************/
-
- int
- inc_esc(void)
- {
-
- bwx_DEBUG(__FUNCTION__);
-
- ++CURTASK expsc;
- if (CURTASK expsc >= ESTACKSIZE)
- {
- --CURTASK expsc;
- sprintf(bwb_ebuf, "in inc_esc(): Maximum expression stack exceeded <%d>",
- CURTASK expsc);
- bwb_error(bwb_ebuf);
- return OP_NULL;
- }
- CURTASK exps[CURTASK expsc].type = NUMBER;
- CURTASK exps[CURTASK expsc].operation = OP_NULL;
- CURTASK exps[CURTASK expsc].pos_adv = 0;
-
- return TRUE;
- }
-
- /***************************************************************
-
- FUNCTION: dec_esc()
-
- DESCRIPTION: This function decrements the expression
- stack counter.
-
- ***************************************************************/
-
- int
- dec_esc(void)
- {
-
- bwx_DEBUG(__FUNCTION__);
-
- --CURTASK expsc;
- if (CURTASK expsc < 0)
- {
- CURTASK expsc = 0;
- sprintf(bwb_ebuf, "in dec_esc(): Expression stack counter < 0.");
- bwb_error(bwb_ebuf);
- return OP_NULL;
- }
- return TRUE;
- }
-
-
- /* EOF */
|