static int op_modulus(int level, int precision) { static double iportion; bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for string * addition; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be divided."); bwb_error(bwb_ebuf); return FALSE; break; case NUMBER: { /* N = X MOD Y */ if (exp_getnval(&(CURTASK exps[level + 1])) == 0) { CURTASK exps[level - 1].nval = -1; op_pulldown(2); sprintf(bwb_ebuf, "Modulus by 0."); bwb_error(bwb_ebuf); return FALSE; } CURTASK exps[level].nval = exp_getnval(&(CURTASK exps[level - 1])) / exp_getnval(&(CURTASK exps[level + 1])); modf((double) CURTASK exps[level].nval, &iportion); CURTASK exps[level - 1].nval = exp_getnval(&(CURTASK exps[level - 1])) - (exp_getnval(&(CURTASK exps[level + 1])) * iportion); } break; } /* set variable to requested precision */ CURTASK exps[level - 1].type = (char) precision; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
static int op_intdiv(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for string * addition; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be divided."); bwb_error(bwb_ebuf); return FALSE; break; default: { /* N = X \ Y */ long X; long Y; long N; X = exp_getival(&(CURTASK exps[level - 1])); Y = exp_getival(&(CURTASK exps[level + 1])); if (Y == 0) { sprintf(bwb_ebuf, "Integer Divide by 0."); bwb_error(bwb_ebuf); return FALSE; } N = X / Y; CURTASK exps[level - 1].nval = N; } break; } /* set variable to requested precision */ CURTASK exps[level - 1].type = NUMBER; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
BasicNumberType VerifyNumeric(BasicNumberType Value) { bwx_DEBUG(__FUNCTION__); /* check Value */ if (isnan(Value)) { /*** FATAL - INTERNAL ERROR - SHOULD NEVER HAPPEN ***/ bwb_error("NOT A NUMBER"); return 0; } else if (isinf(Value)) { /* - Evaluation of an expression results in an overflow * (nonfatal, the recommended recovery procedure is to supply * machine in- finity with the algebraically correct sign and * continue). */ if (Value < 0) { Value = -DBL_MAX; } else { Value = DBL_MAX; } bwb_Warning_Overflow("*** Arithmetic Overflow ***"); } return Value; }
static int op_gteq(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for string * addition; if not, report an error */ if ((op_islevelstr(level - 1) != TRUE) || (op_islevelstr(level + 1) != TRUE)) { sprintf(bwb_ebuf, "Type mismatch in string comparison."); bwb_error(bwb_ebuf); return FALSE; } /* compare the two strings */ if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])), exp_getsval(&(CURTASK exps[level + 1]))) >= 0) { CURTASK exps[level - 1].nval = TRUE; } else { CURTASK exps[level - 1].nval = FALSE; } break; case NUMBER: if (exp_getnval(&(CURTASK exps[level - 1])) >= exp_getnval(&(CURTASK exps[level + 1]))) { CURTASK exps[level - 1].nval = TRUE; } else { CURTASK exps[level - 1].nval = FALSE; } break; } /* set variable to integer and operation to NUMBER: this must be done * at the end, since at the beginning it might cause op_islevelstr() * to return a false error */ CURTASK exps[level - 1].type = NUMBER; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack */ op_pulldown(2); return TRUE; }
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; }
static int op_add(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be strings for string * addition; if not, report an error */ if ((op_islevelstr(level - 1) != TRUE) || (op_islevelstr(level + 1) != TRUE)) { sprintf(bwb_ebuf, "in op_add(): Type mismatch in string addition."); bwb_error(bwb_ebuf); return FALSE; } /* concatenate the two strings */ { static bstring b; /* JBV */ b.rab = FALSE; /* JBV */ str_btob(&b, exp_getsval(&(CURTASK exps[level - 1]))); str_cat(&b, exp_getsval(&(CURTASK exps[level + 1]))); str_btob(&(CURTASK exps[level - 1].sval), &b); CURTASK exps[level - 1].operation = CONST_STRING; } break; case NUMBER: CURTASK exps[level - 1].nval = exp_getnval(&(CURTASK exps[level - 1])) + exp_getnval(&(CURTASK exps[level + 1])); CURTASK exps[level - 1].operation = NUMBER; break; } /* set variable to requested precision */ CURTASK exps[level - 1].type = (char) precision; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
struct bwb_line * bwb_edit( struct bwb_line *l ) { char tbuf[ MAXSTRINGSIZE + 1 ]; char edname[ MAXSTRINGSIZE + 1 ]; struct bwb_variable *ed; FILE *loadfile; ed = var_find( DEFVNAME_EDITOR ); str_btoc( edname, var_getsval( ed )); sprintf( tbuf, "%s %s", edname, CURTASK progfile ); #if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwb_edit(): command line <%s>", tbuf ); bwb_debug( bwb_ebuf ); #else nl(); endwin(); /* Added by JBV 10/11/97 */ system( tbuf ); /*-----------------------*/ /* Added by JBV 10/11/97 */ /*-----------------------*/ fprintf( stderr, "Press RETURN when ready..." ); fgets( tbuf, MAXREADLINESIZE, stdin ); refresh(); nonl(); #endif /* open edited file for read */ if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL ) { sprintf( bwb_ebuf, err_openfile, CURTASK progfile ); bwb_error( bwb_ebuf ); ncu_setpos(); return bwb_zline( l ); } /* clear current contents */ bwb_new( l ); /* Relocated by JBV (bug found by DD) */ /* and (re)load the file into memory */ bwb_fload( loadfile ); ncu_setpos(); return bwb_zline( l ); }
static int op_and(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for logical * comparison; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be compared logically."); bwb_error(bwb_ebuf); return FALSE; break; case NUMBER: { /* N = X AND Y */ long X; long Y; long N; X = exp_getival(&(CURTASK exps[level - 1])); Y = exp_getival(&(CURTASK exps[level + 1])); N = X & Y; CURTASK exps[level - 1].nval = N; } break; } /* set variable type to integer */ CURTASK exps[level - 1].type = NUMBER; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
struct bwb_line * bwb_edit( struct bwb_line *l ) { char tbuf[ MAXSTRINGSIZE + 1 ]; char edname[ MAXSTRINGSIZE + 1 ]; struct bwb_variable *ed; FILE *loadfile; ed = var_find( DEFVNAME_EDITOR ); str_btoc( edname, var_getsval( ed )); sprintf( tbuf, "%s %s", edname, CURTASK progfile ); #if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwb_edit(): command line <%s>", tbuf ); bwb_debug( bwb_ebuf ); #else system( tbuf ); #endif /* open edited file for read */ if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL ) { sprintf( bwb_ebuf, err_openfile, CURTASK progfile ); bwb_error( bwb_ebuf ); iqc_setpos(); return bwb_zline( l ); } /* clear current contents */ bwb_new( l ); /* Relocated by JBV (bug found by DD) */ /* and (re)load the file into memory */ bwb_fload( loadfile ); iqc_setpos(); return bwb_zline( l ); }
static int op_posation(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for logical * comparison; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be compared logically."); bwb_error(bwb_ebuf); return FALSE; break; default: CURTASK exps[level].nval = (exp_getnval(&(CURTASK exps[level + 1]))); break; } /* set variable type to requested precision (JBV) */ CURTASK exps[level].type = (char) precision; CURTASK exps[level].operation = NUMBER; /* decrement the stack once */ op_pulldown(1); return TRUE; }
static int op_multiply(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for string * addition; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be multiplied."); bwb_error(bwb_ebuf); return FALSE; break; case NUMBER: CURTASK exps[level - 1].nval = exp_getnval(&(CURTASK exps[level - 1])) * exp_getnval(&(CURTASK exps[level + 1])); break; } /* set variable to requested precision */ CURTASK exps[level - 1].type = (char) precision; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
struct bwb_line * bwb_OPEN(struct bwb_line * l) { /* OPEN filename [FOR mode] AS filenumber [LEN reclen] */ char filename[BasicStringLengthMax + 1]; char mode[BasicStringLengthMax + 1]; char filenumber[BasicStringLengthMax + 1]; char reclen[BasicStringLengthMax + 1]; char OutputBuffer[BasicStringLengthMax + 1]; int p; bwx_DEBUG(__FUNCTION__); /* OPEN filename [FOR mode] AS */ if (GetKeyword(l, filename, " FOR ")) { /* OPEN filename FOR */ if (GetKeyword(l, mode, " AS ")) { /* FOR mode AS */ } else { bwb_error("syntax error"); } } else if (GetKeyword(l, filename, " AS ")) { /* OPEN filename AS */ strcpy(mode, "BINARY"); /* default for structured OPEN */ } else { bwb_error("syntax error"); } /* AS filenumber [LEN reclen] */ if (GetKeyword(l, filenumber, " LEN ")) { /* AS filenumber LEN reclen */ GetRestOfLine(l, reclen); } else { /* AS filenumber */ GetRestOfLine(l, filenumber); strcpy(reclen, "128"); /* default for structured OPEN */ } OutputBuffer[0] = '\0'; strcat(OutputBuffer, "OPEN("); strcat(OutputBuffer, "\""); strcat(OutputBuffer, mode); strcat(OutputBuffer, "\""); strcat(OutputBuffer, ","); strcat(OutputBuffer, filenumber); strcat(OutputBuffer, ","); strcat(OutputBuffer, filename); strcat(OutputBuffer, ","); strcat(OutputBuffer, reclen); strcat(OutputBuffer, ")"); p = 0; bwb_exp(OutputBuffer, FALSE, &p); if (ERROR_PENDING) { /* oops */ } return bwb_zline(l); }
static struct bwb_line * dio_lrset(struct bwb_line * l, int rset) { char varname[BasicNameLengthMax + 1]; bstring *d, *s; int *pp; int n_params; int p; register int n, i; int startpos; struct exp_ese *e; struct bwb_variable *v; int pos; bwx_DEBUG(__FUNCTION__); /* find the variable name */ bwb_getvarname(l->buffer, varname, &(l->position)); v = var_find(varname); if (v == NULL) { sprintf(bwb_ebuf, "in dio_lrset(): failed to find variable"); bwb_error(bwb_ebuf); } if (v->type != STRING) { sprintf(bwb_ebuf, "in dio_lrset(): assignment must be to string variable"); bwb_error(bwb_ebuf); } /* read subscripts */ pos = 0; if ((v->dimensions == 1) && (v->array_sizes[0] == 1)) { n_params = 1; pp = &p; pp[0] = dim_base; } else { dim_getparams(l->buffer, &(l->position), &n_params, &pp); } CURTASK exps[CURTASK expsc].pos_adv = pos; for (n = 0; n < v->dimensions; ++n) { v->array_pos[n] = pp[n]; } /* get bstring pointer */ d = var_findsval(v, pp); /* find equals sign */ adv_ws(l->buffer, &(l->position)); if (l->buffer[l->position] != '=') { sprintf(bwb_ebuf, "in dio_lrset(): failed to find equal sign"); bwb_error(bwb_ebuf); } ++(l->position); adv_ws(l->buffer, &(l->position)); /* read remainder of line to get value */ e = bwb_exp(l->buffer, FALSE, &(l->position)); if (ERROR_PENDING) { return bwb_zline(l); } s = exp_getsval(e); /* set starting position */ startpos = 0; if (rset == TRUE) { if (s->length < d->length) { startpos = d->length - s->length; } } /* write characters to new position */ i = 0; for (n = startpos; (i < (int) s->length) && (n < (int) d->length); ++n) { d->sbuffer[n] = s->sbuffer[i]; ++i; } /* return */ return bwb_zline(l); }
struct bwb_line * bwb_FIELD(struct bwb_line * l) { int dev_number; struct exp_ese *e; int current_pos; char atbuf[BasicStringLengthMax + 1]; int pos; bwx_DEBUG(__FUNCTION__); current_pos = 0; /* first read device number */ adv_ws(l->buffer, &(l->position)); if (l->buffer[l->position] == BasicFileNumberPrefix) { ++(l->position); adv_ws(l->buffer, &(l->position)); } adv_element(l->buffer, &(l->position), atbuf); pos = 0; e = bwb_exp(atbuf, FALSE, &pos); if (ERROR_PENDING) { return bwb_zline(l); } if (e->type != NUMBER) { bwb_error("in bwb_field(): Number was expected for device number"); return bwb_zline(l); } dev_number = exp_getival(e); if (dev_number < 1 || dev_number > BasicFileNumberMax) { bwb_error("in bwb_field(): Requested device number is not VALID."); return bwb_zline(l); } /* be sure that the requested device is open */ if (dev_table[dev_number].mode != DEVMODE_RANDOM) { bwb_error("in bwb_field(): Requested device number is not RANDOM."); return bwb_zline(l); } /* loop to read variables */ do { int length; struct bwb_variable *v; bstring *b; /* read the comma and advance beyond it */ adv_ws(l->buffer, &(l->position)); if (l->buffer[l->position] == ',') { ++(l->position); } /* first find the size of the field */ adv_element(l->buffer, &(l->position), atbuf); /* get element */ pos = 0; e = bwb_exp(atbuf, FALSE, &pos); if (ERROR_PENDING) { return bwb_zline(l); } if (e->type != NUMBER) { bwb_error("in bwb_field(): number value for field size not found"); return bwb_zline(l); } length = exp_getival(e); /* read the AS */ adv_element(l->buffer, &(l->position), atbuf); /* get element */ if (strcasecmp(atbuf, "AS") != 0) { bwb_error("in bwb_field(): AS statement not found"); return bwb_zline(l); } /* read the string variable name */ #if 0 adv_element(l->buffer, &(l->position), atbuf); /* get element */ #endif bwb_getvarname(l->buffer, atbuf, &(l->position)); v = var_find(atbuf); if (v->type != STRING) { bwb_error("in bwb_field(): string variable name not found"); return bwb_zline(l); } /* check for overflow of record length */ if ((current_pos + length) > dev_table[dev_number].width) { bwb_error("in bwb_field(): record length exceeded"); return bwb_zline(l); } /* set buffer */ b = var_findsval(v, v->array_pos); b->sbuffer = dev_table[dev_number].buffer + current_pos; b->length = (unsigned int) length; /* Was unsigned char * (JBV 9/4/97) */ b->rab = TRUE; current_pos += length; /* eat up any remaining whitespace */ adv_ws(l->buffer, &(l->position)); } while (l->buffer[l->position] == ','); /* return */ return bwb_zline(l); }
struct bwb_line * bwb_NAME(struct bwb_line * l) { int r; int position; struct exp_ese *e; char atbuf[BasicStringLengthMax + 1]; char btbuf[BasicStringLengthMax + 1]; bwx_DEBUG(__FUNCTION__); /* get the first argument in atbuf */ adv_element(l->buffer, &(l->position), atbuf); /* interpret the first argument */ position = 0; e = bwb_exp(atbuf, FALSE, &position); if (ERROR_PENDING) { return bwb_zline(l); } if (e->type != STRING) { bwb_error(err_argstr); return bwb_zline(l); } /* this argument must be copied back to atbuf, else the next call to * bwb_exp() will overwrite the structure to which e refers */ str_btoc(atbuf, &(e->sval)); /* get the second argument in btbuf */ adv_element(l->buffer, &(l->position), btbuf); if (strcasecmp(btbuf, "AS") != 0) { bwb_error(err_syntax); return bwb_zline(l); } /* get the third argument in btbuf */ adv_element(l->buffer, &(l->position), btbuf); /* interpret the third argument */ position = 0; e = bwb_exp(btbuf, FALSE, &position); if (ERROR_PENDING) { return bwb_zline(l); } if (e->type != STRING) { bwb_error(err_argstr); return bwb_zline(l); } str_btoc(btbuf, &(e->sval)); /* try to rename the file */ r = rename(atbuf, btbuf); /* detect error */ if (r != 0) { bwb_error(err_opsys); } return bwb_zline(l); }
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; }
static int op_assign(int level, int precision) { bwx_DEBUG(__FUNCTION__); /* Make sure the position one level below is a variable */ if (CURTASK exps[level - 1].operation != VARIABLE) { op_pulldown(2); sprintf(bwb_ebuf, "in op_assign(): Assignment must be to variable: level -1 <%d> op <%d>", level - 1, CURTASK exps[level - 1].operation); bwb_error(bwb_ebuf); return FALSE; } if (CURTASK exps[level - 1].type != CURTASK exps[level + 1].type) { bwb_error("Type Mismatch"); return FALSE; } /* if the assignment is numerical, then the precision should be set * to that of the variable on the left-hand side of the assignment */ if (precision != STRING) { precision = (int) CURTASK exps[level - 1].type; } switch (precision) { case STRING: str_btob(exp_getsval(&(CURTASK exps[level - 1])), exp_getsval(&(CURTASK exps[level + 1]))); break; case NUMBER: if (TRUE) { double Value; Value = exp_getnval(&(CURTASK exps[level + 1])); Value = VerifyNumeric(Value); /* assign Value */ *var_findnval(CURTASK exps[level - 1].xvar, CURTASK exps[level - 1].array_pos) = CURTASK exps[level - 1].nval = Value; } break; default: sprintf(bwb_ebuf, "in op_assign(): Variable before assignment operator has unidentified type."); bwb_error(bwb_ebuf); return FALSE; } /* set variable to requested precision */ CURTASK exps[level - 1].type = (char) precision; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
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; } }
static int op_divide(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for * division; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be divided."); bwb_error(bwb_ebuf); return FALSE; break; case NUMBER: if (exp_getnval(&(CURTASK exps[level + 1])) == 0) { /* - Evaluation of an expression results in division * by zero (nonfatal, the recommended recovery * procedure is to supply machine infinity with the * sign of the numerator and continue) */ if (exp_getnval(&(CURTASK exps[level - 1])) < 0) { /* NEGATIVE */ CURTASK exps[level - 1].nval = -(DBL_MAX); /* NEGATIVE INFINITY */ } else { /* POSITIVE */ CURTASK exps[level - 1].nval = (DBL_MAX); /* POSITIVE INFINITY */ } bwb_Warning_Overflow("*** WARNING: Divide by 0 ***"); } else { CURTASK exps[level - 1].nval = exp_getnval(&(CURTASK exps[level - 1])) / exp_getnval(&(CURTASK exps[level + 1])); } break; } /* set variable to requested precision */ CURTASK exps[level - 1].type = (char) precision; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack twice */ op_pulldown(2); return TRUE; }
extern int bwx_shell( struct bwb_line *l ) { static char *s_buffer; static int init = FALSE; static int position; /* get memory for temporary buffer if necessary */ if ( init == FALSE ) { init = TRUE; /* Revised to CALLOC pass-thru call by JBV */ if ( ( s_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ),"bwx_shell" )) == NULL ) { bwb_error( err_getmem ); return FALSE; } } /* get the first element and check for a line number */ #if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwx_shell(): line buffer is <%s>.", l->buffer ); bwb_debug( bwb_ebuf ); #endif position = 0; adv_element( l->buffer, &position, s_buffer ); if ( is_numconst( s_buffer ) != TRUE ) /* not a line number */ { #if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwx_shell(): no line number, command <%s>.", l->buffer ); bwb_debug( bwb_ebuf ); #endif nl(); endwin(); /* Added by JBV 10/11/97 */ if ( system( l->buffer ) == 0 ) { refresh(); /* Added by JBV 10/11/97 */ nonl(); ncu_setpos(); return TRUE; } else { refresh(); /* Added by JBV 10/11/97 */ nonl(); ncu_setpos(); return FALSE; } } else /* advance past line number */ { adv_ws( l->buffer, &position ); /* advance past whitespace */ #if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwx_shell(): line number, command <%s>.", l->buffer ); bwb_debug( bwb_ebuf ); #endif nl(); endwin(); /* Added by JBV 10/11/97 */ if ( system( &( l->buffer[ position ] ) ) == 0 ) { refresh(); /* Added by JBV 10/11/97 */ nonl(); ncu_setpos(); return TRUE; } else { refresh(); /* Added by JBV 10/11/97 */ nonl(); ncu_setpos(); return FALSE; } } }
static int op_oplevel(int level) { int precision; bwx_DEBUG(__FUNCTION__); /* set the precision */ if ((precision = op_getprecision(level)) == OP_ERROR) { op_pulldown(2); sprintf(bwb_ebuf, "exp_operation(): failed to set precision."); bwb_error(bwb_ebuf); return FALSE; } /* precision is set correctly */ else { switch (CURTASK exps[level].operation) { case OP_ADD: op_add(level, precision); break; case OP_SUBTRACT: op_subtract(level, precision); break; case OP_MULTIPLY: op_multiply(level, precision); break; case OP_DIVIDE: op_divide(level, precision); break; case OP_ASSIGN: op_assign(level, precision); break; case OP_EQUALS: op_equals(level, precision); break; case OP_LESSTHAN: op_lessthan(level, precision); break; case OP_GREATERTHAN: op_greaterthan(level, precision); break; case OP_LTEQ: op_lteq(level, precision); break; case OP_GTEQ: op_gteq(level, precision); break; case OP_NOTEQUAL: op_notequal(level, precision); break; case OP_MODULUS: op_modulus(level, precision); break; case OP_INTDIVISION: op_intdiv(level, precision); break; case OP_OR: op_or(level, precision); break; case OP_AND: op_and(level, precision); break; case OP_NOT: op_not(level, precision); break; case OP_XOR: op_xor(level, precision); break; case OP_IMPLIES: op_imp(level, precision); break; case OP_EQUIV: op_eqv(level, precision); break; case OP_EXPONENT: op_exponent(level, precision); break; case OP_NEGATION: /* JBV */ op_negation(level, precision); break; case OP_POSATION: op_posation(level, precision); break; default: sprintf(bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[level].operation); op_pulldown(2); bwb_error(bwb_ebuf); return FALSE; break; } /* end of case statement for operators */ } /* end of else statement, precision set */ return TRUE; } /* end of function op_oplevel() */
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; }
static int op_exponent(int level, int precision) { bwx_DEBUG(__FUNCTION__); switch (precision) { case STRING: /* both sides of the operation should be numbers for string * addition; if not, report an error */ sprintf(bwb_ebuf, "Strings cannot be taken as exponents."); bwb_error(bwb_ebuf); return FALSE; break; case NUMBER: if (TRUE) { /* N = X ^ Y */ BasicNumberType X; BasicNumberType Y; BasicNumberType N; X = exp_getnval(&(CURTASK exps[level - 1])); Y = exp_getnval(&(CURTASK exps[level + 1])); if (X < 0 && Y != (int) Y) { /*** FATAL ***/ /* - Evaluation of the operation of * involution results in a nega- tive number * being raised to a non-integral power * (fatal). */ N = 0; bwb_error("NEGATIVE QUANTITY RAISED TO A NON-INTEGRAL POWER"); return FALSE; } else if (X == 0 && Y < 0) { /* - Evaluation of the operation of * involution results in a zero be- ing * raised to a negative value (nonfatal, the * recommended re- covery procedure is to * supply positive machine infinity and * continue). */ N = (DBL_MAX); bwb_Warning_Overflow("*** Arithmetic Overflow ***"); } else { N = pow(X, Y); } CURTASK exps[level - 1].nval = N; } break; } /* set variable to requested precision */ CURTASK exps[level - 1].type = (char) precision; CURTASK exps[level - 1].operation = NUMBER; /* decrement the stack twice */ op_pulldown(2); return TRUE; }