2 * opcodes - opcode execution module
4 * Copyright (C) 1999-2007 David I. Bell and Ernest Bowen
6 * Primary author: David I. Bell
8 * Calc is open software; you can redistribute it and/or modify it under
9 * the terms of the version 2.1 of the GNU Lesser General Public License
10 * as published by the Free Software Foundation.
12 * Calc is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
15 * Public License for more details.
17 * A copy of version 2.1 of the GNU Lesser General Public License is
18 * distributed with calc under the filename COPYING-LGPL. You should have
19 * received a copy with calc; if not, write to Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * @(#) $Revision: 30.5 $
23 * @(#) $Id: opcodes.c,v 30.5 2013/08/11 08:41:38 chongo Exp $
24 * @(#) $Source: /usr/local/src/bin/calc/RCS/opcodes.c,v $
26 * Under source code control: 1990/02/15 01:48:19
27 * File existed as early as: before 1990
29 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
34 #include <sys/types.h>
45 #include "have_fpos.h"
51 #include "have_unused.h"
53 #define QUICKLOCALS 20 /* local vars to handle quickly */
56 STATIC VALUE stackarray
[MAXSTACK
]; /* storage for stack */
57 STATIC VALUE oldvalue
; /* previous calculation value */
58 STATIC BOOL saveval
= TRUE
; /* to enable or disable saving */
59 STATIC
int calc_errno
; /* most recent error-number */
60 STATIC
int errcount
; /* counts calls to error_value */
62 STATIC
long calc_depth
;
67 VALUE
*stack
; /* current location of top of stack */
68 int dumpnames
; /* names if TRUE, otherwise indices */
69 char *funcname
; /* function being executed */
70 long funcline
; /* function line being executed */
74 * forward declarations
76 S_FUNC
void showsizes(void);
77 S_FUNC
void o_paramaddr(FUNC
*fp
, int argcnt
, VALUE
*args
, long index
);
78 S_FUNC
void o_getvalue(void);
82 * Types of opcodes (depends on arguments saved after the opcode).
84 #define OPNUL 1 /* opcode has no arguments */
85 #define OPONE 2 /* opcode has one integer argument */
86 #define OPTWO 3 /* opcode has two integer arguments */
87 #define OPJMP 4 /* opcode is a jump (with one pointer argument) */
88 #define OPRET 5 /* opcode is a return (with no argument) */
89 #define OPGLB 6 /* opcode has global symbol pointer argument */
90 #define OPPAR 7 /* opcode has parameter index argument */
91 #define OPLOC 8 /* opcode needs local variable pointer (with one arg) */
92 #define OPSTR 9 /* opcode has a string constant arg */
93 #define OPARG 10 /* opcode is given number of arguments */
94 #define OPSTI 11 /* opcode is static initialization */
98 * opcode - info about each opcode
101 void (*o_func
)(); /* routine to call for opcode */
102 int o_type
; /* type of opcode */
103 char *o_name
; /* name of opcode */
108 * external configuration functions
110 E_FUNC
void config_value(CONFIG
*cfg
, int type
, VALUE
*ret
);
111 E_FUNC
void setconfig(int type
, VALUE
*vp
);
115 * Initialize the stack.
122 /* on first init, setup the stack array */
124 for (i
=0; i
< sizeof(stackarray
)/sizeof(stackarray
[0]); ++i
) {
125 stackarray
[i
].v_type
= V_NULL
;
126 stackarray
[i
].v_subtype
= V_NOSUBTYPE
;
130 /* on subsequent inits, free the old stack */
132 while (stack
> stackarray
) {
136 /* initialize calc_depth */
143 * The various opcodes
152 o_localaddr(FUNC
*fp
, VALUE
*locals
, long index
)
154 if ((unsigned long)index
>= fp
->f_localcount
) {
155 math_error("Bad local variable index");
160 stack
->v_addr
= locals
;
161 stack
->v_type
= V_ADDR
;
162 stack
->v_subtype
= V_NOSUBTYPE
;
168 o_globaladdr(FUNC UNUSED
*fp
, GLOBAL
*sp
)
171 math_error("Global variable \"%s\" not initialized",
176 stack
->v_addr
= &sp
->g_value
;
177 stack
->v_type
= V_ADDR
;
178 stack
->v_subtype
= V_NOSUBTYPE
;
184 o_paramaddr(FUNC UNUSED
*fp
, int argcount
, VALUE
*args
, long index
)
186 if ((long)index
>= argcount
) {
187 math_error("Bad parameter index");
192 if (args
->v_type
== V_OCTET
|| args
->v_type
== V_ADDR
) {
196 stack
->v_addr
= args
;
197 stack
->v_type
= V_ADDR
;
198 /* stack->v_subtype = V_NOSUBTYPE; */ /* XXX ??? */
203 o_localvalue(FUNC
*fp
, VALUE
*locals
, long index
)
205 if ((unsigned long)index
>= fp
->f_localcount
) {
206 math_error("Bad local variable index");
210 copyvalue(locals
, ++stack
);
216 o_globalvalue(FUNC UNUSED
*fp
, GLOBAL
*sp
)
219 math_error("Global variable not defined");
222 copyvalue(&sp
->g_value
, ++stack
);
228 o_paramvalue(FUNC UNUSED
*fp
, int argcount
, VALUE
*args
, long index
)
230 if ((long)index
>= argcount
) {
231 math_error("Bad parameter index");
235 if (args
->v_type
== V_ADDR
)
237 copyvalue(args
, ++stack
);
242 o_argvalue(FUNC
*fp
, int argcount
, VALUE
*args
)
248 if (vp
->v_type
== V_ADDR
)
250 if ((vp
->v_type
!= V_NUM
) || qisneg(vp
->v_num
) ||
251 qisfrac(vp
->v_num
)) {
252 math_error("Illegal argument for arg function");
255 if (qiszero(vp
->v_num
)) {
256 if (stack
->v_type
== V_NUM
)
258 stack
->v_num
= itoq((long) argcount
);
259 stack
->v_type
= V_NUM
;
260 stack
->v_subtype
= V_NOSUBTYPE
;
263 index
= qtoi(vp
->v_num
) - 1;
264 if (stack
->v_type
== V_NUM
)
267 (void) o_paramaddr(fp
, argcount
, args
, index
);
273 o_number(FUNC UNUSED
*fp
, long arg
)
279 math_error("Numeric constant value not found");
283 stack
->v_num
= qlink(q
);
284 stack
->v_type
= V_NUM
;
285 stack
->v_subtype
= V_NOSUBTYPE
;
291 o_imaginary(FUNC UNUSED
*fp
, long arg
)
298 math_error("Numeric constant value not found");
302 stack
->v_subtype
= V_NOSUBTYPE
;
304 stack
->v_num
= qlink(q
);
305 stack
->v_type
= V_NUM
;
312 stack
->v_type
= V_COM
;
318 o_string(FUNC UNUSED
*fp
, long arg
)
321 stack
->v_str
= slink(findstring(arg
));
322 stack
->v_type
= V_STR
;
323 stack
->v_subtype
= V_NOSUBTYPE
;
331 stack
->v_type
= V_NULL
;
332 stack
->v_subtype
= V_NOSUBTYPE
;
338 o_matcreate(FUNC UNUSED
*fp
, long dim
)
340 register MATRIX
*mp
; /* matrix being defined */
341 NUMBER
*num1
; /* first number from stack */
342 NUMBER
*num2
; /* second number from stack */
344 long min
[MAXDIM
]; /* minimum range */
345 long max
[MAXDIM
]; /* maximum range */
347 long tmp
; /* temporary */
348 long size
; /* size of matrix */
350 if ((dim
< 0) || (dim
> MAXDIM
)) {
351 math_error("Bad dimension %ld for matrix", dim
);
355 for (i
= dim
- 1; i
>= 0; i
--) {
358 if (v1
->v_type
== V_ADDR
)
360 if (v2
->v_type
== V_ADDR
)
362 if ((v1
->v_type
!= V_NUM
) || (v2
->v_type
!= V_NUM
)) {
363 math_error("Non-numeric bounds for matrix");
368 if (qisfrac(num1
) || qisfrac(num2
)) {
369 math_error("Non-integral bounds for matrix");
372 if (zge31b(num1
->num
) || zge31b(num2
->num
)) {
373 math_error("Very large bounds for matrix");
378 if (min
[i
] > max
[i
]) {
383 size
*= (max
[i
] - min
[i
] + 1);
384 if (size
> 10000000) {
385 math_error("Very large size for matrix");
393 for (i
= 0; i
< dim
; i
++) {
394 mp
->m_min
[i
] = min
[i
];
395 mp
->m_max
[i
] = max
[i
];
398 stack
->v_type
= V_MAT
;
399 stack
->v_subtype
= V_NOSUBTYPE
;
406 o_eleminit(FUNC UNUSED
*fp
, long index
)
413 unsigned short subtype
;
416 if (vp
->v_type
== V_ADDR
)
418 if (vp
->v_type
< 0) {
420 error_value(E_INIT1
);
423 if (vp
->v_subtype
& V_NOCOPYTO
) {
425 error_value(E_INIT2
);
428 switch (vp
->v_type
) {
430 if ((index
< 0) || (index
>= vp
->v_mat
->m_size
)) {
432 error_value(E_INIT3
);
435 oldvp
= &vp
->v_mat
->m_table
[index
];
438 if (index
< 0 || index
>= vp
->v_obj
->o_actions
->oa_count
) {
440 error_value(E_INIT3
);
443 oldvp
= &vp
->v_obj
->o_table
[index
];
446 oldvp
= listfindex(vp
->v_list
, index
);
449 error_value(E_INIT3
);
454 if (index
< 0 || (size_t)index
>= vp
->v_str
->s_len
) {
456 error_value(E_INIT3
);
459 ptr
= (OCTET
*)(&vp
->v_str
->s_str
[index
]);
461 if (vp
->v_type
== V_ADDR
)
468 if (vp
->v_type
== V_NBLOCK
) {
469 blk
= vp
->v_nblock
->blk
;
470 if (blk
->data
== NULL
) {
472 error_value(E_INIT4
);
478 if (index
>= blk
->maxsize
) {
480 error_value(E_INIT3
);
483 ptr
= blk
->data
+ index
;
485 if (vp
->v_type
== V_ADDR
)
488 if (index
>= blk
->datalen
)
489 blk
->datalen
= index
+ 1;
494 error_value(E_INIT5
);
498 subtype
= oldvp
->v_subtype
;
499 if (subtype
& V_NOASSIGNTO
) {
501 error_value(E_INIT6
);
504 if (vp
->v_type
== V_ADDR
) {
512 if ((subtype
& V_NONEWVALUE
) && comparevalue(oldvp
, &tmp
)) {
514 error_value(E_INIT7
);
517 if ((subtype
& V_NONEWTYPE
) && oldvp
->v_type
!= tmp
.v_type
) {
519 error_value(E_INIT8
);
522 if ((subtype
& V_NOERROR
) && tmp
.v_type
< 0) {
523 error_value(E_INIT9
);
526 if (tmp
.v_subtype
& (V_NOASSIGNFROM
| V_NOCOPYFROM
)) {
528 error_value(E_INIT10
);
531 tmp
.v_subtype
|= oldvp
->v_subtype
;
541 * fp function to calculate
542 * dim dimension of matrix
543 * writeflag nonzero if element will be written
547 o_indexaddr(FUNC UNUSED
*fp
, long dim
, long writeflag
)
553 VALUE indices
[MAXDIM
]; /* index values */
554 long index
; /* single dimension index for blocks */
555 VALUE ret
; /* OCTET from as indexed from a block */
558 flag
= (writeflag
!= 0);
560 math_error("Negative dimension for indexing");
564 if (val
->v_type
!= V_NBLOCK
&& val
->v_type
!= V_FILE
) {
565 if (val
->v_type
!= V_ADDR
) {
566 math_error("Non-pointer for indexaddr");
572 vp
= &stack
[-dim
+ 1];
573 for (i
= 0; i
< dim
; i
++) {
574 if (vp
->v_type
== V_ADDR
)
575 indices
[i
] = vp
->v_addr
[0];
581 switch (val
->v_type
) {
583 vp
= matindex(val
->v_mat
, flag
, dim
, indices
);
586 vp
= associndex(val
->v_assoc
, flag
, dim
, indices
);
590 if (val
->v_type
== V_BLOCK
)
593 blk
= val
->v_nblock
->blk
;
594 if (blk
->data
== NULL
) {
595 math_error("Freed block");
600 * obtain single dimensional block index
603 math_error("block has only one dimension");
606 if (indices
[0].v_type
!= V_NUM
) {
607 math_error("Non-numeric index for block");
610 if (qisfrac(indices
[0].v_num
)) {
611 math_error("Non-integral index for block");
614 if (zge31b(indices
[0].v_num
->num
) ||
615 zisneg(indices
[0].v_num
->num
)) {
616 math_error("Index out of bounds for block");
619 index
= ztoi(indices
[0].v_num
->num
);
621 if (index
>= blk
->maxsize
) {
622 math_error("Index out of bounds for block");
625 if (index
>= blk
->datalen
)
626 blk
->datalen
= index
+ 1;
627 ret
.v_type
= V_OCTET
;
628 ret
.v_subtype
= val
->v_subtype
;
629 ret
.v_octet
= &blk
->data
[index
];
635 math_error("string has only one dimension");
638 if (indices
[0].v_type
!= V_NUM
) {
639 math_error("Non-numeric index for string");
642 if (qisfrac(indices
[0].v_num
)) {
643 math_error("Non-integral index for string");
646 if (zge31b(indices
[0].v_num
->num
) ||
647 zisneg(indices
[0].v_num
->num
)) {
648 math_error("Index out of bounds for string");
651 index
= ztoi(indices
[0].v_num
->num
);
652 if (index
< 0 || (size_t)index
>= val
->v_str
->s_len
) {
653 math_error("Index out of bounds for string");
656 ret
.v_type
= V_OCTET
;
657 ret
.v_subtype
= val
->v_subtype
;
658 ret
.v_octet
= (OCTET
*)(val
->v_str
->s_str
+ index
);
664 math_error("list has only one dimension");
667 if (indices
[0].v_type
!= V_NUM
) {
668 math_error("Non-numeric index for list");
671 if (qisfrac(indices
[0].v_num
)) {
672 math_error("Non-integral index for list");
675 if (zge31b(indices
[0].v_num
->num
) ||
676 zisneg(indices
[0].v_num
->num
)) {
677 math_error("Index out of bounds for list");
680 index
= ztoi(indices
[0].v_num
->num
);
681 vp
= listfindex(val
->v_list
, index
);
683 math_error("Index out of bounds for list");
688 math_error("Illegal value for indexing");
693 stack
->v_type
= V_ADDR
;
700 o_elemaddr(FUNC UNUSED
*fp
, long index
)
708 if (vp
->v_type
== V_ADDR
)
710 switch (vp
->v_type
) {
713 if ((index
< 0) || (index
>= mp
->m_size
)) {
714 math_error("Non-existent element for matrix");
717 vp
= &mp
->m_table
[index
];
721 offset
= objoffset(op
, index
);
723 math_error("Non-existent element for object");
726 vp
= &op
->o_table
[offset
];
729 vp
= listfindex(vp
->v_list
, index
);
731 math_error("Index out of bounds for list");
736 math_error("Not initializing matrix, object or list");
739 stack
->v_type
= V_ADDR
;
746 o_elemvalue(FUNC
*fp
, long index
)
748 o_elemaddr(fp
, index
);
749 copyvalue(stack
->v_addr
, stack
);
755 o_objcreate(FUNC UNUSED
*fp
, long arg
)
758 stack
->v_type
= V_OBJ
;
759 stack
->v_subtype
= V_NOSUBTYPE
;
760 stack
->v_obj
= objalloc(arg
);
767 VALUE
*var
; /* variable value */
770 unsigned short subtype
;
774 * get what we will store into
779 * If what we will store into is an OCTET, we must
780 * handle this specially. Only the bottom 8 bits of
781 * certain value types will be assigned ... not the
784 if (var
->v_type
== V_OCTET
) {
785 if (var
->v_subtype
& V_NOCOPYTO
) {
787 *stack
= error_value(E_ASSIGN1
);
791 if (vp
->v_type
== V_ADDR
)
793 if (vp
->v_subtype
& V_NOCOPYFROM
|| vp
->v_type
< 0) {
795 *stack
= error_value(E_ASSIGN2
);
798 copy2octet(vp
, &octet
);
800 if ((var
->v_subtype
& V_NONEWVALUE
) && *var
->v_octet
!= octet
) {
801 *stack
= error_value(E_ASSIGN3
);
804 *var
->v_octet
= octet
;
807 if (var
->v_type
!= V_ADDR
) {
809 *stack
= error_value(E_ASSIGN4
);
814 subtype
= var
->v_subtype
;
815 if (subtype
& V_NOASSIGNTO
) {
817 *stack
= error_value(E_ASSIGN5
);
823 if (var
->v_type
== V_OBJ
) {
824 if (vp
->v_type
== V_ADDR
)
826 (void) objcall(OBJ_ASSIGN
, var
, vp
, NULL_VALUE
);
834 * Get what we will store from
835 * If what will store from is an address, make a copy
836 * of the de-referenced address instead.
838 if (vp
->v_type
== V_ADDR
) {
842 if (vp
->v_subtype
& V_NOASSIGNFROM
) {
843 *stack
= error_value(E_ASSIGN6
);
847 } else if (vp
->v_type
== V_OCTET
) {
856 if ((subtype
& V_NONEWVALUE
) && comparevalue(var
, &tmp
)) {
858 *stack
= error_value(E_ASSIGN7
);
861 if ((subtype
& V_NONEWTYPE
) && var
->v_type
!= tmp
.v_type
) {
863 *stack
= error_value(E_ASSIGN8
);
866 if ((subtype
& V_NOERROR
) && tmp
.v_type
< 0) {
867 *stack
= error_value(E_ASSIGN9
);
872 * perform the assignment
876 var
->v_subtype
|= subtype
;
886 stack
[-1] = stack
[0];
903 switch (stack
->v_type
) {
905 stack
->v_type
= V_VPTR
;
908 stack
->v_type
= V_OPTR
;
912 stack
->v_type
= V_SPTR
;
916 stack
->v_type
= V_NPTR
;
919 math_error("Addressing non-addressable type");
932 if (stack
->v_type
== V_OCTET
) {
933 stack
->v_num
= itoq(*vp
->v_octet
);
934 stack
->v_type
= V_NUM
;
937 if (stack
->v_type
== V_OPTR
) {
938 stack
->v_type
= V_OCTET
;
941 if (stack
->v_type
== V_VPTR
) {
942 stack
->v_type
= V_ADDR
;
945 if (stack
->v_type
== V_SPTR
) {
946 stack
->v_type
= V_STR
;
949 if (stack
->v_type
== V_NPTR
) {
950 if (stack
->v_num
->links
== 0) {
951 stack
->v_type
= V_NULL
;
954 stack
->v_type
= V_NUM
;
955 stack
->v_num
->links
++;
958 if (stack
->v_type
!= V_ADDR
) {
959 math_error("Dereferencing a non-variable");
963 switch (vp
->v_type
) {
970 stack
->v_type
= V_OCTET
;
974 stack
->v_type
= V_ADDR
;
978 stack
->v_type
= V_STR
;
981 if (vp
->v_num
->links
== 0) {
982 stack
->v_type
= V_NULL
;
985 stack
->v_type
= V_NUM
;
986 stack
->v_num
= vp
->v_num
;
987 stack
->v_num
->links
++;
990 copyvalue(vp
, stack
);
998 VALUE
*v1
, *v2
; /* variables to be swapped */
1005 if (v1
->v_type
== V_OCTET
&& v2
->v_type
== V_OCTET
) {
1006 if (v1
->v_octet
!= v2
->v_octet
&&
1007 ((v1
->v_subtype
| v2
->v_subtype
) &
1008 (V_NOCOPYTO
| V_NOCOPYFROM
))) {
1009 *stack
= error_value(E_SWAP1
);
1013 *v1
->v_octet
= *v2
->v_octet
;
1015 } else if (v1
->v_type
== V_ADDR
&& v2
->v_type
== V_ADDR
) {
1018 if (v1
!= v2
&& ((v1
->v_subtype
| v2
->v_subtype
) &
1019 (V_NOASSIGNTO
| V_NOASSIGNFROM
))) {
1020 *stack
= error_value(E_SWAP2
);
1027 *stack
= error_value(E_SWAP3
);
1030 stack
->v_type
= V_NULL
;
1031 stack
->v_subtype
= V_NOSUBTYPE
;
1044 if (v1
->v_type
== V_ADDR
)
1046 if (v2
->v_type
== V_ADDR
)
1048 if (v1
->v_type
== V_OCTET
) {
1050 w1
.v_subtype
= V_NOSUBTYPE
;
1051 w1
.v_num
= itoq(*v1
->v_octet
);
1054 if (v2
->v_type
== V_OCTET
) {
1056 w2
.v_subtype
= V_NOSUBTYPE
;
1057 w2
.v_num
= itoq(*v2
->v_octet
);
1061 addvalue(v1
, v2
, &tmp
);
1081 if (v1
->v_type
== V_ADDR
)
1083 if (v2
->v_type
== V_ADDR
)
1085 if (v1
->v_type
== V_OCTET
) {
1087 w1
.v_subtype
= V_NOSUBTYPE
;
1088 w1
.v_num
= itoq((unsigned char) *v1
->v_octet
);
1091 if (v2
->v_type
== V_OCTET
) {
1093 w2
.v_subtype
= V_NOSUBTYPE
;
1094 w2
.v_num
= itoq((unsigned char) *v2
->v_octet
);
1098 subvalue(v1
, v2
, &tmp
);
1118 if (v1
->v_type
== V_ADDR
)
1120 if (v2
->v_type
== V_ADDR
)
1122 if (v1
->v_type
== V_OCTET
) {
1124 w1
.v_subtype
= V_NOSUBTYPE
;
1125 w1
.v_num
= itoq(*v1
->v_octet
);
1128 if (v2
->v_type
== V_OCTET
) {
1130 w2
.v_subtype
= V_NOSUBTYPE
;
1131 w2
.v_num
= itoq(*v2
->v_octet
);
1134 mulvalue(v1
, v2
, &tmp
);
1153 if (v1
->v_type
== V_ADDR
)
1155 if (v2
->v_type
== V_ADDR
)
1157 powvalue(v1
, v2
, &tmp
);
1173 if (v1
->v_type
== V_ADDR
)
1175 if (v2
->v_type
== V_ADDR
)
1177 if (v1
->v_type
== V_OCTET
) {
1179 w1
.v_subtype
= V_NOSUBTYPE
;
1180 w1
.v_num
= itoq(*v1
->v_octet
);
1183 if (v2
->v_type
== V_OCTET
) {
1185 w2
.v_subtype
= V_NOSUBTYPE
;
1186 w2
.v_num
= itoq(*v2
->v_octet
);
1189 divvalue(v1
, v2
, &tmp
);
1208 if (v1
->v_type
== V_ADDR
)
1210 if (v2
->v_type
== V_ADDR
)
1212 null
.v_type
= V_NULL
;
1213 null
.v_subtype
= V_NOSUBTYPE
;
1214 quovalue(v1
, v2
, &null
, &tmp
);
1229 if (v1
->v_type
== V_ADDR
)
1231 if (v2
->v_type
== V_ADDR
)
1233 null
.v_type
= V_NULL
;
1234 null
.v_subtype
= V_NOSUBTYPE
;
1235 modvalue(v1
, v2
, &null
, &tmp
);
1250 if (v1
->v_type
== V_ADDR
)
1252 if (v2
->v_type
== V_ADDR
)
1255 andvalue(v1
, v2
, &tmp
);
1270 if (v1
->v_type
== V_ADDR
)
1272 if (v2
->v_type
== V_ADDR
)
1275 orvalue(v1
, v2
, &tmp
);
1290 if (v1
->v_type
== V_ADDR
)
1292 if (v2
->v_type
== V_ADDR
)
1295 xorvalue(v1
, v2
, &tmp
);
1309 if (vp
->v_type
== V_ADDR
)
1311 compvalue(vp
, &tmp
);
1325 if (vp
->v_type
== V_ADDR
)
1327 if (vp
->v_type
== V_OBJ
) {
1328 val
= objcall(OBJ_NOT
, vp
, NULL_VALUE
, NULL_VALUE
);
1335 stack
->v_num
= (r
? qlink(&_qzero_
) : qlink(&_qone_
));
1336 stack
->v_type
= V_NUM
;
1337 stack
->v_subtype
= V_NOSUBTYPE
;
1348 if (vp
->v_type
== V_ADDR
)
1351 tmp
.v_type
= V_NULL
;
1352 tmp
.v_subtype
= V_NOSUBTYPE
;
1353 switch (vp
->v_type
) {
1355 tmp
= objcall(OBJ_PLUS
, vp
, NULL_VALUE
, NULL_VALUE
);
1358 addlistitems(vp
->v_list
, &tmp
);
1376 if (vp
->v_type
== V_ADDR
)
1378 if (vp
->v_type
== V_NUM
) {
1379 q
= qneg(vp
->v_num
);
1380 if (stack
->v_type
== V_NUM
)
1381 qfree(stack
->v_num
);
1383 stack
->v_type
= V_NUM
;
1384 stack
->v_subtype
= V_NOSUBTYPE
;
1400 if (vp
->v_type
== V_ADDR
)
1403 invertvalue(vp
, &tmp
);
1417 if (v1
->v_type
== V_ADDR
)
1419 if (v2
->v_type
== V_ADDR
)
1421 scalevalue(v2
, v1
, &tmp
);
1435 if (vp
->v_type
== V_ADDR
)
1450 if (vp
->v_type
== V_ADDR
)
1452 fracvalue(vp
, &tmp
);
1467 if (v1
->v_type
== V_ADDR
)
1469 if (v2
->v_type
== V_ADDR
)
1471 if ((v1
->v_type
!= V_NUM
) || (v2
->v_type
!= V_NUM
) ||
1472 !qispos(v2
->v_num
)) {
1473 absvalue(v1
, v2
, &tmp
);
1479 if (stack
->v_type
== V_NUM
)
1480 qfree(stack
->v_num
);
1482 if ((stack
->v_type
== V_NUM
) && !qisneg(v1
->v_num
))
1484 q
= qqabs(v1
->v_num
);
1485 if (stack
->v_type
== V_NUM
)
1486 qfree(stack
->v_num
);
1488 stack
->v_type
= V_NUM
;
1489 stack
->v_subtype
= V_NOSUBTYPE
;
1501 if (vp
->v_type
== V_ADDR
)
1503 if (vp
->v_type
== V_NUM
) {
1504 q
= qsquare(vp
->v_num
);
1505 if (stack
->v_type
== V_NUM
)
1506 qfree(stack
->v_num
);
1508 stack
->v_type
= V_NUM
;
1509 stack
->v_subtype
= V_NOSUBTYPE
;
1512 normvalue(vp
, &tmp
);
1526 if (vp
->v_type
== V_ADDR
)
1528 if (vp
->v_type
== V_NUM
) {
1529 q
= qsquare(vp
->v_num
);
1530 if (stack
->v_type
== V_NUM
)
1531 qfree(stack
->v_num
);
1533 stack
->v_type
= V_NUM
;
1534 stack
->v_subtype
= V_NOSUBTYPE
;
1537 squarevalue(vp
, &tmp
);
1550 if (vp
->v_type
== V_ADDR
)
1554 stack
->v_type
= V_NUM
;
1555 stack
->v_subtype
= V_NOSUBTYPE
;
1556 stack
->v_num
= i
? qlink(&_qone_
) : qlink(&_qzero_
);
1568 haveaddress
= (vp
->v_type
== V_ADDR
);
1571 switch (vp
->v_type
) {
1572 case V_NUM
: links
= vp
->v_num
->links
; break;
1573 case V_COM
: links
= vp
->v_com
->links
; break;
1574 case V_STR
: links
= vp
->v_str
->s_links
; break;
1580 math_error("Non-positive links!!!");
1586 stack
->v_type
= V_NUM
;
1587 stack
->v_subtype
= V_NOSUBTYPE
;
1588 stack
->v_num
= itoq(links
);
1601 if (v1
->v_type
== V_ADDR
)
1603 if (v2
->v_type
== V_ADDR
)
1605 if (v2
->v_type
!= V_NUM
|| qisfrac(v2
->v_num
)) {
1608 *stack
= error_value(E_BIT1
);
1611 if (zge31b(v2
->v_num
->num
)) {
1614 *stack
= error_value(E_BIT2
);
1617 index
= qtoi(v2
->v_num
);
1618 switch (v1
->v_type
) {
1620 r
= qisset(v1
->v_num
, index
);
1623 r
= stringbit(v1
->v_str
, index
);
1631 *stack
= error_value(E_BIT1
);
1633 stack
->v_type
= V_NULL
;
1635 stack
->v_type
= V_NUM
;
1636 stack
->v_num
= itoq(r
);
1638 stack
->v_subtype
= V_NOSUBTYPE
;
1649 if (vp
->v_type
== V_ADDR
)
1651 switch (vp
->v_type
) {
1653 if (qiszero(vp
->v_num
)) {
1657 if (qisfrac(vp
->v_num
)) {
1661 index
= zhighbit(vp
->v_num
->num
);
1664 index
= stringhighbit(vp
->v_str
);
1668 for (index
= -1; u
; u
>>= 1, ++index
);
1676 *stack
= error_value(E_HIGHBIT1
);
1679 *stack
= error_value(E_HIGHBIT2
);
1682 stack
->v_type
= V_NUM
;
1683 stack
->v_subtype
= V_NOSUBTYPE
;
1684 stack
->v_num
= itoq(index
);
1697 if (vp
->v_type
== V_ADDR
)
1699 switch (vp
->v_type
) {
1701 if (qiszero(vp
->v_num
)) {
1705 if (qisfrac(vp
->v_num
)) {
1709 index
= zlowbit(vp
->v_num
->num
);
1712 index
= stringlowbit(vp
->v_str
);
1728 *stack
= error_value(E_LOWBIT1
);
1731 *stack
= error_value(E_LOWBIT2
);
1734 stack
->v_type
= V_NUM
;
1735 stack
->v_subtype
= V_NOSUBTYPE
;
1736 stack
->v_num
= itoq(index
);
1748 if (vp
->v_type
== V_ADDR
)
1750 contentvalue(vp
, &tmp
);
1764 if (v1
->v_type
== V_ADDR
)
1766 if (v2
->v_type
== V_ADDR
)
1768 hashopvalue(v1
, v2
, &tmp
);
1782 if (vp
->v_type
== V_ADDR
)
1784 backslashvalue(vp
, &tmp
);
1798 if (v1
->v_type
== V_ADDR
)
1800 if (v2
->v_type
== V_ADDR
)
1802 setminusvalue(v1
, v2
, &tmp
);
1817 if (v1
->v_type
== V_ADDR
)
1819 if (v2
->v_type
== V_ADDR
)
1821 if ((v1
->v_type
!= V_OBJ
) || (v2
->v_type
!= V_OBJ
))
1822 r
= (v1
->v_type
== v2
->v_type
);
1824 r
= (v1
->v_obj
->o_actions
== v2
->v_obj
->o_actions
);
1827 stack
->v_num
= itoq((long) r
);
1828 stack
->v_type
= V_NUM
;
1829 stack
->v_subtype
= V_NOSUBTYPE
;
1840 if (vp
->v_type
== V_ADDR
)
1842 if (vp
->v_type
!= V_NUM
) {
1844 stack
->v_num
= qlink(&_qzero_
);
1845 stack
->v_type
= V_NUM
;
1846 stack
->v_subtype
= V_NOSUBTYPE
;
1849 if (qisint(vp
->v_num
))
1852 q
= qlink(&_qzero_
);
1853 if (stack
->v_type
== V_NUM
)
1854 qfree(stack
->v_num
);
1856 stack
->v_type
= V_NUM
;
1857 stack
->v_subtype
= V_NOSUBTYPE
;
1867 if (vp
->v_type
== V_ADDR
)
1869 switch (vp
->v_type
) {
1871 if (stack
->v_type
== V_NUM
)
1872 qfree(stack
->v_num
);
1875 if (stack
->v_type
== V_COM
)
1876 comfree(stack
->v_com
);
1880 stack
->v_num
= qlink(&_qzero_
);
1881 stack
->v_type
= V_NUM
;
1882 stack
->v_subtype
= V_NOSUBTYPE
;
1885 stack
->v_num
= qlink(&_qone_
);
1886 stack
->v_type
= V_NUM
;
1887 stack
->v_subtype
= V_NOSUBTYPE
;
1897 if (vp
->v_type
== V_ADDR
)
1899 if (vp
->v_type
!= V_MAT
) {
1901 stack
->v_num
= qlink(&_qzero_
);
1902 stack
->v_type
= V_NUM
;
1903 stack
->v_subtype
= V_NOSUBTYPE
;
1907 stack
->v_type
= V_NUM
;
1908 stack
->v_subtype
= V_NOSUBTYPE
;
1909 stack
->v_num
= qlink(&_qone_
);
1920 if (vp
->v_type
== V_ADDR
)
1922 r
= (vp
->v_type
== V_LIST
);
1924 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
1925 stack
->v_type
= V_NUM
;
1926 stack
->v_subtype
= V_NOSUBTYPE
;
1937 if (vp
->v_type
== V_ADDR
)
1939 r
= (vp
->v_type
== V_OBJ
);
1941 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
1942 stack
->v_type
= V_NUM
;
1943 stack
->v_subtype
= V_NOSUBTYPE
;
1954 if (vp
->v_type
== V_ADDR
)
1956 r
= (vp
->v_type
== V_STR
);
1958 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
1959 stack
->v_type
= V_NUM
;
1960 stack
->v_subtype
= V_NOSUBTYPE
;
1971 if (vp
->v_type
== V_ADDR
)
1973 r
= (vp
->v_type
== V_FILE
);
1975 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
1976 stack
->v_type
= V_NUM
;
1977 stack
->v_subtype
= V_NOSUBTYPE
;
1988 if (vp
->v_type
== V_ADDR
)
1990 r
= (vp
->v_type
== V_RAND
);
1992 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
1993 stack
->v_type
= V_NUM
;
1994 stack
->v_subtype
= V_NOSUBTYPE
;
2005 if (vp
->v_type
== V_ADDR
)
2007 r
= (vp
->v_type
== V_RANDOM
);
2009 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
2010 stack
->v_type
= V_NUM
;
2011 stack
->v_subtype
= V_NOSUBTYPE
;
2022 if (vp
->v_type
== V_ADDR
)
2024 r
= (vp
->v_type
== V_CONFIG
);
2026 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
2027 stack
->v_type
= V_NUM
;
2028 stack
->v_subtype
= V_NOSUBTYPE
;
2039 if (vp
->v_type
== V_ADDR
)
2041 r
= (vp
->v_type
== V_HASH
);
2043 r
= vp
->v_hash
->hashtype
;
2045 stack
->v_num
= itoq((long) r
);
2046 stack
->v_type
= V_NUM
;
2047 stack
->v_subtype
= V_NOSUBTYPE
;
2058 if (vp
->v_type
== V_ADDR
)
2060 r
= (vp
->v_type
== V_ASSOC
);
2062 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
2063 stack
->v_type
= V_NUM
;
2064 stack
->v_subtype
= V_NOSUBTYPE
;
2075 if (vp
->v_type
== V_ADDR
)
2078 if (vp
->v_type
== V_NBLOCK
)
2080 else if (vp
->v_type
== V_BLOCK
)
2083 stack
->v_num
= itoq(r
);
2084 stack
->v_type
= V_NUM
;
2085 stack
->v_subtype
= V_NOSUBTYPE
;
2096 if (vp
->v_type
== V_ADDR
)
2098 r
= (vp
->v_type
== V_OCTET
);
2100 stack
->v_num
= itoq(r
);
2101 stack
->v_type
= V_NUM
;
2102 stack
->v_subtype
= V_NOSUBTYPE
;
2113 if (vp
->v_type
== V_ADDR
)
2116 switch(vp
->v_type
) {
2117 case V_OPTR
: r
= 1; break;
2118 case V_VPTR
: r
= 2; break;
2119 case V_SPTR
: r
= 3; break;
2120 case V_NPTR
: r
= 4; break;
2123 stack
->v_num
= itoq(r
);
2124 stack
->v_type
= V_NUM
;
2125 stack
->v_subtype
= V_NOSUBTYPE
;
2137 if (vp
->v_type
== V_ADDR
)
2139 if (vp
->v_type
!= V_STR
) {
2140 math_error("Non-string argument for isdefined");
2144 index
= getbuiltinfunc(vp
->v_str
->s_str
);
2148 index
= getuserfunc(vp
->v_str
->s_str
);
2153 stack
->v_num
= itoq(r
);
2154 stack
->v_type
= V_NUM
;
2155 stack
->v_subtype
= V_NOSUBTYPE
;
2166 if (vp
->v_type
== V_ADDR
)
2168 if (vp
->v_type
!= V_STR
) {
2169 math_error("Non-string argument for isobjtype");
2172 index
= checkobject(vp
->v_str
->s_str
);
2174 stack
->v_num
= itoq(index
>= 0);
2175 stack
->v_type
= V_NUM
;
2176 stack
->v_subtype
= V_NOSUBTYPE
;
2187 if (vp
->v_type
== V_ADDR
)
2190 switch (vp
->v_type
) {
2198 stack
->v_num
= (r
? qlink(&_qone_
) : qlink(&_qzero_
));
2199 stack
->v_type
= V_NUM
;
2200 stack
->v_subtype
= V_NOSUBTYPE
;
2210 if (vp
->v_type
== V_ADDR
)
2212 if ((vp
->v_type
== V_NUM
) && qisodd(vp
->v_num
)) {
2213 if (stack
->v_type
== V_NUM
)
2214 qfree(stack
->v_num
);
2215 stack
->v_num
= qlink(&_qone_
);
2216 stack
->v_type
= V_NUM
;
2217 stack
->v_subtype
= V_NOSUBTYPE
;
2221 stack
->v_num
= qlink(&_qzero_
);
2222 stack
->v_type
= V_NUM
;
2223 stack
->v_subtype
= V_NOSUBTYPE
;
2233 if (vp
->v_type
== V_ADDR
)
2235 if ((vp
->v_type
== V_NUM
) && qiseven(vp
->v_num
)) {
2236 if (stack
->v_type
== V_NUM
)
2237 qfree(stack
->v_num
);
2238 stack
->v_num
= qlink(&_qone_
);
2239 stack
->v_type
= V_NUM
;
2240 stack
->v_subtype
= V_NOSUBTYPE
;
2244 stack
->v_num
= qlink(&_qzero_
);
2245 stack
->v_type
= V_NUM
;
2246 stack
->v_subtype
= V_NOSUBTYPE
;
2256 if (vp
->v_type
== V_ADDR
)
2258 if (vp
->v_type
== V_NUM
) {
2259 if (stack
->v_type
== V_NUM
)
2260 qfree(stack
->v_num
);
2261 stack
->v_num
= qlink(&_qone_
);
2262 stack
->v_type
= V_NUM
;
2263 stack
->v_subtype
= V_NOSUBTYPE
;
2267 stack
->v_num
= qlink(&_qzero_
);
2268 stack
->v_type
= V_NUM
;
2269 stack
->v_subtype
= V_NOSUBTYPE
;
2279 if (vp
->v_type
== V_ADDR
)
2281 if (vp
->v_type
!= V_NULL
) {
2283 stack
->v_num
= qlink(&_qzero_
);
2284 stack
->v_type
= V_NUM
;
2285 stack
->v_subtype
= V_NOSUBTYPE
;
2289 stack
->v_num
= qlink(&_qone_
);
2290 stack
->v_type
= V_NUM
;
2291 stack
->v_subtype
= V_NOSUBTYPE
;
2302 if (vp
->v_type
== V_ADDR
)
2304 if (vp
->v_type
== V_NUM
) {
2305 if (stack
->v_type
== V_ADDR
) {
2306 stack
->v_num
= qlink(vp
->v_num
);
2307 stack
->v_type
= V_NUM
;
2308 stack
->v_subtype
= V_NOSUBTYPE
;
2312 if (vp
->v_type
!= V_COM
) {
2313 math_error("Taking real part of non-number");
2316 q
= qlink(vp
->v_com
->real
);
2317 if (stack
->v_type
== V_COM
)
2318 comfree(stack
->v_com
);
2320 stack
->v_type
= V_NUM
;
2321 stack
->v_subtype
= V_NOSUBTYPE
;
2332 if (vp
->v_type
== V_ADDR
)
2334 if (vp
->v_type
== V_NUM
) {
2335 if (stack
->v_type
== V_NUM
)
2336 qfree(stack
->v_num
);
2337 stack
->v_num
= qlink(&_qzero_
);
2338 stack
->v_type
= V_NUM
;
2339 stack
->v_subtype
= V_NOSUBTYPE
;
2342 if (vp
->v_type
!= V_COM
) {
2343 math_error("Taking imaginary part of non-number");
2346 q
= qlink(vp
->v_com
->imag
);
2347 if (stack
->v_type
== V_COM
)
2348 comfree(stack
->v_com
);
2350 stack
->v_type
= V_NUM
;
2351 stack
->v_subtype
= V_NOSUBTYPE
;
2362 if (vp
->v_type
== V_ADDR
)
2364 if (vp
->v_type
== V_NUM
) {
2365 if (stack
->v_type
== V_ADDR
) {
2366 stack
->v_num
= qlink(vp
->v_num
);
2367 stack
->v_type
= V_NUM
;
2368 stack
->v_subtype
= V_NOSUBTYPE
;
2372 conjvalue(vp
, &tmp
);
2381 register MATRIX
*m
; /* current matrix element */
2382 LIST
*lp
; /* list header */
2383 ASSOC
*ap
; /* association header */
2384 VALUE
*vp
; /* stack value */
2385 long index
; /* index value as an integer */
2390 if (vp
->v_type
== V_ADDR
)
2392 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
)) {
2393 math_error("Fast indexing by non-integer");
2396 index
= qtoi(vp
->v_num
);
2397 if (zge31b(vp
->v_num
->num
) || (index
< 0)) {
2398 math_error("Index out of range for fast indexing");
2401 if (stack
->v_type
== V_NUM
)
2402 qfree(stack
->v_num
);
2405 if (vp
->v_type
!= V_ADDR
) {
2406 math_error("Non-pointer for fast indexing");
2410 switch (vp
->v_type
) {
2412 if (index
>= vp
->v_obj
->o_actions
->oa_count
) {
2413 math_error("Index out of bounds for object");
2416 res
= vp
->v_obj
->o_table
+ index
;
2420 if (index
>= m
->m_size
) {
2421 math_error("Index out of bounds for matrix");
2424 res
= m
->m_table
+ index
;
2428 res
= listfindex(lp
, index
);
2430 math_error("Index out of bounds for list");
2436 res
= assocfindex(ap
, index
);
2438 math_error("Index out of bounds for association");
2443 math_error("Bad variable type for fast indexing");
2446 stack
->v_addr
= res
;
2454 (void) o_getvalue();
2466 if (vp
->v_type
== V_ADDR
)
2468 if (vp
->v_type
== V_NUM
) {
2469 q
= qsign(vp
->v_num
);
2470 if (stack
->v_type
== V_NUM
)
2473 stack
->v_type
= V_NUM
;
2474 stack
->v_subtype
= V_NOSUBTYPE
;
2490 if (vp
->v_type
== V_ADDR
)
2492 if (vp
->v_type
!= V_NUM
) {
2493 math_error("Numerator of non-number");
2496 if ((stack
->v_type
== V_NUM
) && qisint(vp
->v_num
))
2498 q
= qnum(vp
->v_num
);
2499 if (stack
->v_type
== V_NUM
)
2500 qfree(stack
->v_num
);
2502 stack
->v_type
= V_NUM
;
2503 stack
->v_subtype
= V_NOSUBTYPE
;
2514 if (vp
->v_type
== V_ADDR
)
2516 if (vp
->v_type
!= V_NUM
) {
2517 math_error("Denominator of non-number");
2520 q
= qden(vp
->v_num
);
2521 if (stack
->v_type
== V_NUM
)
2522 qfree(stack
->v_num
);
2524 stack
->v_type
= V_NUM
;
2525 stack
->v_subtype
= V_NOSUBTYPE
;
2542 if (stack
->v_type
== V_ADDR
)
2543 copyvalue(stack
->v_addr
, stack
+ 1);
2545 copyvalue(stack
, stack
+ 1);
2565 o_jumpz(FUNC UNUSED
*fp
, BOOL
*dojump
)
2568 int i
; /* result of comparison */
2571 if (vp
->v_type
== V_ADDR
)
2573 if (vp
->v_type
== V_NUM
) {
2574 i
= !qiszero(vp
->v_num
);
2575 if (stack
->v_type
== V_NUM
)
2576 qfree(stack
->v_num
);
2589 o_jumpnz(FUNC UNUSED
*fp
, BOOL
*dojump
)
2592 int i
; /* result of comparison */
2595 if (vp
->v_type
== V_ADDR
)
2597 if (vp
->v_type
== V_NUM
) {
2598 i
= !qiszero(vp
->v_num
);
2599 if (stack
->v_type
== V_NUM
)
2600 qfree(stack
->v_num
);
2612 * jumpnn invokes a jump if top value points to a null value
2616 o_jumpnn(FUNC UNUSED
*fp
, BOOL
*dojump
)
2618 if (stack
->v_addr
->v_type
) {
2627 o_condorjump(FUNC UNUSED
*fp
, BOOL
*dojump
)
2632 if (vp
->v_type
== V_ADDR
)
2634 if (vp
->v_type
== V_NUM
) {
2635 if (!qiszero(vp
->v_num
)) {
2639 if (stack
->v_type
== V_NUM
)
2640 qfree(stack
->v_num
);
2653 o_condandjump(FUNC UNUSED
*fp
, BOOL
*dojump
)
2658 if (vp
->v_type
== V_ADDR
)
2660 if (vp
->v_type
== V_NUM
) {
2661 if (qiszero(vp
->v_num
)) {
2665 if (stack
->v_type
== V_NUM
)
2666 qfree(stack
->v_num
);
2678 * Compare the top two values on the stack for equality and jump if they are
2679 * different, popping off the top element, leaving the first one on the stack.
2680 * If they are equal, pop both values and do not jump.
2684 o_casejump(FUNC UNUSED
*fp
, BOOL
*dojump
)
2691 if (v1
->v_type
== V_ADDR
)
2693 if (v2
->v_type
== V_ADDR
)
2695 r
= comparevalue(v1
, v2
);
2706 o_jump(FUNC UNUSED
*fp
, BOOL
*dojump
)
2713 o_usercall(FUNC
*fp
, long index
, long argcount
)
2715 fp
= findfunc(index
);
2717 math_error("Function \"%s\" is undefined", namefunc(index
));
2720 calculate(fp
, (int) argcount
);
2726 o_call(FUNC UNUSED
*fp
, long index
, long argcount
)
2730 result
= builtinfunc(index
, (int) argcount
, stack
);
2731 while (--argcount
>= 0)
2741 if (stack
->v_type
== V_ADDR
)
2742 copyvalue(stack
->v_addr
, stack
);
2754 if (v1
->v_type
== V_ADDR
)
2756 if (v2
->v_type
== V_ADDR
)
2758 relvalue(v1
, v2
, &tmp
);
2773 if (v1
->v_type
== V_ADDR
)
2775 if (v2
->v_type
== V_ADDR
)
2777 r
= comparevalue(v1
, v2
);
2780 stack
->v_num
= itoq((long) (r
== 0));
2781 stack
->v_type
= V_NUM
;
2782 stack
->v_subtype
= V_NOSUBTYPE
;
2794 if (v1
->v_type
== V_ADDR
)
2796 if (v2
->v_type
== V_ADDR
)
2798 r
= comparevalue(v1
, v2
);
2801 stack
->v_num
= itoq((long) (r
!= 0));
2802 stack
->v_type
= V_NUM
;
2803 stack
->v_subtype
= V_NOSUBTYPE
;
2815 if (v1
->v_type
== V_ADDR
)
2817 if (v2
->v_type
== V_ADDR
)
2819 relvalue(v1
, v2
, &tmp
);
2823 stack
->v_type
= V_NUM
;
2824 stack
->v_subtype
= V_NOSUBTYPE
;
2825 if (tmp
.v_type
== V_NUM
) {
2826 stack
->v_num
= !qispos(tmp
.v_num
) ? qlink(&_qone_
):
2828 } else if (tmp
.v_type
== V_COM
) {
2829 stack
->v_num
= qlink(&_qzero_
);
2831 stack
->v_type
= V_NULL
;
2845 if (v1
->v_type
== V_ADDR
)
2847 if (v2
->v_type
== V_ADDR
)
2849 relvalue(v1
, v2
, &tmp
);
2852 stack
->v_type
= V_NUM
;
2853 stack
->v_subtype
= V_NOSUBTYPE
;
2854 if (tmp
.v_type
== V_NUM
) {
2855 stack
->v_num
= !qisneg(tmp
.v_num
) ? qlink(&_qone_
):
2857 } else if (tmp
.v_type
== V_COM
) {
2858 stack
->v_num
= qlink(&_qzero_
);
2860 stack
->v_type
= V_NULL
;
2874 if (v1
->v_type
== V_ADDR
)
2876 if (v2
->v_type
== V_ADDR
)
2878 relvalue(v1
, v2
, &tmp
);
2881 stack
->v_type
= V_NUM
;
2882 stack
->v_subtype
= V_NOSUBTYPE
;
2883 if (tmp
.v_type
== V_NUM
) {
2884 stack
->v_num
= qisneg(tmp
.v_num
) ? qlink(&_qone_
):
2886 } else if (tmp
.v_type
== V_COM
) {
2887 stack
->v_num
= qlink(&_qzero_
);
2889 stack
->v_type
= V_NULL
;
2903 if (v1
->v_type
== V_ADDR
)
2905 if (v2
->v_type
== V_ADDR
)
2907 relvalue(v1
, v2
, &tmp
);
2910 stack
->v_type
= V_NUM
;
2911 stack
->v_subtype
= V_NOSUBTYPE
;
2912 if (tmp
.v_type
== V_NUM
) {
2913 stack
->v_num
= qispos(tmp
.v_num
) ? qlink(&_qone_
):
2915 } else if (tmp
.v_type
== V_COM
) {
2916 stack
->v_num
= qlink(&_qzero_
);
2918 stack
->v_type
= V_NULL
;
2929 if (stack
->v_type
== V_OCTET
) {
2930 if (stack
->v_subtype
& (V_NONEWVALUE
| V_NOCOPYTO
)) {
2931 *stack
= error_value(E_PREINC1
);
2934 stack
->v_octet
[0] = stack
->v_octet
[0] + 1;
2937 if (stack
->v_type
!= V_ADDR
) {
2939 *stack
= error_value(E_PREINC2
);
2944 if (vp
->v_subtype
& (V_NONEWVALUE
| V_NOASSIGNTO
)) {
2945 *stack
= error_value(E_PREINC3
);
2959 if (stack
->v_type
== V_OCTET
) {
2960 if (stack
->v_subtype
& (V_NONEWVALUE
| V_NOCOPYTO
)) {
2961 *stack
= error_value(E_PREDEC1
);
2964 --(*stack
->v_octet
);
2967 if (stack
->v_type
!= V_ADDR
) {
2969 *stack
= error_value(E_PREDEC2
);
2973 if (vp
->v_subtype
& (V_NONEWVALUE
| V_NOASSIGNTO
)) {
2974 *stack
= error_value(E_PREDEC3
);
2989 if (stack
->v_type
== V_OCTET
) {
2990 if (stack
->v_subtype
& (V_NONEWVALUE
| V_NOCOPYTO
)) {
2991 *stack
++ = error_value(E_POSTINC1
);
2992 stack
->v_type
= V_NULL
;
2995 stack
[1] = stack
[0];
2996 stack
->v_type
= V_NUM
;
2997 stack
->v_subtype
= V_NOSUBTYPE
;
2998 stack
->v_num
= itoq((long) stack
->v_octet
[0]);
3000 stack
->v_octet
[0]++;
3003 if (stack
->v_type
!= V_ADDR
) {
3005 *stack
= error_value(E_POSTINC2
);
3010 if (vp
->v_subtype
& V_NONEWVALUE
) {
3012 *stack
= error_value(E_POSTINC3
);
3016 copyvalue(vp
, stack
++);
3020 stack
->v_type
= V_ADDR
;
3021 stack
->v_subtype
= V_NOSUBTYPE
;
3032 if (stack
->v_type
== V_OCTET
) {
3033 if (stack
->v_subtype
& (V_NONEWVALUE
| V_NOCOPYTO
)) {
3034 *stack
++ = error_value(E_POSTDEC1
);
3035 stack
->v_type
= V_NULL
;
3038 stack
[1] = stack
[0];
3039 stack
->v_type
= V_NUM
;
3040 stack
->v_num
= itoq((long) stack
->v_octet
[0]);
3042 stack
->v_octet
[0]--;
3045 if (stack
->v_type
!= V_ADDR
) {
3047 *stack
= error_value(E_POSTDEC2
);
3052 if (vp
->v_subtype
& (V_NONEWVALUE
| V_NOASSIGNTO
)) {
3054 *stack
= error_value(E_POSTDEC3
);
3058 copyvalue(vp
, stack
++);
3062 stack
->v_type
= V_ADDR
;
3063 stack
->v_subtype
= V_NOSUBTYPE
;
3076 if (v1
->v_type
== V_ADDR
)
3078 if (v2
->v_type
== V_ADDR
)
3080 shiftvalue(v1
, v2
, FALSE
, &tmp
);
3095 if (v1
->v_type
== V_ADDR
)
3097 if (v2
->v_type
== V_ADDR
)
3099 shiftvalue(v1
, v2
, TRUE
, &tmp
);
3108 o_debug(FUNC UNUSED
*fp
, long line
)
3111 if (abortlevel
>= ABORT_STATEMENT
) {
3112 math_error("Calculation aborted at statement boundary");
3129 if (vp
->v_type
== V_ADDR
)
3136 if (vp
->v_type
!= V_NULL
) {
3139 printvalue(vp
, PRINT_UNAMBIG
);
3149 o_print(FUNC UNUSED
*fp
, long flags
)
3154 if (vp
->v_type
== V_ADDR
)
3156 printvalue(vp
, (int) flags
);
3158 if (conf
->traceflags
& TRACE_OPCODES
)
3176 if (conf
->traceflags
& TRACE_OPCODES
)
3183 o_printstring(FUNC UNUSED
*fp
, long index
)
3188 s
= findstring(index
);
3191 if (conf
->traceflags
& TRACE_OPCODES
)
3201 stack
->v_type
= V_NUM
;
3202 stack
->v_subtype
= V_NOSUBTYPE
;
3203 stack
->v_num
= qlink(&_qzero_
);
3211 stack
->v_type
= V_NUM
;
3212 stack
->v_subtype
= V_NOSUBTYPE
;
3213 stack
->v_num
= qlink(&_qone_
);
3222 if (saveval
|| fp
->f_name
[1] == '*') {
3224 if (vp
->v_type
== V_ADDR
)
3226 freevalue(&fp
->f_savedvalue
);
3227 copyvalue(vp
, &fp
->f_savedvalue
);
3236 stack
->v_type
= V_ADDR
;
3237 stack
->v_addr
= &oldvalue
;
3247 if (vp
->v_type
== V_ADDR
)
3249 saveval
= testvalue(vp
);
3255 o_quit(FUNC
*fp
, long index
)
3262 s
= findstring(index
);
3265 if (inputisterminal() && !strcmp(fp
->f_name
, "*")) {
3269 while (stack
> stackarray
) {
3272 freevalue(stackarray
);
3273 run_state
= RUN_EXIT
;
3274 if (calc_use_scanerr_jmpbuf
!= 0) {
3275 longjmp(calc_scanerr_jmpbuf
, 50);
3278 "calc_scanerr_jmpbuf not setup, exiting code 50\n");
3279 libcalc_call_me_last();
3285 else if (conf
->verbose_quit
)
3286 printf("quit or abort executed\n");
3287 if (!inputisterminal() && !strcmp(fp
->f_name
, "*"))
3294 o_abort(FUNC
*fp
, long index
)
3305 stack
->v_type
= V_NUM
;
3306 stack
->v_subtype
= V_NOSUBTYPE
;
3307 stack
->v_num
= qlink(conf
->epsilon
);
3318 if (vp
->v_type
== V_ADDR
)
3320 if (vp
->v_type
!= V_NUM
) {
3321 math_error("Non-numeric for epsilon");
3325 stack
->v_num
= qlink(conf
->epsilon
);
3327 if (stack
->v_type
== V_NUM
)
3329 stack
->v_type
= V_NUM
;
3330 stack
->v_subtype
= V_NOSUBTYPE
;
3343 if (v1
->v_type
== V_ADDR
)
3345 if (v2
->v_type
== V_ADDR
)
3347 if (v1
->v_type
!= V_STR
) {
3348 math_error("Non-string for config");
3351 type
= configtype(v1
->v_str
->s_str
);
3353 math_error("Unknown config name \"%s\"",
3357 config_value(conf
, type
, &tmp
);
3358 setconfig(type
, v2
);
3372 if (vp
->v_type
== V_ADDR
)
3374 if (vp
->v_type
!= V_STR
) {
3375 math_error("Non-string for config");
3378 type
= configtype(vp
->v_str
->s_str
);
3380 math_error("Unknown config name \"%s\"",
3385 config_value(conf
, type
, stack
);
3390 * Set the 'old' value to the last value saved during the calculation.
3393 updateoldvalue(FUNC
*fp
)
3395 if (fp
->f_savedvalue
.v_type
== V_NULL
)
3397 freevalue(&oldvalue
);
3398 oldvalue
= fp
->f_savedvalue
;
3399 fp
->f_savedvalue
.v_type
= V_NULL
;
3400 fp
->f_savedvalue
.v_subtype
= V_NOSUBTYPE
;
3405 * error_value - return error as a value and store type in calc_errno
3417 if (errmax
>= 0 && errcount
> errmax
) {
3418 math_error("Error %d caused errcount to exceed errmax", e
);
3421 res
.v_type
= (short) -e
;
3422 res
.v_subtype
= V_NOSUBTYPE
;
3427 * set_errno - return and set calc_errno
3442 * set_errcount - return and set errcount
3457 * Fill a newly created matrix at v1 with copies of value at v2.
3469 if (v1
->v_type
== V_ADDR
)
3471 if (v2
->v_type
== V_ADDR
)
3473 if (v1
->v_type
!= V_MAT
) {
3474 math_error("Non-matrix argument for o_initfill");
3477 s
= v1
->v_mat
->m_size
;
3478 vp
= v1
->v_mat
->m_table
;
3480 copyvalue(v2
, vp
++);
3487 o_show(FUNC
*fp
, long arg
)
3492 case 1: showbuiltins(); return;
3493 case 2: showglobals(); return;
3494 case 3: showfunctions(); return;
3495 case 4: showobjfuncs(); return;
3496 case 5: config_print(conf
); putchar('\n'); return;
3497 case 6: showobjtypes(); return;
3498 case 7: showfiles(); return;
3499 case 8: showsizes(); return;
3500 case 9: showerrors(); return;
3501 case 10: showcustom(); return;
3502 case 11: shownblocks(); return;
3503 case 12: showconstants(); return;
3504 case 13: showallglobals(); return;
3505 case 14: showstatics(); return;
3506 case 15: shownumbers(); return;
3507 case 16: showredcdata(); return;
3508 case 17: showstrings(); return;
3509 case 18: showliterals(); return;
3511 fp
= findfunc(arg
- 19);
3513 printf("Function not defined\n");
3517 for (size
= 0; size
< fp
->f_opcodecount
; ) {
3518 printf("%ld: ", (long)size
);
3519 size
+= dumpop(&fp
->f_opcodes
[size
]);
3527 printf("\tchar\t\t%4ld\n", (long)sizeof(char));
3528 printf("\tshort\t\t%4ld\n", (long)sizeof(short));
3529 printf("\tint\t\t%4ld\n", (long)sizeof(int));
3530 printf("\tlong\t\t%4ld\n", (long)sizeof(long));
3531 printf("\tpointer\t\t%4ld\n", (long)sizeof(void *));
3532 printf("\tFILEPOS\t\t%4ld\n", (long)sizeof(FILEPOS
));
3533 printf("\toff_t\t\t%4ld\n", (long)sizeof(off_t
));
3534 printf("\tHALF\t\t%4ld\n", (long)sizeof(HALF
));
3535 printf("\tFULL\t\t%4ld\n", (long)sizeof(FULL
));
3536 printf("\tVALUE\t\t%4ld\n", (long)sizeof(VALUE
));
3537 printf("\tNUMBER\t\t%4ld\n", (long)sizeof(NUMBER
));
3538 printf("\tZVALUE\t\t%4ld\n", (long)sizeof(ZVALUE
));
3539 printf("\tCOMPLEX\t\t%4ld\n", (long)sizeof(COMPLEX
));
3540 printf("\tSTRING\t\t%4ld\n", (long)sizeof(STRING
));
3541 printf("\tMATRIX\t\t%4ld\n", (long)sizeof(MATRIX
));
3542 printf("\tLIST\t\t%4ld\n", (long)sizeof(LIST
));
3543 printf("\tLISTELEM\t%4ld\n", (long)sizeof(LISTELEM
));
3544 printf("\tOBJECT\t\t%4ld\n", (long)sizeof(OBJECT
));
3545 printf("\tOBJECTACTIONS\t%4ld\n", (long)sizeof(OBJECTACTIONS
));
3546 printf("\tASSOC\t\t%4ld\n", (long)sizeof(ASSOC
));
3547 printf("\tASSOCELEM\t%4ld\n", (long)sizeof(ASSOCELEM
));
3548 printf("\tBLOCK\t\t%4ld\n", (long)sizeof(BLOCK
));
3549 printf("\tNBLOCK\t\t%4ld\n", (long)sizeof(NBLOCK
));
3550 printf("\tCONFIG\t\t%4ld\n", (long)sizeof(CONFIG
));
3551 printf("\tFILEIO\t\t%4ld\n", (long)sizeof(FILEIO
));
3552 printf("\tRAND\t\t%4ld\n", (long)sizeof(RAND
));
3553 printf("\tRANDOM\t\t%4ld\n", (long)sizeof(RANDOM
));
3558 * Information about each opcode.
3560 STATIC
struct opcode opcodes
[MAX_OPCODE
+1] = {
3562 "NOP"}, /* no operation */
3563 {o_localaddr
, OPLOC
,
3564 "LOCALADDR"}, /* address of local variable */
3565 {o_globaladdr
, OPGLB
,
3566 "GLOBALADDR"}, /* address of global variable */
3567 {o_paramaddr
, OPPAR
,
3568 "PARAMADDR"}, /* address of parameter variable */
3569 {o_localvalue
, OPLOC
,
3570 "LOCALVALUE"}, /* value of local variable */
3571 {o_globalvalue
, OPGLB
,
3572 "GLOBALVALUE"}, /* value of global variable */
3573 {o_paramvalue
, OPPAR
,
3574 "PARAMVALUE"}, /* value of parameter variable */
3576 "NUMBER"}, /* constant real numeric value */
3577 {o_indexaddr
, OPTWO
,
3578 "INDEXADDR"}, /* array index address */
3579 {o_printresult
, OPNUL
,
3580 "PRINTRESULT"}, /* print result of top-level expression */
3582 "ASSIGN"}, /* assign value to variable */
3584 "ADD"}, /* add top two values */
3586 "SUB"}, /* subtract top two values */
3588 "MUL"}, /* multiply top two values */
3590 "DIV"}, /* divide top two values */
3592 "MOD"}, /* take mod of top two values */
3594 "SAVE"}, /* save value for later use */
3596 "NEGATE"}, /* negate top value */
3598 "INVERT"}, /* invert top value */
3600 "INT"}, /* take integer part */
3602 "FRAC"}, /* take fraction part */
3603 {o_numerator
, OPNUL
,
3604 "NUMERATOR"}, /* take numerator */
3605 {o_denominator
, OPNUL
,
3606 "DENOMINATOR"}, /* take denominator */
3607 {o_duplicate
, OPNUL
,
3608 "DUPLICATE"}, /* duplicate top value */
3610 "POP"}, /* pop top value */
3612 "RETURN"}, /* return value of function */
3614 "JUMPZ"}, /* jump if value zero */
3616 "JUMPNZ"}, /* jump if value nonzero */
3618 "JUMP"}, /* jump unconditionally */
3620 "USERCALL"}, /* call a user function */
3622 "GETVALUE"}, /* convert address to value */
3624 "EQ"}, /* test elements for equality */
3626 "NE"}, /* test elements for inequality */
3628 "LE"}, /* test elements for <= */
3630 "GE"}, /* test elements for >= */
3632 "LT"}, /* test elements for < */
3634 "GT"}, /* test elements for > */
3636 "PREINC"}, /* add one to variable (++x) */
3638 "PREDEC"}, /* subtract one from variable (--x) */
3640 "POSTINC"}, /* add one to variable (x++) */
3642 "POSTDEC"}, /* subtract one from variable (x--) */
3644 "DEBUG"}, /* debugging point */
3646 "PRINT"}, /* print value */
3647 {o_assignpop
, OPNUL
,
3648 "ASSIGNPOP"}, /* assign to variable and pop it */
3650 "ZERO"}, /* put zero on the stack */
3652 "ONE"}, /* put one on the stack */
3654 "PRINTEOL"}, /* print end of line */
3655 {o_printspace
, OPNUL
,
3656 "PRINTSPACE"}, /* print a space */
3657 {o_printstring
, OPONE
,
3658 "PRINTSTR"}, /* print constant string */
3660 "DUPVALUE"}, /* duplicate value of top value */
3662 "OLDVALUE"}, /* old value from previous calc */
3664 "QUO"}, /* integer quotient of top values */
3666 "POWER"}, /* value raised to a power */
3668 "QUIT"}, /* quit program */
3670 "CALL"}, /* call built-in routine */
3671 {o_getepsilon
, OPNUL
,
3672 "GETEPSILON"}, /* get allowed error for calculations */
3674 "AND"}, /* arithmetic and or top two values */
3676 "OR"}, /* arithmetic or of top two values */
3678 "NOT"}, /* logical not or top value */
3680 "ABS"}, /* absolute value of top value */
3682 "SGN"}, /* sign of number */
3684 "ISINT"}, /* whether number is an integer */
3685 {o_condorjump
, OPJMP
,
3686 "CONDORJUMP"}, /* conditional or jump */
3687 {o_condandjump
, OPJMP
,
3688 "CONDANDJUMP"}, /* conditional and jump */
3690 "SQUARE"}, /* square top value */
3692 "STRING"}, /* string constant value */
3694 "ISNUM"}, /* whether value is a number */
3696 "UNDEF"}, /* load undefined value on stack */
3698 "ISNULL"}, /* whether value is the null value */
3700 "ARGVALUE"}, /* load value of arg (parameter) n */
3701 {o_matcreate
, OPONE
,
3702 "MATCREATE"}, /* create matrix */
3704 "ISMAT"}, /* whether value is a matrix */
3706 "ISSTR"}, /* whether value is a string */
3707 {o_getconfig
, OPNUL
,
3708 "GETCONFIG"}, /* get value of configuration parameter */
3709 {o_leftshift
, OPNUL
,
3710 "LEFTSHIFT"}, /* left shift of integer */
3711 {o_rightshift
, OPNUL
,
3712 "RIGHTSHIFT"}, /* right shift of integer */
3714 "CASEJUMP"}, /* test case and jump if not matched */
3716 "ISODD"}, /* whether value is odd integer */
3718 "ISEVEN"}, /* whether value is even integer */
3720 "FIADDR"}, /* 'fast index' matrix address */
3722 "FIVALUE"}, /* 'fast index' matrix value */
3724 "ISREAL"}, /* whether value is real number */
3725 {o_imaginary
, OPONE
,
3726 "IMAGINARY"}, /* constant imaginary numeric value */
3728 "RE"}, /* real part of complex number */
3730 "IM"}, /* imaginary part of complex number */
3731 {o_conjugate
, OPNUL
,
3732 "CONJUGATE"}, /* complex conjugate */
3733 {o_objcreate
, OPONE
,
3734 "OBJCREATE"}, /* create object */
3736 "ISOBJ"}, /* whether value is an object */
3738 "NORM"}, /* norm of value (square of abs) */
3740 "ELEMADDR"}, /* address of element of object */
3741 {o_elemvalue
, OPONE
,
3742 "ELEMVALUE"}, /* value of element of object */
3744 "ISTYPE"}, /* whether types are the same */
3746 "SCALE"}, /* scale value by a power of two */
3748 "ISLIST"}, /* whether value is a list */
3750 "SWAP"}, /* swap values of two variables */
3752 "ISSIMPLE"}, /* whether value is simple type */
3754 "CMP"}, /* compare values returning -1, 0, 1 */
3755 {o_setconfig
, OPNUL
,
3756 "SETCONFIG"}, /* set configuration parameter */
3757 {o_setepsilon
, OPNUL
,
3758 "SETEPSILON"}, /* set allowed error for calculations */
3760 "ISFILE"}, /* whether value is a file */
3762 "ISASSOC"}, /* whether value is an association */
3764 "INITSTATIC"}, /* once only code for static init */
3766 "ELEMINIT"}, /* assign element of matrix or object */
3768 "ISCONFIG"}, /* whether value is a configuration state */
3770 "ISHASH"}, /* whether value is a hash state */
3772 "ISRAND"}, /* whether value is a rand element */
3774 "ISRANDOM"}, /* whether value is a random element */
3776 "SHOW"}, /* show current state data */
3778 "INITFILL"}, /* initially fill matrix */
3779 {o_assignback
, OPNUL
,
3780 "ASSIGNBACK"}, /* assign in reverse order */
3782 "TEST"}, /* test that value is "nonzero" */
3783 {o_isdefined
, OPNUL
,
3784 "ISDEFINED"}, /* whether a string names a function */
3785 {o_isobjtype
, OPNUL
,
3786 "ISOBJTYPE"}, /* whether a string names an object type */
3788 "ISBLK"}, /* whether value is a block */
3790 "PTR"}, /* octet pointer */
3792 "DEREF"}, /* dereference an octet pointer */
3794 "ISOCTET"}, /* whether a value is an octet */
3796 "ISPTR"}, /* whether a value is a pointer */
3797 {o_setsaveval
, OPNUL
,
3798 "SAVEVAL"}, /* enable or disable saving */
3800 "LINKS"}, /* links to number or string */
3802 "BIT"}, /* whether bit is set */
3804 "COMP"}, /* complement value */
3806 "XOR"}, /* xor (~) of values */
3808 "HIGHBIT"}, /* highbit of value */
3810 "LOWBIT"}, /* lowbit of value */
3812 "CONTENT"}, /* unary hash op */
3814 "HASHOP"}, /* binary hash op */
3815 {o_backslash
, OPNUL
,
3816 "BACKSLASH"}, /* unary backslash op */
3818 "SETMINUS"}, /* binary backslash op */
3820 "PLUS"}, /* unary + op */
3822 "JUMPNN"}, /* jump if non-null */
3824 "ABORT"} /* abort operation */
3829 * Compute the result of a function by interpreting opcodes.
3830 * Arguments have just been pushed onto the evaluation stack.
3833 * fp function to calculate
3834 * argcount number of arguments called with
3837 calculate(FUNC
*fp
, int argcount
)
3839 register unsigned long pc
; /* current pc inside function */
3840 register struct opcode
*op
; /* current opcode pointer */
3841 register VALUE
*locals
; /* pointer to local variables */
3842 long oldline
; /* old value of line counter */
3843 unsigned int opnum
; /* current opcode number */
3844 int origargcount
; /* original number of arguments */
3845 unsigned int i
; /* loop counter */
3846 BOOL dojump
; /* TRUE if jump is to occur */
3847 char *oldname
; /* old function name being executed */
3848 VALUE
*beginstack
; /* beginning of stack frame */
3849 VALUE
*args
; /* pointer to function arguments */
3850 VALUE retval
; /* function return value */
3851 VALUE localtable
[QUICKLOCALS
]; /* some local variables */
3855 funcname
= fp
->f_name
;
3859 origargcount
= argcount
;
3860 while ((unsigned)argcount
< fp
->f_paramcount
) {
3862 stack
->v_type
= V_NULL
;
3863 stack
->v_subtype
= V_NOSUBTYPE
;
3866 locals
= localtable
;
3867 if (fp
->f_localcount
> QUICKLOCALS
) {
3868 locals
= (VALUE
*) malloc(sizeof(VALUE
) * fp
->f_localcount
);
3869 if (locals
== NULL
) {
3870 math_error("No memory for local variables");
3874 for (i
= 0; i
< fp
->f_localcount
; i
++) {
3875 locals
[i
].v_num
= qlink(&_qzero_
);
3876 locals
[i
].v_type
= V_NUM
;
3877 locals
[i
].v_subtype
= V_NOSUBTYPE
;
3881 args
= beginstack
- (argcount
- 1);
3883 if (abortlevel
>= ABORT_OPCODE
) {
3884 math_error("Calculation aborted in opcode");
3887 if (pc
>= fp
->f_opcodecount
) {
3888 math_error("Function pc out of range");
3891 if (stack
> &stackarray
[MAXSTACK
-3]) {
3892 math_error("Evaluation stack depth exceeded");
3895 opnum
= fp
->f_opcodes
[pc
];
3896 if (opnum
> MAX_OPCODE
) {
3897 math_error("Function opcode out of range");
3900 op
= &opcodes
[opnum
];
3901 if (conf
->traceflags
& TRACE_OPCODES
) {
3903 printf("%8s, pc %4ld: ", fp
->f_name
, pc
);
3904 (void)dumpop(&fp
->f_opcodes
[pc
]);
3907 * Now call the opcode routine appropriately.
3910 switch (op
->o_type
) {
3911 case OPNUL
: /* no extra arguments */
3912 /* ignore Saber-C warning #65 - has 1 arg, expected 0 */
3913 /* ok to ignore in proc calculate */
3917 case OPONE
: /* one extra integer argument */
3918 (*op
->o_func
)(fp
, fp
->f_opcodes
[pc
++]);
3921 case OPTWO
: /* two extra integer arguments */
3922 (*op
->o_func
)(fp
, fp
->f_opcodes
[pc
],
3923 fp
->f_opcodes
[pc
+1]);
3927 case OPJMP
: /* jump opcodes (one extra pointer arg) */
3929 (*op
->o_func
)(fp
, &dojump
);
3931 pc
= fp
->f_opcodes
[pc
];
3936 case OPGLB
: /* global symbol reference (pointer arg) */
3937 /* ignore Saber-C warning #68 - benign type mismatch */
3938 /* ok to ignore in proc calculate */
3939 (*op
->o_func
)(fp
, *((char **) &fp
->f_opcodes
[pc
]));
3943 case OPLOC
: /* local variable reference */
3944 (*op
->o_func
)(fp
, locals
, fp
->f_opcodes
[pc
++]);
3947 case OPPAR
: /* parameter variable reference */
3948 (*op
->o_func
)(fp
, argcount
, args
, fp
->f_opcodes
[pc
++]);
3951 case OPARG
: /* parameter variable reference */
3952 (*op
->o_func
)(fp
, origargcount
, args
);
3955 case OPRET
: /* return from function */
3956 if (stack
->v_type
== V_ADDR
)
3957 copyvalue(stack
->v_addr
, stack
);
3958 for (i
= 0; i
< fp
->f_localcount
; i
++)
3959 freevalue(&locals
[i
]);
3960 if (locals
!= localtable
)
3962 if (stack
!= &beginstack
[1]) {
3963 math_error("Misaligned stack");
3968 while (--argcount
>= 0)
3977 case OPSTI
: /* static initialization code */
3978 fp
->f_opcodes
[pc
++ - 1] = OP_JUMP
;
3982 math_error("Unknown opcode type: %d", op
->o_type
);
3986 for (i
= 0; i
< fp
->f_localcount
; i
++)
3987 freevalue(&locals
[i
]);
3988 if (locals
!= localtable
)
3990 if (conf
->calc_debug
& CALCDBG_FUNC_QUIT
)
3991 printf("\t\"%s\": line %ld\n", funcname
, funcline
);
3992 while (stack
> beginstack
)
4002 * Dump an opcode at a particular address.
4003 * Returns the size of the opcode so that it can easily be skipped over.
4006 * pc location of the opcode
4009 dumpop(unsigned long *pc
)
4012 unsigned long op
; /* opcode number */
4015 if (op
<= MAX_OPCODE
)
4016 printf("%s", opcodes
[op
].o_name
);
4018 printf("OP%ld", op
);
4020 case OP_LOCALADDR
: case OP_LOCALVALUE
:
4022 printf(" %s\n", localname((long)*pc
));
4024 printf(" %ld\n", *pc
);
4026 case OP_GLOBALADDR
: case OP_GLOBALVALUE
:
4027 sp
= * (GLOBAL
**) pc
;
4028 printf(" %s", sp
->g_name
);
4029 if (sp
->g_filescope
> SCOPE_GLOBAL
)
4030 printf(" %p", (void *) &sp
->g_value
);
4032 return (1 + PTR_SIZE
);
4033 case OP_PARAMADDR
: case OP_PARAMVALUE
:
4035 printf(" %s\n", paramname((long)*pc
));
4037 printf(" %ld\n", *pc
);
4039 case OP_PRINTSTRING
: case OP_STRING
:
4040 printf(" \"%s\"\n", findstring((long)(*pc
))->s_str
);
4042 case OP_QUIT
: case OP_ABORT
:
4043 if ((long)(*pc
) >= 0)
4044 printf(" \"%s\"", findstring((long)(*pc
))->s_str
);
4048 printf(" %ld %ld\n", pc
[0], pc
[1]);
4050 case OP_PRINT
: case OP_JUMPZ
: case OP_JUMPNZ
: case OP_JUMP
:
4051 case OP_CONDORJUMP
: case OP_CONDANDJUMP
: case OP_CASEJUMP
:
4052 case OP_INITSTATIC
: case OP_MATCREATE
:
4053 case OP_SHOW
: case OP_ELEMINIT
: case OP_ELEMADDR
:
4054 case OP_ELEMVALUE
: case OP_JUMPNN
:
4055 printf(" %ld\n", *pc
);
4058 printf(" %s\n", objtypename(*pc
));
4060 case OP_NUMBER
: case OP_IMAGINARY
:
4061 qprintf(" %r", constvalue(*pc
));
4065 printf(" line %ld\n", *pc
);
4068 printf(" %s with %ld args\n",
4069 builtinname((long)pc
[0]), (long)pc
[1]);
4072 printf(" %s with %ld args\n",
4073 namefunc((long)pc
[0]), (long)pc
[1]);
4083 * Free the constant numbers in a function definition
4086 freenumbers(FUNC
*fp
)
4092 for (pc
= 0; pc
< fp
->f_opcodecount
; ) {
4093 opnum
= fp
->f_opcodes
[pc
++];
4094 op
= &opcodes
[opnum
];
4095 switch (op
->o_type
) {
4104 freeconstant(fp
->f_opcodes
[pc
]);
4106 case OP_PRINTSTRING
:
4110 (long)fp
->f_opcodes
[pc
]);
4126 math_error("Unknown opcode type for freeing");
4130 if (pc
!= fp
->f_opcodecount
) {
4131 math_error("Incorrect opcodecount ???");
4141 return calc_depth
- 1;