home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / calc-2.9.0 / part07 < prev    next >
Text File  |  1993-12-07  |  58KB  |  2,797 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@canb.auug.org.au (David I. Bell)
  3. Subject: v27i134: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part07/19
  4. References: <1.755316719.21314@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: dbell@canb.auug.org.au (David I. Bell)
  9. Posting-Number: Volume 27, Issue 134
  10. Archive-Name: calc-2.9.0/part07
  11.  
  12. #!/bin/sh
  13. # this is part 7 of a multipart archive
  14. # do not concatenate these parts, unpack them in order with /bin/sh
  15. # file calc2.9.0/obj.c continued
  16. #
  17. CurArch=7
  18. if test ! -r s2_seq_.tmp
  19. then echo "Please unpack part 1 first!"
  20.      exit 1; fi
  21. ( read Scheck
  22.   if test "$Scheck" != $CurArch
  23.   then echo "Please unpack part $Scheck next!"
  24.        exit 1;
  25.   else exit 0; fi
  26. ) < s2_seq_.tmp || exit 1
  27. echo "x - Continuing file calc2.9.0/obj.c"
  28. sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/obj.c
  29. X * This converts the element index from the element table into an offset
  30. X * into the object value array.  Returns -1 if the element index is unknown.
  31. X */
  32. Xint
  33. Xobjoffset(op, index)
  34. X    OBJECT *op;
  35. X    long index;
  36. X{
  37. X    register OBJECTACTIONS *oap;
  38. X    int offset;            /* offset into value array */
  39. X
  40. X    oap = op->o_actions;
  41. X    for (offset = oap->count - 1; offset >= 0; offset--) {
  42. X        if (oap->elements[offset] == index)
  43. X            return offset;
  44. X    }
  45. X    return -1;
  46. X}
  47. X
  48. X
  49. X/*
  50. X * Allocate a new object structure with the specified index.
  51. X */
  52. XOBJECT *
  53. Xobjalloc(index)
  54. X    long index;
  55. X{
  56. X    OBJECTACTIONS *oap;
  57. X    OBJECT *op;
  58. X    VALUE *vp;
  59. X    int i;
  60. X
  61. X    if ((unsigned) index >= MAXOBJECTS)
  62. X        math_error("Allocating bad object index");
  63. X    oap = objects[index];
  64. X    if (oap == NULL)
  65. X        math_error("Object type not defined");
  66. X    i = oap->count;
  67. X    if (i < USUAL_ELEMENTS)
  68. X        i = USUAL_ELEMENTS;
  69. X    if (i == USUAL_ELEMENTS)
  70. X        op = (OBJECT *) allocitem(&freelist);
  71. X    else
  72. X        op = (OBJECT *) malloc(objectsize(i));
  73. X    if (op == NULL)
  74. X        math_error("Cannot allocate object");
  75. X    op->o_actions = oap;
  76. X    vp = op->o_table;
  77. X    for (i = oap->count; i-- > 0; vp++) {
  78. X        vp->v_num = qlink(&_qzero_);
  79. X        vp->v_type = V_NUM;
  80. X    }
  81. X    return op;
  82. X}
  83. X
  84. X
  85. X/*
  86. X * Free an object structure.
  87. X */
  88. Xvoid
  89. Xobjfree(op)
  90. X    register OBJECT *op;
  91. X{
  92. X    VALUE *vp;
  93. X    int i;
  94. X
  95. X    vp = op->o_table;
  96. X    for (i = op->o_actions->count; i-- > 0; vp++) {
  97. X        if (vp->v_type == V_NUM) {
  98. X            qfree(vp->v_num);
  99. X        } else
  100. X            freevalue(vp);
  101. X    }
  102. X    if (op->o_actions->count <= USUAL_ELEMENTS)
  103. X        freeitem(&freelist, (FREEITEM *) op);
  104. X    else
  105. X        free((char *) op);
  106. X}
  107. X
  108. X
  109. X/*
  110. X * Copy an object value
  111. X */
  112. XOBJECT *
  113. Xobjcopy(op)
  114. X    OBJECT *op;
  115. X{
  116. X    VALUE *v1, *v2;
  117. X    OBJECT *np;
  118. X    int i;
  119. X
  120. X    i = op->o_actions->count;
  121. X    if (i < USUAL_ELEMENTS)
  122. X        i = USUAL_ELEMENTS;
  123. X    if (i == USUAL_ELEMENTS)
  124. X        np = (OBJECT *) allocitem(&freelist);
  125. X    else
  126. X        np = (OBJECT *) malloc(objectsize(i));
  127. X    if (np == NULL)
  128. X        math_error("Cannot allocate object");
  129. X    np->o_actions = op->o_actions;
  130. X    v1 = op->o_table;
  131. X    v2 = np->o_table;
  132. X    for (i = op->o_actions->count; i-- > 0; v1++, v2++) {
  133. X        if (v1->v_type == V_NUM) {
  134. X            v2->v_num = qlink(v1->v_num);
  135. X            v2->v_type = V_NUM;
  136. X        } else
  137. X            copyvalue(v1, v2);
  138. X    }
  139. X    return np;
  140. X}
  141. X
  142. X
  143. X/*
  144. X * Return a trivial hash value for an object.
  145. X */
  146. XHASH
  147. Xobjhash(op)
  148. X    OBJECT *op;
  149. X{
  150. X    HASH hash;
  151. X    int i;
  152. X
  153. X    hash = 0;
  154. X    i = op->o_actions->count;
  155. X    while (--i >= 0)
  156. X        hash = hash * 4000037 + hashvalue(&op->o_table[i]);
  157. X    return hash;
  158. X}
  159. X
  160. X/* END CODE */
  161. SHAR_EOF
  162. echo "File calc2.9.0/obj.c is complete"
  163. chmod 0644 calc2.9.0/obj.c || echo "restore of calc2.9.0/obj.c fails"
  164. set `wc -c calc2.9.0/obj.c`;Sum=$1
  165. if test "$Sum" != "15522"
  166. then echo original size 15522, current size $Sum;fi
  167. echo "x - extracting calc2.9.0/opcodes.c (Text)"
  168. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/opcodes.c &&
  169. X/*
  170. X * Copyright (c) 1993 David I. Bell
  171. X * Permission is granted to use, distribute, or modify this source,
  172. X * provided that this copyright notice remains intact.
  173. X *
  174. X * Opcode execution module
  175. X */
  176. X
  177. X#include "stdarg.h"
  178. X#include "calc.h"
  179. X#include "opcodes.h"
  180. X#include "func.h"
  181. X#include "symbol.h"
  182. X#include "hist.h"
  183. X
  184. X#define    QUICKLOCALS    20        /* local vars to handle quickly */
  185. X
  186. X
  187. XVALUE *stack;                /* current location of top of stack */
  188. Xstatic VALUE stackarray[MAXSTACK];    /* storage for stack */
  189. Xstatic VALUE oldvalue;            /* previous calculation value */
  190. Xstatic char *funcname;            /* function being executed */
  191. Xstatic long funcline;            /* function line being executed */
  192. X
  193. XFLAG traceflags;            /* current trace flags */
  194. X
  195. X
  196. X/*
  197. X * Routine definitions
  198. X */
  199. Xstatic void o_nop(), o_localaddr(), o_globaladdr(), o_paramaddr();
  200. Xstatic void o_globalvalue(), o_paramvalue(), o_number(), o_indexaddr();
  201. Xstatic void o_assign(), o_add(), o_sub(), o_mul(), o_div();
  202. Xstatic void o_mod(), o_save(), o_negate(), o_invert(), o_int(), o_frac();
  203. Xstatic void o_numerator(), o_denominator(), o_duplicate(), o_pop();
  204. Xstatic void o_jumpeq(), o_jumpne(), o_jump(), o_usercall(), o_getvalue();
  205. Xstatic void o_eq(), o_ne(), o_le(), o_ge(), o_lt(), o_gt(), o_preinc();
  206. Xstatic void o_postinc(), o_postdec(), o_debug(), o_print(), o_assignpop();
  207. Xstatic void o_zero(), o_one(), o_printeol(), o_printspace(), o_printstring();
  208. Xstatic void o_oldvalue(), o_quo(), o_power(), o_quit(), o_call(), o_swap();
  209. Xstatic void o_dupvalue(), o_getepsilon(), o_and(), o_or(), o_not();
  210. Xstatic void o_abs(), o_sgn(), o_isint(), o_condorjump(), o_condandjump();
  211. Xstatic void o_square(), o_string(), o_isnum(), o_undef(), o_isnull();
  212. Xstatic void o_matcreate(), o_ismat(), o_isstr(), o_getconfig(), o_predec();
  213. Xstatic void o_leftshift(), o_rightshift(), o_casejump();
  214. Xstatic void o_isodd(), o_iseven(), o_fiaddr(), o_fivalue(), o_argvalue();
  215. Xstatic void o_isreal(), o_imaginary(), o_re(), o_im(), o_conjugate();
  216. Xstatic void o_objcreate(), o_isobj(), o_norm(), o_elemaddr(), o_elemvalue();
  217. Xstatic void o_istype(), o_scale(), o_localvalue(), o_return(), o_islist();
  218. Xstatic void o_issimple(), o_cmp(), o_quomod(), o_setconfig(), o_setepsilon();
  219. Xstatic void o_printresult(), o_isfile(), o_isassoc(), o_eleminit();
  220. X
  221. X
  222. X/*
  223. X * Types of opcodes (depends on arguments saved after the opcode).
  224. X */
  225. X#define OPNUL    1    /* opcode has no arguments */
  226. X#define OPONE    2    /* opcode has one integer argument */
  227. X#define OPTWO    3    /* opcode has two integer arguments */
  228. X#define OPJMP    4    /* opcode is a jump (with one pointer argument) */
  229. X#define OPRET    5    /* opcode is a return (with no argument) */
  230. X#define OPGLB    6    /* opcode has global symbol pointer argument */
  231. X#define OPPAR    7    /* opcode has parameter index argument */
  232. X#define OPLOC    8    /* opcode needs local variable pointer (with one arg) */
  233. X#define OPSTR    9    /* opcode has a string constant arg */
  234. X#define OPARG    10    /* opcode is given number of arguments */
  235. X#define    OPSTI    11    /* opcode is static initialization */
  236. X
  237. X
  238. X/*
  239. X * Information about each opcode.
  240. X */
  241. Xstatic struct opcode {
  242. X    void (*o_func)();    /* routine to call for opcode */
  243. X    int o_type;        /* type of opcode */
  244. X    char *o_name;        /* name of opcode */
  245. X} opcodes[MAX_OPCODE+1] = {
  246. X    o_nop,        OPNUL,  "NOP",        /* no operation */
  247. X    o_localaddr,    OPLOC,  "LOCALADDR",    /* address of local variable */
  248. X    o_globaladdr,    OPGLB,  "GLOBALADDR",    /* address of global variable */
  249. X    o_paramaddr,    OPPAR,  "PARAMADDR",    /* address of paramater variable */
  250. X    o_localvalue,    OPLOC,  "LOCALVALUE",    /* value of local variable */
  251. X    o_globalvalue,    OPGLB,  "GLOBALVALUE",    /* value of global variable */
  252. X    o_paramvalue,    OPPAR,  "PARAMVALUE",     /* value of paramater variable */
  253. X    o_number,    OPONE,  "NUMBER",    /* constant real numeric value */
  254. X    o_indexaddr,    OPTWO,  "INDEXADDR",    /* array index address */
  255. X    o_printresult,    OPNUL,  "PRINTRESULT",    /* print result of top-level expression */
  256. X    o_assign,    OPNUL,  "ASSIGN",    /* assign value to variable */
  257. X    o_add,        OPNUL,  "ADD",        /* add top two values */
  258. X    o_sub,        OPNUL,  "SUB",        /* subtract top two values */
  259. X    o_mul,        OPNUL,  "MUL",        /* multiply top two values */
  260. X    o_div,        OPNUL,  "DIV",        /* divide top two values */
  261. X    o_mod,        OPNUL,  "MOD",        /* take mod of top two values */
  262. X    o_save,        OPNUL,  "SAVE",        /* save value for later use */
  263. X    o_negate,    OPNUL,  "NEGATE",    /* negate top value */
  264. X    o_invert,    OPNUL,  "INVERT",    /* invert top value */
  265. X    o_int,        OPNUL,  "INT",        /* take integer part */
  266. X    o_frac,        OPNUL,  "FRAC",        /* take fraction part */
  267. X    o_numerator,    OPNUL,  "NUMERATOR",    /* take numerator */
  268. X    o_denominator,    OPNUL,  "DENOMINATOR",    /* take denominator */
  269. X    o_duplicate,    OPNUL,  "DUPLICATE",    /* duplicate top value */
  270. X    o_pop,        OPNUL,  "POP",        /* pop top value */
  271. X    o_return,    OPRET,  "RETURN",    /* return value of function */
  272. X    o_jumpeq,    OPJMP,  "JUMPEQ",    /* jump if value zero */
  273. X    o_jumpne,    OPJMP,  "JUMPNE",    /* jump if value nonzero */
  274. X    o_jump,        OPJMP,  "JUMP",        /* jump unconditionally */
  275. X    o_usercall,    OPTWO,  "USERCALL",    /* call a user function */
  276. X    o_getvalue,    OPNUL,  "GETVALUE",    /* convert address to value */
  277. X    o_eq,        OPNUL,  "EQ",        /* test elements for equality */
  278. X    o_ne,        OPNUL,  "NE",        /* test elements for inequality */
  279. X    o_le,        OPNUL,  "LE",        /* test elements for <= */
  280. X    o_ge,        OPNUL,  "GE",        /* test elements for >= */
  281. X    o_lt,        OPNUL,  "LT",        /* test elements for < */
  282. X    o_gt,        OPNUL,  "GT",        /* test elements for > */
  283. X    o_preinc,    OPNUL,  "PREINC",    /* add one to variable (++x) */
  284. X    o_predec,    OPNUL,  "PREDEC",    /* subtract one from variable (--x) */
  285. X    o_postinc,    OPNUL,  "POSTINC",    /* add one to variable (x++) */
  286. X    o_postdec,    OPNUL,  "POSTDEC",    /* subtract one from variable (x--) */
  287. X    o_debug,    OPONE,  "DEBUG",    /* debugging point */
  288. X    o_print,    OPONE,  "PRINT",    /* print value */
  289. X    o_assignpop,    OPNUL,  "ASSIGNPOP",    /* assign to variable and pop it */
  290. X    o_zero,        OPNUL,  "ZERO",        /* put zero on the stack */
  291. X    o_one,        OPNUL,  "ONE",        /* put one on the stack */
  292. X    o_printeol,    OPNUL,  "PRINTEOL",    /* print end of line */
  293. X    o_printspace,    OPNUL,  "PRINTSPACE",    /* print a space */
  294. X    o_printstring,    OPSTR,  "PRINTSTR",    /* print constant string */
  295. X    o_dupvalue,    OPNUL,  "DUPVALUE",    /* duplicate value of top value */
  296. X    o_oldvalue,    OPNUL,  "OLDVALUE",    /* old value from previous calc */
  297. X    o_quo,        OPNUL,  "QUO",        /* integer quotient of top values */
  298. X    o_power,    OPNUL,  "POWER",    /* value raised to a power */
  299. X    o_quit,        OPSTR,  "QUIT",        /* quit program */
  300. X    o_call,        OPTWO,  "CALL",        /* call built-in routine */
  301. X    o_getepsilon,    OPNUL,  "GETEPSILON",    /* get allowed error for calculations */
  302. X    o_and,        OPNUL,  "AND",        /* arithmetic and or top two values */
  303. X    o_or,        OPNUL,  "OR",        /* arithmetic or of top two values */
  304. X    o_not,        OPNUL,  "NOT",        /* logical not or top value */
  305. X    o_abs,        OPNUL,  "ABS",        /* absolute value of top value */
  306. X    o_sgn,        OPNUL,  "SGN",        /* sign of number */
  307. X    o_isint,    OPNUL,  "ISINT",    /* whether number is an integer */
  308. X    o_condorjump,    OPJMP,  "CONDORJUMP",    /* conditional or jump */
  309. X    o_condandjump,    OPJMP,  "CONDANDJUMP",    /* conditional and jump */
  310. X    o_square,    OPNUL,  "SQUARE",    /* square top value */
  311. X    o_string,    OPSTR,  "STRING",    /* string constant value */
  312. X    o_isnum,    OPNUL,  "ISNUM",    /* whether value is a number */
  313. X    o_undef,    OPNUL,  "UNDEF",    /* load undefined value on stack */
  314. X    o_isnull,    OPNUL,  "ISNULL",    /* whether value is the null value */
  315. X    o_argvalue,    OPARG,  "ARGVALUE",    /* load value of arg (parameter) n */
  316. X    o_matcreate,    OPONE,  "MATCREATE",    /* create matrix */
  317. X    o_ismat,    OPNUL,  "ISMAT",    /* whether value is a matrix */
  318. X    o_isstr,    OPNUL,  "ISSTR",    /* whether value is a string */
  319. X    o_getconfig,    OPNUL,  "GETCONFIG",    /* get value of configuration parameter */
  320. X    o_leftshift,    OPNUL,  "LEFTSHIFT",    /* left shift of integer */
  321. X    o_rightshift,    OPNUL,  "RIGHTSHIFT",    /* right shift of integer */
  322. X    o_casejump,    OPJMP,  "CASEJUMP",    /* test case and jump if not matched */
  323. X    o_isodd,    OPNUL,  "ISODD",    /* whether value is odd integer */
  324. X    o_iseven,    OPNUL,  "ISEVEN",    /* whether value is even integer */
  325. X    o_fiaddr,    OPNUL,  "FIADDR",    /* 'fast index' matrix address */
  326. X    o_fivalue,    OPNUL,  "FIVALUE",    /* 'fast index' matrix value */
  327. X    o_isreal,    OPNUL,  "ISREAL",    /* whether value is real number */
  328. X    o_imaginary,    OPONE,  "IMAGINARY",    /* constant imaginary numeric value */
  329. X    o_re,        OPNUL,  "RE",        /* real part of complex number */
  330. X    o_im,        OPNUL,  "IM",        /* imaginary part of complex number */
  331. X    o_conjugate,    OPNUL,  "CONJUGATE",    /* complex conjugate */
  332. X    o_objcreate,    OPONE,  "OBJCREATE",    /* create object */
  333. X    o_isobj,    OPNUL,  "ISOBJ",    /* whether value is an object */
  334. X    o_norm,        OPNUL,  "NORM",        /* norm of value (square of abs) */
  335. X    o_elemaddr,    OPONE,  "ELEMADDR",    /* address of element of object */
  336. X    o_elemvalue,    OPONE,  "ELEMVALUE",    /* value of element of object */
  337. X    o_istype,    OPNUL,  "ISTYPE",    /* whether types are the same */
  338. X    o_scale,    OPNUL,  "SCALE",    /* scale value by a power of two */
  339. X    o_islist,    OPNUL,    "ISLIST",    /* whether value is a list */
  340. X    o_swap,        OPNUL,    "SWAP",        /* swap values of two variables */
  341. X    o_issimple,    OPNUL,    "ISSIMPLE",    /* whether value is simple type */
  342. X    o_cmp,        OPNUL,    "CMP",        /* compare values returning -1, 0, 1 */
  343. X    o_quomod,    OPNUL,    "QUOMOD",    /* calculate quotient and remainder */
  344. X    o_setconfig,    OPNUL,    "SETCONFIG",    /* set configuration parameter */
  345. X    o_setepsilon,    OPNUL,  "SETEPSILON",    /* set allowed error for calculations */
  346. X    o_isfile,    OPNUL,  "ISFILE",    /* whether value is a file */
  347. X    o_isassoc,    OPNUL,  "ISASSOC",    /* whether value is an association */
  348. X    o_nop,        OPSTI,  "INITSTATIC",    /* once only code for static init */
  349. X    o_eleminit,    OPONE,    "ELEMINIT"    /* assign element of matrix or object */
  350. X};
  351. X
  352. X
  353. X
  354. X/*
  355. X * Initialize the stack.
  356. X */
  357. Xvoid
  358. Xinitstack()
  359. X{
  360. X    if (stack == NULL)
  361. X        stack = stackarray;
  362. X    while (stack != stackarray)
  363. X        freevalue(stack--);
  364. X}
  365. X
  366. X
  367. X/*
  368. X * Compute the result of a function by interpreting opcodes.
  369. X * Arguments have just been pushed onto the evaluation stack.
  370. X */
  371. Xvoid
  372. Xcalculate(fp, argcount)
  373. X    register FUNC *fp;        /* function to calculate */
  374. X    int argcount;            /* number of arguments called with */
  375. X{
  376. X    register unsigned long pc;    /* current pc inside function */
  377. X    register struct opcode *op;    /* current opcode pointer */
  378. X    register VALUE *locals;        /* pointer to local variables */
  379. X    long oldline;            /* old value of line counter */
  380. X    unsigned int opnum;        /* current opcode number */
  381. X    int origargcount;        /* original number of arguments */
  382. X    int i;                /* loop counter */
  383. X    BOOL dojump;            /* TRUE if jump is to occur */
  384. X    char *oldname;            /* old function name being executed */
  385. X    VALUE *beginstack;        /* beginning of stack frame */
  386. X    VALUE *args;            /* pointer to function arguments */
  387. X    VALUE retval;            /* function return value */
  388. X    VALUE localtable[QUICKLOCALS];    /* some local variables */
  389. X
  390. X    oldname = funcname;
  391. X    oldline = funcline;
  392. X    funcname = fp->f_name;
  393. X    funcline = 0;
  394. X    origargcount = argcount;
  395. X    while (argcount < fp->f_paramcount) {
  396. X        stack++;
  397. X        stack->v_type = V_NULL;
  398. X        argcount++;
  399. X    }
  400. X    locals = localtable;
  401. X    if (fp->f_localcount > QUICKLOCALS) {
  402. X        locals = (VALUE *) malloc(sizeof(VALUE) * fp->f_localcount);
  403. X        if (locals == NULL)
  404. X            math_error("No memory for local variables");
  405. X    }
  406. X    for (i = 0; i < fp->f_localcount; i++) {
  407. X        locals[i].v_num = qlink(&_qzero_);
  408. X        locals[i].v_type = V_NUM;
  409. X    }
  410. X    pc = 0;
  411. X    beginstack = stack;
  412. X    args = beginstack - (argcount - 1);
  413. X    for (;;) {
  414. X        if (abortlevel >= ABORT_OPCODE)
  415. X            math_error("Calculation aborted in opcode");
  416. X        if (pc >= fp->f_opcodecount)
  417. X            math_error("Function pc out of range");
  418. X        if (stack > &stackarray[MAXSTACK-3])
  419. X            math_error("Evaluation stack depth exceeded");
  420. X        opnum = fp->f_opcodes[pc];
  421. X        if (opnum > MAX_OPCODE)
  422. X            math_error("Function opcode out of range");
  423. X        op = &opcodes[opnum];
  424. X        if (traceflags & TRACE_OPCODES) {
  425. X            printf("%8s, pc %4ld:  ", fp->f_name, pc);
  426. X            (void)dumpop(&fp->f_opcodes[pc]);
  427. X        }
  428. X        /*
  429. X         * Now call the opcode routine appropriately.
  430. X         */
  431. X        pc++;
  432. X        switch (op->o_type) {
  433. X        case OPNUL:    /* no extra arguments */
  434. X            (*op->o_func)(fp);
  435. X            break;
  436. X
  437. X        case OPONE:    /* one extra integer argument */
  438. X            (*op->o_func)(fp, fp->f_opcodes[pc++]);
  439. X            break;
  440. X
  441. X        case OPTWO:    /* two extra integer arguments */
  442. X            (*op->o_func)(fp, fp->f_opcodes[pc],
  443. X                fp->f_opcodes[pc+1]);
  444. X            pc += 2;
  445. X            break;
  446. X
  447. X        case OPJMP:    /* jump opcodes (one extra pointer arg) */
  448. X            dojump = FALSE;
  449. X            (*op->o_func)(fp, &dojump);
  450. X            if (dojump)
  451. X                pc = fp->f_opcodes[pc];
  452. X            else
  453. X                pc++;
  454. X            break;
  455. X
  456. X        case OPGLB:    /* global symbol reference (pointer arg) */
  457. X        case OPSTR:    /* string constant address */
  458. X            (*op->o_func)(fp, *((char **) &fp->f_opcodes[pc]));
  459. X            pc += PTR_SIZE;
  460. X            break;
  461. X
  462. X        case OPLOC:    /* local variable reference */
  463. X            (*op->o_func)(fp, locals, fp->f_opcodes[pc++]);
  464. X            break;
  465. X
  466. X        case OPPAR:    /* parameter variable reference */
  467. X            (*op->o_func)(fp, argcount, args, fp->f_opcodes[pc++]);
  468. X            break;
  469. X
  470. X        case OPARG:    /* parameter variable reference */
  471. X            (*op->o_func)(fp, origargcount, args);
  472. X            break;
  473. X
  474. X        case OPRET:    /* return from function */
  475. X            if (stack->v_type == V_ADDR)
  476. X                copyvalue(stack->v_addr, stack);
  477. X            for (i = 0; i < fp->f_localcount; i++)
  478. X                freevalue(&locals[i]);
  479. X            if (locals != localtable)
  480. X                free(locals);
  481. X            if (stack != &beginstack[1])
  482. X                math_error("Misaligned stack");
  483. X            if (argcount <= 0) {
  484. X                funcname = oldname;
  485. X                funcline = oldline;
  486. X                return;
  487. X            }
  488. X            retval = *stack--;
  489. X            while (--argcount >= 0)
  490. X                freevalue(stack--);
  491. X            *++stack = retval;
  492. X            funcname = oldname;
  493. X            funcline = oldline;
  494. X            return;
  495. X
  496. X        case OPSTI:    /* static initialization code */
  497. X            fp->f_opcodes[pc++ - 1] = OP_JUMP;
  498. X            break;
  499. X        
  500. X        default:
  501. X            math_error("Unknown opcode type");
  502. X        }
  503. X    }
  504. X}
  505. X
  506. X
  507. X/*
  508. X * Dump an opcode at a particular address.
  509. X * Returns the size of the opcode so that it can easily be skipped over.
  510. X */
  511. Xint
  512. Xdumpop(pc)
  513. X    long *pc;        /* location of the opcode */
  514. X{
  515. X    unsigned long op;    /* opcode number */
  516. X
  517. X    op = *pc++;
  518. X    if (op <= MAX_OPCODE)
  519. X        printf("%s", opcodes[op].o_name);
  520. X    else
  521. X        printf("OP%ld", op);
  522. X    switch (op) {
  523. X        case OP_LOCALADDR: case OP_LOCALVALUE:
  524. X            printf(" %s\n", localname(*pc));
  525. X            return 2;
  526. X        case OP_GLOBALADDR: case OP_GLOBALVALUE:
  527. X            printf(" %s\n", globalname(*((GLOBAL **) pc)));
  528. X            return (1 + PTR_SIZE);
  529. X        case OP_PARAMADDR: case OP_PARAMVALUE:
  530. X            printf(" %s\n", paramname(*pc));
  531. X            return 2;
  532. X        case OP_PRINTSTRING: case OP_STRING:
  533. X            printf(" \"%s\"\n", *((char **) pc));
  534. X            return (1 + PTR_SIZE);
  535. X        case OP_QUIT:
  536. X            if (*(char **) pc)
  537. X                printf(" \"%s\"\n", *((char **) pc));
  538. X            else
  539. X                printf("\n");
  540. X            return (1 + PTR_SIZE);
  541. X        case OP_INDEXADDR:
  542. X            printf(" %ld %ld\n", pc[0], pc[1]);
  543. X            return 3;
  544. X        case OP_PRINT: case OP_JUMPEQ: case OP_JUMPNE: case OP_JUMP:
  545. X        case OP_CONDORJUMP: case OP_CONDANDJUMP: case OP_CASEJUMP:
  546. X        case OP_INITSTATIC: case OP_MATCREATE: case OP_OBJCREATE:
  547. X            printf(" %ld\n", *pc);
  548. X            return 2;
  549. X        case OP_NUMBER: case OP_IMAGINARY:
  550. X            qprintf(" %r\n", constvalue(*pc));
  551. X            return 2;
  552. X        case OP_DEBUG:
  553. X            printf(" line %ld\n", *pc);
  554. X            return 2;
  555. X        case OP_CALL:
  556. X            printf(" %s with %ld args\n", builtinname(pc[0]), pc[1]);
  557. X            return 3;
  558. X        case OP_USERCALL:
  559. X            printf(" %s with %ld args\n", namefunc(pc[0]), pc[1]);
  560. X            return 3;
  561. X        default:
  562. X            printf("\n");
  563. X            return 1;
  564. X    }
  565. X}
  566. X
  567. X
  568. X/*
  569. X * The various opcodes
  570. X */
  571. X
  572. Xstatic void
  573. Xo_nop()
  574. X{
  575. X}
  576. X
  577. X
  578. Xstatic void
  579. Xo_localaddr(fp, locals, index)
  580. X    FUNC *fp;
  581. X    VALUE *locals;
  582. X    long index;
  583. X{
  584. X    if ((unsigned long)index >= fp->f_localcount)
  585. X        math_error("Bad local variable index");
  586. X    locals += index;
  587. X    stack++;
  588. X    stack->v_addr = locals;
  589. X    stack->v_type = V_ADDR;
  590. X}
  591. X
  592. X
  593. X/*ARGSUSED*/
  594. Xstatic void
  595. Xo_globaladdr(fp, sp)
  596. X    FUNC *fp;
  597. X    GLOBAL *sp;
  598. X{
  599. X    if (sp == NULL)
  600. X        math_error("Global variable \"%s\" not initialized", sp->g_name);
  601. X    stack++;
  602. X    stack->v_addr = &sp->g_value;
  603. X    stack->v_type = V_ADDR;
  604. X}
  605. X
  606. X
  607. X/*ARGSUSED*/
  608. Xstatic void
  609. Xo_paramaddr(fp, argcount, args, index)
  610. X    FUNC *fp;
  611. X    int argcount;
  612. X    VALUE *args;
  613. X    long index;
  614. X{
  615. X    if ((unsigned long)index >= argcount)
  616. X        math_error("Bad parameter index");
  617. X    args += index;
  618. X    stack++;
  619. X    if (args->v_type == V_ADDR)
  620. X        stack->v_addr = args->v_addr;
  621. X    else
  622. X        stack->v_addr = args;
  623. X    stack->v_type = V_ADDR;
  624. X}
  625. X
  626. X
  627. Xstatic void
  628. Xo_localvalue(fp, locals, index)
  629. X    FUNC *fp;
  630. X    VALUE *locals;
  631. X    long index;
  632. X{
  633. X    if ((unsigned long)index >= fp->f_localcount)
  634. X        math_error("Bad local variable index");
  635. X    locals += index;
  636. X    copyvalue(locals, ++stack);
  637. X}
  638. X
  639. X
  640. X/*ARGSUSED*/
  641. Xstatic void
  642. Xo_globalvalue(fp, sp)
  643. X    FUNC *fp;
  644. X    GLOBAL *sp;        /* global symbol */
  645. X{
  646. X    if (sp == NULL)
  647. X        math_error("Global variable not defined");
  648. X    copyvalue(&sp->g_value, ++stack);
  649. X}
  650. X
  651. X
  652. X/*ARGSUSED*/
  653. Xstatic void
  654. Xo_paramvalue(fp, argcount, args, index)
  655. X    FUNC *fp;
  656. X    int argcount;
  657. X    VALUE *args;
  658. X    long index;
  659. X{
  660. X    if ((unsigned long)index >= argcount)
  661. X        math_error("Bad paramaeter index");
  662. X    args += index;
  663. X    if (args->v_type == V_ADDR)
  664. X        args = args->v_addr;
  665. X    copyvalue(args, ++stack);
  666. X}
  667. X
  668. X
  669. Xstatic void
  670. Xo_argvalue(fp, argcount, args)
  671. X    FUNC *fp;
  672. X    int argcount;
  673. X    VALUE *args;
  674. X{
  675. X    VALUE *vp;
  676. X    long index;
  677. X
  678. X    vp = stack;
  679. X    if (vp->v_type == V_ADDR)
  680. X        vp = vp->v_addr;
  681. X    if ((vp->v_type != V_NUM) || qisneg(vp->v_num) ||
  682. X        qisfrac(vp->v_num))
  683. X            math_error("Illegal argument for arg function");
  684. X    if (qiszero(vp->v_num)) {
  685. X        if (stack->v_type == V_NUM)
  686. X            qfree(stack->v_num);
  687. X        stack->v_num = itoq((long) argcount);
  688. X        stack->v_type = V_NUM;
  689. X        return;
  690. X    }
  691. X    index = qtoi(vp->v_num) - 1;
  692. X    if (stack->v_type == V_NUM)
  693. X        qfree(stack->v_num);
  694. X    stack--;
  695. X    (void) o_paramvalue(fp, argcount, args, index);
  696. X}
  697. X
  698. X
  699. X/*ARGSUSED*/
  700. Xstatic void
  701. Xo_number(fp, arg)
  702. X    FUNC *fp;
  703. X    long arg;
  704. X{
  705. X    NUMBER *q;
  706. X
  707. X    q = constvalue(arg);
  708. X    if (q == NULL)
  709. X        math_error("Numeric constant value not found");
  710. X    stack++;
  711. X    stack->v_num = qlink(q);
  712. X    stack->v_type = V_NUM;
  713. X}
  714. X
  715. X
  716. X/*ARGSUSED*/
  717. Xstatic void
  718. Xo_imaginary(fp, arg)
  719. X    FUNC *fp;
  720. X    long arg;
  721. X{
  722. X    NUMBER *q;
  723. X    COMPLEX *c;
  724. X
  725. X    q = constvalue(arg);
  726. X    if (q == NULL)
  727. X        math_error("Numeric constant value not found");
  728. X    stack++;
  729. X    if (qiszero(q)) {
  730. X        stack->v_num = qlink(q);
  731. X        stack->v_type = V_NUM;
  732. X        return;
  733. X    }
  734. X    c = comalloc();
  735. X    c->real = qlink(&_qzero_);
  736. X    c->imag = qlink(q);
  737. X    stack->v_com = c;
  738. X    stack->v_type = V_COM;
  739. X}
  740. X
  741. X
  742. X/*ARGSUSED*/
  743. Xstatic void
  744. Xo_string(fp, cp)
  745. X    FUNC *fp;
  746. X    char *cp;
  747. X{
  748. X    stack++;
  749. X    stack->v_str = cp;
  750. X    stack->v_type = V_STR;
  751. X    stack->v_subtype = V_STRLITERAL;
  752. X}
  753. X
  754. X
  755. Xstatic void
  756. Xo_undef()
  757. X{
  758. X    stack++;
  759. X    stack->v_type = V_NULL;
  760. X}
  761. X
  762. X
  763. X/*ARGSUSED*/
  764. Xstatic void
  765. Xo_matcreate(fp, dim)
  766. X    FUNC *fp;
  767. X    long dim;
  768. X{
  769. X    register MATRIX *mp;    /* matrix being defined */
  770. X    NUMBER *num1;        /* first number from stack */
  771. X    NUMBER *num2;        /* second number from stack */
  772. X    VALUE *vp;        /* value being defined */
  773. X    VALUE *v1, *v2;
  774. X    long min[MAXDIM];    /* minimum range */
  775. X    long max[MAXDIM];    /* maximum range */
  776. X    long i;            /* index */
  777. X    long tmp;        /* temporary */
  778. X    long size;        /* size of matrix */
  779. X
  780. X    if ((dim <= 0) || (dim > MAXDIM))
  781. X        math_error("Bad dimension %ld for matrix", dim);
  782. X    if (stack[-2*dim].v_type != V_ADDR)
  783. X        math_error("Attempting to init matrix for non-address");
  784. X    size = 1;
  785. X    for (i = dim - 1; i >= 0; i--) {
  786. X        v1 = &stack[-1];
  787. X        v2 = &stack[0];
  788. X        if (v1->v_type == V_ADDR)
  789. X            v1 = v1->v_addr;
  790. X        if (v2->v_type == V_ADDR)
  791. X            v2 = v2->v_addr;
  792. X        if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
  793. X            math_error("Non-numeric bounds for matrix");
  794. X        num1 = v1->v_num;
  795. X        num2 = v2->v_num;
  796. X        if (qisfrac(num1) || qisfrac(num2))
  797. X            math_error("Non-integral bounds for matrix");
  798. X        if (zisbig(num1->num) || zisbig(num2->num))
  799. X            math_error("Very large bounds for matrix");
  800. X        min[i] = qtoi(num1);
  801. X        max[i] = qtoi(num2);
  802. X        if (min[i] > max[i]) {
  803. X            tmp = min[i];
  804. X            min[i] = max[i];
  805. X            max[i] = tmp;
  806. X        }
  807. X        size *= (max[i] - min[i] + 1);
  808. X        if (size > 10000000)
  809. X            math_error("Very large size for matrix");
  810. X        freevalue(stack--);
  811. X        freevalue(stack--);
  812. X    }
  813. X    mp = matalloc(size);
  814. X    mp->m_dim = dim;
  815. X    for (i = 0; i < dim; i++) {
  816. X        mp->m_min[i] = min[i];
  817. X        mp->m_max[i] = max[i];
  818. X    }
  819. X    vp = mp->m_table;
  820. X    for (i = 0; i < size; i++) {
  821. X        vp->v_type = V_NUM;
  822. X        vp->v_num = qlink(&_qzero_);
  823. X        vp++;
  824. X    }
  825. X    vp = stack[0].v_addr;
  826. X    vp->v_type = V_MAT;
  827. X    vp->v_mat = mp;
  828. X}
  829. X
  830. X
  831. X/*ARGSUSED*/
  832. Xstatic void
  833. Xo_eleminit(fp, index)
  834. X    FUNC *fp;
  835. X    long index;
  836. X{
  837. X    VALUE *vp;
  838. X    VALUE *oldvp;
  839. X    MATRIX *mp;
  840. X    OBJECT *op;
  841. X
  842. X    vp = &stack[-1];
  843. X    if (vp->v_type == V_ADDR)
  844. X        vp = vp->v_addr;
  845. X    switch (vp->v_type) {
  846. X        case V_MAT:
  847. X            mp = vp->v_mat;
  848. X            if ((index < 0) || (index >= mp->m_size))
  849. X                math_error("Too many initializer values");
  850. X            oldvp = &mp->m_table[index];
  851. X            break;
  852. X        case V_OBJ:
  853. X            op = vp->v_obj;
  854. X            if ((index < 0) || (index >= op->o_actions->count))
  855. X                math_error("Too many initializer values");
  856. X            oldvp = &op->o_table[index];
  857. X            break;
  858. X        default:
  859. X            math_error("Attempt to initialize non matrix or object");
  860. X    }
  861. X    vp = stack;
  862. X    if (vp->v_type == V_ADDR)
  863. X        vp = vp->v_addr;
  864. X    freevalue(oldvp);
  865. X    copyvalue(vp, oldvp);
  866. X    stack--;
  867. X}
  868. X
  869. X
  870. X/*ARGSUSED*/
  871. Xstatic void
  872. Xo_indexaddr(fp, dim, writeflag)
  873. X    FUNC *fp;
  874. X    long dim;        /* dimension of matrix */
  875. X    long writeflag;        /* nonzero if element will be written */
  876. X{
  877. X    int i;
  878. X    BOOL flag;
  879. X    VALUE *val;
  880. X    VALUE *vp;
  881. X    VALUE indices[MAXDIM];    /* index values */
  882. X
  883. X    flag = (writeflag != 0);
  884. X    if ((dim <= 0) || (dim > MAXDIM))
  885. X        math_error("Too many dimensions for indexing");
  886. X    val = &stack[-dim];
  887. X    if (val->v_type != V_ADDR)
  888. X        math_error("Non-pointer for index operation");
  889. X    val = val->v_addr;
  890. X    vp = &stack[-dim + 1];
  891. X    for (i = 0; i < dim; i++) {
  892. X        if (vp->v_type == V_ADDR)
  893. X            indices[i] = vp->v_addr[0];
  894. X        else
  895. X            indices[i] = vp[0];
  896. X        vp++;
  897. X    }
  898. X    switch (val->v_type) {
  899. X        case V_MAT:
  900. X            vp = matindex(val->v_mat, flag, dim, indices);
  901. X            break;
  902. X        case V_ASSOC:
  903. X            vp = associndex(val->v_assoc, flag, dim, indices);
  904. X            break;
  905. X        default:
  906. X            math_error("Illegal value for indexing");
  907. X    }
  908. X    while (dim-- > 0)
  909. X        freevalue(stack--);
  910. X    stack->v_type = V_ADDR;
  911. X    stack->v_addr = vp;
  912. X}
  913. X
  914. X
  915. X/*ARGSUSED*/
  916. Xstatic void
  917. Xo_elemaddr(fp, index)
  918. X    FUNC *fp;
  919. X    long index;
  920. X{
  921. X    if (stack->v_type != V_ADDR)
  922. X        math_error("Non-pointer for element reference");
  923. X    if (stack->v_addr->v_type != V_OBJ)
  924. X        math_error("Referencing element of non-object");
  925. X    index = objoffset(stack->v_addr->v_obj, index);
  926. X    if (index < 0)
  927. X        math_error("Element does not exist for object");
  928. X    stack->v_addr = &stack->v_addr->v_obj->o_table[index];
  929. X}
  930. X
  931. X
  932. Xstatic void
  933. Xo_elemvalue(fp, index)
  934. X    FUNC *fp;
  935. X    long index;
  936. X{
  937. X    if (stack->v_type != V_OBJ) {
  938. X        (void) o_elemaddr(fp, index);
  939. X        (void) o_getvalue();
  940. X        return;
  941. X    }
  942. X    index = objoffset(stack->v_obj, index);
  943. X    if (index < 0)
  944. X        math_error("Element does not exist for object");
  945. X    copyvalue(&stack->v_obj->o_table[index], stack);
  946. X}
  947. X
  948. X
  949. X/*ARGSUSED*/
  950. Xstatic void
  951. Xo_objcreate(fp, arg)
  952. X    FUNC *fp;
  953. X    long arg;
  954. X{
  955. X    OBJECT *op;        /* object being created */
  956. X    VALUE *vp;        /* value being defined */
  957. X
  958. X    if (stack->v_type != V_ADDR)
  959. X        math_error("Attempting to init object for non-address");
  960. X    op = objalloc(arg);
  961. X    vp = stack->v_addr;
  962. X    vp->v_type = V_OBJ;
  963. X    vp->v_obj = op;
  964. X}
  965. X
  966. X
  967. Xstatic void
  968. Xo_assign()
  969. X{
  970. X    VALUE *var;        /* variable value */
  971. X    VALUE *vp;
  972. X
  973. X    var = &stack[-1];
  974. X    if (var->v_type != V_ADDR)
  975. X        math_error("Assignment into non-variable");
  976. X    var = var->v_addr;
  977. X    stack[-1] = stack[0];
  978. X    stack--;
  979. X    vp = stack;
  980. X    if (vp->v_type == V_ADDR) {
  981. X        vp = vp->v_addr;
  982. X        if (vp == var)
  983. X            return;
  984. X    }
  985. X    freevalue(var);
  986. X    copyvalue(vp, var);
  987. X}
  988. X
  989. X
  990. Xstatic void
  991. Xo_assignpop()
  992. X{
  993. X    VALUE *var;        /* variable value */
  994. X    VALUE *vp;
  995. X
  996. X    var = &stack[-1];
  997. X    if (var->v_type != V_ADDR)
  998. X        math_error("Assignment into non-variable");
  999. X    var = var->v_addr;
  1000. X    vp = &stack[0];
  1001. X    if ((vp->v_type == V_ADDR) && (vp->v_addr == var)) {
  1002. X        stack -= 2;
  1003. X        return;
  1004. X    }
  1005. X    freevalue(var);
  1006. X    if (vp->v_type == V_ADDR)
  1007. X        copyvalue(vp->v_addr, var);
  1008. X    else
  1009. X        *var = *vp;
  1010. X    stack -= 2;
  1011. X}
  1012. X
  1013. X
  1014. Xstatic void
  1015. Xo_swap()
  1016. X{
  1017. X    VALUE *v1, *v2;        /* variables to be swapped */
  1018. X    VALUE tmp;
  1019. X
  1020. X    v1 = &stack[-1];
  1021. X    v2 = &stack[0];
  1022. X    if ((v1->v_type != V_ADDR) || (v2->v_type != V_ADDR))
  1023. X        math_error("Swapping non-variables");
  1024. X    tmp = v1->v_addr[0];
  1025. X    v1->v_addr[0] = v2->v_addr[0];
  1026. X    v2->v_addr[0] = tmp;
  1027. X    stack--;
  1028. X    stack->v_type = V_NULL;
  1029. X}
  1030. X
  1031. X
  1032. Xstatic void
  1033. Xo_add()
  1034. X{
  1035. X    VALUE *v1, *v2;
  1036. X    NUMBER *q;
  1037. X    VALUE tmp;
  1038. X
  1039. X    v1 = &stack[-1];
  1040. X    v2 = &stack[0];
  1041. X    if (v1->v_type == V_ADDR)
  1042. X        v1 = v1->v_addr;
  1043. X    if (v2->v_type == V_ADDR)
  1044. X        v2 = v2->v_addr;
  1045. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1046. X        addvalue(v1, v2, &tmp);
  1047. X        freevalue(stack--);
  1048. X        freevalue(stack);
  1049. X        *stack = tmp;
  1050. X        return;
  1051. X    }
  1052. X    q = qadd(v1->v_num, v2->v_num);
  1053. X    if (stack->v_type == V_NUM)
  1054. X        qfree(stack->v_num);
  1055. X    stack--;
  1056. X    if (stack->v_type == V_NUM)
  1057. X        qfree(stack->v_num);
  1058. X    stack->v_num = q;
  1059. X    stack->v_type = V_NUM;
  1060. X}
  1061. X
  1062. X
  1063. Xstatic void
  1064. Xo_sub()
  1065. X{
  1066. X    VALUE *v1, *v2;
  1067. X    NUMBER *q;
  1068. X    VALUE tmp;
  1069. X
  1070. X    v1 = &stack[-1];
  1071. X    v2 = &stack[0];
  1072. X    if (v1->v_type == V_ADDR)
  1073. X        v1 = v1->v_addr;
  1074. X    if (v2->v_type == V_ADDR)
  1075. X        v2 = v2->v_addr;
  1076. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1077. X        subvalue(v1, v2, &tmp);
  1078. X        freevalue(stack--);
  1079. X        freevalue(stack);
  1080. X        *stack = tmp;
  1081. X        return;
  1082. X    }
  1083. X    q = qsub(v1->v_num, v2->v_num);
  1084. X    if (stack->v_type == V_NUM)
  1085. X        qfree(stack->v_num);
  1086. X    stack--;
  1087. X    if (stack->v_type == V_NUM)
  1088. X        qfree(stack->v_num);
  1089. X    stack->v_num = q;
  1090. X    stack->v_type = V_NUM;
  1091. X}
  1092. X
  1093. X
  1094. Xstatic void
  1095. Xo_mul()
  1096. X{
  1097. X    VALUE *v1, *v2;
  1098. X    NUMBER *q;
  1099. X    VALUE tmp;
  1100. X
  1101. X    v1 = &stack[-1];
  1102. X    v2 = &stack[0];
  1103. X    if (v1->v_type == V_ADDR)
  1104. X        v1 = v1->v_addr;
  1105. X    if (v2->v_type == V_ADDR)
  1106. X        v2 = v2->v_addr;
  1107. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1108. X        mulvalue(v1, v2, &tmp);
  1109. X        freevalue(stack--);
  1110. X        freevalue(stack);
  1111. X        *stack = tmp;
  1112. X        return;
  1113. X    }
  1114. X    q = qmul(v1->v_num, v2->v_num);
  1115. X    if (stack->v_type == V_NUM)
  1116. X        qfree(stack->v_num);
  1117. X    stack--;
  1118. X    if (stack->v_type == V_NUM)
  1119. X        qfree(stack->v_num);
  1120. X    stack->v_num = q;
  1121. X    stack->v_type = V_NUM;
  1122. X}
  1123. X
  1124. X
  1125. Xstatic void
  1126. Xo_power()
  1127. X{
  1128. X    VALUE *v1, *v2;
  1129. X    VALUE tmp;
  1130. X
  1131. X    v1 = &stack[-1];
  1132. X    v2 = &stack[0];
  1133. X    if (v1->v_type == V_ADDR)
  1134. X        v1 = v1->v_addr;
  1135. X    if (v2->v_type == V_ADDR)
  1136. X        v2 = v2->v_addr;
  1137. X    powivalue(v1, v2, &tmp);
  1138. X    freevalue(stack--);
  1139. X    freevalue(stack);
  1140. X    *stack = tmp;
  1141. X}
  1142. X
  1143. X
  1144. Xstatic void
  1145. Xo_div()
  1146. X{
  1147. X    VALUE *v1, *v2;
  1148. X    NUMBER *q;
  1149. X    VALUE tmp;
  1150. X
  1151. X    v1 = &stack[-1];
  1152. X    v2 = &stack[0];
  1153. X    if (v1->v_type == V_ADDR)
  1154. X        v1 = v1->v_addr;
  1155. X    if (v2->v_type == V_ADDR)
  1156. X        v2 = v2->v_addr;
  1157. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1158. X        divvalue(v1, v2, &tmp);
  1159. X        freevalue(stack--);
  1160. X        freevalue(stack);
  1161. X        *stack = tmp;
  1162. X        return;
  1163. X    }
  1164. X    q = qdiv(v1->v_num, v2->v_num);
  1165. X    if (stack->v_type == V_NUM)
  1166. X        qfree(stack->v_num);
  1167. X    stack--;
  1168. X    if (stack->v_type == V_NUM)
  1169. X        qfree(stack->v_num);
  1170. X    stack->v_num = q;
  1171. X    stack->v_type = V_NUM;
  1172. X}
  1173. X
  1174. X
  1175. Xstatic void
  1176. Xo_quo()
  1177. X{
  1178. X    VALUE *v1, *v2;
  1179. X    NUMBER *q;
  1180. X    VALUE tmp;
  1181. X
  1182. X    v1 = &stack[-1];
  1183. X    v2 = &stack[0];
  1184. X    if (v1->v_type == V_ADDR)
  1185. X        v1 = v1->v_addr;
  1186. X    if (v2->v_type == V_ADDR)
  1187. X        v2 = v2->v_addr;
  1188. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1189. X        quovalue(v1, v2, &tmp);
  1190. X        freevalue(stack--);
  1191. X        freevalue(stack);
  1192. X        *stack = tmp;
  1193. X        return;
  1194. X    }
  1195. X    q = qquo(v1->v_num, v2->v_num);
  1196. X    if (stack->v_type == V_NUM)
  1197. X        qfree(stack->v_num);
  1198. X    stack--;
  1199. X    if (stack->v_type == V_NUM)
  1200. X        qfree(stack->v_num);
  1201. X    stack->v_num = q;
  1202. X    stack->v_type = V_NUM;
  1203. X}
  1204. X
  1205. X
  1206. Xstatic void
  1207. Xo_mod()
  1208. X{
  1209. X    VALUE *v1, *v2;
  1210. X    NUMBER *q;
  1211. X    VALUE tmp;
  1212. X
  1213. X    v1 = &stack[-1];
  1214. X    v2 = &stack[0];
  1215. X    if (v1->v_type == V_ADDR)
  1216. X        v1 = v1->v_addr;
  1217. X    if (v2->v_type == V_ADDR)
  1218. X        v2 = v2->v_addr;
  1219. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1220. X        modvalue(v1, v2, &tmp);
  1221. X        freevalue(stack--);
  1222. X        freevalue(stack);
  1223. X        *stack = tmp;
  1224. X        return;
  1225. X    }
  1226. X    q = qmod(v1->v_num, v2->v_num);
  1227. X    if (stack->v_type == V_NUM)
  1228. X        qfree(stack->v_num);
  1229. X    stack--;
  1230. X    if (stack->v_type == V_NUM)
  1231. X        qfree(stack->v_num);
  1232. X    stack->v_num = q;
  1233. X    stack->v_type = V_NUM;
  1234. X}
  1235. X
  1236. X
  1237. Xstatic void
  1238. Xo_quomod()
  1239. X{
  1240. X    VALUE *v1, *v2, *v3, *v4;
  1241. X    VALUE valquo, valmod;
  1242. X    BOOL res;
  1243. X
  1244. X    v1 = &stack[-3];
  1245. X    v2 = &stack[-2];
  1246. X    v3 = &stack[-1];
  1247. X    v4 = &stack[0];
  1248. X    if (v1->v_type == V_ADDR)
  1249. X        v1 = v1->v_addr;
  1250. X    if (v2->v_type == V_ADDR)
  1251. X        v2 = v2->v_addr;
  1252. X    if ((v3->v_type != V_ADDR) || (v4->v_type != V_ADDR))
  1253. X        math_error("Non-variable for quomod");
  1254. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
  1255. X        math_error("Non-reals for quomod");
  1256. X    v3 = v3->v_addr;
  1257. X    v4 = v4->v_addr;
  1258. X    valquo.v_type = V_NUM;
  1259. X    valmod.v_type = V_NUM;
  1260. X    res = qquomod(v1->v_num, v2->v_num, &valquo.v_num, &valmod.v_num);
  1261. X    freevalue(stack--);
  1262. X    freevalue(stack--);
  1263. X    stack--;
  1264. X    stack->v_num = (res ? qlink(&_qone_) : qlink(&_qzero_));
  1265. X    stack->v_type = V_NUM;
  1266. X    freevalue(v3);
  1267. X    freevalue(v4);
  1268. X    *v3 = valquo;
  1269. X    *v4 = valmod;
  1270. X}
  1271. X
  1272. X
  1273. Xstatic void
  1274. Xo_and()
  1275. X{
  1276. X    VALUE *v1, *v2;
  1277. X    NUMBER *q;
  1278. X
  1279. X    v1 = &stack[-1];
  1280. X    v2 = &stack[0];
  1281. X    if (v1->v_type == V_ADDR)
  1282. X        v1 = v1->v_addr;
  1283. X    if (v2->v_type == V_ADDR)
  1284. X        v2 = v2->v_addr;
  1285. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
  1286. X        math_error("Non-numerics for and");
  1287. X    q = qand(v1->v_num, v2->v_num);
  1288. X    if (stack->v_type == V_NUM)
  1289. X        qfree(stack->v_num);
  1290. X    stack--;
  1291. X    if (stack->v_type == V_NUM)
  1292. X        qfree(stack->v_num);
  1293. X    stack->v_num = q;
  1294. X    stack->v_type = V_NUM;
  1295. X}
  1296. X
  1297. X
  1298. Xstatic void
  1299. Xo_or()
  1300. X{
  1301. X    VALUE *v1, *v2;
  1302. X    NUMBER *q;
  1303. X
  1304. X    v1 = &stack[-1];
  1305. X    v2 = &stack[0];
  1306. X    if (v1->v_type == V_ADDR)
  1307. X        v1 = v1->v_addr;
  1308. X    if (v2->v_type == V_ADDR)
  1309. X        v2 = v2->v_addr;
  1310. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))
  1311. X        math_error("Non-numerics for or");
  1312. X    q = qor(v1->v_num, v2->v_num);
  1313. X    if (stack->v_type == V_NUM)
  1314. X        qfree(stack->v_num);
  1315. X    stack--;
  1316. X    if (stack->v_type == V_NUM)
  1317. X        qfree(stack->v_num);
  1318. X    stack->v_num = q;
  1319. X    stack->v_type = V_NUM;
  1320. X}
  1321. X
  1322. X
  1323. Xstatic void
  1324. Xo_not()
  1325. X{
  1326. X    VALUE *vp;
  1327. X    int r;
  1328. X
  1329. X    vp = stack;
  1330. X    if (vp->v_type == V_ADDR)
  1331. X        vp = vp->v_addr;
  1332. X    r = testvalue(vp);
  1333. X    freevalue(stack);
  1334. X    stack->v_num = (r ? qlink(&_qzero_) : qlink(&_qone_));        
  1335. X    stack->v_type = V_NUM;
  1336. X}
  1337. X
  1338. X
  1339. Xstatic void
  1340. Xo_negate()
  1341. X{
  1342. X    VALUE *vp;
  1343. X    NUMBER *q;
  1344. X    VALUE tmp;
  1345. X
  1346. X    vp = stack;
  1347. X    if (vp->v_type == V_ADDR)
  1348. X        vp = vp->v_addr;
  1349. X    if (vp->v_type == V_NUM) {
  1350. X        q = qneg(vp->v_num);
  1351. X        if (stack->v_type == V_NUM)
  1352. X            qfree(stack->v_num);
  1353. X        stack->v_num = q;
  1354. X        stack->v_type = V_NUM;
  1355. X        return;
  1356. X    }
  1357. X    negvalue(vp, &tmp);
  1358. X    freevalue(stack);
  1359. X    *stack = tmp;
  1360. X}
  1361. X
  1362. X
  1363. Xstatic void
  1364. Xo_invert()
  1365. X{
  1366. X    VALUE *vp;
  1367. X    NUMBER *q;
  1368. X    VALUE tmp;
  1369. X
  1370. X    vp = stack;
  1371. X    if (vp->v_type == V_ADDR)
  1372. X        vp = vp->v_addr;
  1373. X    if (vp->v_type == V_NUM) {
  1374. X        q = qinv(vp->v_num);
  1375. X        if (stack->v_type == V_NUM)
  1376. X            qfree(stack->v_num);
  1377. X        stack->v_num = q;
  1378. X        stack->v_type = V_NUM;
  1379. X        return;
  1380. X    }
  1381. X    invertvalue(vp, &tmp);
  1382. X    freevalue(stack);
  1383. X    *stack = tmp;
  1384. X}
  1385. X
  1386. X
  1387. Xstatic void
  1388. Xo_scale()
  1389. X{
  1390. X    VALUE *v1, *v2;
  1391. X    NUMBER *q;
  1392. X    VALUE tmp;
  1393. X
  1394. X    v1 = &stack[0];
  1395. X    v2 = &stack[-1];
  1396. X    if (v1->v_type == V_ADDR)
  1397. X        v1 = v1->v_addr;
  1398. X    if (v2->v_type == V_ADDR)
  1399. X        v2 = v2->v_addr;
  1400. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM)) {
  1401. X        scalevalue(v2, v1, &tmp);
  1402. X        freevalue(stack--);
  1403. X        freevalue(stack);
  1404. X        *stack = tmp;
  1405. X        return;
  1406. X    }
  1407. X    q = v1->v_num;
  1408. X    if (qisfrac(q))
  1409. X        math_error("Non-integral scaling factor");
  1410. X    if (zisbig(q->num))
  1411. X        math_error("Very large scaling factor");
  1412. X    q = qscale(v2->v_num, qtoi(q));
  1413. X    if (stack->v_type == V_NUM)
  1414. X        qfree(stack->v_num);
  1415. X    stack--;
  1416. X    if (stack->v_type == V_NUM)
  1417. X        qfree(stack->v_num);
  1418. X    stack->v_num = q;
  1419. X    stack->v_type = V_NUM;
  1420. X}
  1421. X
  1422. X
  1423. Xstatic void
  1424. Xo_int()
  1425. X{
  1426. X    VALUE *vp;
  1427. X    NUMBER *q;
  1428. X    VALUE tmp;
  1429. X
  1430. X    vp = stack;
  1431. X    if (vp->v_type == V_ADDR)
  1432. X        vp = vp->v_addr;
  1433. X    if (vp->v_type == V_NUM) {
  1434. X        if (qisint(vp->v_num) && (stack->v_type == V_NUM))
  1435. X            return;
  1436. X        q = qint(vp->v_num);
  1437. X        if (stack->v_type == V_NUM)
  1438. X            qfree(stack->v_num);
  1439. X        stack->v_num = q;
  1440. X        stack->v_type = V_NUM;
  1441. X        return;
  1442. X    }
  1443. X    intvalue(vp, &tmp);
  1444. X    freevalue(stack);
  1445. X    *stack = tmp;
  1446. X}
  1447. X
  1448. X
  1449. Xstatic void
  1450. Xo_frac()
  1451. X{
  1452. X    VALUE *vp;
  1453. X    NUMBER *q;
  1454. X    VALUE tmp;
  1455. X
  1456. X    vp = stack;
  1457. X    if (vp->v_type == V_ADDR)
  1458. X        vp = vp->v_addr;
  1459. X    if (vp->v_type == V_NUM) {
  1460. X        q = qfrac(vp->v_num);
  1461. X        if (stack->v_type == V_NUM)
  1462. X            qfree(stack->v_num);
  1463. X        stack->v_num = q;
  1464. X        stack->v_type = V_NUM;
  1465. X        return;
  1466. X    }
  1467. X    fracvalue(vp, &tmp);
  1468. X    freevalue(stack);
  1469. X    *stack = tmp;
  1470. X}
  1471. X
  1472. X
  1473. Xstatic void
  1474. Xo_abs()
  1475. X{
  1476. X    VALUE *v1, *v2;
  1477. X    NUMBER *q;
  1478. X    VALUE tmp;
  1479. X
  1480. X    v1 = &stack[-1];
  1481. X    v2 = &stack[0];
  1482. X    if (v1->v_type == V_ADDR)
  1483. X        v1 = v1->v_addr;
  1484. X    if (v2->v_type == V_ADDR)
  1485. X        v2 = v2->v_addr;
  1486. X    if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM) ||
  1487. X        !qispos(v2->v_num))
  1488. X    {
  1489. X        absvalue(v1, v2, &tmp);
  1490. X        freevalue(stack--);
  1491. X        freevalue(stack);
  1492. X        *stack = tmp;
  1493. X        return;
  1494. X    }
  1495. X    if (stack->v_type == V_NUM)
  1496. X        qfree(stack->v_num);
  1497. X    stack--;
  1498. X    if ((stack->v_type == V_NUM) && !qisneg(v1->v_num))
  1499. X        return;
  1500. X    q = qabs(v1->v_num);
  1501. X    if (stack->v_type == V_NUM)
  1502. X        qfree(stack->v_num);
  1503. X    stack->v_num = q;
  1504. X    stack->v_type = V_NUM;
  1505. X}
  1506. X
  1507. X
  1508. Xstatic void
  1509. Xo_norm()
  1510. X{
  1511. X    VALUE *vp;
  1512. X    NUMBER *q;
  1513. X    VALUE tmp;
  1514. X
  1515. X    vp = stack;
  1516. X    if (vp->v_type == V_ADDR)
  1517. X        vp = vp->v_addr;
  1518. X    if (vp->v_type == V_NUM) {
  1519. X        q = qsquare(vp->v_num);
  1520. X        if (stack->v_type == V_NUM)
  1521. X            qfree(stack->v_num);
  1522. X        stack->v_num = q;
  1523. X        stack->v_type = V_NUM;
  1524. X        return;
  1525. X    }
  1526. X    normvalue(vp, &tmp);
  1527. X    freevalue(stack);
  1528. X    *stack = tmp;
  1529. X}
  1530. X
  1531. X
  1532. Xstatic void
  1533. Xo_square()
  1534. X{
  1535. X    VALUE *vp;
  1536. X    NUMBER *q;
  1537. X    VALUE tmp;
  1538. X
  1539. X    vp = stack;
  1540. X    if (vp->v_type == V_ADDR)
  1541. X        vp = vp->v_addr;
  1542. X    if (vp->v_type == V_NUM) {
  1543. X        q = qsquare(vp->v_num);
  1544. X        if (stack->v_type == V_NUM)
  1545. X            qfree(stack->v_num);
  1546. X        stack->v_num = q;
  1547. X        stack->v_type = V_NUM;
  1548. X        return;
  1549. X    }
  1550. X    squarevalue(vp, &tmp);
  1551. X    freevalue(stack);
  1552. X    *stack = tmp;
  1553. X}
  1554. X
  1555. X
  1556. Xstatic void
  1557. Xo_istype()
  1558. X{
  1559. X    VALUE *v1, *v2;
  1560. X    int r;
  1561. X
  1562. X    v1 = &stack[-1];
  1563. X    v2 = &stack[0];
  1564. X    if (v1->v_type == V_ADDR)
  1565. X        v1 = v1->v_addr;
  1566. X    if (v2->v_type == V_ADDR)
  1567. X        v2 = v2->v_addr;
  1568. X    if ((v1->v_type != V_OBJ) || (v2->v_type != V_OBJ))
  1569. X        r = (v1->v_type == v2->v_type);
  1570. X    else
  1571. X        r = (v1->v_obj->o_actions == v2->v_obj->o_actions);
  1572. X    freevalue(stack--);
  1573. X    freevalue(stack);
  1574. X    stack->v_num = itoq((long) r);
  1575. X    stack->v_type = V_NUM;
  1576. X}
  1577. X
  1578. X
  1579. Xstatic void
  1580. Xo_isint()
  1581. X{
  1582. X    VALUE *vp;
  1583. X    NUMBER *q;
  1584. X
  1585. X    vp = stack;
  1586. X    if (vp->v_type == V_ADDR)
  1587. X        vp = stack->v_addr;
  1588. X    if (vp->v_type != V_NUM) {
  1589. X        freevalue(stack);
  1590. X        stack->v_num = qlink(&_qzero_);
  1591. X        stack->v_type = V_NUM;
  1592. X        return;
  1593. X    }
  1594. X    if (qisint(vp->v_num))
  1595. X        q = qlink(&_qone_);
  1596. X    else
  1597. X        q = qlink(&_qzero_);
  1598. X    if (stack->v_type == V_NUM)
  1599. X        qfree(stack->v_num);
  1600. X    stack->v_num = q;
  1601. X    stack->v_type = V_NUM;
  1602. X}
  1603. X
  1604. X
  1605. Xstatic void
  1606. Xo_isnum()
  1607. X{
  1608. X    VALUE *vp;
  1609. X
  1610. X    vp = stack;
  1611. X    if (vp->v_type == V_ADDR)
  1612. X        vp = vp->v_addr;
  1613. X    switch (vp->v_type) {
  1614. X        case V_NUM:
  1615. X            if (stack->v_type == V_NUM)
  1616. X                qfree(stack->v_num);
  1617. X            break;
  1618. X        case V_COM:
  1619. X            if (stack->v_type == V_COM)
  1620. X                comfree(stack->v_com);
  1621. X            break;
  1622. X        default:
  1623. X            freevalue(stack);
  1624. X            stack->v_num = qlink(&_qzero_);
  1625. X            stack->v_type = V_NUM;
  1626. X            return;
  1627. X    }
  1628. X    stack->v_num = qlink(&_qone_);
  1629. X    stack->v_type = V_NUM;
  1630. X}
  1631. X
  1632. X
  1633. Xstatic void
  1634. Xo_ismat()
  1635. X{
  1636. X    VALUE *vp;
  1637. X
  1638. X    vp = stack;
  1639. X    if (vp->v_type == V_ADDR)
  1640. X        vp = vp->v_addr;
  1641. X    if (vp->v_type != V_MAT) {
  1642. X        freevalue(stack);
  1643. X        stack->v_num = qlink(&_qzero_);
  1644. X        stack->v_type = V_NUM;
  1645. X        return;
  1646. X    }
  1647. X    freevalue(stack);
  1648. X    stack->v_type = V_NUM;
  1649. X    stack->v_num = qlink(&_qone_);
  1650. X}
  1651. X
  1652. X
  1653. Xstatic void
  1654. Xo_islist()
  1655. X{
  1656. X    VALUE *vp;
  1657. X    int r;
  1658. X
  1659. X    vp = stack;
  1660. X    if (vp->v_type == V_ADDR)
  1661. X        vp = vp->v_addr;
  1662. X    r = (vp->v_type == V_LIST);
  1663. X    freevalue(stack);
  1664. X    stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
  1665. X    stack->v_type = V_NUM;
  1666. X}
  1667. X
  1668. X
  1669. Xstatic void
  1670. Xo_isobj()
  1671. X{
  1672. X    VALUE *vp;
  1673. X    int r;
  1674. X
  1675. X    vp = stack;
  1676. X    if (vp->v_type == V_ADDR)
  1677. X        vp = vp->v_addr;
  1678. X    r = (vp->v_type == V_OBJ);
  1679. X    freevalue(stack);
  1680. X    stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
  1681. X    stack->v_type = V_NUM;
  1682. X}
  1683. X
  1684. X
  1685. Xstatic void
  1686. Xo_isstr()
  1687. X{
  1688. X    VALUE *vp;
  1689. X    int r;
  1690. X
  1691. X    vp = stack;
  1692. X    if (vp->v_type == V_ADDR)
  1693. X        vp = vp->v_addr;
  1694. X    r = (vp->v_type == V_STR);
  1695. X    freevalue(stack);
  1696. X    stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
  1697. X    stack->v_type = V_NUM;
  1698. X}
  1699. X
  1700. X
  1701. Xstatic void
  1702. Xo_isfile()
  1703. X{
  1704. X    VALUE *vp;
  1705. X    int r;
  1706. X
  1707. X    vp = stack;
  1708. X    if (vp->v_type == V_ADDR)
  1709. X        vp = vp->v_addr;
  1710. X    r = (vp->v_type == V_FILE);
  1711. X    freevalue(stack);
  1712. X    stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
  1713. X    stack->v_type = V_NUM;
  1714. X}
  1715. X
  1716. X
  1717. Xstatic void
  1718. Xo_isassoc()
  1719. X{
  1720. X    VALUE *vp;
  1721. X    int r;
  1722. X
  1723. X    vp = stack;
  1724. X    if (vp->v_type == V_ADDR)
  1725. X        vp = vp->v_addr;
  1726. X    r = (vp->v_type == V_ASSOC);
  1727. X    freevalue(stack);
  1728. X    stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
  1729. X    stack->v_type = V_NUM;
  1730. X}
  1731. X
  1732. X
  1733. Xstatic void
  1734. Xo_issimple()
  1735. X{
  1736. X    VALUE *vp;
  1737. X    int r;
  1738. X
  1739. X    vp = stack;
  1740. X    if (vp->v_type == V_ADDR)
  1741. X        vp = vp->v_addr;
  1742. X    r = 0;
  1743. X    switch (vp->v_type) {
  1744. X        case V_NULL:
  1745. X        case V_NUM:
  1746. X        case V_COM:
  1747. X        case V_STR:
  1748. X            r = 1;
  1749. X    }
  1750. X    freevalue(stack);
  1751. X    stack->v_num = (r ? qlink(&_qone_) : qlink(&_qzero_));
  1752. X    stack->v_type = V_NUM;
  1753. X}
  1754. X
  1755. X
  1756. Xstatic void
  1757. Xo_isodd()
  1758. X{
  1759. X    VALUE *vp;
  1760. X
  1761. X    vp = stack;
  1762. X    if (vp->v_type == V_ADDR)
  1763. X        vp = vp->v_addr;
  1764. X    if ((vp->v_type == V_NUM) && qisodd(vp->v_num)) {
  1765. X        if (stack->v_type == V_NUM)
  1766. X            qfree(stack->v_num);
  1767. X        stack->v_num = qlink(&_qone_);
  1768. X        stack->v_type = V_NUM;
  1769. X        return;
  1770. X    }
  1771. X    freevalue(stack);
  1772. X    stack->v_num = qlink(&_qzero_);
  1773. X    stack->v_type = V_NUM;
  1774. X}
  1775. X
  1776. X
  1777. Xstatic void
  1778. Xo_iseven()
  1779. X{
  1780. X    VALUE *vp;
  1781. X
  1782. X    vp = stack;
  1783. X    if (vp->v_type == V_ADDR)
  1784. X        vp = vp->v_addr;
  1785. X    if ((vp->v_type == V_NUM) && qiseven(vp->v_num)) {
  1786. X        if (stack->v_type == V_NUM)
  1787. X            qfree(stack->v_num);
  1788. X        stack->v_num = qlink(&_qone_);
  1789. X        stack->v_type = V_NUM;
  1790. X        return;
  1791. X    }
  1792. X    freevalue(stack);
  1793. X    stack->v_num = qlink(&_qzero_);
  1794. X    stack->v_type = V_NUM;
  1795. X}
  1796. X
  1797. X
  1798. Xstatic void
  1799. Xo_isreal()
  1800. X{
  1801. X    VALUE *vp;
  1802. X
  1803. X    vp = stack;
  1804. X    if (vp->v_type == V_ADDR)
  1805. X        vp = vp->v_addr;
  1806. X    if (vp->v_type == V_NUM) {
  1807. X        if (stack->v_type == V_NUM)
  1808. X            qfree(stack->v_num);
  1809. X        stack->v_num = qlink(&_qone_);
  1810. X        stack->v_type = V_NUM;
  1811. X        return;
  1812. X    }
  1813. X    freevalue(stack);
  1814. X    stack->v_num = qlink(&_qzero_);
  1815. X    stack->v_type = V_NUM;
  1816. X}
  1817. X
  1818. X
  1819. Xstatic void
  1820. Xo_isnull()
  1821. X{
  1822. X    VALUE *vp;
  1823. X
  1824. X    vp = stack;
  1825. X    if (vp->v_type == V_ADDR)
  1826. X        vp = vp->v_addr;
  1827. X    if (vp->v_type != V_NULL) {
  1828. X        freevalue(stack);
  1829. X        stack->v_num = qlink(&_qzero_);
  1830. X        stack->v_type = V_NUM;
  1831. X        return;
  1832. X    }
  1833. X    freevalue(stack);
  1834. X    stack->v_num = qlink(&_qone_);
  1835. X    stack->v_type = V_NUM;
  1836. X}
  1837. X
  1838. X
  1839. Xstatic void
  1840. Xo_re()
  1841. X{
  1842. X    VALUE *vp;
  1843. X    NUMBER *q;
  1844. X
  1845. X    vp = stack;
  1846. X    if (vp->v_type == V_ADDR)
  1847. X        vp = vp->v_addr;
  1848. X    if (vp->v_type == V_NUM) {
  1849. X        if (stack->v_type == V_ADDR) {
  1850. X            stack->v_num = qlink(vp->v_num);
  1851. X            stack->v_type = V_NUM;
  1852. X        }
  1853. X        return;
  1854. X    }
  1855. X    if (vp->v_type != V_COM)
  1856. X        math_error("Taking real part of non-number");
  1857. X    q = qlink(vp->v_com->real);
  1858. X    if (stack->v_type == V_COM)
  1859. X        comfree(stack->v_com);
  1860. X    stack->v_num = q;
  1861. X    stack->v_type = V_NUM;
  1862. X}
  1863. X
  1864. X
  1865. Xstatic void
  1866. Xo_im()
  1867. X{
  1868. X    VALUE *vp;
  1869. X    NUMBER *q;
  1870. X
  1871. X    vp = stack;
  1872. X    if (vp->v_type == V_ADDR)
  1873. X        vp = vp->v_addr;
  1874. X    if (vp->v_type == V_NUM) {
  1875. X        if (stack->v_type == V_NUM)
  1876. X            qfree(stack->v_num);
  1877. X        stack->v_num = qlink(&_qzero_);
  1878. X        stack->v_type = V_NUM;
  1879. X        return;
  1880. X    }
  1881. X    if (vp->v_type != V_COM)
  1882. X        math_error("Taking imaginary part of non-number");
  1883. X    q = qlink(vp->v_com->imag);
  1884. X    if (stack->v_type == V_COM)
  1885. X        comfree(stack->v_com);
  1886. X    stack->v_num = q;
  1887. X    stack->v_type = V_NUM;
  1888. X}
  1889. X
  1890. X
  1891. Xstatic void
  1892. Xo_conjugate()
  1893. X{
  1894. X    VALUE *vp;
  1895. X    VALUE tmp;
  1896. X
  1897. X    vp = stack;
  1898. X    if (vp->v_type == V_ADDR)
  1899. X        vp = vp->v_addr;
  1900. X    if (vp->v_type == V_NUM) {
  1901. X        if (stack->v_type == V_ADDR) {
  1902. X            stack->v_num = qlink(vp->v_num);
  1903. X            stack->v_type = V_NUM;
  1904. X        }
  1905. X        return;
  1906. X    }
  1907. X    conjvalue(vp, &tmp);
  1908. X    freevalue(stack);
  1909. X    *stack = tmp;
  1910. X}
  1911. X
  1912. X
  1913. Xstatic void
  1914. Xo_fiaddr()
  1915. X{
  1916. X    register MATRIX *m;    /* current matrix element */
  1917. X    NUMBER *q;        /* index value */
  1918. X    LIST *lp;        /* list header */
  1919. X    ASSOC *ap;        /* association header */
  1920. X    VALUE *vp;        /* stack value */
  1921. X    long index;        /* index value as an integer */
  1922. X
  1923. X    vp = stack;
  1924. X    if (vp->v_type == V_ADDR)
  1925. X        vp = vp->v_addr;
  1926. X    if (vp->v_type != V_NUM)
  1927. X        math_error("Fast indexing by non-number");
  1928. X    q = vp->v_num;
  1929. X    if (qisfrac(q))
  1930. X        math_error("Fast indexing by non-integer");
  1931. X    index = qtoi(q);
  1932. X    if (zisbig(q->num) || (index < 0))
  1933. X        math_error("Index out of range for fast indexing");
  1934. X    if (stack->v_type == V_NUM)
  1935. X        qfree(q);
  1936. X    stack--;
  1937. X    vp = stack;
  1938. X    if (vp->v_type != V_ADDR)
  1939. X        math_error("Bad value for fast indexing");
  1940. X    switch (vp->v_addr->v_type) {
  1941. X        case V_OBJ:
  1942. X            if (index >= vp->v_addr->v_obj->o_actions->count)
  1943. X                math_error("Index out of bounds for object");
  1944. X            vp->v_addr = vp->v_addr->v_obj->o_table + index;
  1945. X            break;
  1946. X        case V_MAT:
  1947. X            m = vp->v_addr->v_mat;
  1948. X            if (index >= m->m_size)
  1949. X                math_error("Index out of bounds for matrix");
  1950. X            vp->v_addr = m->m_table + index;
  1951. X            break;
  1952. X        case V_LIST:
  1953. X            lp = vp->v_addr->v_list;
  1954. X            vp->v_addr = listfindex(lp, index);
  1955. X            if (vp->v_addr == NULL)
  1956. X                math_error("Index out of bounds for list");
  1957. X            break;
  1958. X        case V_ASSOC:
  1959. X            ap = vp->v_addr->v_assoc;
  1960. X            vp->v_addr = assocfindex(ap, index);
  1961. X            if (vp->v_addr == NULL)
  1962. X                math_error("Index out of bounds for association");
  1963. X            break;
  1964. X        default:
  1965. X            math_error("Bad variable type for fast indexing");
  1966. X    }
  1967. X}
  1968. X
  1969. X
  1970. Xstatic void
  1971. Xo_fivalue()
  1972. X{
  1973. X    (void) o_fiaddr();
  1974. X    (void) o_getvalue();
  1975. X}
  1976. X
  1977. X
  1978. Xstatic void
  1979. Xo_sgn()
  1980. X{
  1981. X    VALUE *vp;
  1982. X    NUMBER *q;
  1983. X    VALUE val;
  1984. X
  1985. X    vp = stack;
  1986. X    if (vp->v_type == V_ADDR)
  1987. X        vp = vp->v_addr;
  1988. X    switch (vp->v_type) {
  1989. X        case V_NUM:
  1990. X            q = qsign(vp->v_num);
  1991. X            if (stack->v_type == V_NUM)
  1992. X                qfree(vp->v_num);
  1993. X            stack->v_num = q;
  1994. X            stack->v_type = V_NUM;
  1995. X            break;
  1996. X        case V_OBJ:
  1997. X            val = objcall(OBJ_SGN, vp, NULL_VALUE, NULL_VALUE);
  1998. X            q = itoq(val.v_int);
  1999. X            freevalue(stack);
  2000. X            stack->v_num = q;
  2001. X            stack->v_type = V_NUM;
  2002. X            break;
  2003. X        default:
  2004. X            math_error("Bad value for sgn");
  2005. X    }
  2006. X}
  2007. X
  2008. X
  2009. Xstatic void
  2010. Xo_numerator()
  2011. X{
  2012. X    VALUE *vp;
  2013. X    NUMBER *q;
  2014. X
  2015. X    vp = stack;
  2016. X    if (vp->v_type == V_ADDR)
  2017. X        vp = vp->v_addr;
  2018. X    if (vp->v_type != V_NUM)
  2019. X        math_error("Numerator of non-number");
  2020. X    if ((stack->v_type == V_NUM) && qisint(vp->v_num))
  2021. X        return;
  2022. X    q = qnum(vp->v_num);
  2023. X    if (stack->v_type == V_NUM)
  2024. X        qfree(stack->v_num);
  2025. X    stack->v_num = q;
  2026. X    stack->v_type = V_NUM;
  2027. X}
  2028. X
  2029. X
  2030. Xstatic void
  2031. Xo_denominator()
  2032. X{
  2033. X    VALUE *vp;
  2034. X    NUMBER *q;
  2035. X
  2036. X    vp = stack;
  2037. X    if (vp->v_type == V_ADDR)
  2038. X        vp = vp->v_addr;
  2039. X    if (vp->v_type != V_NUM)
  2040. X        math_error("Denominator of non-number");
  2041. X    q = qden(vp->v_num);
  2042. X    if (stack->v_type == V_NUM)
  2043. X        qfree(stack->v_num);
  2044. X    stack->v_num = q;
  2045. X    stack->v_type = V_NUM;
  2046. X}
  2047. X
  2048. X
  2049. Xstatic void
  2050. Xo_duplicate()
  2051. X{
  2052. X    copyvalue(stack, stack + 1);
  2053. X    stack++;
  2054. X}
  2055. X
  2056. X
  2057. Xstatic void
  2058. Xo_dupvalue()
  2059. X{
  2060. X    if (stack->v_type == V_ADDR)
  2061. X        copyvalue(stack->v_addr, stack + 1);
  2062. X    else
  2063. X        copyvalue(stack, stack + 1);
  2064. X    stack++;
  2065. X}
  2066. X
  2067. X
  2068. Xstatic void
  2069. Xo_pop()
  2070. X{
  2071. X    freevalue(stack--);
  2072. X}
  2073. X
  2074. X
  2075. Xstatic void
  2076. Xo_return()
  2077. X{
  2078. X}
  2079. X
  2080. X
  2081. X/*ARGSUSED*/
  2082. Xstatic void
  2083. Xo_jumpeq(fp, dojump)
  2084. X    FUNC *fp;
  2085. X    BOOL *dojump;
  2086. X{
  2087. X    VALUE *vp;
  2088. X    int i;            /* result of comparison */
  2089. X
  2090. X    vp = stack;
  2091. X    if (vp->v_type == V_ADDR)
  2092. X        vp = vp->v_addr;
  2093. X    if (vp->v_type == V_NUM) {
  2094. X        i = !qiszero(vp->v_num);
  2095. X        if (stack->v_type == V_NUM)
  2096. X            qfree(stack->v_num);
  2097. X    } else {
  2098. X        i = testvalue(vp);
  2099. X        freevalue(stack);
  2100. X    }
  2101. X    stack--;
  2102. X    if (!i)
  2103. X        *dojump = TRUE;
  2104. X}
  2105. X
  2106. X
  2107. X/*ARGSUSED*/
  2108. Xstatic void
  2109. Xo_jumpne(fp, dojump)
  2110. X    FUNC *fp;
  2111. X    BOOL *dojump;
  2112. X{
  2113. X    VALUE *vp;
  2114. X    int i;            /* result of comparison */
  2115. X
  2116. X    vp = stack;
  2117. X    if (vp->v_type == V_ADDR)
  2118. X        vp = vp->v_addr;
  2119. X    if (vp->v_type == V_NUM) {
  2120. X        i = !qiszero(vp->v_num);
  2121. X        if (stack->v_type == V_NUM)
  2122. X            qfree(stack->v_num);
  2123. X    } else {
  2124. X        i = testvalue(vp);
  2125. X        freevalue(stack);
  2126. X    }
  2127. X    stack--;
  2128. X    if (i)
  2129. X        *dojump = TRUE;
  2130. X}
  2131. X
  2132. X
  2133. X/*ARGSUSED*/
  2134. Xstatic void
  2135. Xo_condorjump(fp, dojump)
  2136. X    FUNC *fp;
  2137. X    BOOL *dojump;
  2138. X{
  2139. X    VALUE *vp;
  2140. X
  2141. X    vp = stack;
  2142. X    if (vp->v_type == V_ADDR)
  2143. X        vp = vp->v_addr;
  2144. X    if (vp->v_type == V_NUM) {
  2145. X        if (!qiszero(vp->v_num)) {
  2146. X            *dojump = TRUE;
  2147. X            return;
  2148. X        }
  2149. X        if (stack->v_type == V_NUM)
  2150. X            qfree(stack->v_num);
  2151. X        stack--;
  2152. X        return;
  2153. X    }
  2154. X    if (testvalue(vp))
  2155. X        *dojump = TRUE;
  2156. X    else
  2157. X        freevalue(stack--);
  2158. X}
  2159. X
  2160. X
  2161. X/*ARGSUSED*/
  2162. Xstatic void
  2163. Xo_condandjump(fp, dojump)
  2164. X    FUNC *fp;
  2165. X    BOOL *dojump;
  2166. X{
  2167. X    VALUE *vp;
  2168. X
  2169. X    vp = stack;
  2170. X    if (vp->v_type == V_ADDR)
  2171. X        vp = vp->v_addr;
  2172. X    if (vp->v_type == V_NUM) {
  2173. X        if (qiszero(vp->v_num)) {
  2174. X            *dojump = TRUE;
  2175. X            return;
  2176. X        }
  2177. X        if (stack->v_type == V_NUM)
  2178. X            qfree(stack->v_num);
  2179. X        stack--;
  2180. X        return;
  2181. X    }
  2182. X    if (!testvalue(vp))
  2183. X        *dojump = TRUE;
  2184. X    else
  2185. X        freevalue(stack--);
  2186. X}
  2187. X
  2188. X
  2189. X/*
  2190. X * Compare the top two values on the stack for equality and jump if they are
  2191. X * different, popping off the top element, leaving the first one on the stack.
  2192. X * If they are equal, pop both values and do not jump.
  2193. X */
  2194. X/*ARGSUSED*/
  2195. Xstatic void
  2196. Xo_casejump(fp, dojump)
  2197. X    FUNC *fp;
  2198. X    BOOL *dojump;
  2199. X{
  2200. X    VALUE *v1, *v2;
  2201. X    int r;
  2202. X
  2203. X    v1 = &stack[-1];
  2204. X    v2 = &stack[0];
  2205. X    if (v1->v_type == V_ADDR)
  2206. X        v1 = v1->v_addr;
  2207. X    if (v2->v_type == V_ADDR)
  2208. X        v2 = v2->v_addr;
  2209. X    r = comparevalue(v1, v2);
  2210. X    freevalue(stack--);
  2211. X    if (r)
  2212. X        *dojump = TRUE;
  2213. X    else
  2214. X        freevalue(stack--);
  2215. X}
  2216. X
  2217. X
  2218. X/*ARGSUSED*/
  2219. Xstatic void
  2220. Xo_jump(fp, dojump)
  2221. X    FUNC *fp;
  2222. X    BOOL *dojump;
  2223. X{
  2224. X    *dojump = TRUE;
  2225. X}
  2226. X
  2227. X
  2228. Xstatic void
  2229. Xo_usercall(fp, index, argcount)
  2230. X    FUNC *fp;
  2231. X    long index, argcount;
  2232. X{
  2233. X    fp = findfunc(index);
  2234. X    if (fp == NULL)
  2235. X        math_error("Function \"%s\" is undefined", namefunc(index));
  2236. X    calculate(fp, (int) argcount);
  2237. X}
  2238. X
  2239. X
  2240. X/*ARGSUSED*/
  2241. Xstatic void
  2242. Xo_call(fp, index, argcount)
  2243. X    FUNC *fp;
  2244. X    long index, argcount;
  2245. X{
  2246. X    VALUE result;
  2247. X
  2248. X    result = builtinfunc(index, (int) argcount, stack);
  2249. X    while (--argcount >= 0)
  2250. X        freevalue(stack--);
  2251. X    stack++;
  2252. X    *stack = result;
  2253. X}
  2254. X
  2255. X
  2256. Xstatic void
  2257. Xo_getvalue()
  2258. X{
  2259. X    if (stack->v_type == V_ADDR)
  2260. X        copyvalue(stack->v_addr, stack);
  2261. X}
  2262. X
  2263. X
  2264. Xstatic void
  2265. Xo_cmp()
  2266. X{
  2267. X    VALUE *v1, *v2;
  2268. X    int r;
  2269. X
  2270. X    v1 = &stack[-1];
  2271. X    v2 = &stack[0];
  2272. X    if (v1->v_type == V_ADDR)
  2273. X        v1 = v1->v_addr;
  2274. X    if (v2->v_type == V_ADDR)
  2275. X        v2 = v2->v_addr;
  2276. X    r = relvalue(v1, v2);
  2277. X    freevalue(stack--);
  2278. X    freevalue(stack);
  2279. X    stack->v_num = itoq((long) r);
  2280. X    stack->v_type = V_NUM;
  2281. X}
  2282. X
  2283. X
  2284. Xstatic void
  2285. Xo_eq()
  2286. X{
  2287. X    VALUE *v1, *v2;
  2288. X    int r;
  2289. X
  2290. X    v1 = &stack[-1];
  2291. X    v2 = &stack[0];
  2292. X    if (v1->v_type == V_ADDR)
  2293. X        v1 = v1->v_addr;
  2294. X    if (v2->v_type == V_ADDR)
  2295. X        v2 = v2->v_addr;
  2296. X    r = comparevalue(v1, v2);
  2297. X    freevalue(stack--);
  2298. X    freevalue(stack);
  2299. X    stack->v_num = itoq((long) (r == 0));
  2300. X    stack->v_type = V_NUM;
  2301. X}
  2302. X
  2303. X
  2304. Xstatic void
  2305. Xo_ne()
  2306. X{
  2307. X    VALUE *v1, *v2;
  2308. X    int r;
  2309. X
  2310. X    v1 = &stack[-1];
  2311. X    v2 = &stack[0];
  2312. X    if (v1->v_type == V_ADDR)
  2313. X        v1 = v1->v_addr;
  2314. X    if (v2->v_type == V_ADDR)
  2315. X        v2 = v2->v_addr;
  2316. X    r = comparevalue(v1, v2);
  2317. X    freevalue(stack--);
  2318. X    freevalue(stack);
  2319. X    stack->v_num = itoq((long) (r != 0));
  2320. X    stack->v_type = V_NUM;
  2321. X}
  2322. X
  2323. X
  2324. Xstatic void
  2325. Xo_le()
  2326. X{
  2327. X    VALUE *v1, *v2;
  2328. X    int r;
  2329. X
  2330. X    v1 = &stack[-1];
  2331. X    v2 = &stack[0];
  2332. X    if (v1->v_type == V_ADDR)
  2333. X        v1 = v1->v_addr;
  2334. X    if (v2->v_type == V_ADDR)
  2335. X        v2 = v2->v_addr;
  2336. X    r = relvalue(v1, v2);
  2337. X    freevalue(stack--);
  2338. X    freevalue(stack);
  2339. X    stack->v_num = itoq((long) (r <= 0));
  2340. X    stack->v_type = V_NUM;
  2341. X}
  2342. X
  2343. X
  2344. Xstatic void
  2345. Xo_ge()
  2346. X{
  2347. X    VALUE *v1, *v2;
  2348. X    int r;
  2349. X
  2350. X    v1 = &stack[-1];
  2351. X    v2 = &stack[0];
  2352. X    if (v1->v_type == V_ADDR)
  2353. X        v1 = v1->v_addr;
  2354. X    if (v2->v_type == V_ADDR)
  2355. X        v2 = v2->v_addr;
  2356. X    r = relvalue(v1, v2);
  2357. X    freevalue(stack--);
  2358. X    freevalue(stack);
  2359. X    stack->v_num = itoq((long) (r >= 0));
  2360. X    stack->v_type = V_NUM;
  2361. X}
  2362. X
  2363. X
  2364. Xstatic void
  2365. Xo_lt()
  2366. X{
  2367. X    VALUE *v1, *v2;
  2368. X    int r;
  2369. X
  2370. X    v1 = &stack[-1];
  2371. X    v2 = &stack[0];
  2372. X    if (v1->v_type == V_ADDR)
  2373. X        v1 = v1->v_addr;
  2374. X    if (v2->v_type == V_ADDR)
  2375. X        v2 = v2->v_addr;
  2376. X    r = relvalue(v1, v2);
  2377. X    freevalue(stack--);
  2378. X    freevalue(stack);
  2379. X    stack->v_num = itoq((long) (r < 0));
  2380. X    stack->v_type = V_NUM;
  2381. X}
  2382. X
  2383. X
  2384. Xstatic void
  2385. Xo_gt()
  2386. X{
  2387. X    VALUE *v1, *v2;
  2388. X    int r;
  2389. X
  2390. X    v1 = &stack[-1];
  2391. X    v2 = &stack[0];
  2392. X    if (v1->v_type == V_ADDR)
  2393. X        v1 = v1->v_addr;
  2394. X    if (v2->v_type == V_ADDR)
  2395. X        v2 = v2->v_addr;
  2396. X    r = relvalue(v1, v2);
  2397. X    freevalue(stack--);
  2398. X    freevalue(stack);
  2399. X    stack->v_num = itoq((long) (r > 0));
  2400. X    stack->v_type = V_NUM;
  2401. X}
  2402. X
  2403. X
  2404. Xstatic void
  2405. Xo_preinc()
  2406. X{
  2407. X    NUMBER *q, **np;
  2408. X    VALUE *vp, tmp;
  2409. X
  2410. X    if (stack->v_type != V_ADDR)
  2411. X        math_error("Preincrementing non-variable");
  2412. X    if (stack->v_addr->v_type == V_NUM) {
  2413. X        np = &stack->v_addr->v_num;
  2414. X        q = qinc(*np);
  2415. X        qfree(*np);
  2416. X        *np = q;
  2417. X        stack->v_type = V_NUM;
  2418. X        stack->v_num = qlink(q);
  2419. X        return;
  2420. X    }
  2421. X    vp = stack->v_addr;
  2422. X    incvalue(vp, &tmp);
  2423. X    freevalue(vp);
  2424. X    *vp = tmp;
  2425. X    copyvalue(&tmp, stack);
  2426. X}
  2427. X
  2428. X
  2429. Xstatic void
  2430. Xo_predec()
  2431. X{
  2432. X    NUMBER *q, **np;
  2433. X    VALUE *vp, tmp;
  2434. X
  2435. X    if (stack->v_type != V_ADDR)
  2436. X        math_error("Predecrementing non-variable");
  2437. X    if (stack->v_addr->v_type == V_NUM) {
  2438. X        np = &stack->v_addr->v_num;
  2439. X        q = qdec(*np);
  2440. X        qfree(*np);
  2441. X        *np = q;
  2442. X        stack->v_type = V_NUM;
  2443. X        stack->v_num = qlink(q);
  2444. X        return;
  2445. X    }
  2446. X    vp = stack->v_addr;
  2447. X    decvalue(vp, &tmp);
  2448. X    freevalue(vp);
  2449. X    *vp = tmp;
  2450. X    copyvalue(&tmp, stack);
  2451. X}
  2452. X
  2453. X
  2454. Xstatic void
  2455. Xo_postinc()
  2456. X{
  2457. X    NUMBER *q, **np;
  2458. X    VALUE *vp, tmp;
  2459. X
  2460. X    if (stack->v_type != V_ADDR)
  2461. X        math_error("Postincrementing non-variable");
  2462. X    if (stack->v_addr->v_type == V_NUM) {
  2463. X        np = &stack->v_addr->v_num;
  2464. X        q = *np;
  2465. X        *np = qinc(q);
  2466. X        stack->v_type = V_NUM;
  2467. X        stack->v_num = q;
  2468. X        return;
  2469. X    }
  2470. X    vp = stack->v_addr;
  2471. X    tmp = *vp;
  2472. X    incvalue(&tmp, vp);
  2473. X    *stack = tmp;
  2474. X}
  2475. X
  2476. X
  2477. Xstatic void
  2478. Xo_postdec()
  2479. X{
  2480. X    NUMBER *q, **np;
  2481. X    VALUE *vp, tmp;
  2482. X
  2483. X    if (stack->v_type != V_ADDR)
  2484. X        math_error("Postdecrementing non-variable");
  2485. X    if (stack->v_addr->v_type == V_NUM) {
  2486. X        np = &stack->v_addr->v_num;
  2487. X        q = *np;
  2488. X        *np = qdec(q);
  2489. X        stack->v_type = V_NUM;
  2490. X        stack->v_num = q;
  2491. X        return;
  2492. X    }
  2493. X    vp = stack->v_addr;
  2494. X    tmp = *vp;
  2495. X    decvalue(&tmp, vp);
  2496. X    *stack = tmp;
  2497. X}
  2498. X
  2499. X
  2500. Xstatic void
  2501. Xo_leftshift()
  2502. X{
  2503. X    VALUE *v1, *v2;
  2504. X    VALUE tmp;
  2505. X
  2506. X    v1 = &stack[-1];
  2507. X    v2 = &stack[0];
  2508. X    if (v1->v_type == V_ADDR)
  2509. X        v1 = v1->v_addr;
  2510. X    if (v2->v_type == V_ADDR)
  2511. X        v2 = v2->v_addr;
  2512. X    shiftvalue(v1, v2, FALSE, &tmp);
  2513. X    freevalue(stack--);
  2514. X    freevalue(stack);
  2515. X    *stack = tmp;
  2516. X}
  2517. X
  2518. X
  2519. Xstatic void
  2520. Xo_rightshift()
  2521. X{
  2522. X    VALUE *v1, *v2;
  2523. X    VALUE tmp;
  2524. X
  2525. X    v1 = &stack[-1];
  2526. X    v2 = &stack[0];
  2527. X    if (v1->v_type == V_ADDR)
  2528. X        v1 = v1->v_addr;
  2529. X    if (v2->v_type == V_ADDR)
  2530. X        v2 = v2->v_addr;
  2531. X    shiftvalue(v1, v2, TRUE, &tmp);
  2532. X    freevalue(stack--);
  2533. X    freevalue(stack);
  2534. X    *stack = tmp;
  2535. X}
  2536. X
  2537. X
  2538. X/*ARGSUSED*/
  2539. Xstatic void
  2540. Xo_debug(fp, line)
  2541. X    FUNC *fp;
  2542. X    long line;
  2543. X{
  2544. X    funcline = line;
  2545. X    if (abortlevel >= ABORT_STATEMENT)
  2546. X        math_error("Calculation aborted at statement boundary");
  2547. X}
  2548. X
  2549. X
  2550. Xstatic void
  2551. Xo_printresult()
  2552. X{
  2553. X    VALUE *vp;
  2554. X
  2555. X    vp = stack;
  2556. X    if (vp->v_type == V_ADDR)
  2557. X        vp = vp->v_addr;
  2558. X    if (vp->v_type != V_NULL) {
  2559. X        math_chr('\t');
  2560. X        printvalue(vp, PRINT_UNAMBIG);
  2561. X        math_chr('\n');
  2562. X        math_flush();
  2563. X    }
  2564. X    freevalue(stack--);
  2565. X}
  2566. X
  2567. X
  2568. X/*ARGSUSED*/
  2569. Xstatic void
  2570. Xo_print(fp, flags)
  2571. X    FUNC *fp;
  2572. X    long flags;
  2573. X{
  2574. X    VALUE *vp;
  2575. X
  2576. X    vp = stack;
  2577. X    if (vp->v_type == V_ADDR)
  2578. X        vp = vp->v_addr;
  2579. X    printvalue(vp, (int) flags);
  2580. X    freevalue(stack--);
  2581. X    if (traceflags & TRACE_OPCODES)
  2582. X        printf("\n");
  2583. X    math_flush();
  2584. X}
  2585. X
  2586. X
  2587. Xstatic void
  2588. Xo_printeol()
  2589. X{
  2590. X    math_chr('\n');
  2591. X    math_flush();
  2592. X}
  2593. X
  2594. X
  2595. Xstatic void
  2596. Xo_printspace()
  2597. X{
  2598. X    math_chr(' ');
  2599. X    if (traceflags & TRACE_OPCODES)
  2600. X        printf("\n");
  2601. X}
  2602. X
  2603. X
  2604. X/*ARGSUSED*/
  2605. Xstatic void
  2606. Xo_printstring(fp, cp)
  2607. X    FUNC *fp;
  2608. X    char *cp;
  2609. X{
  2610. X    math_str(cp);
  2611. X    if (traceflags & TRACE_OPCODES)
  2612. X        printf("\n");
  2613. X    math_flush();
  2614. X}
  2615. X
  2616. X
  2617. Xstatic void
  2618. Xo_zero()
  2619. X{
  2620. X    stack++;
  2621. X    stack->v_type = V_NUM;
  2622. X    stack->v_num = qlink(&_qzero_);
  2623. X}
  2624. X
  2625. X
  2626. Xstatic void
  2627. Xo_one()
  2628. X{
  2629. X    stack++;
  2630. X    stack->v_type = V_NUM;
  2631. X    stack->v_num = qlink(&_qone_);
  2632. X}
  2633. X
  2634. X
  2635. Xstatic void
  2636. Xo_save(fp)
  2637. X    FUNC *fp;
  2638. X{
  2639. X    VALUE *vp;
  2640. X
  2641. X    vp = stack;
  2642. X    if (vp->v_type == V_ADDR)
  2643. X        vp = vp->v_addr;
  2644. X    freevalue(&fp->f_savedvalue);
  2645. X    copyvalue(vp, &fp->f_savedvalue);
  2646. X}
  2647. X
  2648. X
  2649. Xstatic void
  2650. Xo_oldvalue()
  2651. X{
  2652. X    copyvalue(&oldvalue, ++stack);
  2653. X}
  2654. X
  2655. X
  2656. Xstatic void
  2657. Xo_quit(fp, cp)
  2658. X    FUNC *fp;
  2659. X    char *cp;
  2660. X{
  2661. X    if ((fp->f_name[0] == '*') && (fp->f_name[1] == '\0')) {
  2662. X        if (cp)
  2663. X            printf("%s\n", cp);
  2664. X        hist_term();
  2665. X        exit(0);
  2666. X    }
  2667. X    if (cp)
  2668. X        math_error("%s", cp);
  2669. X    math_error("quit statement executed");
  2670. X}
  2671. X
  2672. X
  2673. Xstatic void
  2674. Xo_getepsilon()
  2675. X{
  2676. X    stack++;
  2677. X    stack->v_type = V_NUM;
  2678. X    stack->v_num = qlink(_epsilon_);
  2679. X}
  2680. X
  2681. X
  2682. Xstatic void
  2683. Xo_setepsilon()
  2684. X{
  2685. X    VALUE *vp;
  2686. X    NUMBER *newep;
  2687. X
  2688. X    vp = &stack[0];
  2689. X    if (vp->v_type == V_ADDR)
  2690. X        vp = vp->v_addr;
  2691. X    if (vp->v_type != V_NUM)
  2692. X        math_error("Non-numeric for epsilon");
  2693. X    newep = vp->v_num;
  2694. X    stack->v_num = qlink(_epsilon_);
  2695. X    setepsilon(newep);
  2696. X    qfree(newep);
  2697. X}
  2698. X
  2699. X
  2700. Xstatic void
  2701. Xo_setconfig()
  2702. X{
  2703. X    int type;
  2704. X    VALUE *v1, *v2;
  2705. X    VALUE tmp;
  2706. X
  2707. X    v1 = &stack[-1];
  2708. X    v2 = &stack[0];
  2709. X    if (v1->v_type == V_ADDR)
  2710. X        v1 = v1->v_addr;
  2711. X    if (v2->v_type == V_ADDR)
  2712. X        v2 = v2->v_addr;
  2713. X    if (v1->v_type != V_STR)
  2714. X        math_error("Non-string for config");
  2715. X    type = configtype(v1->v_str);
  2716. X    if (type < 0)
  2717. X        math_error("Unknown config name \"%s\"", v1->v_str);
  2718. X    getconfig(type, &tmp);
  2719. X    setconfig(type, v2);
  2720. X    freevalue(stack--);
  2721. X    freevalue(stack);
  2722. X    *stack = tmp;
  2723. X}
  2724. X
  2725. X
  2726. Xstatic void
  2727. Xo_getconfig()
  2728. X{
  2729. X    int type;
  2730. X    VALUE *vp;
  2731. X
  2732. X    vp = &stack[0];
  2733. X    if (vp->v_type == V_ADDR)
  2734. X        vp = vp->v_addr;
  2735. X    if (vp->v_type != V_STR)
  2736. X        math_error("Non-string for config");
  2737. X    type = configtype(vp->v_str);
  2738. X    if (type < 0)
  2739. X        math_error("Unknown config name \"%s\"", vp->v_str);
  2740. X    freevalue(stack);
  2741. X    getconfig(type, stack);
  2742. X}
  2743. X
  2744. X
  2745. X/*
  2746. X * Set the 'old' value to the last value saved during the calculation.
  2747. X */
  2748. Xvoid
  2749. Xupdateoldvalue(fp)
  2750. X    FUNC *fp;
  2751. X{
  2752. X    if (fp->f_savedvalue.v_type == V_NULL)
  2753. X        return;
  2754. X    freevalue(&oldvalue);
  2755. X    oldvalue = fp->f_savedvalue;
  2756. X    fp->f_savedvalue.v_type = V_NULL;
  2757. X}
  2758. X
  2759. X
  2760. X/*
  2761. X * Routine called on any runtime error, to complain about it (with possible
  2762. X * arguments), and then longjump back to the top level command scanner.
  2763. X */
  2764. X#ifdef VARARGS
  2765. X# define VA_ALIST fmt, va_alist
  2766. X# define VA_DCL char *fmt; va_dcl
  2767. X#else
  2768. X# ifdef __STDC__
  2769. X#  define VA_ALIST char *fmt, ...
  2770. X#  define VA_DCL
  2771. X# else
  2772. X#  define VA_ALIST fmt
  2773. X#  define VA_DCL char *fmt;
  2774. X# endif
  2775. X#endif
  2776. X/*VARARGS*/
  2777. Xvoid
  2778. Xmath_error(VA_ALIST)
  2779. X    VA_DCL
  2780. X{
  2781. X    va_list ap;
  2782. X    char buf[MAXERROR+1];
  2783. X
  2784. X    if (funcname && (*funcname != '*'))
  2785. X        fprintf(stderr, "\"%s\": ", funcname);
  2786. X    if (funcline && ((funcname && (*funcname != '*')) || !inputisterminal()))
  2787. X        fprintf(stderr, "line %ld: ", funcline);
  2788. X#ifdef VARARGS
  2789. X    va_start(ap);
  2790. X#else
  2791. X    va_start(ap, fmt);
  2792. SHAR_EOF
  2793. echo "End of part 7"
  2794. echo "File calc2.9.0/opcodes.c is continued in part 8"
  2795. echo "8" > s2_seq_.tmp
  2796. exit 0
  2797.