|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203 |
- /****************************************************************
-
- bwb_elx.c Parse Elements of Expressions
- 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: 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;
- int s_pos; /* position in build buffer */
- int loop;
- int paren_level;
-
- bwx_DEBUG(__FUNCTION__);
-
- /* find a string enclosed by parentheses */
-
- CURTASK exps[CURTASK expsc].pos_adv = 1; /* start beyond open
- * paren */
- s_pos = 0;
- loop = TRUE;
- paren_level = 1;
- CURTASK exps[CURTASK expsc].string[0] = '\0';
-
- while (loop == TRUE)
- {
-
- /* check the current character */
-
- switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
- {
- case '\0':
- bwb_error(err_incomplete);
- loop = FALSE;
- break;
-
- case '(':
- ++paren_level;
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
-
- case ')':
-
- --paren_level;
- if (paren_level == 0)
- {
- loop = FALSE;
- }
- else
- {
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- }
- break;
-
- case '\"': /* embedded string constant */
- ++CURTASK exps[CURTASK expsc].pos_adv;
- while ((expression[CURTASK exps[CURTASK expsc].pos_adv] != '\"')
- && (expression[CURTASK exps[CURTASK expsc].pos_adv] != '\0'))
- {
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- ++CURTASK exps[CURTASK expsc].pos_adv;
- }
- break;
-
- default:
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
- }
-
- /* advance the counter */
-
- ++CURTASK exps[CURTASK expsc].pos_adv;
-
- }
-
-
- /* call bwb_exp() recursively to interpret this expression */
-
- CURTASK exps[CURTASK expsc].rec_pos = 0;
- e = bwb_exp(CURTASK exps[CURTASK expsc].string, FALSE,
- &(CURTASK exps[CURTASK expsc].rec_pos));
-
- /* assign operation and value at this level */
-
- CURTASK exps[CURTASK expsc].type = e->type;
-
- switch (e->type)
- {
- case STRING:
- CURTASK exps[CURTASK expsc].operation = CONST_STRING;
- str_btob(exp_getsval(&(CURTASK exps[CURTASK expsc])), exp_getsval(e));
- break;
- default:
- CURTASK exps[CURTASK expsc].operation = NUMBER;
- CURTASK exps[CURTASK expsc].nval = exp_getnval(e);
- break;
- }
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_strconst()
-
- DESCRIPTION: This function interprets a string
- constant.
-
- ***************************************************************/
-
- int
- exp_strconst(char *expression)
- {
- int e_pos, s_pos;
-
- bwx_DEBUG(__FUNCTION__);
-
- /* assign values to structure */
-
- CURTASK exps[CURTASK expsc].type = STRING;
- CURTASK exps[CURTASK expsc].operation = CONST_STRING;
-
- /* set counters */
-
- s_pos = 0;
- CURTASK exps[CURTASK expsc].pos_adv = e_pos = 1;
- CURTASK exps[CURTASK expsc].string[0] = '\0';
-
- /* read the string up until the next quotation mark */
-
- /* While yer at it, check for a null terminator too (JBV, found by
- * DD) */
- while ((expression[e_pos] != '\"') && (expression[e_pos] != '\0'))
- {
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[e_pos];
- ++e_pos;
- ++s_pos;
- ++CURTASK exps[CURTASK expsc].pos_adv;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- if (s_pos > BasicStringLengthMax)
- {
- sprintf(bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
- expression, BasicStringLengthMax);
- bwb_error(bwb_ebuf);
- return OP_NULL;
- }
- }
-
- /* now write string over to bstring */
-
- str_ctob(&(CURTASK exps[CURTASK expsc].sval), CURTASK exps[CURTASK expsc].string);
-
- /* advance past last quotation mark */
-
- /*-------------------------------------------------------------*/
- /* Of course, it doesn't hurt to make sure it's really a quote */
- /* (JBV, found by DD) */
- /*-------------------------------------------------------------*/
- if (expression[e_pos] == '\"')
- ++CURTASK exps[CURTASK expsc].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;
- unsigned int u;
-
- bwx_DEBUG(__FUNCTION__);
-
- /* initialize the variable if necessary */
-
-
- if (init == FALSE)
- {
- init = TRUE;
- var_make(&mantissa, NUMBER);
- }
- /* 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;
-
-
- need_pm = FALSE;
- CURTASK exps[CURTASK expsc].nval = 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:
-
- sprintf(bwb_ebuf, "expression <%s> is not a numerical constant.",
- expression);
- bwb_error(bwb_ebuf);
- return OP_NULL;
- }
-
- /* now build the mantissa according to the numerical base */
-
- switch (base)
- {
-
- case 10: /* decimal constant */
-
- /* initialize counters */
-
- CURTASK exps[CURTASK expsc].pos_adv = man_start;
- CURTASK exps[CURTASK expsc].type = NUMBER;
- CURTASK exps[CURTASK expsc].string[0] = '\0';
- s_pos = 0;
- exponent = OP_NULL;
- build_loop = TRUE;
-
- /* loop to build the string */
-
- while (build_loop == TRUE)
- {
- switch (expression[CURTASK exps[CURTASK expsc].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 (CURTASK exps[CURTASK expsc].pos_adv == man_start)
- {
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- ++s_pos;
- CURTASK exps[CURTASK expsc].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 */
- case '0': /* or ordinary digit */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
-
- 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 */
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- CURTASK exps[CURTASK expsc].type = NUMBER;
- exponent = FALSE;
- build_loop = FALSE;
- break;
-
- case 'E': /* exponential, single precision */
- case 'e':
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- CURTASK exps[CURTASK expsc].type = NUMBER;
- exponent = TRUE;
- build_loop = FALSE;
- break;
-
- case 'D': /* exponential, double precision */
- case 'd':
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- CURTASK exps[CURTASK expsc].type = NUMBER;
- exponent = TRUE;
- build_loop = FALSE;
- break;
-
- default: /* anything else, terminate */
- build_loop = FALSE;
- break;
- }
-
- }
-
- /* assign the value to the mantissa variable */
-
- sscanf(CURTASK exps[CURTASK expsc].string, BasicNumberScanFormat,
- var_findnval(&mantissa, mantissa.array_pos));
-
-
- /* test if integer bounds have been exceeded */
-
- if (CURTASK exps[CURTASK expsc].type == NUMBER)
- {
- int i;
- BasicNumberType d;
-
- i = (int) var_getnval(&mantissa);
- d = (BasicNumberType) i;
- if (d != var_getnval(&mantissa))
- {
- CURTASK exps[CURTASK expsc].type = NUMBER;
- }
- }
- /* read the exponent if there is one */
-
- if (exponent == TRUE)
- {
-
- /* allow a plus or minus once at the beginning */
-
- need_pm = TRUE;
-
- /* initialize counters */
-
- CURTASK exps[CURTASK expsc].string[0] = '\0';
- s_pos = 0;
- build_loop = TRUE;
-
- /* loop to build the string */
-
- while (build_loop == TRUE)
- {
- switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
- {
- case '-': /* prefixed plus or minus */
- case '+':
-
- if (need_pm == TRUE) /* only allow once */
- {
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- ++s_pos;
- CURTASK exps[CURTASK expsc].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':
-
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- ++s_pos;
- CURTASK exps[CURTASK expsc].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(CURTASK exps[CURTASK expsc].string, BasicNumberScanFormat,
- &(CURTASK exps[CURTASK expsc].nval));
-
-
- } /* end of exponent search */
- if (CURTASK exps[CURTASK expsc].nval == 0)
- {
- CURTASK exps[CURTASK expsc].nval = var_getnval(&mantissa);
- }
- else
- {
- CURTASK exps[CURTASK expsc].nval = var_getnval(&mantissa)
- * pow(10.0, CURTASK exps[CURTASK expsc].nval);
- }
-
- break;
-
- case 8: /* octal constant */
-
- /* initialize counters */
-
- CURTASK exps[CURTASK expsc].pos_adv = man_start;
- CURTASK exps[CURTASK expsc].type = NUMBER;
- CURTASK exps[CURTASK expsc].string[0] = '\0';
- s_pos = 0;
- exponent = OP_NULL;
- build_loop = TRUE;
-
- /* loop to build the string */
-
- while (build_loop == TRUE)
- {
- switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
- {
- case '0': /* or ordinary digit */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
-
- default: /* anything else, terminate */
- build_loop = FALSE;
- break;
- }
-
- }
-
- /* now scan the string to determine the number */
-
- sscanf(CURTASK exps[CURTASK expsc].string, "%o", &u);
- CURTASK exps[CURTASK expsc].nval = u;
-
- break;
-
- case 16: /* hexadecimal constant */
-
- /* initialize counters */
-
- CURTASK exps[CURTASK expsc].pos_adv = man_start;
- CURTASK exps[CURTASK expsc].type = NUMBER;
- CURTASK exps[CURTASK expsc].string[0] = '\0';
- s_pos = 0;
- exponent = OP_NULL;
- build_loop = TRUE;
-
- /* loop to build the string */
-
- while (build_loop == TRUE)
- {
- switch (expression[CURTASK exps[CURTASK expsc].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':
- case 'F': /* Don't forget these! (JBV) */
- case 'f':
- CURTASK exps[CURTASK expsc].string[s_pos] = expression[CURTASK exps[CURTASK expsc].pos_adv];
-
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance to next
- * character */
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
-
- default: /* anything else, terminate */
- build_loop = FALSE;
- break;
- }
-
- }
-
- /* now scan the string to determine the number */
-
- sscanf(CURTASK exps[CURTASK expsc].string, "%x", &u);
- CURTASK exps[CURTASK expsc].nval = u;
- break;
- }
-
- /* note that the operation at this level is now a determined NUMBER */
-
- CURTASK exps[CURTASK expsc].operation = NUMBER;
-
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_function()
-
- DESCRIPTION: This function interprets a function,
- calling bwb_exp() (recursively) to resolve any
- parameters to the function.
-
- ***************************************************************/
-
- struct bwb_variable *
- var_chain(struct bwb_variable * argv)
- {
- /* create a variable chain */
- struct bwb_variable *argn;
-
- bwx_DEBUG(__FUNCTION__);
-
- if (argv == NULL)
- {
- /* we are the first variable in the chain */
- argn = (struct bwb_variable *) CALLOC(1, sizeof(struct bwb_variable), "exp_function");
- }
- else
- {
- /* find the end of the chain */
- for (argn = argv; argn->next != NULL; argn = argn->next);
- /* add ourself to the end */
- argn->next = (struct bwb_variable *) CALLOC(1, sizeof(struct bwb_variable), "exp_function");
- argn = argn->next;
- }
- argn->next = NULL;
- /* return pointer to the variable just created */
- return argn;
- }
-
-
- int
- exp_function(char *expression)
- {
- struct exp_ese *e;
- int s_pos; /* position in build buffer */
- int loop;
- int paren_level;
- int n_args;
- /* struct bwb_variable argv[ MAX_FARGS ]; *//* Removed by JBV */
- struct bwb_variable *argv; /* Added by JBV */
- struct bwb_variable *argn;
- bstring *b;
-
- bwx_DEBUG(__FUNCTION__);
-
-
- argv = var_chain(NULL); /* RETURN variable */
- argn = NULL;
-
- /* assign pointers to argument stack */
-
- /* get the function name */
-
- exp_getvfname(expression, CURTASK exps[CURTASK expsc].string);
-
-
- /* now find the function itself */
-
- CURTASK exps[CURTASK expsc].function = fnc_find(CURTASK exps[CURTASK expsc].string);
-
- /* check to see if it is valid */
-
- if (CURTASK exps[CURTASK expsc].function == NULL)
- {
- sprintf(bwb_ebuf, "Failed to find function <%s>.",
- CURTASK exps[CURTASK expsc].string);
- bwb_error(bwb_ebuf);
- return OP_ERROR;
- }
- /* note that this level is a function */
-
- CURTASK exps[CURTASK expsc].operation = FUNCTION;
- CURTASK exps[CURTASK expsc].pos_adv = strlen(CURTASK exps[CURTASK expsc].string);
-
- /* check for begin parenthesis */
-
- loop = TRUE;
- while (loop == TRUE)
- {
- switch (expression[CURTASK exps[CURTASK expsc].pos_adv])
- {
-
- case ' ': /* whitespace */
- ++CURTASK exps[CURTASK expsc].pos_adv; /* advance */
- break;
-
- case '(': /* begin paren */
-
-
- ++CURTASK exps[CURTASK expsc].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 parameters */
- break;
- }
- }
-
- /* find parameters within parentheses */
- /* for each argument, find a string ending with ',' or with end
- * parenthesis */
-
- n_args = 0;
- s_pos = 0;
- CURTASK exps[CURTASK expsc].string[0] = '\0';
-
- while (paren_level > 0)
- {
-
- /* check the current character */
-
- switch (expression[CURTASK exps[CURTASK expsc].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(CURTASK exps[CURTASK expsc].string) == TRUE)
- {
-
- CURTASK exps[CURTASK expsc].rec_pos = 0;
- e = bwb_exp(CURTASK exps[CURTASK expsc].string, FALSE,
- &(CURTASK exps[CURTASK expsc].rec_pos));
-
- /* assign operation and value at this
- * level */
- argn = var_chain(argv);
- /* 'argn' is the vaiable to use */
- var_make(argn, e->type);
- switch (argn->type)
- {
- case NUMBER:
- *var_findnval(argn, argn->array_pos)
- = exp_getnval(e);
- break;
- case STRING:
- str_btob(var_findsval(argn,
- argn->array_pos), exp_getsval(e));
- break;
- }
- ++n_args; /* increment number of
- * parameters */
-
- }
- s_pos = 0; /* reset counter */
- CURTASK exps[CURTASK expsc].string[0] = '\0';
- }
- else
- {
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- }
- break;
-
- case '(':
- ++paren_level;
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
-
- case ')':
- --paren_level;
-
-
- if (paren_level == 0)
- {
-
-
- /* call bwb_exp() recursively to resolve the
- * argument */
-
- if (exp_validarg(CURTASK exps[CURTASK expsc].string) == TRUE)
- {
-
- CURTASK exps[CURTASK expsc].rec_pos = 0;
- e = bwb_exp(CURTASK exps[CURTASK expsc].string, FALSE,
- &(CURTASK exps[CURTASK expsc].rec_pos));
-
-
- /* assign operation and value at this
- * level */
- argn = var_chain(argv);
- /* 'argn' is the vaiable to use */
- var_make(argn, e->type);
- switch (argn->type)
- {
- case NUMBER:
- *var_findnval(argn, argn->array_pos)
- = exp_getnval(e);
- break;
- case STRING:
- str_btob(var_findsval(argn,
- argn->array_pos), exp_getsval(e));
- break;
- }
- ++n_args; /* increment number of
- * parameters */
-
- }
- s_pos = 0; /* reset counter */
- CURTASK exps[CURTASK expsc].string[0] = '\0';
- }
- else
- {
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- }
- break;
-
- case '\"': /* embedded string constant */
-
- /* add the initial quotation mark */
-
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- ++CURTASK exps[CURTASK expsc].pos_adv;
-
- /* add intervening characters */
-
- while ((expression[CURTASK exps[CURTASK expsc].pos_adv] != '\"')
- && (expression[CURTASK exps[CURTASK expsc].pos_adv] != '\0'))
- {
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- ++CURTASK exps[CURTASK expsc].pos_adv;
- }
-
- /* add the concluding quotation mark */
-
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].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 */
- /* ++CURTASK exps[ CURTASK expsc ].pos_adv; */
- break;
-
- default:
- CURTASK exps[CURTASK expsc].string[s_pos]
- = expression[CURTASK exps[CURTASK expsc].pos_adv];
- ++s_pos;
- CURTASK exps[CURTASK expsc].string[s_pos] = '\0';
- break;
- }
-
- /* advance the counter */
-
- ++CURTASK exps[CURTASK expsc].pos_adv;
-
- }
-
-
- /* call the function vector */
-
-
- if (TRUE)
- {
- /* Compare the parameter signature of the caller to the
- * callee. This allows for function overloading based upon
- * different parameter signatures. It also eliminates the
- * need for any intrinsic function to check it's parameter
- * count or check the type of it's parameters. The function
- * will only be callled with the correct type and count of
- * parameters. Examples of common intrinsic functions which
- * are overloaded based upon the parameter signature are
- * INSTR and MID$. INSTR( [Start], In$, Find$ ) -> instr(
- * string, string ) -> 2 parameters instr( number,
- * string, string ) -> 3 parameters */
- struct bwb_function *f;
- char *name;
-
- f = CURTASK exps[CURTASK expsc].function;
- name = f->Name;
-
-
- /* There are two choices for USER DEFINE FUNCTIONS: #1 - A
- * fixed number of upto 32 parameters, declared as FUNCTION
- * FRED( A$, B$, X, Y ) #2 - A variant number of upto MAXINT
- * parameters, declared as FUNCTION FRED( ... ) */
-
- /* Determine the caller's parameter signature, using an
- * algorithm matching the intrinsic table: First argument is
- * bit 0; if it is 1 then STRING else NUMBER. Second argument
- * is bit 1, and so on. */
- if (TRUE)
- {
- /* VERIFY */
- unsigned char ParameterCount;
- unsigned long ParameterTypes;
-
- if (n_args > 32)
- {
- /* VARIANT */
- ParameterCount = 0xFF;
- ParameterTypes = 0;
- }
- else
- {
- int i;
- ParameterCount = n_args; /* <= 32 */
- ParameterTypes = 0;
- argn = argv;
- for (i = 0; i < ParameterCount; i++)
- {
- argn = argn->next;
- if (argn->type == STRING)
- {
- ParameterTypes |= (1 << i);
- }
- }
- }
- /* did we find the correct function above? */
- if (f->ParameterCount != ParameterCount || f->ParameterTypes != ParameterTypes)
- {
- /* oops */
-
- f = fnc_find_exact(name, ParameterCount, ParameterTypes);
- if (f == NULL)
- {
- /* NOT FOUND */
- f = fnc_find_exact(name, 0xFF, 0); /* look for VARIANT */
- }
- if (f == NULL)
- {
- /* NOT FOUND */
- sprintf(bwb_ebuf, "*** Illegal Function Call (%s) ***", name);
- bwb_error(bwb_ebuf);
- return OP_ERROR;
- }
- /* FOUND */
- CURTASK exps[CURTASK expsc].function = f;
- }
- }
- }
- /* defaullt the return value */
- #define RESULT_NUMBER *argv->memnum
- #define RESULT_BUFFER argv->memstr->sbuffer
- #define RESULT_LENGTH argv->memstr->length
- /* defaullt the return value */
- {
- if ((CURTASK exps[CURTASK expsc].function->ReturnType & 0x00FF) == STRING)
- {
- var_make(argv, STRING);
- RESULT_BUFFER = (char *) CALLOC(BasicStringLengthMax + 1, 1, "exp_function");
- RESULT_LENGTH = 0;
- RESULT_BUFFER[RESULT_LENGTH] = '\0';
- }
- else
- {
- var_make(argv, NUMBER);
- RESULT_NUMBER = 0;
- }
- strcpy(argv->name, CURTASK exps[CURTASK expsc].function->Name);
- }
- if (CURTASK exps[CURTASK expsc].function->ReturnType & 0xFF00 /* UniqueID is a line
- number */ )
- {
- /* for all USER DEFINED FUNCTIONS: f->UniqueID == line number
- * of DEF FN... */
- unsigned short cmdnum;
- cmdnum = (CURTASK exps[CURTASK expsc].function->ReturnType & 0xFF00) >> 8;
- switch (cmdnum)
- {
- case C_DEF: /* execute a user function declared using DEF
- * FN...(...) = ... */
- case C_FUNCTION: /* execute a user function declared
- * using FUNCTION ...(...) */
- case C_SUB: /* execute a user subroutine declared using
- * SUB ...(...) */
- fnc_deffn(n_args, argv, CURTASK exps[CURTASK expsc].function->UniqueID);
- break;
- case C_USER_LBL: /* IF ERL > label1 AND ERL < label2
- * THEN ... */
- if (n_args > 0)
- {
- bwb_error("SYNTAX ERROR");
- }
- /* return the line number associated with the label */
- RESULT_NUMBER = CURTASK exps[CURTASK expsc].function->UniqueID;
- break;
- default:
- sprintf(bwb_ebuf, "INTERNAL ERROR, in exp_function(): unexpected cmdnum %d", cmdnum);
- bwb_error(bwb_ebuf);
- break;
- }
- }
- else
- {
- /* for all INTRINSIC FUNCTIONS: f->UniqueID == #define F_... */
- fnc_intrinsic(n_args, argv, CURTASK exps[CURTASK expsc].function->UniqueID);
- }
-
-
- CURTASK exps[CURTASK expsc].type = (char) argv->type;
-
- switch (argv->type)
- {
- case STRING:
- CURTASK exps[CURTASK expsc].operation = CONST_STRING;
-
-
- b = var_findsval(argv, argv->array_pos);
- str_btob(exp_getsval(&(CURTASK exps[CURTASK expsc])), b);
-
-
- break;
-
- default:
- CURTASK exps[CURTASK expsc].operation = NUMBER;
- CURTASK exps[CURTASK expsc].nval = var_getnval(argv);
- break;
- }
- /*-------------------------------------------------*/
- /* Now free the argv memory */
- /* (some other less fortunate routine may need it) */
- /* JBV, 10/95 */
- /*-------------------------------------------------*/
-
- var_free(argv);
- /* return */
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_variable()
-
- DESCRIPTION: This function interprets a variable.
-
- ***************************************************************/
-
- int
- exp_variable(char *expression)
- {
- int pos;
- register int n;
- struct bwb_variable *v;
- bstring *b;
- int n_params;
- int pp[MAX_DIMS];
-
- bwx_DEBUG(__FUNCTION__);
-
- /* get the variable name */
-
- exp_getvfname(expression, CURTASK exps[CURTASK expsc].string);
-
- /* now find the variable itself */
-
- v = CURTASK exps[CURTASK expsc].xvar = var_find(CURTASK exps[CURTASK expsc].string);
-
-
- /* note that this level is a variable */
-
- CURTASK exps[CURTASK expsc].operation = VARIABLE;
-
- /* read subscripts */
-
- pos = strlen(CURTASK exps[CURTASK expsc].string);
- if ((v->dimensions == 1) && (v->array_sizes[0] == 1))
- {
- pos = strlen(v->name);
- n_params = 1;
- pp[0] = dim_base;
- }
- else
- {
- v->IsInDim++;
- n_params = dim_getparams_FIXED(expression, &pos, pp);
- v->IsInDim--;
- }
- if (n_params != v->dimensions)
- {
- sprintf(bwb_ebuf, "DIMENSION OUT OF RANGE %s(%d)", v->name, n_params);
- bwb_error(bwb_ebuf);
- return FALSE;
- }
- CURTASK exps[CURTASK expsc].pos_adv = pos;
- for (n = 0; n < v->dimensions; ++n)
- {
- /* newvar->array_sizes[ n ] = pp[ n ] + ( 1 - dim_base ); */
- if ((pp[n] < dim_base) || ((pp[n] + (1 - dim_base)) > v->array_sizes[n]))
- {
- sprintf(bwb_ebuf, "SUBSCRIPT OUT OF RANGE %s(%d)", v->name, pp[n]);
- bwb_error(bwb_ebuf);
- return FALSE;
- }
- CURTASK exps[CURTASK expsc].array_pos[n] = v->array_pos[n] = pp[n];
- }
-
-
- /* assign the type and value at this level */
-
- CURTASK exps[CURTASK expsc].type = (char) v->type;
-
- switch (v->type)
- {
- case STRING:
- b = var_findsval(v, v->array_pos);
- str_btob(&(CURTASK exps[CURTASK expsc].sval), b);
- break;
- default:
- CURTASK exps[CURTASK expsc].nval = var_getnval(v);
-
-
-
- break;
- }
-
-
- /* return */
-
- return TRUE;
-
- }
-
- /* EOF */
|