home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
calc-2.9.0
/
part07
< prev
next >
Wrap
Text File
|
1993-12-07
|
58KB
|
2,797 lines
Newsgroups: comp.sources.unix
From: dbell@canb.auug.org.au (David I. Bell)
Subject: v27i134: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part07/19
References: <1.755316719.21314@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com
Submitted-By: dbell@canb.auug.org.au (David I. Bell)
Posting-Number: Volume 27, Issue 134
Archive-Name: calc-2.9.0/part07
#!/bin/sh
# this is part 7 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc2.9.0/obj.c continued
#
CurArch=7
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file calc2.9.0/obj.c"
sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/obj.c
X * This converts the element index from the element table into an offset
X * into the object value array. Returns -1 if the element index is unknown.
X */
Xint
Xobjoffset(op, index)
X OBJECT *op;
X long index;
X{
X register OBJECTACTIONS *oap;
X int offset; /* offset into value array */
X
X oap = op->o_actions;
X for (offset = oap->count - 1; offset >= 0; offset--) {
X if (oap->elements[offset] == index)
X return offset;
X }
X return -1;
X}
X
X
X/*
X * Allocate a new object structure with the specified index.
X */
XOBJECT *
Xobjalloc(index)
X long index;
X{
X OBJECTACTIONS *oap;
X OBJECT *op;
X VALUE *vp;
X int i;
X
X if ((unsigned) index >= MAXOBJECTS)
X math_error("Allocating bad object index");
X oap = objects[index];
X if (oap == NULL)
X math_error("Object type not defined");
X i = oap->count;
X if (i < USUAL_ELEMENTS)
X i = USUAL_ELEMENTS;
X if (i == USUAL_ELEMENTS)
X op = (OBJECT *) allocitem(&freelist);
X else
X op = (OBJECT *) malloc(objectsize(i));
X if (op == NULL)
X math_error("Cannot allocate object");
X op->o_actions = oap;
X vp = op->o_table;
X for (i = oap->count; i-- > 0; vp++) {
X vp->v_num = qlink(&_qzero_);
X vp->v_type = V_NUM;
X }
X return op;
X}
X
X
X/*
X * Free an object structure.
X */
Xvoid
Xobjfree(op)
X register OBJECT *op;
X{
X VALUE *vp;
X int i;
X
X vp = op->o_table;
X for (i = op->o_actions->count; i-- > 0; vp++) {
X if (vp->v_type == V_NUM) {
X qfree(vp->v_num);
X } else
X freevalue(vp);
X }
X if (op->o_actions->count <= USUAL_ELEMENTS)
X freeitem(&freelist, (FREEITEM *) op);
X else
X free((char *) op);
X}
X
X
X/*
X * Copy an object value
X */
XOBJECT *
Xobjcopy(op)
X OBJECT *op;
X{
X VALUE *v1, *v2;
X OBJECT *np;
X int i;
X
X i = op->o_actions->count;
X if (i < USUAL_ELEMENTS)
X i = USUAL_ELEMENTS;
X if (i == USUAL_ELEMENTS)
X np = (OBJECT *) allocitem(&freelist);
X else
X np = (OBJECT *) malloc(objectsize(i));
X if (np == NULL)
X math_error("Cannot allocate object");
X np->o_actions = op->o_actions;
X v1 = op->o_table;
X v2 = np->o_table;
X for (i = op->o_actions->count; i-- > 0; v1++, v2++) {
X if (v1->v_type == V_NUM) {
X v2->v_num = qlink(v1->v_num);
X v2->v_type = V_NUM;
X } else
X copyvalue(v1, v2);
X }
X return np;
X}
X
X
X/*
X * Return a trivial hash value for an object.
X */
XHASH
Xobjhash(op)
X OBJECT *op;
X{
X HASH hash;
X int i;
X
X hash = 0;
X i = op->o_actions->count;
X while (--i >= 0)
X hash = hash * 4000037 + hashvalue(&op->o_table[i]);
X return hash;
X}
X
X/* END CODE */
SHAR_EOF
echo "File calc2.9.0/obj.c is complete"
chmod 0644 calc2.9.0/obj.c || echo "restore of calc2.9.0/obj.c fails"
set `wc -c calc2.9.0/obj.c`;Sum=$1
if test "$Sum" != "15522"
then echo original size 15522, current size $Sum;fi
echo "x - extracting calc2.9.0/opcodes.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/opcodes.c &&
X/*
X * Copyright (c) 1993 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X *
X * Opcode execution module
X */
X
X#include "stdarg.h"
X#include "calc.h"
X#include "opcodes.h"
X#include "func.h"
X#include "symbol.h"
X#include "hist.h"
X
X#define QUICKLOCALS 20 /* local vars to handle quickly */
X
X
XVALUE *stack; /* current location of top of stack */
Xstatic VALUE stackarray[MAXSTACK]; /* storage for stack */
Xstatic VALUE oldvalue; /* previous calculation value */
Xstatic char *funcname; /* function being executed */
Xstatic long funcline; /* function line being executed */
X
XFLAG traceflags; /* current trace flags */
X
X
X/*
X * Routine definitions
X */
Xstatic void o_nop(), o_localaddr(), o_globaladdr(), o_paramaddr();
Xstatic void o_globalvalue(), o_paramvalue(), o_number(), o_indexaddr();
Xstatic void o_assign(), o_add(), o_sub(), o_mul(), o_div();
Xstatic void o_mod(), o_save(), o_negate(), o_invert(), o_int(), o_frac();
Xstatic void o_numerator(), o_denominator(), o_duplicate(), o_pop();
Xstatic void o_jumpeq(), o_jumpne(), o_jump(), o_usercall(), o_getvalue();
Xstatic void o_eq(), o_ne(), o_le(), o_ge(), o_lt(), o_gt(), o_preinc();
Xstatic void o_postinc(), o_postdec(), o_debug(), o_print(), o_assignpop();
Xstatic void o_zero(), o_one(), o_printeol(), o_printspace(), o_printstring();
Xstatic void o_oldvalue(), o_quo(), o_power(), o_quit(), o_call(), o_swap();
Xstatic void o_dupvalue(), o_getepsilon(), o_and(), o_or(), o_not();
Xstatic void o_abs(), o_sgn(), o_isint(), o_condorjump(), o_condandjump();
Xstatic void o_square(), o_string(), o_isnum(), o_undef(), o_isnull();
Xstatic void o_matcreate(), o_ismat(), o_isstr(), o_getconfig(), o_predec();
Xstatic void o_leftshift(), o_rightshift(), o_casejump();
Xstatic void o_isodd(), o_iseven(), o_fiaddr(), o_fivalue(), o_argvalue();
Xstatic void o_isreal(), o_imaginary(), o_re(), o_im(), o_conjugate();
Xstatic void o_objcreate(), o_isobj(), o_norm(), o_elemaddr(), o_elemvalue();
Xstatic void o_istype(), o_scale(), o_localvalue(), o_return(), o_islist();
Xstatic void o_issimple(), o_cmp(), o_quomod(), o_setconfig(), o_setepsilon();
Xstatic void o_printresult(), o_isfile(), o_isassoc(), o_eleminit();
X
X
X/*
X * Types of opcodes (depends on arguments saved after the opcode).
X */
X#define OPNUL 1 /* opcode has no arguments */
X#define OPONE 2 /* opcode has one integer argument */
X#define OPTWO 3 /* opcode has two integer arguments */
X#define OPJMP 4 /* opcode is a jump (with one pointer argument) */
X#define OPRET 5 /* opcode is a return (with no argument) */
X#define OPGLB 6 /* opcode has global symbol pointer argument */
X#define OPPAR 7 /* opcode has parameter index argument */
X#define OPLOC 8 /* opcode needs local variable pointer (with one arg) */
X#define OPSTR 9 /* opcode has a string constant arg */
X#define OPARG 10 /* opcode is given number of arguments */
X#define OPSTI 11 /* opcode is static initialization */
X
X
X/*
X * Information about each opcode.
X */
Xstatic struct opcode {
X void (*o_func)(); /* routine to call for opcode */
X int o_type; /* type of opcode */
X char *o_name; /* name of opcode */
X} opcodes[MAX_OPCODE+1] = {
X o_nop, OPNUL, "NOP", /* no operation */
X o_localaddr, OPLOC, "LOCALADDR", /* address of local variable */
X o_globaladdr, OPGLB, "GLOBALADDR", /* address of global variable */
X o_paramaddr, OPPAR, "PARAMADDR", /* address of paramater variable */
X o_localvalue, OPLOC, "LOCALVALUE", /* value of local variable */
X o_globalvalue, OPGLB, "GLOBALVALUE", /* value of global variable */
X o_paramvalue, OPPAR, "PARAMVALUE", /* value of paramater variable */
X o_number, OPONE, "NUMBER", /* constant real numeric value */
X o_indexaddr, OPTWO, "INDEXADDR", /* array index address */
X o_printresult, OPNUL, "PRINTRESULT", /* print result of top-level expression */
X o_assign, OPNUL, "ASSIGN", /* assign value to variable */
X o_add, OPNUL, "ADD", /* add top two values */
X o_sub, OPNUL, "SUB", /* subtract top two values */
X o_mul, OPNUL, "MUL", /* multiply top two values */
X o_div, OPNUL, "DIV", /* divide top two values */
X o_mod, OPNUL, "MOD", /* take mod of top two values */
X o_save, OPNUL, "SAVE", /* save value for later use */
X o_negate, OPNUL, "NEGATE", /* negate top value */
X o_invert, OPNUL, "INVERT", /* invert top value */
X o_int, OPNUL, "INT", /* take integer part */
X o_frac, OPNUL, "FRAC", /* take fraction part */
X o_numerator, OPNUL, "NUMERATOR", /* take numerator */
X o_denominator, OPNUL, "DENOMINATOR", /* take denominator */
X o_duplicate, OPNUL, "DUPLICATE", /* duplicate top value */
X o_pop, OPNUL, "POP", /* pop top value */
X o_return, OPRET, "RETURN", /* return value of function */
X o_jumpeq, OPJMP, "JUMPEQ", /* jump if value zero */
X o_jumpne, OPJMP, "JUMPNE", /* jump if value nonzero */
X o_jump, OPJMP, "JUMP", /* jump unconditionally */
X o_usercall, OPTWO, "USERCALL", /* call a user function */
X o_getvalue, OPNUL, "GETVALUE", /* convert address to value */
X o_eq, OPNUL, "EQ", /* test elements for equality */
X o_ne, OPNUL, "NE", /* test elements for inequality */
X o_le, OPNUL, "LE", /* test elements for <= */
X o_ge, OPNUL, "GE", /* test elements for >= */
X o_lt, OPNUL, "LT", /* test elements for < */
X o_gt, OPNUL, "GT", /* test elements for > */
X o_preinc, OPNUL, "PREINC", /* add one to variable (++x) */
X o_predec, OPNUL, "PREDEC", /* subtract one from variable (--x) */
X o_postinc, OPNUL, "POSTINC", /* add one to variable (x++) */
X o_postdec, OPNUL, "POSTDEC", /* subtract one from variable (x--) */
X o_debug, OPONE, "DEBUG", /* debugging point */
X o_print, OPONE, "PRINT", /* print value */
X o_assignpop, OPNUL, "ASSIGNPOP", /* assign to variable and pop it */
X o_zero, OPNUL, "ZERO", /* put zero on the stack */
X o_one, OPNUL, "ONE", /* put one on the stack */
X o_printeol, OPNUL, "PRINTEOL", /* print end of line */
X o_printspace, OPNUL, "PRINTSPACE", /* print a space */
X o_printstring, OPSTR, "PRINTSTR", /* print constant string */
X o_dupvalue, OPNUL, "DUPVALUE", /* duplicate value of top value */
X o_oldvalue, OPNUL, "OLDVALUE", /* old value from previous calc */
X o_quo, OPNUL, "QUO", /* integer quotient of top values */
X o_power, OPNUL, "POWER", /* value raised to a power */
X o_quit, OPSTR, "QUIT", /* quit program */
X o_call, OPTWO, "CALL", /* call built-in routine */
X o_getepsilon, OPNUL, "GETEPSILON", /* get allowed error for calculations */
X o_and, OPNUL, "AND", /* arithmetic and or top two values */
X o_or, OPNUL, "OR", /* arithmetic or of top two values */
X o_not, OPNUL, "NOT", /* logical not or top value */
X o_abs, OPNUL, "ABS", /* absolute value of top value */
X o_sgn, OPNUL, "SGN", /* sign of number */
X o_isint, OPNUL, "ISINT", /* whether number is an integer */
X o_condorjump, OPJMP, "CONDORJUMP", /* conditional or jump */
X o_condandjump, OPJMP, "CONDANDJUMP", /* conditional and jump */
X o_square, OPNUL, "SQUARE", /* square top value */
X o_string, OPSTR, "STRING", /* string constant value */
X o_isnum, OPNUL, "ISNUM", /* whether value is a number */
X o_undef, OPNUL, "UNDEF", /* load undefined value on stack */
X o_isnull, OPNUL, "ISNULL", /* whether value is the null value */
X o_argvalue, OPARG, "ARGVALUE", /* load value of arg (parameter) n */
X o_matcreate, OPONE, "MATCREATE", /* create matrix */
X o_ismat, OPNUL, "ISMAT", /* whether value is a matrix */
X o_isstr, OPNUL, "ISSTR", /* whether value is a string */
X o_getconfig, OPNUL, "GETCONFIG", /* get value of configuration parameter */
X o_leftshift, OPNUL, "LEFTSHIFT", /* left shift of integer */
X o_rightshift, OPNUL, "RIGHTSHIFT", /* right shift of integer */
X o_casejump, OPJMP, "CASEJUMP", /* test case and jump if not matched */
X o_isodd, OPNUL, "ISODD", /* whether value is odd integer */
X o_iseven, OPNUL, "ISEVEN", /* whether value is even integer */
X o_fiaddr, OPNUL, "FIADDR", /* 'fast index' matrix address */
X o_fivalue, OPNUL, "FIVALUE", /* 'fast index' matrix value */
X o_isreal, OPNUL, "ISREAL", /* whether value is real number */
X o_imaginary, OPONE, "IMAGINARY", /* constant imaginary numeric value */
X o_re, OPNUL, "RE", /* real part of complex number */
X o_im, OPNUL, "IM", /* imaginary part of complex number */
X o_conjugate, OPNUL, "CONJUGATE", /* complex conjugate */
X o_objcreate, OPONE, "OBJCREATE", /* create object */
X o_isobj, OPNUL, "ISOBJ", /* whether value is an object */
X o_norm, OPNUL, "NORM", /* norm of value (square of abs) */
X o_elemaddr, OPONE, "ELEMADDR", /* address of element of object */
X o_elemvalue, OPONE, "ELEMVALUE", /* value of element of object */
X o_istype, OPNUL, "ISTYPE", /* whether types are the same */
X o_scale, OPNUL, "SCALE", /* scale value by a power of two */
X o_islist, OPNUL, "ISLIST", /* whether value is a list */
X o_swap, OPNUL, "SWAP", /* swap values of two variables */
X o_issimple, OPNUL, "ISSIMPLE", /* whether value is simple type */
X o_cmp, OPNUL, "CMP", /* compare values returning -1, 0, 1 */
X o_quomod, OPNUL, "QUOMOD", /* calculate quotient and remainder */
X o_setconfig, OPNUL, "SETCONFIG", /* set configuration parameter */
X o_setepsilon, OPNUL, "SETEPSILON", /* set allowed error for calculations */
X o_isfile, OPNUL, "ISFILE", /* whether value is a file */
X o_isassoc, OPNUL, "ISASSOC", /* whether value is an association */
X o_nop, OPSTI, "INITSTATIC", /* once only code for static init */
X o_eleminit, OPONE, "ELEMINIT" /* assign element of matrix or object */
X};
X
X
X
X/*
X * Initialize the stack.
X */
Xvoid
Xinitstack()
X{
X if (stack == NULL)
X stack = stackarray;
X while (stack != stackarray)
X freevalue(stack--);
X}
X
X
X/*
X * Compute the result of a function by interpreting opcodes.
X * Arguments have just been pushed onto the evaluation stack.
X */
Xvoid
Xcalculate(fp, argcount)
X register FUNC *fp; /* function to calculate */
X int argcount; /* number of arguments called with */
X{
X register unsigned long pc; /* current pc inside function */
X register struct opcode *op; /* current opcode pointer */
X register VALUE *locals; /* pointer to local variables */
X long oldline; /* old value of line counter */
X unsigned int opnum; /* current opcode number */
X int origargcount; /* original number of arguments */
X int i; /* loop counter */
X BOOL dojump; /* TRUE if jump is to occur */
X char *oldname; /* old function name being executed */
X VALUE *beginstack; /* beginning of stack frame */
X VALUE *args; /* pointer to function arguments */
X VALUE retval; /* function return value */
X VALUE localtable[QUICKLOCALS]; /* some local variables */
X
X oldname = funcname;
X oldline = funcline;
X funcname = fp->f_name;
X funcline = 0;
X origargcount = argcount;
X while (argcount < fp->f_paramcount) {
X stack++;
X stack->v_type = V_NULL;
X argcount++;
X }
X locals = localtable;
X if (fp->f_localcount > QUICKLOCALS) {
X locals = (VALUE *) malloc(sizeof(VALUE) * fp->f_localcount);
X if (locals == NULL)
X math_error("No memory for local variables");
X }
X for (i = 0; i < fp->f_localcount; i++) {
X locals[i].v_num = qlink(&_qzero_);
X locals[i].v_type = V_NUM;
X }
X pc = 0;
X beginstack = stack;
X args = beginstack - (argcount - 1);
X for (;;) {
X if (abortlevel >= ABORT_OPCODE)
X math_error("Calculation aborted in opcode");
X if (pc >= fp->f_opcodecount)
X math_error("Function pc out of range");
X if (stack > &stackarray[MAXSTACK-3])
X math_error("Evaluation stack depth exceeded");
X opnum = fp->f_opcodes[pc];
X if (opnum > MAX_OPCODE)
X math_error("Function opcode out of range");
X op = &opcodes[opnum];
X if (traceflags & TRACE_OPCODES) {
X printf("%8s, pc %4ld: ", fp->f_name, pc);
X (void)dumpop(&fp->f_opcodes[pc]);
X }
X /*
X * Now call the opcode routine appropriately.
X */
X pc++;
X switch (op->o_type) {
X case OPNUL: /* no extra arguments */
X (*op->o_func)(fp);
X break;
X
X case OPONE: /* one extra integer argument */
X (*op->o_func)(fp, fp->f_opcodes[pc++]);
X break;
X
X case OPTWO: /* two extra integer arguments */
X (*op->o_func)(fp, fp->f_opcodes[pc],
X fp->f_opcodes[pc+1]);
X pc += 2;
X break;
X
X case OPJMP: /* jump opcodes (one extra pointer arg) */
X dojump = FALSE;
X (*op->o_func)(fp, &dojump);
X if (dojump)
X pc = fp->f_opcodes[pc];
X else
X pc++;
X break;
X
X case OPGLB: /* global symbol reference (pointer arg) */
X case OPSTR: /* string constant address */
X (*op->o_func)(fp, *((char **) &fp->f_opcodes[pc]));
X pc += PTR_SIZE;
X break;
X
X case OPLOC: /* local variable reference */
X (*op->o_func)(fp, locals, fp->f_opcodes[pc++]);
X break;
X
X case OPPAR: /* parameter variable reference */
X (*op->o_func)(fp, argcount, args, fp->f_opcodes[pc++]);
X break;
X
X case OPARG: /* parameter variable reference */
X (*op->o_func)(fp, origargcount, args);
X break;
X
X case OPRET: /* return from function */
X if (stack->v_type == V_ADDR)
X copyvalue(stack->v_addr, stack);
X for (i = 0; i < fp->f_localcount; i++)
X freevalue(&locals[i]);
X if (locals != localtable)
X free(locals);
X if (stack != &beginstack[1])
X math_error("Misaligned stack");
X if (argcount <= 0) {
X funcname = oldname;
X funcline = oldline;
X return;
X }
X retval = *stack--;
X while (--argcount >= 0)
X freevalue(stack--);
X *++stack = retval;
X funcname = oldname;
X funcline = oldline;
X return;
X
X case OPSTI: /* static initialization code */
X fp->f_opcodes[pc++ - 1] = OP_JUMP;
X break;
X
X default:
X math_error("Unknown opcode type");
X }
X }
X}
X
X
X/*
X * Dump an opcode at a particular address.
X * Returns the size of the opcode so that it can easily be skipped over.
X */
Xint
Xdumpop(pc)
X long *pc; /* location of the opcode */
X{
X unsigned long op; /* opcode number */
X
X op = *pc++;
X if (op <= MAX_OPCODE)
X printf("%s", opcodes[op].o_name);
X else
X printf("OP%ld", op);
X switch (op) {
X case OP_LOCALADDR: case OP_LOCALVALUE:
X printf(" %s\n", localname(*pc));
X return 2;
X case OP_GLOBALADDR: case OP_GLOBALVALUE:
X printf(" %s\n", globalname(*((GLOBAL **) pc)));
X return (1 + PTR_SIZE);
X case OP_PARAMADDR: case OP_PARAMVALUE:
X printf(" %s\n", paramname(*pc));
X return 2;
X case OP_PRINTSTRING: case OP_STRING:
X printf(" \"%s\"\n", *((char **) pc));
X return (1 + PTR_SIZE);
X case OP_QUIT:
X if (*(char **) pc)
X printf(" \"%s\"\n", *((char **) pc));
X else
X printf("\n");
X return (1 + PTR_SIZE);
X case OP_INDEXADDR:
X printf(" %ld %ld\n", pc[0], pc[1]);
X return 3;
X case OP_PRINT: case OP_JUMPEQ: case OP_JUMPNE: case OP_JUMP:
X case OP_CONDORJUMP: case OP_CONDANDJUMP: case OP_CASEJUMP:
X case OP_INITSTATIC: case OP_MATCREATE: case OP_OBJCREATE:
X printf(" %ld\n", *pc);
X return 2;
X case OP_NUMBER: case OP_IMAGINARY:
X qprintf(" %r\n", constvalue(*pc));
X return 2;
X case OP_DEBUG:
X printf(" line %ld\n", *pc);
X return 2;
X case OP_CALL:
X printf(" %s with %ld args\n", builtinname(pc[0]), pc[1]);
X return 3;
X case OP_USERCALL:
X printf(" %s with %ld args\n", namefunc(pc[0]), pc[1]);
X return 3;
X default:
X printf("\n");
X return 1;
X }
X}
X
X
X/*
X * The various opcodes
X */
X
Xstatic void
Xo_nop()
X{
X}
X
X
Xstatic void
Xo_localaddr(fp, locals, index)
X FUNC *fp;
X VALUE *locals;
X long index;
X{
X if ((unsigned long)index >= fp->f_localcount)
X math_error("Bad local variable index");
X locals += index;
X stack++;
X stack->v_addr = locals;
X stack->v_type = V_ADDR;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_globaladdr(fp, sp)
X FUNC *fp;
X GLOBAL *sp;
X{
X if (sp == NULL)
X math_error("Global variable \"%s\" not initialized", sp->g_name);
X stack++;
X stack->v_addr = &sp->g_value;
X stack->v_type = V_ADDR;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_paramaddr(fp, argcount, args, index)
X FUNC *fp;
X int argcount;
X VALUE *args;
X long index;
X{
X if ((unsigned long)index >= argcount)
X math_error("Bad parameter index");
X args += index;
X stack++;
X if (args->v_type == V_ADDR)
X stack->v_addr = args->v_addr;
X else
X stack->v_addr = args;
X stack->v_type = V_ADDR;
X}
X
X
Xstatic void
Xo_localvalue(fp, locals, index)
X FUNC *fp;
X VALUE *locals;
X long index;
X{
X if ((unsigned long)index >= fp->f_localcount)
X math_error("Bad local variable index");
X locals += index;
X copyvalue(locals, ++stack);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_globalvalue(fp, sp)
X FUNC *fp;
X GLOBAL *sp; /* global symbol */
X{
X if (sp == NULL)
X math_error("Global variable not defined");
X copyvalue(&sp->g_value, ++stack);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_paramvalue(fp, argcount, args, index)
X FUNC *fp;
X int argcount;
X VALUE *args;
X long index;
X{
X if ((unsigned long)index >= argcount)
X math_error("Bad paramaeter index");
X args += index;
X if (args->v_type == V_ADDR)
X args = args->v_addr;
X copyvalue(args, ++stack);
X}
X
X
Xstatic void
Xo_argvalue(fp, argcount, args)
X FUNC *fp;
X int argcount;
X VALUE *args;
X{
X VALUE *vp;
X long index;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if ((vp->v_type != V_NUM) || qisneg(vp->v_num) ||
X qisfrac(vp->v_num))
X math_error("Illegal argument for arg function");
X if (qiszero(vp->v_num)) {
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = itoq((long) argcount);
X stack->v_type = V_NUM;
X return;
X }
X index = qtoi(vp->v_num) - 1;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X (void) o_paramvalue(fp, argcount, args, index);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_number(fp, arg)
X FUNC *fp;
X long arg;
X{
X NUMBER *q;
X
X q = constvalue(arg);
X if (q == NULL)
X math_error("Numeric constant value not found");
X stack++;
X stack->v_num = qlink(q);
X stack->v_type = V_NUM;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_imaginary(fp, arg)
X FUNC *fp;
X long arg;
X{
X NUMBER *q;
X COMPLEX *c;
X
X q = constvalue(arg);
X if (q == NULL)
X math_error("Numeric constant value not found");
X stack++;
X if (qiszero(q)) {
X stack->v_num = qlink(q);
X stack->v_type = V_NUM;
X return;
X }
X c = comalloc();
X c->real = qlink(&_qzero_);
X c->imag = qlink(q);
X stack->v_com = c;
X stack->v_type = V_COM;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_string(fp, cp)
X FUNC *fp;
X char *cp;
X{
X stack++;
X stack->v_str = cp;
X stack->v_type = V_STR;
X stack->v_subtype = V_STRLITERAL;
X}
X
X
Xstatic void
Xo_undef()
X{
X stack++;
X stack->v_type = V_NULL;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_matcreate(fp, dim)
X FUNC *fp;
X long dim;
X{
X register MATRIX *mp; /* matrix being defined */
X NUMBER *num1; /* first number from stack */
X NUMBER *num2; /* second number from stack */
X VALUE *vp; /* value being defined */
X VALUE *v1, *v2;
X long min[MAXDIM]; /* minimum range */
X long max[MAXDIM]; /* maximum range */
X long i; /* index */
X long tmp; /* temporary */
X long size; /* size of matrix */
X
X if ((dim <= 0) || (dim > MAXDIM))
X math_error("Bad dimension %ld for matrix", dim);
X if (stack[-2*dim].v_type != V_ADDR)
X math_error("Attempting to init matrix for non-address");
X size = 1;
X for (i = dim - 1; i >= 0; i--) {
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
X math_error("Non-numeric bounds for matrix");
X num1 = v1->v_num;
X num2 = v2->v_num;
X if (qisfrac(num1) || qisfrac(num2))
X math_error("Non-integral bounds for matrix");
X if (zisbig(num1->num) || zisbig(num2->num))
X math_error("Very large bounds for matrix");
X min[i] = qtoi(num1);
X max[i] = qtoi(num2);
X if (min[i] > max[i]) {
X tmp = min[i];
X min[i] = max[i];
X max[i] = tmp;
X }
X size *= (max[i] - min[i] + 1);
X if (size > 10000000)
X math_error("Very large size for matrix");
X freevalue(stack--);
X freevalue(stack--);
X }
X mp = matalloc(size);
X mp->m_dim = dim;
X for (i = 0; i < dim; i++) {
X mp->m_min[i] = min[i];
X mp->m_max[i] = max[i];
X }
X vp = mp->m_table;
X for (i = 0; i < size; i++) {
X vp->v_type = V_NUM;
X vp->v_num = qlink(&_qzero_);
X vp++;
X }
X vp = stack[0].v_addr;
X vp->v_type = V_MAT;
X vp->v_mat = mp;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_eleminit(fp, index)
X FUNC *fp;
X long index;
X{
X VALUE *vp;
X VALUE *oldvp;
X MATRIX *mp;
X OBJECT *op;
X
X vp = &stack[-1];
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X switch (vp->v_type) {
X case V_MAT:
X mp = vp->v_mat;
X if ((index < 0) || (index >= mp->m_size))
X math_error("Too many initializer values");
X oldvp = &mp->m_table[index];
X break;
X case V_OBJ:
X op = vp->v_obj;
X if ((index < 0) || (index >= op->o_actions->count))
X math_error("Too many initializer values");
X oldvp = &op->o_table[index];
X break;
X default:
X math_error("Attempt to initialize non matrix or object");
X }
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X freevalue(oldvp);
X copyvalue(vp, oldvp);
X stack--;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_indexaddr(fp, dim, writeflag)
X FUNC *fp;
X long dim; /* dimension of matrix */
X long writeflag; /* nonzero if element will be written */
X{
X int i;
X BOOL flag;
X VALUE *val;
X VALUE *vp;
X VALUE indices[MAXDIM]; /* index values */
X
X flag = (writeflag != 0);
X if ((dim <= 0) || (dim > MAXDIM))
X math_error("Too many dimensions for indexing");
X val = &stack[-dim];
X if (val->v_type != V_ADDR)
X math_error("Non-pointer for index operation");
X val = val->v_addr;
X vp = &stack[-dim + 1];
X for (i = 0; i < dim; i++) {
X if (vp->v_type == V_ADDR)
X indices[i] = vp->v_addr[0];
X else
X indices[i] = vp[0];
X vp++;
X }
X switch (val->v_type) {
X case V_MAT:
X vp = matindex(val->v_mat, flag, dim, indices);
X break;
X case V_ASSOC:
X vp = associndex(val->v_assoc, flag, dim, indices);
X break;
X default:
X math_error("Illegal value for indexing");
X }
X while (dim-- > 0)
X freevalue(stack--);
X stack->v_type = V_ADDR;
X stack->v_addr = vp;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_elemaddr(fp, index)
X FUNC *fp;
X long index;
X{
X if (stack->v_type != V_ADDR)
X math_error("Non-pointer for element reference");
X if (stack->v_addr->v_type != V_OBJ)
X math_error("Referencing element of non-object");
X index = objoffset(stack->v_addr->v_obj, index);
X if (index < 0)
X math_error("Element does not exist for object");
X stack->v_addr = &stack->v_addr->v_obj->o_table[index];
X}
X
X
Xstatic void
Xo_elemvalue(fp, index)
X FUNC *fp;
X long index;
X{
X if (stack->v_type != V_OBJ) {
X (void) o_elemaddr(fp, index);
X (void) o_getvalue();
X return;
X }
X index = objoffset(stack->v_obj, index);
X if (index < 0)
X math_error("Element does not exist for object");
X copyvalue(&stack->v_obj->o_table[index], stack);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_objcreate(fp, arg)
X FUNC *fp;
X long arg;
X{
X OBJECT *op; /* object being created */
X VALUE *vp; /* value being defined */
X
X if (stack->v_type != V_ADDR)
X math_error("Attempting to init object for non-address");
X op = objalloc(arg);
X vp = stack->v_addr;
X vp->v_type = V_OBJ;
X vp->v_obj = op;
X}
X
X
Xstatic void
Xo_assign()
X{
X VALUE *var; /* variable value */
X VALUE *vp;
X
X var = &stack[-1];
X if (var->v_type != V_ADDR)
X math_error("Assignment into non-variable");
X var = var->v_addr;
X stack[-1] = stack[0];
X stack--;
X vp = stack;
X if (vp->v_type == V_ADDR) {
X vp = vp->v_addr;
X if (vp == var)
X return;
X }
X freevalue(var);
X copyvalue(vp, var);
X}
X
X
Xstatic void
Xo_assignpop()
X{
X VALUE *var; /* variable value */
X VALUE *vp;
X
X var = &stack[-1];
X if (var->v_type != V_ADDR)
X math_error("Assignment into non-variable");
X var = var->v_addr;
X vp = &stack[0];
X if ((vp->v_type == V_ADDR) && (vp->v_addr == var)) {
X stack -= 2;
X return;
X }
X freevalue(var);
X if (vp->v_type == V_ADDR)
X copyvalue(vp->v_addr, var);
X else
X *var = *vp;
X stack -= 2;
X}
X
X
Xstatic void
Xo_swap()
X{
X VALUE *v1, *v2; /* variables to be swapped */
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if ((v1->v_type != V_ADDR) || (v2->v_type != V_ADDR))
X math_error("Swapping non-variables");
X tmp = v1->v_addr[0];
X v1->v_addr[0] = v2->v_addr[0];
X v2->v_addr[0] = tmp;
X stack--;
X stack->v_type = V_NULL;
X}
X
X
Xstatic void
Xo_add()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X addvalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = qadd(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_sub()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X subvalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = qsub(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_mul()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X mulvalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = qmul(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_power()
X{
X VALUE *v1, *v2;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X powivalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_div()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X divvalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = qdiv(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_quo()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X quovalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = qquo(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_mod()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X modvalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = qmod(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_quomod()
X{
X VALUE *v1, *v2, *v3, *v4;
X VALUE valquo, valmod;
X BOOL res;
X
X v1 = &stack[-3];
X v2 = &stack[-2];
X v3 = &stack[-1];
X v4 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v3->v_type != V_ADDR) || (v4->v_type != V_ADDR))
X math_error("Non-variable for quomod");
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
X math_error("Non-reals for quomod");
X v3 = v3->v_addr;
X v4 = v4->v_addr;
X valquo.v_type = V_NUM;
X valmod.v_type = V_NUM;
X res = qquomod(v1->v_num, v2->v_num, &valquo.v_num, &valmod.v_num);
X freevalue(stack--);
X freevalue(stack--);
X stack--;
X stack->v_num = (res ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X freevalue(v3);
X freevalue(v4);
X *v3 = valquo;
X *v4 = valmod;
X}
X
X
Xstatic void
Xo_and()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
X math_error("Non-numerics for and");
X q = qand(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_or()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
X math_error("Non-numerics for or");
X q = qor(v1->v_num, v2->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_not()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = testvalue(vp);
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qzero_) : qlink(&_qone_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_negate()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X q = qneg(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X return;
X }
X negvalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_invert()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X q = qinv(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X return;
X }
X invertvalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_scale()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[0];
X v2 = &stack[-1];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
X scalevalue(v2, v1, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X q = v1->v_num;
X if (qisfrac(q))
X math_error("Non-integral scaling factor");
X if (zisbig(q->num))
X math_error("Very large scaling factor");
X q = qscale(v2->v_num, qtoi(q));
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_int()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (qisint(vp->v_num) && (stack->v_type == V_NUM))
X return;
X q = qint(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X return;
X }
X intvalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_frac()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X q = qfrac(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X return;
X }
X fracvalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_abs()
X{
X VALUE *v1, *v2;
X NUMBER *q;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM) ||
X !qispos(v2->v_num))
X {
X absvalue(v1, v2, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X return;
X }
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X if ((stack->v_type == V_NUM) && !qisneg(v1->v_num))
X return;
X q = qabs(v1->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_norm()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X q = qsquare(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X return;
X }
X normvalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_square()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X q = qsquare(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X return;
X }
X squarevalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_istype()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if ((v1->v_type != V_OBJ) || (v2->v_type != V_OBJ))
X r = (v1->v_type == v2->v_type);
X else
X r = (v1->v_obj->o_actions == v2->v_obj->o_actions);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) r);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isint()
X{
X VALUE *vp;
X NUMBER *q;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = stack->v_addr;
X if (vp->v_type != V_NUM) {
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X return;
X }
X if (qisint(vp->v_num))
X q = qlink(&_qone_);
X else
X q = qlink(&_qzero_);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isnum()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X switch (vp->v_type) {
X case V_NUM:
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X break;
X case V_COM:
X if (stack->v_type == V_COM)
X comfree(stack->v_com);
X break;
X default:
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X return;
X }
X stack->v_num = qlink(&_qone_);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_ismat()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_MAT) {
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X return;
X }
X freevalue(stack);
X stack->v_type = V_NUM;
X stack->v_num = qlink(&_qone_);
X}
X
X
Xstatic void
Xo_islist()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = (vp->v_type == V_LIST);
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isobj()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = (vp->v_type == V_OBJ);
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isstr()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = (vp->v_type == V_STR);
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isfile()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = (vp->v_type == V_FILE);
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isassoc()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = (vp->v_type == V_ASSOC);
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_issimple()
X{
X VALUE *vp;
X int r;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X r = 0;
X switch (vp->v_type) {
X case V_NULL:
X case V_NUM:
X case V_COM:
X case V_STR:
X r = 1;
X }
X freevalue(stack);
X stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isodd()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if ((vp->v_type == V_NUM) && qisodd(vp->v_num)) {
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = qlink(&_qone_);
X stack->v_type = V_NUM;
X return;
X }
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_iseven()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if ((vp->v_type == V_NUM) && qiseven(vp->v_num)) {
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = qlink(&_qone_);
X stack->v_type = V_NUM;
X return;
X }
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isreal()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = qlink(&_qone_);
X stack->v_type = V_NUM;
X return;
X }
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_isnull()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_NULL) {
X freevalue(stack);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X return;
X }
X freevalue(stack);
X stack->v_num = qlink(&_qone_);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_re()
X{
X VALUE *vp;
X NUMBER *q;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (stack->v_type == V_ADDR) {
X stack->v_num = qlink(vp->v_num);
X stack->v_type = V_NUM;
X }
X return;
X }
X if (vp->v_type != V_COM)
X math_error("Taking real part of non-number");
X q = qlink(vp->v_com->real);
X if (stack->v_type == V_COM)
X comfree(stack->v_com);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_im()
X{
X VALUE *vp;
X NUMBER *q;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = qlink(&_qzero_);
X stack->v_type = V_NUM;
X return;
X }
X if (vp->v_type != V_COM)
X math_error("Taking imaginary part of non-number");
X q = qlink(vp->v_com->imag);
X if (stack->v_type == V_COM)
X comfree(stack->v_com);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_conjugate()
X{
X VALUE *vp;
X VALUE tmp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (stack->v_type == V_ADDR) {
X stack->v_num = qlink(vp->v_num);
X stack->v_type = V_NUM;
X }
X return;
X }
X conjvalue(vp, &tmp);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_fiaddr()
X{
X register MATRIX *m; /* current matrix element */
X NUMBER *q; /* index value */
X LIST *lp; /* list header */
X ASSOC *ap; /* association header */
X VALUE *vp; /* stack value */
X long index; /* index value as an integer */
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_NUM)
X math_error("Fast indexing by non-number");
X q = vp->v_num;
X if (qisfrac(q))
X math_error("Fast indexing by non-integer");
X index = qtoi(q);
X if (zisbig(q->num) || (index < 0))
X math_error("Index out of range for fast indexing");
X if (stack->v_type == V_NUM)
X qfree(q);
X stack--;
X vp = stack;
X if (vp->v_type != V_ADDR)
X math_error("Bad value for fast indexing");
X switch (vp->v_addr->v_type) {
X case V_OBJ:
X if (index >= vp->v_addr->v_obj->o_actions->count)
X math_error("Index out of bounds for object");
X vp->v_addr = vp->v_addr->v_obj->o_table + index;
X break;
X case V_MAT:
X m = vp->v_addr->v_mat;
X if (index >= m->m_size)
X math_error("Index out of bounds for matrix");
X vp->v_addr = m->m_table + index;
X break;
X case V_LIST:
X lp = vp->v_addr->v_list;
X vp->v_addr = listfindex(lp, index);
X if (vp->v_addr == NULL)
X math_error("Index out of bounds for list");
X break;
X case V_ASSOC:
X ap = vp->v_addr->v_assoc;
X vp->v_addr = assocfindex(ap, index);
X if (vp->v_addr == NULL)
X math_error("Index out of bounds for association");
X break;
X default:
X math_error("Bad variable type for fast indexing");
X }
X}
X
X
Xstatic void
Xo_fivalue()
X{
X (void) o_fiaddr();
X (void) o_getvalue();
X}
X
X
Xstatic void
Xo_sgn()
X{
X VALUE *vp;
X NUMBER *q;
X VALUE val;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X switch (vp->v_type) {
X case V_NUM:
X q = qsign(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(vp->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X break;
X case V_OBJ:
X val = objcall(OBJ_SGN, vp, NULL_VALUE, NULL_VALUE);
X q = itoq(val.v_int);
X freevalue(stack);
X stack->v_num = q;
X stack->v_type = V_NUM;
X break;
X default:
X math_error("Bad value for sgn");
X }
X}
X
X
Xstatic void
Xo_numerator()
X{
X VALUE *vp;
X NUMBER *q;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_NUM)
X math_error("Numerator of non-number");
X if ((stack->v_type == V_NUM) && qisint(vp->v_num))
X return;
X q = qnum(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_denominator()
X{
X VALUE *vp;
X NUMBER *q;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_NUM)
X math_error("Denominator of non-number");
X q = qden(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack->v_num = q;
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_duplicate()
X{
X copyvalue(stack, stack + 1);
X stack++;
X}
X
X
Xstatic void
Xo_dupvalue()
X{
X if (stack->v_type == V_ADDR)
X copyvalue(stack->v_addr, stack + 1);
X else
X copyvalue(stack, stack + 1);
X stack++;
X}
X
X
Xstatic void
Xo_pop()
X{
X freevalue(stack--);
X}
X
X
Xstatic void
Xo_return()
X{
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_jumpeq(fp, dojump)
X FUNC *fp;
X BOOL *dojump;
X{
X VALUE *vp;
X int i; /* result of comparison */
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X i = !qiszero(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X } else {
X i = testvalue(vp);
X freevalue(stack);
X }
X stack--;
X if (!i)
X *dojump = TRUE;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_jumpne(fp, dojump)
X FUNC *fp;
X BOOL *dojump;
X{
X VALUE *vp;
X int i; /* result of comparison */
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X i = !qiszero(vp->v_num);
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X } else {
X i = testvalue(vp);
X freevalue(stack);
X }
X stack--;
X if (i)
X *dojump = TRUE;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_condorjump(fp, dojump)
X FUNC *fp;
X BOOL *dojump;
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (!qiszero(vp->v_num)) {
X *dojump = TRUE;
X return;
X }
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X return;
X }
X if (testvalue(vp))
X *dojump = TRUE;
X else
X freevalue(stack--);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_condandjump(fp, dojump)
X FUNC *fp;
X BOOL *dojump;
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type == V_NUM) {
X if (qiszero(vp->v_num)) {
X *dojump = TRUE;
X return;
X }
X if (stack->v_type == V_NUM)
X qfree(stack->v_num);
X stack--;
X return;
X }
X if (!testvalue(vp))
X *dojump = TRUE;
X else
X freevalue(stack--);
X}
X
X
X/*
X * Compare the top two values on the stack for equality and jump if they are
X * different, popping off the top element, leaving the first one on the stack.
X * If they are equal, pop both values and do not jump.
X */
X/*ARGSUSED*/
Xstatic void
Xo_casejump(fp, dojump)
X FUNC *fp;
X BOOL *dojump;
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = comparevalue(v1, v2);
X freevalue(stack--);
X if (r)
X *dojump = TRUE;
X else
X freevalue(stack--);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_jump(fp, dojump)
X FUNC *fp;
X BOOL *dojump;
X{
X *dojump = TRUE;
X}
X
X
Xstatic void
Xo_usercall(fp, index, argcount)
X FUNC *fp;
X long index, argcount;
X{
X fp = findfunc(index);
X if (fp == NULL)
X math_error("Function \"%s\" is undefined", namefunc(index));
X calculate(fp, (int) argcount);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_call(fp, index, argcount)
X FUNC *fp;
X long index, argcount;
X{
X VALUE result;
X
X result = builtinfunc(index, (int) argcount, stack);
X while (--argcount >= 0)
X freevalue(stack--);
X stack++;
X *stack = result;
X}
X
X
Xstatic void
Xo_getvalue()
X{
X if (stack->v_type == V_ADDR)
X copyvalue(stack->v_addr, stack);
X}
X
X
Xstatic void
Xo_cmp()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = relvalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) r);
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_eq()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = comparevalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) (r == 0));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_ne()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = comparevalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) (r != 0));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_le()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = relvalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) (r <= 0));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_ge()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = relvalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) (r >= 0));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_lt()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = relvalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) (r < 0));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_gt()
X{
X VALUE *v1, *v2;
X int r;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X r = relvalue(v1, v2);
X freevalue(stack--);
X freevalue(stack);
X stack->v_num = itoq((long) (r > 0));
X stack->v_type = V_NUM;
X}
X
X
Xstatic void
Xo_preinc()
X{
X NUMBER *q, **np;
X VALUE *vp, tmp;
X
X if (stack->v_type != V_ADDR)
X math_error("Preincrementing non-variable");
X if (stack->v_addr->v_type == V_NUM) {
X np = &stack->v_addr->v_num;
X q = qinc(*np);
X qfree(*np);
X *np = q;
X stack->v_type = V_NUM;
X stack->v_num = qlink(q);
X return;
X }
X vp = stack->v_addr;
X incvalue(vp, &tmp);
X freevalue(vp);
X *vp = tmp;
X copyvalue(&tmp, stack);
X}
X
X
Xstatic void
Xo_predec()
X{
X NUMBER *q, **np;
X VALUE *vp, tmp;
X
X if (stack->v_type != V_ADDR)
X math_error("Predecrementing non-variable");
X if (stack->v_addr->v_type == V_NUM) {
X np = &stack->v_addr->v_num;
X q = qdec(*np);
X qfree(*np);
X *np = q;
X stack->v_type = V_NUM;
X stack->v_num = qlink(q);
X return;
X }
X vp = stack->v_addr;
X decvalue(vp, &tmp);
X freevalue(vp);
X *vp = tmp;
X copyvalue(&tmp, stack);
X}
X
X
Xstatic void
Xo_postinc()
X{
X NUMBER *q, **np;
X VALUE *vp, tmp;
X
X if (stack->v_type != V_ADDR)
X math_error("Postincrementing non-variable");
X if (stack->v_addr->v_type == V_NUM) {
X np = &stack->v_addr->v_num;
X q = *np;
X *np = qinc(q);
X stack->v_type = V_NUM;
X stack->v_num = q;
X return;
X }
X vp = stack->v_addr;
X tmp = *vp;
X incvalue(&tmp, vp);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_postdec()
X{
X NUMBER *q, **np;
X VALUE *vp, tmp;
X
X if (stack->v_type != V_ADDR)
X math_error("Postdecrementing non-variable");
X if (stack->v_addr->v_type == V_NUM) {
X np = &stack->v_addr->v_num;
X q = *np;
X *np = qdec(q);
X stack->v_type = V_NUM;
X stack->v_num = q;
X return;
X }
X vp = stack->v_addr;
X tmp = *vp;
X decvalue(&tmp, vp);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_leftshift()
X{
X VALUE *v1, *v2;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X shiftvalue(v1, v2, FALSE, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_rightshift()
X{
X VALUE *v1, *v2;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X shiftvalue(v1, v2, TRUE, &tmp);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_debug(fp, line)
X FUNC *fp;
X long line;
X{
X funcline = line;
X if (abortlevel >= ABORT_STATEMENT)
X math_error("Calculation aborted at statement boundary");
X}
X
X
Xstatic void
Xo_printresult()
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_NULL) {
X math_chr('\t');
X printvalue(vp, PRINT_UNAMBIG);
X math_chr('\n');
X math_flush();
X }
X freevalue(stack--);
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_print(fp, flags)
X FUNC *fp;
X long flags;
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X printvalue(vp, (int) flags);
X freevalue(stack--);
X if (traceflags & TRACE_OPCODES)
X printf("\n");
X math_flush();
X}
X
X
Xstatic void
Xo_printeol()
X{
X math_chr('\n');
X math_flush();
X}
X
X
Xstatic void
Xo_printspace()
X{
X math_chr(' ');
X if (traceflags & TRACE_OPCODES)
X printf("\n");
X}
X
X
X/*ARGSUSED*/
Xstatic void
Xo_printstring(fp, cp)
X FUNC *fp;
X char *cp;
X{
X math_str(cp);
X if (traceflags & TRACE_OPCODES)
X printf("\n");
X math_flush();
X}
X
X
Xstatic void
Xo_zero()
X{
X stack++;
X stack->v_type = V_NUM;
X stack->v_num = qlink(&_qzero_);
X}
X
X
Xstatic void
Xo_one()
X{
X stack++;
X stack->v_type = V_NUM;
X stack->v_num = qlink(&_qone_);
X}
X
X
Xstatic void
Xo_save(fp)
X FUNC *fp;
X{
X VALUE *vp;
X
X vp = stack;
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X freevalue(&fp->f_savedvalue);
X copyvalue(vp, &fp->f_savedvalue);
X}
X
X
Xstatic void
Xo_oldvalue()
X{
X copyvalue(&oldvalue, ++stack);
X}
X
X
Xstatic void
Xo_quit(fp, cp)
X FUNC *fp;
X char *cp;
X{
X if ((fp->f_name[0] == '*') && (fp->f_name[1] == '\0')) {
X if (cp)
X printf("%s\n", cp);
X hist_term();
X exit(0);
X }
X if (cp)
X math_error("%s", cp);
X math_error("quit statement executed");
X}
X
X
Xstatic void
Xo_getepsilon()
X{
X stack++;
X stack->v_type = V_NUM;
X stack->v_num = qlink(_epsilon_);
X}
X
X
Xstatic void
Xo_setepsilon()
X{
X VALUE *vp;
X NUMBER *newep;
X
X vp = &stack[0];
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_NUM)
X math_error("Non-numeric for epsilon");
X newep = vp->v_num;
X stack->v_num = qlink(_epsilon_);
X setepsilon(newep);
X qfree(newep);
X}
X
X
Xstatic void
Xo_setconfig()
X{
X int type;
X VALUE *v1, *v2;
X VALUE tmp;
X
X v1 = &stack[-1];
X v2 = &stack[0];
X if (v1->v_type == V_ADDR)
X v1 = v1->v_addr;
X if (v2->v_type == V_ADDR)
X v2 = v2->v_addr;
X if (v1->v_type != V_STR)
X math_error("Non-string for config");
X type = configtype(v1->v_str);
X if (type < 0)
X math_error("Unknown config name \"%s\"", v1->v_str);
X getconfig(type, &tmp);
X setconfig(type, v2);
X freevalue(stack--);
X freevalue(stack);
X *stack = tmp;
X}
X
X
Xstatic void
Xo_getconfig()
X{
X int type;
X VALUE *vp;
X
X vp = &stack[0];
X if (vp->v_type == V_ADDR)
X vp = vp->v_addr;
X if (vp->v_type != V_STR)
X math_error("Non-string for config");
X type = configtype(vp->v_str);
X if (type < 0)
X math_error("Unknown config name \"%s\"", vp->v_str);
X freevalue(stack);
X getconfig(type, stack);
X}
X
X
X/*
X * Set the 'old' value to the last value saved during the calculation.
X */
Xvoid
Xupdateoldvalue(fp)
X FUNC *fp;
X{
X if (fp->f_savedvalue.v_type == V_NULL)
X return;
X freevalue(&oldvalue);
X oldvalue = fp->f_savedvalue;
X fp->f_savedvalue.v_type = V_NULL;
X}
X
X
X/*
X * Routine called on any runtime error, to complain about it (with possible
X * arguments), and then longjump back to the top level command scanner.
X */
X#ifdef VARARGS
X# define VA_ALIST fmt, va_alist
X# define VA_DCL char *fmt; va_dcl
X#else
X# ifdef __STDC__
X# define VA_ALIST char *fmt, ...
X# define VA_DCL
X# else
X# define VA_ALIST fmt
X# define VA_DCL char *fmt;
X# endif
X#endif
X/*VARARGS*/
Xvoid
Xmath_error(VA_ALIST)
X VA_DCL
X{
X va_list ap;
X char buf[MAXERROR+1];
X
X if (funcname && (*funcname != '*'))
X fprintf(stderr, "\"%s\": ", funcname);
X if (funcline && ((funcname && (*funcname != '*')) || !inputisterminal()))
X fprintf(stderr, "line %ld: ", funcline);
X#ifdef VARARGS
X va_start(ap);
X#else
X va_start(ap, fmt);
SHAR_EOF
echo "End of part 7"
echo "File calc2.9.0/opcodes.c is continued in part 8"
echo "8" > s2_seq_.tmp
exit 0