aboutsummaryrefslogtreecommitdiff
path: root/sys/fmtio/evvexpr.x
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /sys/fmtio/evvexpr.x
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'sys/fmtio/evvexpr.x')
-rw-r--r--sys/fmtio/evvexpr.x5050
1 files changed, 5050 insertions, 0 deletions
diff --git a/sys/fmtio/evvexpr.x b/sys/fmtio/evvexpr.x
new file mode 100644
index 00000000..19bc4790
--- /dev/null
+++ b/sys/fmtio/evvexpr.x
@@ -0,0 +1,5050 @@
+
+# line 2 "evvexpr.y"
+include <lexnum.h>
+include <ctype.h>
+include <mach.h>
+include <math.h>
+include <evvexpr.h>
+
+.help evvexpr
+.nf --------------------------------------------------------------------------
+EVVEXPR.GY -- Generic XYacc source for a general vector expression evaluator.
+
+ o = evvexpr (expr, getop, getop_data, ufcn, ufcn_data, flags)
+ evvfree (o)
+
+Client callbacks:
+
+ getop (client_data, opname, out)
+ ufcn (client_data, fcn, args, nargs, out)
+
+here "out" is the output operand returned to EVVEXPR. Client_data is any
+arbitrary integer or pointer value passed in to EVVEXPR when by the client
+when the callback was registered. "args" is an array of operand structs,
+the arguments for the user function being called. If the operand or
+function call cannot be completed normally an error exit may be made (call
+error) or an invalid operand may be returned (O_TYPE set to 0). The client
+should not free the "args" input operands, this will be handled by EVVEXPR.
+
+Operand struct (lib$evvexpr.h):
+
+ struct operand {
+ int O_TYPE # operand type (bcsilrd)
+ int O_LEN # operand length (0=scalar)
+ int O_FLAGS # O_FREEVAL, O_FREEOP
+ union {
+ char* O_VALC # string
+ short O_VALS
+ int O_VALI # int or bool
+ long O_VALL
+ real O_VALR
+ double O_VALD
+ pointer O_VALP # vector data
+ }
+ }
+
+The macro O_VALC references the string value of a TY_CHAR operand. The
+flags are O_FREEVAL and O_FREEOP, which tell EVVEXPR and EVVFREE whether or
+not to free any vector operand array or the operand struct when the operand
+is freed. The client should set these flags on operands returned to EVVEXPR
+if it wants EVVEXPR to free any operand storage.
+
+Supported types are bool, char (string), and SILRD. Bool is indicated as
+TY_BOOL in the O_TYPE field of the operand struct, but is stored internally
+as an integer and the value field of a boolean operand is given by O_VALI.
+
+Operands may be either scalars or vectors. A vector is indicated by a O_LEN
+value greater than zero. For vector operands O_VALP points to the data array.
+A special case is TY_CHAR (string), in which case O_LEN is the allocated
+length of the EOS-terminated string. A string is logically a scalar value
+even though it is physically stored in the operand as a character vector.
+
+The trig functions operate upon angles in units of radians. The intrinsic
+functions RAD and DEG are available for converting between radians and
+degrees. A string can be coerced to a binary value and vice versa, using
+the INT, STR, etc. intrinsic functions.
+
+This is a generalization of the older EVEXPR routine, adding additional
+datatypes, support for vector operands, and numerous minor enhancements.
+.endhelp ---------------------------------------------------------------------
+
+define YYMAXDEPTH 64 # parser stack length
+define MAX_ARGS 17 # max args in a function call
+define yyparse xvv_parse
+
+# Arglist structure.
+define LEN_ARGSTRUCT (1+MAX_ARGS+(MAX_ARGS*LEN_OPERAND))
+define A_NARGS Memi[$1] # number of arguments
+define A_ARGP Memi[$1+$2] # array of pointers to operand structs
+define A_OPS ($1+MAX_ARGS+1) # offset to operand storage area
+
+# Intrinsic functions.
+
+define LEN_STAB 300 # for symbol table
+define LEN_SBUF 256
+define LEN_INDEX 97
+
+define LEN_SYM 1 # symbol data
+define SYM_CODE Memi[$1]
+
+define KEYWORDS "|abs|acos|asin|atan|atan2|bool|cos|cosh|deg|double|\
+ |exp|hiv|int|len|log|log10|long|lov|max|mean|median|\
+ |min|mod|nint|rad|real|repl|stddev|shift|short|sin|\
+ |sinh|sort|sqrt|str|sum|tan|tanh|"
+
+define F_ABS 01 # function codes
+define F_ACOS 02
+define F_ASIN 03
+define F_ATAN 04
+define F_ATAN2 05
+define F_BOOL 06
+define F_COS 07
+define F_COSH 08
+define F_DEG 09 # radians to degrees
+define F_DOUBLE 10
+ # newline 11
+define F_EXP 12
+define F_HIV 13 # high value
+define F_INT 14
+define F_LEN 15 # vector length
+define F_LOG 16
+define F_LOG10 17
+define F_LONG 18
+define F_LOV 19 # low value
+define F_MAX 20
+define F_MEAN 21
+define F_MEDIAN 22
+ # newline 23
+define F_MIN 24
+define F_MOD 25
+define F_NINT 26
+define F_RAD 27 # degrees to radians
+define F_REAL 28
+define F_REPL 29 # replicate
+define F_STDDEV 30 # standard deviation
+define F_SHIFT 31
+define F_SHORT 32
+define F_SIN 33
+ # newline 34
+define F_SINH 35
+define F_SORT 36 # sort
+define F_SQRT 37 # square root
+define F_STR 38
+define F_SUM 39
+define F_TAN 40
+define F_TANH 41
+
+define T_B TY_BOOL
+define T_C TY_CHAR
+define T_S TY_SHORT
+define T_I TY_INT
+define T_L TY_LONG
+define T_R TY_REAL
+define T_D TY_DOUBLE
+
+
+# EVVEXPR -- Evaluate a general mixed type vector expression. Input consists
+# of the expression to be evaluated (a string) and, optionally, user
+# procedures for fetching external operands and executing external functions.
+# Output is a pointer to an operand structure containing the computed value of
+# the expression. The output operand structure is dynamically allocated by
+# EVVEXPR and must be freed by the user.
+#
+# NOTE: this is not intended to be an especially efficient procedure. Rather,
+# this is a high level, easy to use procedure, intended to provide greater
+# flexibility in the parameterization of applications programs. The main
+# inefficiency is that, since compilation and execution are not broken out as
+# separate steps, when the routine is repeatedly called to evaluate the same
+# expression with different data, all the compile time computation (parsing
+# etc.) has to be repeated.
+
+pointer procedure evvexpr (expr, getop, getop_data, ufcn, ufcn_data, flags)
+
+char expr[ARB] #I expression to be evaluated
+int getop #I user supplied get operand procedure
+int getop_data #I client data for above function
+int ufcn #I user supplied function call procedure
+int ufcn_data #I client data for above function
+int flags #I flag bits
+
+int junk
+pointer sp, ip
+bool debug, first_time
+int strlen(), xvv_parse()
+pointer xvv_loadsymbols()
+extern xvv_gettok()
+
+errchk xvv_parse, calloc
+include "evvexpr.com"
+data debug /false/
+data first_time /true/
+
+begin
+ call smark (sp)
+
+ if (first_time) {
+ # This creates data which remains for the life of the process.
+ ev_st = xvv_loadsymbols (KEYWORDS)
+ first_time = false
+ }
+
+ # Set user function entry point addresses.
+ ev_getop = getop
+ ev_getop_data = getop_data
+ ev_ufcn = ufcn
+ ev_ufcn_data = ufcn_data
+ ev_flags = flags
+
+ # Allocate an operand struct for the expression value.
+ call calloc (ev_oval, LEN_OPERAND, TY_STRUCT)
+
+ # Make a local copy of the input string.
+ call salloc (ip, strlen(expr), TY_CHAR)
+ call strcpy (expr, Memc[ip], ARB)
+
+ # Evaluate the expression. The expression value is copied into the
+ # output operand structure by XVV_PARSE, given the operand pointer
+ # passed in common. A common must be used since the standard parser
+ # subroutine has a fixed calling sequence.
+
+ junk = xvv_parse (ip, debug, xvv_gettok)
+ O_FLAGS(ev_oval) = or (O_FLAGS(ev_oval), O_FREEOP)
+
+ call sfree (sp)
+ return (ev_oval)
+end
+
+
+# EVVFREE -- Free an operand struct such as is returned by EVVEXPR.
+
+procedure evvfree (o)
+
+pointer o # operand struct
+
+begin
+ call xvv_freeop (o)
+end
+
+define CONSTANT 257
+define IDENTIFIER 258
+define NEWLINE 259
+define YYEOS 260
+define PLUS 261
+define MINUS 262
+define STAR 263
+define SLASH 264
+define EXPON 265
+define CONCAT 266
+define QUEST 267
+define COLON 268
+define LT 269
+define GT 270
+define LE 271
+define EQ 272
+define NE 273
+define SE 274
+define LAND 275
+define LOR 276
+define LNOT 277
+define BAND 278
+define BOR 279
+define BXOR 280
+define BNOT 281
+define AT 282
+define GE 283
+define UMINUS 284
+define yyclearin yychar = -1
+define yyerrok yyerrflag = 0
+define YYMOVE call amovi (Memi[$1], Memi[$2], YYOPLEN)
+define YYERRCODE 256
+
+
+# End generic preprocessor escape.
+
+
+
+# XVV_UNOP -- Unary operation. Perform the indicated unary operation on the
+# input operand, returning the result as the output operand.
+
+procedure xvv_unop (opcode, in, out)
+
+int opcode #I operation to be performed
+pointer in #I input operand
+pointer out #I output operand
+
+short val_s
+long val_l
+int val_i, nelem
+errchk xvv_error, xvv_initop
+string s_badswitch "unop: bad switch"
+
+begin
+ nelem = O_LEN(in)
+
+ switch (opcode) {
+ case MINUS:
+ # Unary negation.
+ call xvv_initop (out, nelem, O_TYPE(in))
+ switch (O_TYPE(in)) {
+ case TY_BOOL, TY_CHAR:
+ call xvv_error ("negation of a nonarithmetic operand")
+
+ case TY_SHORT:
+ if (nelem > 0)
+ call anegs (Mems[O_VALP(in)], Mems[O_VALP(out)], nelem)
+ else
+ O_VALS(out) = -O_VALS(in)
+
+ case TY_INT:
+ if (nelem > 0)
+ call anegi (Memi[O_VALP(in)], Memi[O_VALP(out)], nelem)
+ else
+ O_VALI(out) = -O_VALI(in)
+
+ case TY_LONG:
+ if (nelem > 0)
+ call anegl (Meml[O_VALP(in)], Meml[O_VALP(out)], nelem)
+ else
+ O_VALL(out) = -O_VALL(in)
+
+ case TY_REAL:
+ if (nelem > 0)
+ call anegr (Memr[O_VALP(in)], Memr[O_VALP(out)], nelem)
+ else
+ O_VALR(out) = -O_VALR(in)
+
+ case TY_DOUBLE:
+ if (nelem > 0)
+ call anegd (Memd[O_VALP(in)], Memd[O_VALP(out)], nelem)
+ else
+ O_VALD(out) = -O_VALD(in)
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ case LNOT:
+ # Logical NOT.
+
+ call xvv_initop (out, nelem, TY_BOOL)
+ switch (O_TYPE(in)) {
+ case TY_BOOL:
+ if (nelem > 0)
+ call abeqki (Memi[O_VALP(in)], NO, Memi[O_VALP(out)], nelem)
+ else {
+ if (O_VALI(in) == NO)
+ O_VALI(out) = YES
+ else
+ O_VALI(out) = NO
+ }
+
+ case TY_SHORT:
+ if (nelem > 0) {
+ val_s = NO
+ call abeqks (Mems[O_VALP(in)], val_s, Memi[O_VALP(out)],
+ nelem)
+ } else {
+ if (O_VALS(in) == NO)
+ O_VALS(out) = YES
+ else
+ O_VALS(out) = NO
+ }
+
+ case TY_INT:
+ if (nelem > 0) {
+ val_i = NO
+ call abeqki (Memi[O_VALP(in)], val_i, Memi[O_VALP(out)],
+ nelem)
+ } else {
+ if (O_VALI(in) == NO)
+ O_VALI(out) = YES
+ else
+ O_VALI(out) = NO
+ }
+
+ case TY_LONG:
+ if (nelem > 0) {
+ val_l = NO
+ call abeqkl (Meml[O_VALP(in)], val_l, Memi[O_VALP(out)],
+ nelem)
+ } else {
+ if (O_VALL(in) == NO)
+ O_VALL(out) = YES
+ else
+ O_VALL(out) = NO
+ }
+
+ case TY_CHAR, TY_REAL, TY_DOUBLE:
+ call xvv_error ("not of a nonlogical")
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ case BNOT:
+ # Bitwise boolean NOT.
+
+ call xvv_initop (out, nelem, O_TYPE(in))
+ switch (O_TYPE(in)) {
+ case TY_BOOL, TY_CHAR, TY_REAL, TY_DOUBLE:
+ call xvv_error ("boolean not of a noninteger operand")
+
+ case TY_SHORT:
+ if (nelem > 0)
+ call anots (Mems[O_VALP(in)], Mems[O_VALP(out)], nelem)
+ else
+ O_VALS(out) = not(O_VALS(in))
+
+ case TY_INT:
+ if (nelem > 0)
+ call anoti (Memi[O_VALP(in)], Memi[O_VALP(out)], nelem)
+ else
+ O_VALI(out) = not(O_VALI(in))
+
+ case TY_LONG:
+ if (nelem > 0)
+ call anotl (Meml[O_VALP(in)], Meml[O_VALP(out)], nelem)
+ else
+ O_VALL(out) = not(O_VALL(in))
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ call xvv_freeop (in)
+end
+
+
+# XVV_BINOP -- Binary operation. Perform the indicated arithmetic binary
+# operation on the two input operands, returning the result as the output
+# operand.
+
+procedure xvv_binop (opcode, in1, in2, out)
+
+int opcode #I operation to be performed
+pointer in1, in2 #I input operands
+pointer out #I output operand
+
+
+short v_s
+short xvv_nulls()
+extern xvv_nulls()
+
+int v_i
+int xvv_nulli()
+extern xvv_nulli()
+
+long v_l
+long xvv_nulll()
+extern xvv_nulll()
+
+real v_r
+real xvv_nullr()
+extern xvv_nullr()
+
+double v_d
+double xvv_nulld()
+extern xvv_nulld()
+
+pointer sp, otemp, p1, p2, po
+int dtype, nelem, len1, len2
+include "evvexpr.com"
+
+int xvv_newtype(), strlen()
+errchk xvv_newtype, xvv_initop, xvv_chtype, xvv_error
+string s_badswitch "binop: bad case in switch"
+string s_boolop "binop: bitwise boolean operands must be an integer type"
+define done_ 91
+
+begin
+ # Set the datatype of the output operand, taking an error action if
+ # the operands have incompatible datatypes.
+
+ dtype = xvv_newtype (O_TYPE(in1), O_TYPE(in2))
+
+ # Compute the size of the output operand. If both input operands are
+ # vectors the length of the output vector is the shorter of the two.
+
+ switch (dtype) {
+ case TY_BOOL:
+ call xvv_error ("binop: operation illegal for boolean operands")
+ case TY_CHAR:
+ nelem = strlen (O_VALC(in1)) + strlen (O_VALC(in2))
+ default:
+ if (opcode == CONCAT)
+ nelem = max (1, O_LEN(in1)) + max (1, O_LEN(in2))
+ else {
+ if (O_LEN(in1) > 0 && O_LEN(in2) > 0)
+ nelem = min (O_LEN(in1), O_LEN(in2))
+ else if (O_LEN(in1) > 0)
+ nelem = O_LEN(in1)
+ else if (O_LEN(in2) > 0)
+ nelem = O_LEN(in2)
+ else
+ nelem = 0
+ }
+ }
+
+ # Convert input operands to desired type.
+ if (O_TYPE(in1) != dtype)
+ call xvv_chtype (in1, in1, dtype)
+ if (O_TYPE(in2) != dtype)
+ call xvv_chtype (in2, in2, dtype)
+
+ # If this is a scalar/vector operation make sure the vector is the
+ # first operand.
+
+ len1 = O_LEN(in1)
+ len2 = O_LEN(in2)
+
+ if (len1 == 0 && len2 > 0) {
+ switch (opcode) {
+ case PLUS:
+ # Swap operands.
+ call smark (sp)
+ call salloc (otemp, LEN_OPERAND, TY_STRUCT)
+ YYMOVE (in1, otemp)
+ YYMOVE (in2, in1)
+ YYMOVE (otemp, in2)
+ call sfree (sp)
+
+ case CONCAT:
+ ; # Do nothing
+
+ default:
+ # Promote operand to a constant vector. Inefficient, but
+ # better than aborting.
+
+ switch (dtype) {
+
+ case TY_SHORT:
+ v_s = O_VALS(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovks (v_s, Mems[O_VALP(in1)], nelem)
+
+ case TY_INT:
+ v_i = O_VALI(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovki (v_i, Memi[O_VALP(in1)], nelem)
+
+ case TY_LONG:
+ v_l = O_VALL(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovkl (v_l, Meml[O_VALP(in1)], nelem)
+
+ case TY_REAL:
+ v_r = O_VALR(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovkr (v_r, Memr[O_VALP(in1)], nelem)
+
+ case TY_DOUBLE:
+ v_d = O_VALD(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovkd (v_d, Memd[O_VALP(in1)], nelem)
+
+ }
+ }
+
+ len1 = O_LEN(in1)
+ len2 = O_LEN(in2)
+ }
+
+ # Initialize the output operand.
+ call xvv_initop (out, nelem, dtype)
+
+ p1 = O_VALP(in1)
+ p2 = O_VALP(in2)
+ po = O_VALP(out)
+
+ # The bitwise boolean binary operators a special case since only the
+ # integer datatypes are permitted. Otherwise the bitwise booleans
+ # are just like arithmetic booleans.
+
+ if (opcode == BAND || opcode == BOR || opcode == BXOR) {
+ switch (dtype) {
+
+ case TY_SHORT:
+ switch (opcode) {
+ case BAND:
+ if (len1 <= 0) {
+ O_VALS(out) = and (O_VALS(in1), O_VALS(in2))
+ } else if (len2 <= 0) {
+ call aandks (Mems[p1], O_VALS(in2),
+ Mems[po], nelem)
+ } else {
+ call aands (Mems[p1], Mems[p2],
+ Mems[po], nelem)
+ }
+ case BOR:
+ if (len1 <= 0) {
+ O_VALS(out) = or (O_VALS(in1), O_VALS(in2))
+ } else if (len2 <= 0) {
+ call aborks (Mems[p1], O_VALS(in2),
+ Mems[po], nelem)
+ } else {
+ call abors (Mems[p1], Mems[p2],
+ Mems[po], nelem)
+ }
+ case BXOR:
+ if (len1 <= 0) {
+ O_VALS(out) = xor (O_VALS(in1), O_VALS(in2))
+ } else if (len2 <= 0) {
+ call axorks (Mems[p1], O_VALS(in2),
+ Mems[po], nelem)
+ } else {
+ call axors (Mems[p1], Mems[p2],
+ Mems[po], nelem)
+ }
+ }
+
+ case TY_INT:
+ switch (opcode) {
+ case BAND:
+ if (len1 <= 0) {
+ O_VALI(out) = and (O_VALI(in1), O_VALI(in2))
+ } else if (len2 <= 0) {
+ call aandki (Memi[p1], O_VALI(in2),
+ Memi[po], nelem)
+ } else {
+ call aandi (Memi[p1], Memi[p2],
+ Memi[po], nelem)
+ }
+ case BOR:
+ if (len1 <= 0) {
+ O_VALI(out) = or (O_VALI(in1), O_VALI(in2))
+ } else if (len2 <= 0) {
+ call aborki (Memi[p1], O_VALI(in2),
+ Memi[po], nelem)
+ } else {
+ call abori (Memi[p1], Memi[p2],
+ Memi[po], nelem)
+ }
+ case BXOR:
+ if (len1 <= 0) {
+ O_VALI(out) = xor (O_VALI(in1), O_VALI(in2))
+ } else if (len2 <= 0) {
+ call axorki (Memi[p1], O_VALI(in2),
+ Memi[po], nelem)
+ } else {
+ call axori (Memi[p1], Memi[p2],
+ Memi[po], nelem)
+ }
+ }
+
+ case TY_LONG:
+ switch (opcode) {
+ case BAND:
+ if (len1 <= 0) {
+ O_VALL(out) = and (O_VALL(in1), O_VALL(in2))
+ } else if (len2 <= 0) {
+ call aandkl (Meml[p1], O_VALL(in2),
+ Meml[po], nelem)
+ } else {
+ call aandl (Meml[p1], Meml[p2],
+ Meml[po], nelem)
+ }
+ case BOR:
+ if (len1 <= 0) {
+ O_VALL(out) = or (O_VALL(in1), O_VALL(in2))
+ } else if (len2 <= 0) {
+ call aborkl (Meml[p1], O_VALL(in2),
+ Meml[po], nelem)
+ } else {
+ call aborl (Meml[p1], Meml[p2],
+ Meml[po], nelem)
+ }
+ case BXOR:
+ if (len1 <= 0) {
+ O_VALL(out) = xor (O_VALL(in1), O_VALL(in2))
+ } else if (len2 <= 0) {
+ call axorkl (Meml[p1], O_VALL(in2),
+ Meml[po], nelem)
+ } else {
+ call axorl (Meml[p1], Meml[p2],
+ Meml[po], nelem)
+ }
+ }
+
+ default:
+ call xvv_error (s_boolop)
+ }
+
+ goto done_
+ }
+
+ # Perform an arithmetic binary operation.
+ switch (dtype) {
+ case TY_CHAR:
+ switch (opcode) {
+ case CONCAT:
+ call strcpy (O_VALC(in1), O_VALC(out), ARB)
+ call strcat (O_VALC(in2), O_VALC(out), ARB)
+ default:
+ call xvv_error ("binop: operation illegal for string operands")
+ }
+
+ case TY_SHORT:
+ switch (opcode) {
+ case PLUS:
+ if (len1 <= 0) {
+ O_VALS(out) = O_VALS(in1) + O_VALS(in2)
+ } else if (len2 <= 0) {
+ call aaddks (Mems[p1], O_VALS(in2),
+ Mems[po], nelem)
+ } else {
+ call aadds (Mems[p1], Mems[p2],
+ Mems[po], nelem)
+ }
+ case MINUS:
+ if (len1 <= 0)
+ O_VALS(out) = O_VALS(in1) - O_VALS(in2)
+ else if (len2 <= 0)
+ call asubks (Mems[p1], O_VALS(in2), Mems[po], nelem)
+ else
+ call asubs (Mems[p1], Mems[p2], Mems[po], nelem)
+
+ case STAR:
+ if (len1 <= 0)
+ O_VALS(out) = O_VALS(in1) * O_VALS(in2)
+ else if (len2 <= 0)
+ call amulks (Mems[p1], O_VALS(in2), Mems[po], nelem)
+ else
+ call amuls (Mems[p1], Mems[p2], Mems[po], nelem)
+
+ case SLASH:
+ if (and (ev_flags, EV_RNGCHK) == 0) {
+ # No range checking.
+ if (len1 <= 0)
+ O_VALS(out) = O_VALS(in1) / O_VALS(in2)
+ else if (len2 <= 0)
+ call adivks (Mems[p1], O_VALS(in2), Mems[po], nelem)
+ else
+ call adivs (Mems[p1], Mems[p2], Mems[po], nelem)
+ } else {
+ # Check for divide by zero.
+ if (len1 <= 0) {
+ if (O_VALS(in2) == 0)
+ O_VALS(out) = xvv_nulls(0)
+ else
+ O_VALS(out) = O_VALS(in1) / O_VALS(in2)
+ } else if (len2 <= 0) {
+ if (O_VALS(in2) == 0)
+ call amovks (xvv_nulls(0), Mems[po], nelem)
+ else {
+ call adivks (Mems[p1], O_VALS(in2), Mems[po],
+ nelem)
+ }
+ } else {
+ call advzs (Mems[p1], Mems[p2], Mems[po], nelem,
+ xvv_nulls)
+ }
+ }
+ case EXPON:
+ if (len1 <= 0)
+ O_VALS(out) = O_VALS(in1) ** O_VALS(in2)
+ else if (len2 <= 0)
+ call aexpks (Mems[p1], O_VALS(in2), Mems[po], nelem)
+ else
+ call aexps (Mems[p1], Mems[p2], Mems[po], nelem)
+
+ case CONCAT:
+ # Concatenate two numeric operands.
+ if (len1 <= 0) {
+ Mems[po] = O_VALS(in1)
+ po = po + 1
+ } else {
+ call amovs (Mems[p1], Mems[po], len1)
+ po = po + len1
+ }
+ if (len2 <= 0)
+ Mems[po] = O_VALS(in2)
+ else
+ call amovs (Mems[p2], Mems[po], len2)
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ case TY_INT:
+ switch (opcode) {
+ case PLUS:
+ if (len1 <= 0) {
+ O_VALI(out) = O_VALI(in1) + O_VALI(in2)
+ } else if (len2 <= 0) {
+ call aaddki (Memi[p1], O_VALI(in2),
+ Memi[po], nelem)
+ } else {
+ call aaddi (Memi[p1], Memi[p2],
+ Memi[po], nelem)
+ }
+ case MINUS:
+ if (len1 <= 0)
+ O_VALI(out) = O_VALI(in1) - O_VALI(in2)
+ else if (len2 <= 0)
+ call asubki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call asubi (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case STAR:
+ if (len1 <= 0)
+ O_VALI(out) = O_VALI(in1) * O_VALI(in2)
+ else if (len2 <= 0)
+ call amulki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call amuli (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case SLASH:
+ if (and (ev_flags, EV_RNGCHK) == 0) {
+ # No range checking.
+ if (len1 <= 0)
+ O_VALI(out) = O_VALI(in1) / O_VALI(in2)
+ else if (len2 <= 0)
+ call adivki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call adivi (Memi[p1], Memi[p2], Memi[po], nelem)
+ } else {
+ # Check for divide by zero.
+ if (len1 <= 0) {
+ if (O_VALI(in2) == 0)
+ O_VALI(out) = xvv_nulli(0)
+ else
+ O_VALI(out) = O_VALI(in1) / O_VALI(in2)
+ } else if (len2 <= 0) {
+ if (O_VALI(in2) == 0)
+ call amovki (xvv_nulli(0), Memi[po], nelem)
+ else {
+ call adivki (Memi[p1], O_VALI(in2), Memi[po],
+ nelem)
+ }
+ } else {
+ call advzi (Memi[p1], Memi[p2], Memi[po], nelem,
+ xvv_nulli)
+ }
+ }
+ case EXPON:
+ if (len1 <= 0)
+ O_VALI(out) = O_VALI(in1) ** O_VALI(in2)
+ else if (len2 <= 0)
+ call aexpki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call aexpi (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case CONCAT:
+ # Concatenate two numeric operands.
+ if (len1 <= 0) {
+ Memi[po] = O_VALI(in1)
+ po = po + 1
+ } else {
+ call amovi (Memi[p1], Memi[po], len1)
+ po = po + len1
+ }
+ if (len2 <= 0)
+ Memi[po] = O_VALI(in2)
+ else
+ call amovi (Memi[p2], Memi[po], len2)
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ case TY_LONG:
+ switch (opcode) {
+ case PLUS:
+ if (len1 <= 0) {
+ O_VALL(out) = O_VALL(in1) + O_VALL(in2)
+ } else if (len2 <= 0) {
+ call aaddkl (Meml[p1], O_VALL(in2),
+ Meml[po], nelem)
+ } else {
+ call aaddl (Meml[p1], Meml[p2],
+ Meml[po], nelem)
+ }
+ case MINUS:
+ if (len1 <= 0)
+ O_VALL(out) = O_VALL(in1) - O_VALL(in2)
+ else if (len2 <= 0)
+ call asubkl (Meml[p1], O_VALL(in2), Meml[po], nelem)
+ else
+ call asubl (Meml[p1], Meml[p2], Meml[po], nelem)
+
+ case STAR:
+ if (len1 <= 0)
+ O_VALL(out) = O_VALL(in1) * O_VALL(in2)
+ else if (len2 <= 0)
+ call amulkl (Meml[p1], O_VALL(in2), Meml[po], nelem)
+ else
+ call amull (Meml[p1], Meml[p2], Meml[po], nelem)
+
+ case SLASH:
+ if (and (ev_flags, EV_RNGCHK) == 0) {
+ # No range checking.
+ if (len1 <= 0)
+ O_VALL(out) = O_VALL(in1) / O_VALL(in2)
+ else if (len2 <= 0)
+ call adivkl (Meml[p1], O_VALL(in2), Meml[po], nelem)
+ else
+ call adivl (Meml[p1], Meml[p2], Meml[po], nelem)
+ } else {
+ # Check for divide by zero.
+ if (len1 <= 0) {
+ if (O_VALL(in2) == 0)
+ O_VALL(out) = xvv_nulll(0)
+ else
+ O_VALL(out) = O_VALL(in1) / O_VALL(in2)
+ } else if (len2 <= 0) {
+ if (O_VALL(in2) == 0)
+ call amovkl (xvv_nulll(0), Meml[po], nelem)
+ else {
+ call adivkl (Meml[p1], O_VALL(in2), Meml[po],
+ nelem)
+ }
+ } else {
+ call advzl (Meml[p1], Meml[p2], Meml[po], nelem,
+ xvv_nulll)
+ }
+ }
+ case EXPON:
+ if (len1 <= 0)
+ O_VALL(out) = O_VALL(in1) ** O_VALL(in2)
+ else if (len2 <= 0)
+ call aexpkl (Meml[p1], O_VALL(in2), Meml[po], nelem)
+ else
+ call aexpl (Meml[p1], Meml[p2], Meml[po], nelem)
+
+ case CONCAT:
+ # Concatenate two numeric operands.
+ if (len1 <= 0) {
+ Meml[po] = O_VALL(in1)
+ po = po + 1
+ } else {
+ call amovl (Meml[p1], Meml[po], len1)
+ po = po + len1
+ }
+ if (len2 <= 0)
+ Meml[po] = O_VALL(in2)
+ else
+ call amovl (Meml[p2], Meml[po], len2)
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ case TY_REAL:
+ switch (opcode) {
+ case PLUS:
+ if (len1 <= 0) {
+ O_VALR(out) = O_VALR(in1) + O_VALR(in2)
+ } else if (len2 <= 0) {
+ call aaddkr (Memr[p1], O_VALR(in2),
+ Memr[po], nelem)
+ } else {
+ call aaddr (Memr[p1], Memr[p2],
+ Memr[po], nelem)
+ }
+ case MINUS:
+ if (len1 <= 0)
+ O_VALR(out) = O_VALR(in1) - O_VALR(in2)
+ else if (len2 <= 0)
+ call asubkr (Memr[p1], O_VALR(in2), Memr[po], nelem)
+ else
+ call asubr (Memr[p1], Memr[p2], Memr[po], nelem)
+
+ case STAR:
+ if (len1 <= 0)
+ O_VALR(out) = O_VALR(in1) * O_VALR(in2)
+ else if (len2 <= 0)
+ call amulkr (Memr[p1], O_VALR(in2), Memr[po], nelem)
+ else
+ call amulr (Memr[p1], Memr[p2], Memr[po], nelem)
+
+ case SLASH:
+ if (and (ev_flags, EV_RNGCHK) == 0) {
+ # No range checking.
+ if (len1 <= 0)
+ O_VALR(out) = O_VALR(in1) / O_VALR(in2)
+ else if (len2 <= 0)
+ call adivkr (Memr[p1], O_VALR(in2), Memr[po], nelem)
+ else
+ call adivr (Memr[p1], Memr[p2], Memr[po], nelem)
+ } else {
+ # Check for divide by zero.
+ if (len1 <= 0) {
+ if (O_VALR(in2) == 0.0)
+ O_VALR(out) = xvv_nullr(0.0)
+ else
+ O_VALR(out) = O_VALR(in1) / O_VALR(in2)
+ } else if (len2 <= 0) {
+ if (O_VALR(in2) == 0.0)
+ call amovkr (xvv_nullr(0.0), Memr[po], nelem)
+ else {
+ call adivkr (Memr[p1], O_VALR(in2), Memr[po],
+ nelem)
+ }
+ } else {
+ call advzr (Memr[p1], Memr[p2], Memr[po], nelem,
+ xvv_nullr)
+ }
+ }
+ case EXPON:
+ if (len1 <= 0)
+ O_VALR(out) = O_VALR(in1) ** O_VALR(in2)
+ else if (len2 <= 0)
+ call aexpkr (Memr[p1], O_VALR(in2), Memr[po], nelem)
+ else
+ call aexpr (Memr[p1], Memr[p2], Memr[po], nelem)
+
+ case CONCAT:
+ # Concatenate two numeric operands.
+ if (len1 <= 0) {
+ Memr[po] = O_VALR(in1)
+ po = po + 1
+ } else {
+ call amovr (Memr[p1], Memr[po], len1)
+ po = po + len1
+ }
+ if (len2 <= 0)
+ Memr[po] = O_VALR(in2)
+ else
+ call amovr (Memr[p2], Memr[po], len2)
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ case TY_DOUBLE:
+ switch (opcode) {
+ case PLUS:
+ if (len1 <= 0) {
+ O_VALD(out) = O_VALD(in1) + O_VALD(in2)
+ } else if (len2 <= 0) {
+ call aaddkd (Memd[p1], O_VALD(in2),
+ Memd[po], nelem)
+ } else {
+ call aaddd (Memd[p1], Memd[p2],
+ Memd[po], nelem)
+ }
+ case MINUS:
+ if (len1 <= 0)
+ O_VALD(out) = O_VALD(in1) - O_VALD(in2)
+ else if (len2 <= 0)
+ call asubkd (Memd[p1], O_VALD(in2), Memd[po], nelem)
+ else
+ call asubd (Memd[p1], Memd[p2], Memd[po], nelem)
+
+ case STAR:
+ if (len1 <= 0)
+ O_VALD(out) = O_VALD(in1) * O_VALD(in2)
+ else if (len2 <= 0)
+ call amulkd (Memd[p1], O_VALD(in2), Memd[po], nelem)
+ else
+ call amuld (Memd[p1], Memd[p2], Memd[po], nelem)
+
+ case SLASH:
+ if (and (ev_flags, EV_RNGCHK) == 0) {
+ # No range checking.
+ if (len1 <= 0)
+ O_VALD(out) = O_VALD(in1) / O_VALD(in2)
+ else if (len2 <= 0)
+ call adivkd (Memd[p1], O_VALD(in2), Memd[po], nelem)
+ else
+ call adivd (Memd[p1], Memd[p2], Memd[po], nelem)
+ } else {
+ # Check for divide by zero.
+ if (len1 <= 0) {
+ if (O_VALD(in2) == 0.0D0)
+ O_VALD(out) = xvv_nulld(0.0D0)
+ else
+ O_VALD(out) = O_VALD(in1) / O_VALD(in2)
+ } else if (len2 <= 0) {
+ if (O_VALD(in2) == 0.0D0)
+ call amovkd (xvv_nulld(0.0D0), Memd[po], nelem)
+ else {
+ call adivkd (Memd[p1], O_VALD(in2), Memd[po],
+ nelem)
+ }
+ } else {
+ call advzd (Memd[p1], Memd[p2], Memd[po], nelem,
+ xvv_nulld)
+ }
+ }
+ case EXPON:
+ if (len1 <= 0)
+ O_VALD(out) = O_VALD(in1) ** O_VALD(in2)
+ else if (len2 <= 0)
+ call aexpkd (Memd[p1], O_VALD(in2), Memd[po], nelem)
+ else
+ call aexpd (Memd[p1], Memd[p2], Memd[po], nelem)
+
+ case CONCAT:
+ # Concatenate two numeric operands.
+ if (len1 <= 0) {
+ Memd[po] = O_VALD(in1)
+ po = po + 1
+ } else {
+ call amovd (Memd[p1], Memd[po], len1)
+ po = po + len1
+ }
+ if (len2 <= 0)
+ Memd[po] = O_VALD(in2)
+ else
+ call amovd (Memd[p2], Memd[po], len2)
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+done_
+ # Free any storage in input operands.
+ call xvv_freeop (in1)
+ call xvv_freeop (in2)
+end
+
+
+# XVV_BOOLOP -- Boolean (actually logical) binary operations. Perform the
+# indicated logical operation on the two input operands, returning the result
+# as the output operand. The opcodes implemented by this routine are
+# characterized by the fact that they all return a logical result (YES or NO
+# physically expressed as an integer).
+
+procedure xvv_boolop (opcode, in1, in2, out)
+
+int opcode #I operation to be performed
+pointer in1, in2 #I input operands
+pointer out #I output operand
+
+
+short v_s
+
+int v_i
+
+long v_l
+
+real v_r
+
+double v_d
+
+pointer sp, otemp, p1, p2, po
+int dtype, nelem, len1, len2
+int xvv_newtype(), xvv_patmatch(), strncmp(), btoi()
+errchk xvv_newtype, xvv_initop, xvv_chtype, xvv_error
+string s_badop "boolop: illegal operation"
+string s_badswitch "boolop: illegal switch"
+
+begin
+ # Boolean operands are treated as integer within this routine.
+ if (O_TYPE(in1) == TY_BOOL)
+ O_TYPE(in1) = TY_INT
+ if (O_TYPE(in2) == TY_BOOL)
+ O_TYPE(in2) = TY_INT
+
+ # Determine the computation type for the operation, i.e., the type
+ # both input operands must have. This is not the same as the type
+ # of the output operand, which is always boolean for the operations
+ # implemented by this routine.
+
+ dtype = xvv_newtype (O_TYPE(in1), O_TYPE(in2))
+
+ # Compute the size of the output operand. If both input operands are
+ # vectors the length of the output vector is the shorter of the two.
+
+ if (dtype == TY_CHAR)
+ nelem = 0
+ else {
+ if (O_LEN(in1) > 0 && O_LEN(in2) > 0)
+ nelem = min (O_LEN(in1), O_LEN(in2))
+ else if (O_LEN(in1) > 0)
+ nelem = O_LEN(in1)
+ else if (O_LEN(in2) > 0)
+ nelem = O_LEN(in2)
+ else
+ nelem = 0
+ }
+
+ # Convert input operands to desired computation type.
+ if (O_TYPE(in1) != dtype)
+ call xvv_chtype (in1, in1, dtype)
+ if (O_TYPE(in2) != dtype)
+ call xvv_chtype (in2, in2, dtype)
+
+ # If this is a scalar/vector operation make sure the vector is the
+ # first operand.
+
+ len1 = O_LEN(in1)
+ len2 = O_LEN(in2)
+
+ if (len1 == 0 && len2 > 0) {
+ switch (opcode) {
+ case EQ, NE:
+ call smark (sp)
+ call salloc (otemp, LEN_OPERAND, TY_STRUCT)
+ YYMOVE (in1, otemp)
+ YYMOVE (in2, in1)
+ YYMOVE (otemp, in2)
+ call sfree (sp)
+ default:
+ # Promote operand to a constant vector. Inefficient, but
+ # better than aborting.
+
+ switch (dtype) {
+
+ case TY_SHORT:
+ v_s = O_VALS(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovks (v_s, Mems[O_VALP(in1)], nelem)
+
+ case TY_INT:
+ v_i = O_VALI(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovki (v_i, Memi[O_VALP(in1)], nelem)
+
+ case TY_LONG:
+ v_l = O_VALL(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovkl (v_l, Meml[O_VALP(in1)], nelem)
+
+ case TY_REAL:
+ v_r = O_VALR(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovkr (v_r, Memr[O_VALP(in1)], nelem)
+
+ case TY_DOUBLE:
+ v_d = O_VALD(in1)
+ call xvv_initop (in1, nelem, dtype)
+ call amovkd (v_d, Memd[O_VALP(in1)], nelem)
+
+ }
+ }
+
+ len1 = O_LEN(in1)
+ len2 = O_LEN(in2)
+ }
+
+ # Initialize the output operand.
+ call xvv_initop (out, nelem, TY_BOOL)
+
+ p1 = O_VALP(in1)
+ p2 = O_VALP(in2)
+ po = O_VALP(out)
+
+ # Perform the operation.
+ if (dtype == TY_CHAR) {
+ # Character data is a special case.
+
+ switch (opcode) {
+ case SE:
+ O_VALI(out) = btoi(xvv_patmatch (O_VALC(in1), O_VALC(in2)) > 0)
+ case LT:
+ O_VALI(out) = btoi(strncmp (O_VALC(in1), O_VALC(in2), ARB) < 0)
+ case LE:
+ O_VALI(out) = btoi(strncmp (O_VALC(in1), O_VALC(in2), ARB) <= 0)
+ case GT:
+ O_VALI(out) = btoi(strncmp (O_VALC(in1), O_VALC(in2), ARB) > 0)
+ case GE:
+ O_VALI(out) = btoi(strncmp (O_VALC(in1), O_VALC(in2), ARB) >= 0)
+ case EQ:
+ O_VALI(out) = btoi(strncmp (O_VALC(in1), O_VALC(in2), ARB) == 0)
+ case NE:
+ O_VALI(out) = btoi(strncmp (O_VALC(in1), O_VALC(in2), ARB) != 0)
+ default:
+ call xvv_error (s_badop)
+ }
+
+ } else if (opcode == LAND || opcode == LOR) {
+ # Operations supporting only the integer types.
+
+ switch (dtype) {
+
+ case TY_SHORT:
+ switch (opcode) {
+ case LAND:
+ if (len1 <= 0) {
+ O_VALI(out) =
+ btoi (O_VALS(in1) != 0 && O_VALS(in2) != 0)
+ } else if (len2 <= 0) {
+ call alanks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ } else
+ call alans (Mems[p1], Mems[p2], Memi[po], nelem)
+ case LOR:
+ if (len1 <= 0) {
+ O_VALI(out) =
+ btoi (O_VALS(in1) != 0 || O_VALS(in2) != 0)
+ } else if (len2 <= 0) {
+ call alorks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ } else
+ call alors (Mems[p1], Mems[p2], Memi[po], nelem)
+ default:
+ call xvv_error (s_badop)
+ }
+
+ case TY_INT:
+ switch (opcode) {
+ case LAND:
+ if (len1 <= 0) {
+ O_VALI(out) =
+ btoi (O_VALI(in1) != 0 && O_VALI(in2) != 0)
+ } else if (len2 <= 0) {
+ call alanki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ } else
+ call alani (Memi[p1], Memi[p2], Memi[po], nelem)
+ case LOR:
+ if (len1 <= 0) {
+ O_VALI(out) =
+ btoi (O_VALI(in1) != 0 || O_VALI(in2) != 0)
+ } else if (len2 <= 0) {
+ call alorki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ } else
+ call alori (Memi[p1], Memi[p2], Memi[po], nelem)
+ default:
+ call xvv_error (s_badop)
+ }
+
+ case TY_LONG:
+ switch (opcode) {
+ case LAND:
+ if (len1 <= 0) {
+ O_VALI(out) =
+ btoi (O_VALL(in1) != 0 && O_VALL(in2) != 0)
+ } else if (len2 <= 0) {
+ call alankl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ } else
+ call alanl (Meml[p1], Meml[p2], Memi[po], nelem)
+ case LOR:
+ if (len1 <= 0) {
+ O_VALI(out) =
+ btoi (O_VALL(in1) != 0 || O_VALL(in2) != 0)
+ } else if (len2 <= 0) {
+ call alorkl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ } else
+ call alorl (Meml[p1], Meml[p2], Memi[po], nelem)
+ default:
+ call xvv_error (s_badop)
+ }
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+ } else {
+ # Operations supporting any arithmetic type.
+
+ switch (dtype) {
+
+ case TY_SHORT:
+ switch (opcode) {
+ case LT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALS(in1) < O_VALS(in2))
+ else if (len2 <= 0)
+ call abltks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ else
+ call ablts (Mems[p1], Mems[p2], Memi[po], nelem)
+
+ case LE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALS(in1) <= O_VALS(in2))
+ else if (len2 <= 0)
+ call ableks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ else
+ call ables (Mems[p1], Mems[p2], Memi[po], nelem)
+
+ case GT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALS(in1) > O_VALS(in2))
+ else if (len2 <= 0)
+ call abgtks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ else
+ call abgts (Mems[p1], Mems[p2], Memi[po], nelem)
+
+ case GE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALS(in1) >= O_VALS(in2))
+ else if (len2 <= 0)
+ call abgeks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ else
+ call abges (Mems[p1], Mems[p2], Memi[po], nelem)
+
+ case EQ:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALS(in1) == O_VALS(in2))
+ else if (len2 <= 0)
+ call abeqks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ else
+ call abeqs (Mems[p1], Mems[p2], Memi[po], nelem)
+
+ case NE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALS(in1) != O_VALS(in2))
+ else if (len2 <= 0)
+ call abneks (Mems[p1], O_VALS(in2), Memi[po], nelem)
+ else
+ call abnes (Mems[p1], Mems[p2], Memi[po], nelem)
+
+ default:
+ call xvv_error (s_badop)
+ }
+
+ case TY_INT:
+ switch (opcode) {
+ case LT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALI(in1) < O_VALI(in2))
+ else if (len2 <= 0)
+ call abltki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call ablti (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case LE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALI(in1) <= O_VALI(in2))
+ else if (len2 <= 0)
+ call ableki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call ablei (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case GT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALI(in1) > O_VALI(in2))
+ else if (len2 <= 0)
+ call abgtki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call abgti (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case GE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALI(in1) >= O_VALI(in2))
+ else if (len2 <= 0)
+ call abgeki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call abgei (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case EQ:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALI(in1) == O_VALI(in2))
+ else if (len2 <= 0)
+ call abeqki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call abeqi (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ case NE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALI(in1) != O_VALI(in2))
+ else if (len2 <= 0)
+ call abneki (Memi[p1], O_VALI(in2), Memi[po], nelem)
+ else
+ call abnei (Memi[p1], Memi[p2], Memi[po], nelem)
+
+ default:
+ call xvv_error (s_badop)
+ }
+
+ case TY_LONG:
+ switch (opcode) {
+ case LT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALL(in1) < O_VALL(in2))
+ else if (len2 <= 0)
+ call abltkl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ else
+ call abltl (Meml[p1], Meml[p2], Memi[po], nelem)
+
+ case LE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALL(in1) <= O_VALL(in2))
+ else if (len2 <= 0)
+ call ablekl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ else
+ call ablel (Meml[p1], Meml[p2], Memi[po], nelem)
+
+ case GT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALL(in1) > O_VALL(in2))
+ else if (len2 <= 0)
+ call abgtkl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ else
+ call abgtl (Meml[p1], Meml[p2], Memi[po], nelem)
+
+ case GE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALL(in1) >= O_VALL(in2))
+ else if (len2 <= 0)
+ call abgekl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ else
+ call abgel (Meml[p1], Meml[p2], Memi[po], nelem)
+
+ case EQ:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALL(in1) == O_VALL(in2))
+ else if (len2 <= 0)
+ call abeqkl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ else
+ call abeql (Meml[p1], Meml[p2], Memi[po], nelem)
+
+ case NE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALL(in1) != O_VALL(in2))
+ else if (len2 <= 0)
+ call abnekl (Meml[p1], O_VALL(in2), Memi[po], nelem)
+ else
+ call abnel (Meml[p1], Meml[p2], Memi[po], nelem)
+
+ default:
+ call xvv_error (s_badop)
+ }
+
+ case TY_REAL:
+ switch (opcode) {
+ case LT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALR(in1) < O_VALR(in2))
+ else if (len2 <= 0)
+ call abltkr (Memr[p1], O_VALR(in2), Memi[po], nelem)
+ else
+ call abltr (Memr[p1], Memr[p2], Memi[po], nelem)
+
+ case LE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALR(in1) <= O_VALR(in2))
+ else if (len2 <= 0)
+ call ablekr (Memr[p1], O_VALR(in2), Memi[po], nelem)
+ else
+ call abler (Memr[p1], Memr[p2], Memi[po], nelem)
+
+ case GT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALR(in1) > O_VALR(in2))
+ else if (len2 <= 0)
+ call abgtkr (Memr[p1], O_VALR(in2), Memi[po], nelem)
+ else
+ call abgtr (Memr[p1], Memr[p2], Memi[po], nelem)
+
+ case GE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALR(in1) >= O_VALR(in2))
+ else if (len2 <= 0)
+ call abgekr (Memr[p1], O_VALR(in2), Memi[po], nelem)
+ else
+ call abger (Memr[p1], Memr[p2], Memi[po], nelem)
+
+ case EQ:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALR(in1) == O_VALR(in2))
+ else if (len2 <= 0)
+ call abeqkr (Memr[p1], O_VALR(in2), Memi[po], nelem)
+ else
+ call abeqr (Memr[p1], Memr[p2], Memi[po], nelem)
+
+ case NE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALR(in1) != O_VALR(in2))
+ else if (len2 <= 0)
+ call abnekr (Memr[p1], O_VALR(in2), Memi[po], nelem)
+ else
+ call abner (Memr[p1], Memr[p2], Memi[po], nelem)
+
+ default:
+ call xvv_error (s_badop)
+ }
+
+ case TY_DOUBLE:
+ switch (opcode) {
+ case LT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALD(in1) < O_VALD(in2))
+ else if (len2 <= 0)
+ call abltkd (Memd[p1], O_VALD(in2), Memi[po], nelem)
+ else
+ call abltd (Memd[p1], Memd[p2], Memi[po], nelem)
+
+ case LE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALD(in1) <= O_VALD(in2))
+ else if (len2 <= 0)
+ call ablekd (Memd[p1], O_VALD(in2), Memi[po], nelem)
+ else
+ call abled (Memd[p1], Memd[p2], Memi[po], nelem)
+
+ case GT:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALD(in1) > O_VALD(in2))
+ else if (len2 <= 0)
+ call abgtkd (Memd[p1], O_VALD(in2), Memi[po], nelem)
+ else
+ call abgtd (Memd[p1], Memd[p2], Memi[po], nelem)
+
+ case GE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALD(in1) >= O_VALD(in2))
+ else if (len2 <= 0)
+ call abgekd (Memd[p1], O_VALD(in2), Memi[po], nelem)
+ else
+ call abged (Memd[p1], Memd[p2], Memi[po], nelem)
+
+ case EQ:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALD(in1) == O_VALD(in2))
+ else if (len2 <= 0)
+ call abeqkd (Memd[p1], O_VALD(in2), Memi[po], nelem)
+ else
+ call abeqd (Memd[p1], Memd[p2], Memi[po], nelem)
+
+ case NE:
+ if (len1 <= 0)
+ O_VALI(out) = btoi (O_VALD(in1) != O_VALD(in2))
+ else if (len2 <= 0)
+ call abnekd (Memd[p1], O_VALD(in2), Memi[po], nelem)
+ else
+ call abned (Memd[p1], Memd[p2], Memi[po], nelem)
+
+ default:
+ call xvv_error (s_badop)
+ }
+
+ default:
+ call xvv_error (s_badswitch)
+ }
+ }
+
+ # Free any storage in input operands.
+ call xvv_freeop (in1)
+ call xvv_freeop (in2)
+end
+
+
+# XVV_PATMATCH -- Match a string against a pattern, returning the patmatch
+# index if the string matches. The pattern may contain any of the conventional
+# pattern matching metacharacters. Closure (i.e., "*") is mapped to "?*".
+
+int procedure xvv_patmatch (str, pat)
+
+char str[ARB] #I operand string
+char pat[ARB] #I pattern
+
+int junk, ip, index
+pointer sp, patstr, patbuf, op
+int patmake(), patmatch()
+
+begin
+ call smark (sp)
+ call salloc (patstr, SZ_FNAME, TY_CHAR)
+ call salloc (patbuf, SZ_LINE, TY_CHAR)
+ call aclrc (Memc[patstr], SZ_FNAME)
+ call aclrc (Memc[patbuf], SZ_LINE)
+
+ # Map pattern, changing '*' into '?*'.
+ op = patstr
+ for (ip=1; pat[ip] != EOS; ip=ip+1) {
+ if (pat[ip] == '*') {
+ Memc[op] = '?'
+ op = op + 1
+ }
+ Memc[op] = pat[ip]
+ op = op + 1
+ }
+
+ # Encode pattern.
+ junk = patmake (Memc[patstr], Memc[patbuf], SZ_LINE)
+
+ # Perform the pattern matching operation.
+ index = patmatch (str, Memc[patbuf])
+
+ call sfree (sp)
+ return (index)
+end
+
+
+# XVV_NEWTYPE -- Get the datatype of a binary operation, given the datatypes
+# of the two input operands. An error action is taken if the datatypes are
+# incompatible, e.g., boolean and anything else or string and anything else.
+
+int procedure xvv_newtype (type1, type2)
+
+int type1 #I datatype of first operand
+int type2 #I datatype of second operand
+
+int newtype, p, q, i
+int tyindex[NTYPES], ttbl[NTYPES*NTYPES]
+data tyindex /T_B, T_C, T_S, T_I, T_L, T_R, T_D/
+
+data (ttbl(i),i= 1, 7) /T_B, 0, 0, 0, 0, 0, 0/
+data (ttbl(i),i= 8,14) / 0, T_C, 0, 0, 0, 0, 0/
+data (ttbl(i),i=15,21) / 0, 0, T_S, T_I, T_L, T_R, T_D/
+data (ttbl(i),i=22,28) / 0, 0, T_I, T_I, T_L, T_R, T_D/
+data (ttbl(i),i=29,35) / 0, 0, T_L, T_L, T_L, T_R, T_D/
+data (ttbl(i),i=36,42) / 0, 0, T_R, T_R, T_R, T_R, T_D/
+data (ttbl(i),i=43,49) / 0, 0, T_D, T_D, T_D, T_D, T_D/
+
+begin
+ do i = 1, NTYPES {
+ if (tyindex[i] == type1)
+ p = i
+ if (tyindex[i] == type2)
+ q = i
+ }
+
+ newtype = ttbl[(p-1)*NTYPES+q]
+ if (newtype == 0)
+ call xvv_error ("operands have incompatible types")
+ else
+ return (newtype)
+end
+
+
+# XVV_QUEST -- Conditional expression. If the condition operand is true
+# return the first (true) operand, else return the second (false) operand.
+
+procedure xvv_quest (cond, in1, in2, out)
+
+pointer cond #I pointer to condition operand
+pointer in1, in2 #I pointer to true,false operands
+pointer out #I pointer to output operand
+
+int dtype, nelem, i
+pointer sp, otemp, ip1, ip2, op, sel
+errchk xvv_error, xvv_newtype, xvv_initop, xvv_chtype
+int xvv_newtype(), btoi()
+
+begin
+ switch (O_TYPE(cond)) {
+ case TY_BOOL, TY_INT:
+ ;
+ case TY_SHORT, TY_LONG:
+ call xvv_chtype (cond, cond, TY_BOOL)
+ default:
+ call xvv_error ("evvexpr: nonboolean condition operand")
+ }
+
+ if (O_LEN(cond) <= 0 &&
+ (O_LEN(in1) <= 0 || O_TYPE(in1) == TY_CHAR) &&
+ (O_LEN(in2) <= 0 || O_TYPE(in2) == TY_CHAR)) {
+
+ # Both operands and the conditional are scalars; the expression
+ # type is the type of the selected operand.
+
+ if (O_VALI(cond) != 0) {
+ YYMOVE (in1, out)
+ call xvv_freeop (in2)
+ } else {
+ YYMOVE (in2, out)
+ call xvv_freeop (in1)
+ }
+
+ } else if (O_TYPE(in1) == TY_CHAR || O_TYPE(in2) == TY_CHAR) {
+ # This combination is not legal.
+ call xvv_error ("evvexpr: character and vector in cond expr")
+
+ } else {
+ # Vector/scalar or vector/vector operation. Both operands must
+ # be of the same type.
+
+ dtype = xvv_newtype (O_TYPE(in1), O_TYPE(in2))
+
+ # Compute the size of the output operand. If both input operands
+ # are vectors the length of the output vector is the shorter of
+ # the two. The condition operand contributes to the dimension of
+ # the expression result, although not to the datatype.
+
+ nelem = 0
+ if (O_LEN(in1) > 0 && O_LEN(in2) > 0)
+ nelem = min (O_LEN(in1), O_LEN(in2))
+ else if (O_LEN(in1) > 0)
+ nelem = O_LEN(in1)
+ else if (O_LEN(in2) > 0)
+ nelem = O_LEN(in2)
+
+ if (O_LEN(cond) > 0 && nelem > 0)
+ nelem = min (O_LEN(cond), nelem)
+ else if (O_LEN(cond) > 0)
+ nelem = O_LEN(cond)
+
+ # If this is a scalar/vector operation make sure the vector is the
+ # first operand.
+
+ if (O_LEN(in1) == 0 && O_LEN(in2) > 0) {
+ call smark (sp)
+ call salloc (otemp, LEN_OPERAND, TY_STRUCT)
+ YYMOVE (in1, otemp)
+ YYMOVE (in2, in1)
+ YYMOVE (otemp, in2)
+ call sfree (sp)
+
+ # Since we are swapping arguments we need to negate the cond.
+ if (O_LEN(cond) <= 0)
+ O_VALI(cond) = btoi (O_VALI(cond) == 0)
+ else {
+ call abeqki (Memi[O_VALP(cond)], NO, Memi[O_VALP(cond)],
+ nelem)
+ }
+ }
+
+ # Initialize the output operand.
+ call xvv_initop (out, nelem, dtype)
+
+ # Convert input operands to desired computation type.
+ if (O_TYPE(in1) != dtype)
+ call xvv_chtype (in1, in1, dtype)
+ if (O_TYPE(in2) != dtype)
+ call xvv_chtype (in2, in2, dtype)
+
+ ip1 = O_VALP(in1)
+ ip2 = O_VALP(in2)
+ op = O_VALP(out)
+ sel = O_VALP(cond)
+
+ # Perform the operation.
+ switch (dtype) {
+
+ case TY_SHORT:
+ if (O_LEN(in1) <= 0 && O_LEN(in2) <= 0) {
+ # Vector conditional, both operands are scalars.
+ do i = 1, nelem
+ if (Memi[sel+i-1] != 0)
+ Mems[op+i-1] = O_VALS(in1)
+ else
+ Mems[op+i-1] = O_VALS(in2)
+
+ } else if (O_LEN(in2) <= 0) {
+ # Operand 1 is a vector, operand 2 is a scalar.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovs (Mems[ip1], Mems[op], nelem)
+ else
+ call amovks (O_VALS(in2), Mems[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aselks (Mems[ip1], O_VALS(in2), Mems[op],
+ Memi[sel], nelem)
+ }
+ } else {
+ # Both operands are vectors.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovs (Mems[ip1], Mems[op], nelem)
+ else
+ call amovs (Mems[ip2], Mems[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call asels (Mems[ip1], Mems[ip2], Mems[op],
+ Memi[sel], nelem)
+ }
+ }
+
+ case TY_INT:
+ if (O_LEN(in1) <= 0 && O_LEN(in2) <= 0) {
+ # Vector conditional, both operands are scalars.
+ do i = 1, nelem
+ if (Memi[sel+i-1] != 0)
+ Memi[op+i-1] = O_VALI(in1)
+ else
+ Memi[op+i-1] = O_VALI(in2)
+
+ } else if (O_LEN(in2) <= 0) {
+ # Operand 1 is a vector, operand 2 is a scalar.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovi (Memi[ip1], Memi[op], nelem)
+ else
+ call amovki (O_VALI(in2), Memi[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aselki (Memi[ip1], O_VALI(in2), Memi[op],
+ Memi[sel], nelem)
+ }
+ } else {
+ # Both operands are vectors.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovi (Memi[ip1], Memi[op], nelem)
+ else
+ call amovi (Memi[ip2], Memi[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aseli (Memi[ip1], Memi[ip2], Memi[op],
+ Memi[sel], nelem)
+ }
+ }
+
+ case TY_LONG:
+ if (O_LEN(in1) <= 0 && O_LEN(in2) <= 0) {
+ # Vector conditional, both operands are scalars.
+ do i = 1, nelem
+ if (Memi[sel+i-1] != 0)
+ Meml[op+i-1] = O_VALL(in1)
+ else
+ Meml[op+i-1] = O_VALL(in2)
+
+ } else if (O_LEN(in2) <= 0) {
+ # Operand 1 is a vector, operand 2 is a scalar.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovl (Meml[ip1], Meml[op], nelem)
+ else
+ call amovkl (O_VALL(in2), Meml[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aselkl (Meml[ip1], O_VALL(in2), Meml[op],
+ Memi[sel], nelem)
+ }
+ } else {
+ # Both operands are vectors.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovl (Meml[ip1], Meml[op], nelem)
+ else
+ call amovl (Meml[ip2], Meml[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call asell (Meml[ip1], Meml[ip2], Meml[op],
+ Memi[sel], nelem)
+ }
+ }
+
+ case TY_REAL:
+ if (O_LEN(in1) <= 0 && O_LEN(in2) <= 0) {
+ # Vector conditional, both operands are scalars.
+ do i = 1, nelem
+ if (Memi[sel+i-1] != 0)
+ Memr[op+i-1] = O_VALR(in1)
+ else
+ Memr[op+i-1] = O_VALR(in2)
+
+ } else if (O_LEN(in2) <= 0) {
+ # Operand 1 is a vector, operand 2 is a scalar.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovr (Memr[ip1], Memr[op], nelem)
+ else
+ call amovkr (O_VALR(in2), Memr[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aselkr (Memr[ip1], O_VALR(in2), Memr[op],
+ Memi[sel], nelem)
+ }
+ } else {
+ # Both operands are vectors.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovr (Memr[ip1], Memr[op], nelem)
+ else
+ call amovr (Memr[ip2], Memr[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aselr (Memr[ip1], Memr[ip2], Memr[op],
+ Memi[sel], nelem)
+ }
+ }
+
+ case TY_DOUBLE:
+ if (O_LEN(in1) <= 0 && O_LEN(in2) <= 0) {
+ # Vector conditional, both operands are scalars.
+ do i = 1, nelem
+ if (Memi[sel+i-1] != 0)
+ Memd[op+i-1] = O_VALD(in1)
+ else
+ Memd[op+i-1] = O_VALD(in2)
+
+ } else if (O_LEN(in2) <= 0) {
+ # Operand 1 is a vector, operand 2 is a scalar.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovd (Memd[ip1], Memd[op], nelem)
+ else
+ call amovkd (O_VALD(in2), Memd[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aselkd (Memd[ip1], O_VALD(in2), Memd[op],
+ Memi[sel], nelem)
+ }
+ } else {
+ # Both operands are vectors.
+ if (O_LEN(cond) <= 0) {
+ # Conditional is a scalar.
+ if (O_VALI(cond) != 0)
+ call amovd (Memd[ip1], Memd[op], nelem)
+ else
+ call amovd (Memd[ip2], Memd[op], nelem)
+ } else {
+ # Conditional is a vector.
+ call aseld (Memd[ip1], Memd[ip2], Memd[op],
+ Memi[sel], nelem)
+ }
+ }
+
+ default:
+ call xvv_error ("evvexpr: bad datatype in cond expr")
+ }
+
+ call xvv_freeop (in1)
+ call xvv_freeop (in2)
+ }
+
+ call xvv_freeop (cond)
+end
+
+
+# XVV_CALLFCN -- Call an intrinsic function. If the function named is not
+# one of the standard intrinsic functions, call an external user function
+# if a function call procedure was supplied.
+
+procedure xvv_callfcn (fcn, args, nargs, out)
+
+char fcn[ARB] #I function to be called
+pointer args[ARB] #I pointer to arglist descriptor
+int nargs #I number of arguments
+pointer out #I output operand (function value)
+
+
+short v_s
+short ahivs(), alovs()
+short ameds()
+int aravs()
+
+int v_i
+int ahivi(), alovi()
+int amedi()
+int aravi()
+
+long v_l
+long ahivl(), alovl()
+long amedl()
+int aravl()
+
+real v_r
+real ahivr(), alovr()
+real amedr()
+int aravr()
+
+double v_d
+double ahivd(), alovd()
+double amedd()
+int aravd()
+
+
+real mean_r, sigma_r
+double mean_d, sigma_d
+real asums(), asumi(), asumr()
+double asuml(), asumd()
+
+bool rangecheck
+int optype, opcode
+int chunk, repl, nelem, v_nargs, ch, shift, i, j
+pointer sp, sym, buf, ap, ip, op, in1, in2
+include "evvexpr.com"
+
+pointer stfind()
+int xvv_newtype(), strlen(), gctod(), btoi()
+errchk xvv_chtype, xvv_initop, xvv_newtype, xvv_error1, xvv_error2
+errchk zcall5, malloc
+
+string s_badtype "%s: illegal operand type"
+define free_ 91
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_FNAME, TY_CHAR)
+
+ # Lookup the function name in the symbol table.
+ sym = stfind (ev_st, fcn)
+ if (sym != NULL)
+ opcode = SYM_CODE(sym)
+ else
+ opcode = 0
+
+ # If the function named is not a standard one and the user has supplied
+ # the entry point of an external function evaluation procedure, call
+ # the user procedure to evaluate the function, otherwise abort.
+
+ if (opcode <= 0)
+ if (ev_ufcn != NULL) {
+ call zcall5 (ev_ufcn, ev_ufcn_data, fcn, args, nargs, out)
+ if (O_TYPE(out) <= 0)
+ call xvv_error1 ("unrecognized macro or function `%s'", fcn)
+ goto free_
+ } else
+ call xvv_error1 ("unknown function `%s' called", fcn)
+
+ # Range checking on functions that need it?
+ rangecheck = (and (ev_flags, EV_RNGCHK) != 0)
+
+ # Verify correct number of arguments.
+ switch (opcode) {
+ case F_MOD, F_REPL, F_SHIFT:
+ v_nargs = 2
+ case F_MAX, F_MIN, F_ATAN, F_ATAN2, F_MEAN, F_STDDEV, F_MEDIAN:
+ v_nargs = -1
+ default:
+ v_nargs = 1
+ }
+ if (v_nargs > 0 && nargs != v_nargs)
+ call xvv_error2 ("function `%s' requires %d arguments",
+ fcn, v_nargs)
+ else if (v_nargs < 0 && nargs < abs(v_nargs))
+ call xvv_error2 ("function `%s' requires at least %d arguments",
+ fcn, abs(v_nargs))
+
+ # Some functions require that the input operand be a certain type,
+ # e.g. floating. Handle the simple cases, converting input operands
+ # to the desired type.
+
+ switch (opcode) {
+ case F_ACOS, F_ASIN, F_ATAN, F_ATAN2, F_COS, F_COSH, F_DEG, F_EXP,
+ F_LOG, F_LOG10, F_RAD, F_SIN, F_SINH, F_SQRT, F_TAN, F_TANH:
+
+ # These functions want a floating point input operand.
+ optype = TY_REAL
+ do i = 1, nargs {
+ if (O_TYPE(args[i]) == TY_DOUBLE || O_TYPE(args[i]) == TY_LONG)
+ optype = TY_DOUBLE
+ }
+ do i = 1, nargs {
+ if (O_TYPE(args[i]) != optype)
+ call xvv_chtype (args[i], args[i], optype)
+ }
+ call xvv_initop (out, O_LEN(args[1]), optype)
+
+ case F_MOD, F_MIN, F_MAX, F_MEDIAN:
+ # These functions may have multiple arguments, all of which
+ # should be the same type.
+
+ optype = O_TYPE(args[1])
+ nelem = O_LEN(args[1])
+ do i = 2, nargs {
+ optype = xvv_newtype (optype, O_TYPE(args[i]))
+ if (O_LEN(args[i]) > 0)
+ if (nelem > 0)
+ nelem = min (nelem, O_LEN(args[i]))
+ else if (nelem == 0)
+ nelem = O_LEN(args[i])
+ }
+
+ do i = 1, nargs
+ if (O_TYPE(args[i]) != optype)
+ call xvv_chtype (args[i], args[i], optype)
+
+ if (nargs == 1 && opcode == F_MEDIAN)
+ nelem = 0
+ call xvv_initop (out, nelem, optype)
+
+ case F_LEN:
+ # This function always returns an integer scalar value.
+ nelem = 0
+ optype = TY_INT
+ call xvv_initop (out, nelem, optype)
+
+ case F_HIV, F_LOV:
+ # These functions return a scalar value.
+ nelem = 0
+ optype = O_TYPE(args[1])
+ if (optype == TY_BOOL)
+ optype = TY_INT
+ call xvv_initop (out, nelem, optype)
+
+ case F_SUM, F_MEAN, F_STDDEV:
+ # These functions require a vector argument and return a scalar
+ # value.
+
+ nelem = 0
+ optype = O_TYPE(args[1])
+ if (optype == TY_BOOL)
+ optype = TY_INT
+
+ if (optype == TY_DOUBLE)
+ call xvv_initop (out, nelem, TY_DOUBLE)
+ else
+ call xvv_initop (out, nelem, TY_REAL)
+
+ case F_SORT, F_SHIFT:
+ # Vector to vector, no type conversions.
+ nelem = O_LEN(args[1])
+ optype = O_TYPE(args[1])
+ call xvv_initop (out, nelem, optype)
+
+ default:
+ optype = 0
+ }
+
+ # Evaluate the function.
+ ap = args[1]
+
+ switch (opcode) {
+ case F_ABS:
+ call xvv_initop (out, O_LEN(ap), O_TYPE(ap))
+ switch (O_TYPE(ap)) {
+
+ case TY_SHORT:
+ if (O_LEN(ap) > 0) {
+ call aabss (Mems[O_VALP(ap)], Mems[O_VALP(out)],
+ O_LEN(ap))
+ } else
+ O_VALS(out) = abs(O_VALS(ap))
+
+ case TY_INT:
+ if (O_LEN(ap) > 0) {
+ call aabsi (Memi[O_VALP(ap)], Memi[O_VALP(out)],
+ O_LEN(ap))
+ } else
+ O_VALI(out) = abs(O_VALI(ap))
+
+ case TY_LONG:
+ if (O_LEN(ap) > 0) {
+ call aabsl (Meml[O_VALP(ap)], Meml[O_VALP(out)],
+ O_LEN(ap))
+ } else
+ O_VALL(out) = abs(O_VALL(ap))
+
+ case TY_REAL:
+ if (O_LEN(ap) > 0) {
+ call aabsr (Memr[O_VALP(ap)], Memr[O_VALP(out)],
+ O_LEN(ap))
+ } else
+ O_VALR(out) = abs(O_VALR(ap))
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) > 0) {
+ call aabsd (Memd[O_VALP(ap)], Memd[O_VALP(out)],
+ O_LEN(ap))
+ } else
+ O_VALD(out) = abs(O_VALD(ap))
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_ACOS:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = acos (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = acos (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = acos (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = acos (O_VALD(ap))
+
+ case F_ASIN:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = asin (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = asin (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = asin (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = asin (O_VALD(ap))
+
+ case F_COS:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = cos (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = cos (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = cos (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = cos (O_VALD(ap))
+
+ case F_COSH:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = cosh (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = cosh (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = cosh (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = cosh (O_VALD(ap))
+
+ case F_DEG:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = RADTODEG(Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = RADTODEG (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = RADTODEG(Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = RADTODEG (O_VALD(ap))
+
+ case F_EXP:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = exp (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = exp (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = exp (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = exp (O_VALD(ap))
+
+ case F_LOG:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ op = O_VALP(out)
+ do i = 1, O_LEN(ap) {
+ v_r = Memr[O_VALP(ap)+i-1]
+ if (rangecheck && v_r <= 0)
+ Memr[op] = 0
+ else
+ Memr[op] = log (v_r)
+ op = op + 1
+ }
+ } else {
+ v_r = O_VALR(ap)
+ if (rangecheck && v_r <= 0)
+ O_VALR(out) = 0
+ else
+ O_VALR(out) = log (v_r)
+ }
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ op = O_VALP(out)
+ do i = 1, O_LEN(ap) {
+ v_d = Memd[O_VALP(ap)+i-1]
+ if (rangecheck && v_d <= 0)
+ Memd[op] = 0
+ else
+ Memd[op] = log (v_d)
+ op = op + 1
+ }
+ } else {
+ v_d = O_VALD(ap)
+ if (rangecheck && v_d <= 0)
+ O_VALD(out) = 0
+ else
+ O_VALD(out) = log (v_d)
+ }
+
+ case F_LOG10:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ op = O_VALP(out)
+ do i = 1, O_LEN(ap) {
+ v_r = Memr[O_VALP(ap)+i-1]
+ if (rangecheck && v_r <= 0)
+ Memr[op] = 0
+ else
+ Memr[op] = log10 (v_r)
+ op = op + 1
+ }
+ } else {
+ v_r = O_VALR(ap)
+ if (rangecheck && v_r <= 0)
+ O_VALR(out) = 0
+ else
+ O_VALR(out) = log10 (v_r)
+ }
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ op = O_VALP(out)
+ do i = 1, O_LEN(ap) {
+ v_d = Memd[O_VALP(ap)+i-1]
+ if (rangecheck && v_d <= 0)
+ Memd[op] = 0
+ else
+ Memd[op] = log10 (v_d)
+ op = op + 1
+ }
+ } else {
+ v_d = O_VALD(ap)
+ if (rangecheck && v_d <= 0)
+ O_VALD(out) = 0
+ else
+ O_VALD(out) = log10 (v_d)
+ }
+
+ case F_RAD:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = DEGTORAD(Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = DEGTORAD (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = DEGTORAD(Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = DEGTORAD (O_VALD(ap))
+
+ case F_SIN:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = sin (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = sin (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = sin (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = sin (O_VALD(ap))
+
+ case F_SINH:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = sinh (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = sinh (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = sinh (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = sinh (O_VALD(ap))
+
+ case F_SQRT:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ op = O_VALP(out)
+ do i = 1, O_LEN(ap) {
+ v_r = Memr[O_VALP(ap)+i-1]
+ if (rangecheck && v_r < 0)
+ Memr[op] = 0
+ else
+ Memr[op] = sqrt (v_r)
+ op = op + 1
+ }
+ } else {
+ v_r = O_VALR(ap)
+ if (rangecheck && v_r <= 0)
+ O_VALR(out) = 0
+ else
+ O_VALR(out) = sqrt (v_r)
+ }
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ op = O_VALP(out)
+ do i = 1, O_LEN(ap) {
+ v_d = Memd[O_VALP(ap)+i-1]
+ if (rangecheck && v_d < 0)
+ Memd[op] = 0
+ else
+ Memd[op] = sqrt (v_d)
+ op = op + 1
+ }
+ } else {
+ v_d = O_VALD(ap)
+ if (rangecheck && v_d <= 0)
+ O_VALD(out) = 0
+ else
+ O_VALD(out) = sqrt (v_d)
+ }
+
+ case F_TAN:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = tan (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = tan (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = tan (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = tan (O_VALD(ap))
+
+ case F_TANH:
+
+ if (optype == TY_REAL)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] = tanh (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = tanh (O_VALR(ap))
+
+ if (optype == TY_DOUBLE)
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] = tanh (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = tanh (O_VALD(ap))
+
+
+ case F_LEN:
+ # Vector length.
+ O_VALI(out) = O_LEN(ap)
+
+ case F_HIV:
+ # High value.
+ switch (optype) {
+
+ case TY_SHORT:
+ if (O_LEN(ap) > 0)
+ O_VALS(out) = ahivs (Mems[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALS(out) = O_VALS(ap)
+
+ case TY_INT:
+ if (O_LEN(ap) > 0)
+ O_VALI(out) = ahivi (Memi[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALI(out) = O_VALI(ap)
+
+ case TY_LONG:
+ if (O_LEN(ap) > 0)
+ O_VALL(out) = ahivl (Meml[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALL(out) = O_VALL(ap)
+
+ case TY_REAL:
+ if (O_LEN(ap) > 0)
+ O_VALR(out) = ahivr (Memr[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALR(out) = O_VALR(ap)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) > 0)
+ O_VALD(out) = ahivd (Memd[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALD(out) = O_VALD(ap)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+ case F_LOV:
+ # Low value.
+ switch (optype) {
+
+ case TY_SHORT:
+ if (O_LEN(ap) > 0)
+ O_VALS(out) = alovs (Mems[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALS(out) = O_VALS(ap)
+
+ case TY_INT:
+ if (O_LEN(ap) > 0)
+ O_VALI(out) = alovi (Memi[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALI(out) = O_VALI(ap)
+
+ case TY_LONG:
+ if (O_LEN(ap) > 0)
+ O_VALL(out) = alovl (Meml[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALL(out) = O_VALL(ap)
+
+ case TY_REAL:
+ if (O_LEN(ap) > 0)
+ O_VALR(out) = alovr (Memr[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALR(out) = O_VALR(ap)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) > 0)
+ O_VALD(out) = alovd (Memd[O_VALP(ap)], O_LEN(ap))
+ else
+ O_VALD(out) = O_VALD(ap)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_SUM:
+ # Vector sum.
+ switch (optype) {
+
+ case TY_SHORT:
+ if (O_LEN(ap) > 0)
+ v_r = asums (Mems[O_VALP(ap)], O_LEN(ap))
+ else
+ v_r = O_VALS(ap)
+
+ case TY_INT:
+ if (O_LEN(ap) > 0)
+ v_r = asumi (Memi[O_VALP(ap)], O_LEN(ap))
+ else
+ v_r = O_VALI(ap)
+
+ case TY_LONG:
+ if (O_LEN(ap) > 0)
+ v_r = asuml (Meml[O_VALP(ap)], O_LEN(ap))
+ else
+ v_r = O_VALL(ap)
+
+ case TY_REAL:
+ if (O_LEN(ap) > 0)
+ v_r = asumr (Memr[O_VALP(ap)], O_LEN(ap))
+ else
+ v_r = O_VALR(ap)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) > 0)
+ v_d = asumd (Memd[O_VALP(ap)], O_LEN(ap))
+ else
+ v_d = O_VALD(ap)
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ if (optype == TY_DOUBLE)
+ O_VALD(out) = v_d
+ else
+ O_VALR(out) = v_r
+
+ case F_MEAN, F_STDDEV:
+ # Compute the mean or standard deviation of a vector. An optional
+ # second argument may be supplied to compute a K-sigma rejection
+ # mean and sigma.
+
+ if (nargs == 2) {
+ if (O_LEN(args[2]) > 0)
+ call xvv_error1 ("%s: ksigma arg must be a scalar" , fcn)
+
+ switch (O_TYPE(args[2])) {
+ case TY_REAL:
+ v_r = O_VALR(args[2])
+ v_d = v_r
+ case TY_DOUBLE:
+ v_d = O_VALD(args[2])
+ v_r = v_d
+ default:
+ call xvv_chtype (args[2], args[2], TY_REAL)
+ v_r = O_VALR(args[2])
+ v_d = v_r
+ }
+ } else {
+ v_r = 0.0
+ v_d = 0.0
+ }
+
+ switch (optype) {
+
+ case TY_SHORT:
+ v_i = aravs (Mems[O_VALP(ap)], O_LEN(ap), mean_r,sigma_r,v_r)
+
+ case TY_INT:
+ v_i = aravi (Memi[O_VALP(ap)], O_LEN(ap), mean_r,sigma_r,v_r)
+
+ case TY_REAL:
+ v_i = aravr (Memr[O_VALP(ap)], O_LEN(ap), mean_r,sigma_r,v_r)
+
+
+ case TY_LONG:
+ v_i = aravl (Meml[O_VALP(ap)], O_LEN(ap), mean_d,sigma_d,v_d)
+
+ case TY_DOUBLE:
+ v_i = aravd (Memd[O_VALP(ap)], O_LEN(ap), mean_d,sigma_d,v_d)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ if (opcode == F_MEAN) {
+ if (O_TYPE(out) == TY_REAL)
+ O_VALR(out) = mean_r
+ else
+ O_VALD(out) = mean_d
+ } else {
+ if (O_TYPE(out) == TY_REAL)
+ O_VALR(out) = sigma_r
+ else
+ O_VALD(out) = sigma_d
+ }
+
+ case F_MEDIAN:
+ # Compute the median value of a vector, or the vector median
+ # of 3 or more vectors.
+
+ switch (nargs) {
+ case 1:
+ switch (optype) {
+
+ case TY_SHORT:
+ O_VALS(out) = ameds (Mems[O_VALP(ap)], O_LEN(ap))
+
+ case TY_INT:
+ O_VALI(out) = amedi (Memi[O_VALP(ap)], O_LEN(ap))
+
+ case TY_LONG:
+ O_VALL(out) = amedl (Meml[O_VALP(ap)], O_LEN(ap))
+
+ case TY_REAL:
+ O_VALR(out) = amedr (Memr[O_VALP(ap)], O_LEN(ap))
+
+ case TY_DOUBLE:
+ O_VALD(out) = amedd (Memd[O_VALP(ap)], O_LEN(ap))
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+ case 3:
+ switch (optype) {
+
+ case TY_SHORT:
+ call amed3s (Mems[O_VALP(args[1])],
+ Mems[O_VALP(args[2])],
+ Mems[O_VALP(args[3])],
+ Mems[O_VALP(out)], nelem)
+
+ case TY_INT:
+ call amed3i (Memi[O_VALP(args[1])],
+ Memi[O_VALP(args[2])],
+ Memi[O_VALP(args[3])],
+ Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ call amed3l (Meml[O_VALP(args[1])],
+ Meml[O_VALP(args[2])],
+ Meml[O_VALP(args[3])],
+ Meml[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ call amed3r (Memr[O_VALP(args[1])],
+ Memr[O_VALP(args[2])],
+ Memr[O_VALP(args[3])],
+ Memr[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ call amed3d (Memd[O_VALP(args[1])],
+ Memd[O_VALP(args[2])],
+ Memd[O_VALP(args[3])],
+ Memd[O_VALP(out)], nelem)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+ case 4:
+ switch (optype) {
+
+ case TY_SHORT:
+ call amed4s (Mems[O_VALP(args[1])],
+ Mems[O_VALP(args[2])],
+ Mems[O_VALP(args[3])],
+ Mems[O_VALP(args[4])],
+ Mems[O_VALP(out)], nelem)
+
+ case TY_INT:
+ call amed4i (Memi[O_VALP(args[1])],
+ Memi[O_VALP(args[2])],
+ Memi[O_VALP(args[3])],
+ Memi[O_VALP(args[4])],
+ Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ call amed4l (Meml[O_VALP(args[1])],
+ Meml[O_VALP(args[2])],
+ Meml[O_VALP(args[3])],
+ Meml[O_VALP(args[4])],
+ Meml[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ call amed4r (Memr[O_VALP(args[1])],
+ Memr[O_VALP(args[2])],
+ Memr[O_VALP(args[3])],
+ Memr[O_VALP(args[4])],
+ Memr[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ call amed4d (Memd[O_VALP(args[1])],
+ Memd[O_VALP(args[2])],
+ Memd[O_VALP(args[3])],
+ Memd[O_VALP(args[4])],
+ Memd[O_VALP(out)], nelem)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+ case 5:
+ switch (optype) {
+
+ case TY_SHORT:
+ call amed5s (Mems[O_VALP(args[1])],
+ Mems[O_VALP(args[2])],
+ Mems[O_VALP(args[3])],
+ Mems[O_VALP(args[4])],
+ Mems[O_VALP(args[5])],
+ Mems[O_VALP(out)], nelem)
+
+ case TY_INT:
+ call amed5i (Memi[O_VALP(args[1])],
+ Memi[O_VALP(args[2])],
+ Memi[O_VALP(args[3])],
+ Memi[O_VALP(args[4])],
+ Memi[O_VALP(args[5])],
+ Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ call amed5l (Meml[O_VALP(args[1])],
+ Meml[O_VALP(args[2])],
+ Meml[O_VALP(args[3])],
+ Meml[O_VALP(args[4])],
+ Meml[O_VALP(args[5])],
+ Meml[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ call amed5r (Memr[O_VALP(args[1])],
+ Memr[O_VALP(args[2])],
+ Memr[O_VALP(args[3])],
+ Memr[O_VALP(args[4])],
+ Memr[O_VALP(args[5])],
+ Memr[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ call amed5d (Memd[O_VALP(args[1])],
+ Memd[O_VALP(args[2])],
+ Memd[O_VALP(args[3])],
+ Memd[O_VALP(args[4])],
+ Memd[O_VALP(args[5])],
+ Memd[O_VALP(out)], nelem)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+ default:
+ call xvv_error1 ("%s: wrong number of arguments", fcn)
+ }
+
+ case F_REPL:
+ # Replicate an item to make a longer vector.
+
+ chunk = O_LEN(ap)
+ optype = O_TYPE(ap)
+ if (optype == TY_BOOL)
+ optype = TY_INT
+
+ if (O_LEN(args[2]) > 0)
+ call xvv_error1 ("%s: replication factor must be a scalar", fcn)
+ if (O_TYPE(args[2]) != TY_INT)
+ call xvv_chtype (args[2], args[2], TY_INT)
+ repl = max (1, O_VALI(args[2]))
+
+ if (chunk <= 0)
+ nelem = repl
+ else
+ nelem = chunk * repl
+ call xvv_initop (out, nelem, optype)
+
+ switch (optype) {
+
+ case TY_SHORT:
+ if (chunk > 0) {
+ ip = O_VALP(ap)
+ op = O_VALP(out)
+ do i = 1, repl {
+ call amovs (Mems[ip], Mems[op], chunk)
+ op = op + chunk
+ }
+ } else
+ call amovks (O_VALS(ap), Mems[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (chunk > 0) {
+ ip = O_VALP(ap)
+ op = O_VALP(out)
+ do i = 1, repl {
+ call amovi (Memi[ip], Memi[op], chunk)
+ op = op + chunk
+ }
+ } else
+ call amovki (O_VALI(ap), Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (chunk > 0) {
+ ip = O_VALP(ap)
+ op = O_VALP(out)
+ do i = 1, repl {
+ call amovl (Meml[ip], Meml[op], chunk)
+ op = op + chunk
+ }
+ } else
+ call amovkl (O_VALL(ap), Meml[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ if (chunk > 0) {
+ ip = O_VALP(ap)
+ op = O_VALP(out)
+ do i = 1, repl {
+ call amovr (Memr[ip], Memr[op], chunk)
+ op = op + chunk
+ }
+ } else
+ call amovkr (O_VALR(ap), Memr[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ if (chunk > 0) {
+ ip = O_VALP(ap)
+ op = O_VALP(out)
+ do i = 1, repl {
+ call amovd (Memd[ip], Memd[op], chunk)
+ op = op + chunk
+ }
+ } else
+ call amovkd (O_VALD(ap), Memd[O_VALP(out)], nelem)
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_SHIFT:
+ # Vector shift.
+ if (O_LEN(args[2]) > 0)
+ call xvv_error1 ("%s: shift arg must be a scalar" , fcn)
+ if (O_TYPE(args[2]) != TY_INT)
+ call xvv_chtype (args[2], args[2], TY_INT)
+ shift = O_VALI(args[2])
+
+ if (abs(shift) > nelem) {
+ if (shift > 0)
+ shift = nelem
+ else
+ shift = -nelem
+ }
+
+ switch (optype) {
+
+ case TY_SHORT:
+ if (nelem > 0) {
+ do i = 1, nelem {
+ j = i - shift
+ if (j < 1)
+ j = j + nelem
+ else if (j > nelem)
+ j = j - nelem
+ Mems[O_VALP(out)+i-1] = Mems[O_VALP(ap)+j-1]
+ }
+ } else
+ O_VALS(out) = (O_VALS(ap))
+
+ case TY_INT:
+ if (nelem > 0) {
+ do i = 1, nelem {
+ j = i - shift
+ if (j < 1)
+ j = j + nelem
+ else if (j > nelem)
+ j = j - nelem
+ Memi[O_VALP(out)+i-1] = Memi[O_VALP(ap)+j-1]
+ }
+ } else
+ O_VALI(out) = (O_VALI(ap))
+
+ case TY_LONG:
+ if (nelem > 0) {
+ do i = 1, nelem {
+ j = i - shift
+ if (j < 1)
+ j = j + nelem
+ else if (j > nelem)
+ j = j - nelem
+ Meml[O_VALP(out)+i-1] = Meml[O_VALP(ap)+j-1]
+ }
+ } else
+ O_VALL(out) = (O_VALL(ap))
+
+ case TY_REAL:
+ if (nelem > 0) {
+ do i = 1, nelem {
+ j = i - shift
+ if (j < 1)
+ j = j + nelem
+ else if (j > nelem)
+ j = j - nelem
+ Memr[O_VALP(out)+i-1] = Memr[O_VALP(ap)+j-1]
+ }
+ } else
+ O_VALR(out) = (O_VALR(ap))
+
+ case TY_DOUBLE:
+ if (nelem > 0) {
+ do i = 1, nelem {
+ j = i - shift
+ if (j < 1)
+ j = j + nelem
+ else if (j > nelem)
+ j = j - nelem
+ Memd[O_VALP(out)+i-1] = Memd[O_VALP(ap)+j-1]
+ }
+ } else
+ O_VALD(out) = (O_VALD(ap))
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_SORT:
+ # Sort a vector.
+ switch (optype) {
+
+ case TY_SHORT:
+ if (nelem > 0)
+ call asrts (Mems[O_VALP(ap)], Mems[O_VALP(out)], nelem)
+ else
+ O_VALS(out) = (O_VALS(ap))
+
+ case TY_INT:
+ if (nelem > 0)
+ call asrti (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+ else
+ O_VALI(out) = (O_VALI(ap))
+
+ case TY_LONG:
+ if (nelem > 0)
+ call asrtl (Meml[O_VALP(ap)], Meml[O_VALP(out)], nelem)
+ else
+ O_VALL(out) = (O_VALL(ap))
+
+ case TY_REAL:
+ if (nelem > 0)
+ call asrtr (Memr[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+ else
+ O_VALR(out) = (O_VALR(ap))
+
+ case TY_DOUBLE:
+ if (nelem > 0)
+ call asrtd (Memd[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+ else
+ O_VALD(out) = (O_VALD(ap))
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_ATAN, F_ATAN2:
+
+ if (optype == TY_REAL) {
+ if (nargs == 1) {
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] =
+ atan (Memr[O_VALP(ap)+i-1])
+ } else
+ O_VALR(out) = atan (O_VALR(ap))
+ } else {
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memr[O_VALP(out)+i-1] =
+ atan2 (Memr[O_VALP(args[1])+i-1],
+ Memr[O_VALP(args[2])+i-1])
+ } else
+ O_VALR(out) = atan2(O_VALR(args[1]), O_VALR(args[2]))
+ }
+ }
+
+ if (optype == TY_DOUBLE) {
+ if (nargs == 1) {
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] =
+ atan (Memd[O_VALP(ap)+i-1])
+ } else
+ O_VALD(out) = atan (O_VALD(ap))
+ } else {
+ if (O_LEN(ap) > 0) {
+ do i = 1, O_LEN(ap)
+ Memd[O_VALP(out)+i-1] =
+ atan2 (Memd[O_VALP(args[1])+i-1],
+ Memd[O_VALP(args[2])+i-1])
+ } else
+ O_VALD(out) = atan2(O_VALD(args[1]), O_VALD(args[2]))
+ }
+ }
+
+
+ case F_MOD:
+ in1 = args[1]
+ in2 = args[2]
+
+ switch (optype) {
+
+ case TY_SHORT:
+ if (O_LEN(in1) <= 0) {
+ O_VALS(out) = mod (O_VALS(in1), O_VALS(in2))
+ } else if (O_LEN(in2) <= 0) {
+ call amodks (Mems[O_VALP(in1)], O_VALS(in2),
+ Mems[O_VALP(out)], nelem)
+ } else {
+ call amods (Mems[O_VALP(in1)], Mems[O_VALP(in2)],
+ Mems[O_VALP(out)], nelem)
+ }
+
+ case TY_INT:
+ if (O_LEN(in1) <= 0) {
+ O_VALI(out) = mod (O_VALI(in1), O_VALI(in2))
+ } else if (O_LEN(in2) <= 0) {
+ call amodki (Memi[O_VALP(in1)], O_VALI(in2),
+ Memi[O_VALP(out)], nelem)
+ } else {
+ call amodi (Memi[O_VALP(in1)], Memi[O_VALP(in2)],
+ Memi[O_VALP(out)], nelem)
+ }
+
+ case TY_LONG:
+ if (O_LEN(in1) <= 0) {
+ O_VALL(out) = mod (O_VALL(in1), O_VALL(in2))
+ } else if (O_LEN(in2) <= 0) {
+ call amodkl (Meml[O_VALP(in1)], O_VALL(in2),
+ Meml[O_VALP(out)], nelem)
+ } else {
+ call amodl (Meml[O_VALP(in1)], Meml[O_VALP(in2)],
+ Meml[O_VALP(out)], nelem)
+ }
+
+ case TY_REAL:
+ if (O_LEN(in1) <= 0) {
+ O_VALR(out) = mod (O_VALR(in1), O_VALR(in2))
+ } else if (O_LEN(in2) <= 0) {
+ call amodkr (Memr[O_VALP(in1)], O_VALR(in2),
+ Memr[O_VALP(out)], nelem)
+ } else {
+ call amodr (Memr[O_VALP(in1)], Memr[O_VALP(in2)],
+ Memr[O_VALP(out)], nelem)
+ }
+
+ case TY_DOUBLE:
+ if (O_LEN(in1) <= 0) {
+ O_VALD(out) = mod (O_VALD(in1), O_VALD(in2))
+ } else if (O_LEN(in2) <= 0) {
+ call amodkd (Memd[O_VALP(in1)], O_VALD(in2),
+ Memd[O_VALP(out)], nelem)
+ } else {
+ call amodd (Memd[O_VALP(in1)], Memd[O_VALP(in2)],
+ Memd[O_VALP(out)], nelem)
+ }
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_MAX:
+ switch (optype) {
+
+ case TY_SHORT:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovks (O_VALS(ap), Mems[O_VALP(out)], nelem)
+ else
+ O_VALS(out) = O_VALS(ap)
+ } else
+ call amovs (Mems[O_VALP(ap)], Mems[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALS(out) = max (O_VALS(ap), O_VALS(out))
+ else {
+ call amaxks (Mems[O_VALP(out)], O_VALS(ap),
+ Mems[O_VALP(out)], nelem)
+ }
+ } else {
+ call amaxs (Mems[O_VALP(out)], Mems[O_VALP(ap)],
+ Mems[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_INT:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovki (O_VALI(ap), Memi[O_VALP(out)], nelem)
+ else
+ O_VALI(out) = O_VALI(ap)
+ } else
+ call amovi (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALI(out) = max (O_VALI(ap), O_VALI(out))
+ else {
+ call amaxki (Memi[O_VALP(out)], O_VALI(ap),
+ Memi[O_VALP(out)], nelem)
+ }
+ } else {
+ call amaxi (Memi[O_VALP(out)], Memi[O_VALP(ap)],
+ Memi[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_LONG:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovkl (O_VALL(ap), Meml[O_VALP(out)], nelem)
+ else
+ O_VALL(out) = O_VALL(ap)
+ } else
+ call amovl (Meml[O_VALP(ap)], Meml[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALL(out) = max (O_VALL(ap), O_VALL(out))
+ else {
+ call amaxkl (Meml[O_VALP(out)], O_VALL(ap),
+ Meml[O_VALP(out)], nelem)
+ }
+ } else {
+ call amaxl (Meml[O_VALP(out)], Meml[O_VALP(ap)],
+ Meml[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_REAL:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovkr (O_VALR(ap), Memr[O_VALP(out)], nelem)
+ else
+ O_VALR(out) = O_VALR(ap)
+ } else
+ call amovr (Memr[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALR(out) = max (O_VALR(ap), O_VALR(out))
+ else {
+ call amaxkr (Memr[O_VALP(out)], O_VALR(ap),
+ Memr[O_VALP(out)], nelem)
+ }
+ } else {
+ call amaxr (Memr[O_VALP(out)], Memr[O_VALP(ap)],
+ Memr[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_DOUBLE:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovkd (O_VALD(ap), Memd[O_VALP(out)], nelem)
+ else
+ O_VALD(out) = O_VALD(ap)
+ } else
+ call amovd (Memd[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALD(out) = max (O_VALD(ap), O_VALD(out))
+ else {
+ call amaxkd (Memd[O_VALP(out)], O_VALD(ap),
+ Memd[O_VALP(out)], nelem)
+ }
+ } else {
+ call amaxd (Memd[O_VALP(out)], Memd[O_VALP(ap)],
+ Memd[O_VALP(out)], nelem)
+ }
+ }
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_MIN:
+ switch (optype) {
+
+ case TY_SHORT:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovks (O_VALS(ap), Mems[O_VALP(out)], nelem)
+ else
+ O_VALS(out) = O_VALS(ap)
+ } else
+ call amovs (Mems[O_VALP(ap)], Mems[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALS(out) = min (O_VALS(ap), O_VALS(out))
+ else {
+ call aminks (Mems[O_VALP(out)], O_VALS(ap),
+ Mems[O_VALP(out)], nelem)
+ }
+ } else {
+ call amins (Mems[O_VALP(out)], Mems[O_VALP(ap)],
+ Mems[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_INT:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovki (O_VALI(ap), Memi[O_VALP(out)], nelem)
+ else
+ O_VALI(out) = O_VALI(ap)
+ } else
+ call amovi (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALI(out) = min (O_VALI(ap), O_VALI(out))
+ else {
+ call aminki (Memi[O_VALP(out)], O_VALI(ap),
+ Memi[O_VALP(out)], nelem)
+ }
+ } else {
+ call amini (Memi[O_VALP(out)], Memi[O_VALP(ap)],
+ Memi[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_LONG:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovkl (O_VALL(ap), Meml[O_VALP(out)], nelem)
+ else
+ O_VALL(out) = O_VALL(ap)
+ } else
+ call amovl (Meml[O_VALP(ap)], Meml[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALL(out) = min (O_VALL(ap), O_VALL(out))
+ else {
+ call aminkl (Meml[O_VALP(out)], O_VALL(ap),
+ Meml[O_VALP(out)], nelem)
+ }
+ } else {
+ call aminl (Meml[O_VALP(out)], Meml[O_VALP(ap)],
+ Meml[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_REAL:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovkr (O_VALR(ap), Memr[O_VALP(out)], nelem)
+ else
+ O_VALR(out) = O_VALR(ap)
+ } else
+ call amovr (Memr[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALR(out) = min (O_VALR(ap), O_VALR(out))
+ else {
+ call aminkr (Memr[O_VALP(out)], O_VALR(ap),
+ Memr[O_VALP(out)], nelem)
+ }
+ } else {
+ call aminr (Memr[O_VALP(out)], Memr[O_VALP(ap)],
+ Memr[O_VALP(out)], nelem)
+ }
+ }
+
+ case TY_DOUBLE:
+ # Copy the first argument.
+ ap = args[1]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) > 0)
+ call amovkd (O_VALD(ap), Memd[O_VALP(out)], nelem)
+ else
+ O_VALD(out) = O_VALD(ap)
+ } else
+ call amovd (Memd[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ # Process the second and remaining arguments.
+ do i = 2, nargs {
+ ap = args[i]
+ if (O_LEN(ap) <= 0) {
+ if (O_LEN(out) <= 0)
+ O_VALD(out) = min (O_VALD(ap), O_VALD(out))
+ else {
+ call aminkd (Memd[O_VALP(out)], O_VALD(ap),
+ Memd[O_VALP(out)], nelem)
+ }
+ } else {
+ call amind (Memd[O_VALP(out)], Memd[O_VALP(ap)],
+ Memd[O_VALP(out)], nelem)
+ }
+ }
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_BOOL:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_BOOL)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALI(ap)
+ else
+ call amovi (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ch = O_VALC(ap)
+ O_VALI(out) = btoi (ch == 'y' || ch == 'Y')
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = btoi (O_VALS(ap) != 0)
+ else {
+ v_s = 0
+ call abneks (Mems[O_VALP(ap)], v_s, Memi[O_VALP(out)],
+ nelem)
+ }
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = btoi (O_VALI(ap) != 0)
+ else {
+ v_i = 0
+ call abneki (Memi[O_VALP(ap)], v_i, Memi[O_VALP(out)],
+ nelem)
+ }
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = btoi (O_VALL(ap) != 0)
+ else {
+ v_l = 0
+ call abnekl (Meml[O_VALP(ap)], v_l, Memi[O_VALP(out)],
+ nelem)
+ }
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = btoi (O_VALR(ap) != 0.0)
+ else {
+ v_r = 0.0
+ call abnekr (Memr[O_VALP(ap)], v_r, Memi[O_VALP(out)],
+ nelem)
+ }
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = btoi (O_VALD(ap) != 0.0D0)
+ else {
+ v_d = 0.0D0
+ call abnekd (Memd[O_VALP(ap)], v_d, Memi[O_VALP(out)],
+ nelem)
+ }
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_SHORT:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_SHORT)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALS(out) = O_VALI(ap)
+ else
+ call achtis (Memi[O_VALP(ap)], Mems[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ip = O_VALP(ap)
+ if (gctod (Memc, ip, v_d) <= 0)
+ O_VALS(out) = 0
+ else
+ O_VALS(out) = v_d
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALS(out) = O_VALS(ap)
+ else
+ call achtss (Mems[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALS(out) = O_VALI(ap)
+ else
+ call achtis (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALS(out) = O_VALL(ap)
+ else
+ call achtls (Meml[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALS(out) = O_VALR(ap)
+ else
+ call achtrs (Memr[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALS(out) = O_VALD(ap)
+ else
+ call achtds (Memd[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_INT:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_INT)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALI(ap)
+ else
+ call amovi (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ip = O_VALP(ap)
+ if (gctod (Memc, ip, v_d) <= 0)
+ O_VALI(out) = 0
+ else
+ O_VALI(out) = v_d
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALS(ap)
+ else
+ call achtsi (Mems[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALI(ap)
+ else
+ call achtii (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALL(ap)
+ else
+ call achtli (Meml[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALR(ap)
+ else
+ call achtri (Memr[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALD(ap)
+ else
+ call achtdi (Memd[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_LONG:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_LONG)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALL(out) = O_VALI(ap)
+ else
+ call amovi (Memi[O_VALP(ap)], Meml[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ip = O_VALP(ap)
+ if (gctod (Memc, ip, v_d) <= 0)
+ O_VALL(out) = 0
+ else
+ O_VALL(out) = v_d
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALL(out) = O_VALS(ap)
+ else
+ call achtsl (Mems[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALL(out) = O_VALI(ap)
+ else
+ call achtil (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALL(out) = O_VALL(ap)
+ else
+ call achtll (Meml[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALL(out) = O_VALR(ap)
+ else
+ call achtrl (Memr[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALL(out) = O_VALD(ap)
+ else
+ call achtdl (Memd[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_NINT:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_INT)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALI(ap)
+ else
+ call amovi (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ip = O_VALP(ap)
+ if (gctod (Memc, ip, v_d) <= 0)
+ O_VALI(out) = 0
+ else
+ O_VALI(out) = nint (v_d)
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALS(ap)
+ else
+ call achtsi (Mems[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALI(ap)
+ else
+ call achtii (Memi[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = O_VALL(ap)
+ else
+ call achtli (Meml[O_VALP(ap)], Memi[O_VALP(out)], nelem)
+
+
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = nint (O_VALR(ap))
+ else {
+ do i = 1, nelem
+ Memi[O_VALP(out)+i-1] = nint (Memr[O_VALP(ap)+i-1])
+ }
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALI(out) = nint (O_VALD(ap))
+ else {
+ do i = 1, nelem
+ Memi[O_VALP(out)+i-1] = nint (Memd[O_VALP(ap)+i-1])
+ }
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_REAL:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_REAL)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALR(out) = O_VALI(ap)
+ else
+ call achtir (Memi[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ip = O_VALP(ap)
+ if (gctod (Memc, ip, v_d) <= 0)
+ O_VALR(out) = 0
+ else
+ O_VALR(out) = v_d
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALR(out) = O_VALS(ap)
+ else
+ call achtsr (Mems[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALR(out) = O_VALI(ap)
+ else
+ call achtir (Memi[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALR(out) = O_VALL(ap)
+ else
+ call achtlr (Meml[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALR(out) = O_VALR(ap)
+ else
+ call achtrr (Memr[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALR(out) = O_VALD(ap)
+ else
+ call achtdr (Memd[O_VALP(ap)], Memr[O_VALP(out)], nelem)
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_DOUBLE:
+ nelem = 0
+ if (O_LEN(ap) > 0 && O_TYPE(ap) != TY_CHAR)
+ nelem = O_LEN(ap)
+ call xvv_initop (out, nelem, TY_DOUBLE)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ if (O_LEN(ap) <= 0)
+ O_VALD(out) = O_VALI(ap)
+ else
+ call achtid (Memi[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ case TY_CHAR:
+ ip = O_VALP(ap)
+ if (gctod (Memc, ip, v_d) <= 0)
+ O_VALD(out) = 0
+ else
+ O_VALD(out) = v_d
+
+
+ case TY_SHORT:
+ if (O_LEN(ap) <= 0)
+ O_VALD(out) = O_VALS(ap)
+ else
+ call achtsd (Mems[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ case TY_INT:
+ if (O_LEN(ap) <= 0)
+ O_VALD(out) = O_VALI(ap)
+ else
+ call achtid (Memi[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ case TY_LONG:
+ if (O_LEN(ap) <= 0)
+ O_VALD(out) = O_VALL(ap)
+ else
+ call achtld (Meml[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ case TY_REAL:
+ if (O_LEN(ap) <= 0)
+ O_VALD(out) = O_VALR(ap)
+ else
+ call achtrd (Memr[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+ case TY_DOUBLE:
+ if (O_LEN(ap) <= 0)
+ O_VALD(out) = O_VALD(ap)
+ else
+ call achtdd (Memd[O_VALP(ap)], Memd[O_VALP(out)], nelem)
+
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ case F_STR:
+ optype = TY_CHAR
+ if (O_TYPE(ap) == TY_CHAR)
+ nelem = strlen (O_VALC(ap))
+ else
+ nelem = MAX_DIGITS
+ call xvv_initop (out, nelem, TY_CHAR)
+
+ switch (O_TYPE(ap)) {
+ case TY_BOOL:
+ call sprintf (O_VALC(out), nelem, "%b")
+ call pargi (O_VALI(ap))
+ case TY_CHAR:
+ call sprintf (O_VALC(out), nelem, "%s")
+ call pargstr (O_VALC(ap))
+
+ case TY_SHORT:
+ call sprintf (O_VALC(out), nelem, "%d")
+ call pargs (O_VALS(ap))
+
+ case TY_INT:
+ call sprintf (O_VALC(out), nelem, "%d")
+ call pargi (O_VALI(ap))
+
+ case TY_LONG:
+ call sprintf (O_VALC(out), nelem, "%d")
+ call pargl (O_VALL(ap))
+
+
+ case TY_REAL:
+ call sprintf (O_VALC(out), nelem, "%g")
+ call pargr (O_VALR(ap))
+
+ case TY_DOUBLE:
+ call sprintf (O_VALC(out), nelem, "%g")
+ call pargd (O_VALD(ap))
+
+ default:
+ call xvv_error1 (s_badtype, fcn)
+ }
+
+ default:
+ call xvv_error ("callfcn: unknown function type")
+ }
+
+free_
+ # Free any storage used by the argument list operands.
+ do i = 1, nargs
+ call xvv_freeop (args[i])
+
+ call sfree (sp)
+end
+
+
+# XVV_STARTARGLIST -- Allocate an argument list descriptor to receive
+# arguments as a function call is parsed. We are called with either
+# zero or one arguments. The argument list descriptor is pointed to by
+# a ficticious operand. The descriptor itself contains a count of the
+# number of arguments, an array of pointers to the operand structures,
+# as well as storage for the operand structures. The operands must be
+# stored locally since the parser will discard its copy of the operand
+# structure for each argument as the associated grammar rule is reduced.
+
+procedure xvv_startarglist (arg, out)
+
+pointer arg #I pointer to first argument, or NULL
+pointer out #I output operand pointing to arg descriptor
+
+pointer ap
+errchk xvv_initop
+
+begin
+ call xvv_initop (out, LEN_ARGSTRUCT, TY_STRUCT)
+ ap = O_VALP(out)
+
+ if (arg == NULL)
+ A_NARGS(ap) = 0
+ else {
+ A_NARGS(ap) = 1
+ A_ARGP(ap,1) = A_OPS(ap)
+ YYMOVE (arg, A_OPS(ap))
+ }
+end
+
+
+# XVV_ADDARG -- Add an argument to the argument list for a function call.
+
+procedure xvv_addarg (arg, arglist, out)
+
+pointer arg #I pointer to argument to be added
+pointer arglist #I pointer to operand pointing to arglist
+pointer out #I output operand pointing to arg descriptor
+
+pointer ap, o
+int nargs
+
+begin
+ ap = O_VALP(arglist)
+
+ nargs = A_NARGS(ap) + 1
+ A_NARGS(ap) = nargs
+ if (nargs > MAX_ARGS)
+ call xvv_error ("too many function arguments")
+
+ o = A_OPS(ap) + ((nargs - 1) * LEN_OPERAND)
+ A_ARGP(ap,nargs) = o
+ YYMOVE (arg, o)
+
+ YYMOVE (arglist, out)
+end
+
+
+# XVV_ERROR1 -- Take an error action, formatting an error message with one
+# format string plus one string argument.
+
+procedure xvv_error1 (fmt, arg)
+
+char fmt[ARB] #I printf format string
+char arg[ARB] #I string argument
+
+pointer sp, buf
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+
+ call sprintf (Memc[buf], SZ_LINE, fmt)
+ call pargstr (arg)
+
+ call xvv_error (Memc[buf])
+ call sfree (sp)
+end
+
+
+# XVV_ERROR2 -- Take an error action, formatting an error message with one
+# format string plus one string argument and one integer argument.
+
+procedure xvv_error2 (fmt, arg1, arg2)
+
+char fmt[ARB] #I printf format string
+char arg1[ARB] #I string argument
+int arg2 #I integer argument
+
+pointer sp, buf
+
+begin
+ call smark (sp)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+
+ call sprintf (Memc[buf], SZ_LINE, fmt)
+ call pargstr (arg1)
+ call pargi (arg2)
+
+ call xvv_error (Memc[buf])
+ call sfree (sp)
+end
+
+
+# XVV_ERROR -- Take an error action, given an error message string as the
+# sole argument.
+
+procedure xvv_error (errmsg)
+
+char errmsg[ARB] #I error message
+
+begin
+ call error (1, errmsg)
+end
+
+
+# XVV_CHTYPE -- Change the datatype of an operand. The input and output
+# operands may be the same.
+
+procedure xvv_chtype (o1, o2, dtype)
+
+pointer o1 #I input operand
+pointer o2 #I output operand
+int dtype #I new datatype
+
+short v_s
+int v_i
+long v_l
+real v_r
+double v_d
+pointer vp, ip, op
+bool float, freeval
+int old_type, nelem, ch
+
+pointer coerce()
+int sizeof(), btoi(), gctod()
+string s_badtype "chtype: invalid operand type"
+
+begin
+ old_type = O_TYPE(o1)
+ nelem = O_LEN(o1)
+
+ # No type conversion needed?
+ if (old_type == dtype) {
+ if (o1 != o2) {
+ if (nelem <= 0)
+ YYMOVE (o1, o2)
+ else {
+ call xvv_initop (o2, nelem, old_type)
+ call amovc (O_VALC(o1), O_VALC(o2), nelem * sizeof(dtype))
+ }
+ }
+ return
+ }
+
+ if (nelem <= 0) {
+ # Scalar input operand.
+
+ O_TYPE(o2) = dtype
+ O_LEN(o2) = 0
+ float = false
+
+ # Read the old value into a local variable of type long or double.
+ switch (old_type) {
+ case TY_BOOL:
+ v_l = O_VALI(o1)
+ case TY_CHAR:
+ v_l = 0 # null string?
+
+ case TY_SHORT:
+ v_l = O_VALS(o1)
+
+ case TY_INT:
+ v_l = O_VALI(o1)
+
+ case TY_LONG:
+ v_l = O_VALL(o1)
+
+
+ case TY_REAL:
+ v_d = O_VALR(o1)
+ float = true
+
+ case TY_DOUBLE:
+ v_d = O_VALD(o1)
+ float = true
+
+ default:
+ call xvv_error (s_badtype)
+ }
+
+ # Set the value of the output operand.
+ switch (dtype) {
+ case TY_BOOL:
+ if (float)
+ O_VALI(o2) = btoi (v_d != 0)
+ else
+ O_VALI(o2) = btoi (v_l != 0)
+ case TY_CHAR:
+ call xvv_initop (o2, MAX_DIGITS, TY_CHAR)
+ if (float) {
+ call sprintf (O_VALC(o2), MAX_DIGITS, "%g")
+ call pargd (v_d)
+ } else {
+ call sprintf (O_VALC(o2), MAX_DIGITS, "%d")
+ call pargl (v_l)
+ }
+
+ case TY_SHORT:
+ if (float)
+ O_VALS(o2) = v_d
+ else
+ O_VALS(o2) = v_l
+
+ case TY_INT:
+ if (float)
+ O_VALI(o2) = v_d
+ else
+ O_VALI(o2) = v_l
+
+ case TY_LONG:
+ if (float)
+ O_VALL(o2) = v_d
+ else
+ O_VALL(o2) = v_l
+
+
+ case TY_REAL:
+ if (float)
+ O_VALR(o2) = v_d
+ else
+ O_VALR(o2) = v_l
+
+ case TY_DOUBLE:
+ if (float)
+ O_VALD(o2) = v_d
+ else
+ O_VALD(o2) = v_l
+
+ default:
+ call xvv_error (s_badtype)
+ }
+
+ } else {
+ # Vector input operand.
+
+ # Save a pointer to the input operand data vector, to avoid it
+ # getting clobbered if O1 and O2 are the same operand.
+
+ vp = O_VALP(o1)
+
+ # If we have a char string input operand the output numeric
+ # operand can only be a scalar. If we have a char string output
+ # operand nelem is the length of the string.
+
+ if (old_type == TY_CHAR)
+ nelem = 0
+ else if (dtype == TY_CHAR)
+ nelem = MAX_DIGITS
+
+ # Initialize the output operand O2. The freeval flag is cleared
+ # cleared to keep the initop from freeing the input operand array,
+ # inherited when the input operand is copied (or when the input
+ # and output operands are the same). We free the old operand
+ # array manually below.
+
+ if (o1 != o2)
+ YYMOVE (o1, o2)
+ freeval = (and (O_FLAGS(o1), O_FREEVAL) != 0)
+ O_FLAGS(o2) = and (O_FLAGS(o2), not(O_FREEVAL))
+ call xvv_initop (o2, nelem, dtype)
+
+ # Write output value.
+ switch (dtype) {
+ case TY_BOOL:
+ if (old_type == TY_CHAR) {
+ ch = Memc[vp]
+ O_VALI(o2) = btoi (ch == 'y' || ch == 'Y')
+ } else {
+ switch (old_type) {
+
+ case TY_SHORT:
+ v_s = 0
+ call abneks (Mems[vp], v_s, Memi[O_VALP(o2)], nelem)
+
+ case TY_INT:
+ v_i = 0
+ call abneki (Memi[vp], v_i, Memi[O_VALP(o2)], nelem)
+
+ case TY_LONG:
+ v_l = 0
+ call abnekl (Meml[vp], v_l, Memi[O_VALP(o2)], nelem)
+
+ case TY_REAL:
+ v_r = 0.0
+ call abnekr (Memr[vp], v_r, Memi[O_VALP(o2)], nelem)
+
+ case TY_DOUBLE:
+ v_d = 0.0D0
+ call abnekd (Memd[vp], v_d, Memi[O_VALP(o2)], nelem)
+
+ default:
+ call xvv_error (s_badtype)
+ }
+ }
+
+ case TY_CHAR:
+ call xvv_error (s_badtype)
+
+ case TY_SHORT, TY_INT, TY_LONG, TY_REAL, TY_DOUBLE:
+ switch (old_type) {
+ case TY_BOOL:
+ op = coerce (O_VALP(o2), O_TYPE(o2), TY_CHAR)
+ call achti (Memi[vp], Memc[op], nelem, dtype)
+ case TY_CHAR:
+ ip = vp
+ if (gctod (Memc, ip, v_d) <= 0)
+ v_d = 0
+ switch (dtype) {
+
+ case TY_SHORT:
+ O_VALS(o2) = v_d
+
+ case TY_INT:
+ O_VALI(o2) = v_d
+
+ case TY_LONG:
+ O_VALL(o2) = v_d
+
+ case TY_REAL:
+ O_VALR(o2) = v_d
+
+ case TY_DOUBLE:
+ O_VALD(o2) = v_d
+
+ }
+
+ case TY_SHORT:
+ op = coerce (O_VALP(o2), O_TYPE(o2), TY_CHAR)
+ call achts (Mems[vp], Memc[op], nelem, dtype)
+
+ case TY_INT:
+ op = coerce (O_VALP(o2), O_TYPE(o2), TY_CHAR)
+ call achti (Memi[vp], Memc[op], nelem, dtype)
+
+ case TY_LONG:
+ op = coerce (O_VALP(o2), O_TYPE(o2), TY_CHAR)
+ call achtl (Meml[vp], Memc[op], nelem, dtype)
+
+ case TY_REAL:
+ op = coerce (O_VALP(o2), O_TYPE(o2), TY_CHAR)
+ call achtr (Memr[vp], Memc[op], nelem, dtype)
+
+ case TY_DOUBLE:
+ op = coerce (O_VALP(o2), O_TYPE(o2), TY_CHAR)
+ call achtd (Memd[vp], Memc[op], nelem, dtype)
+
+ default:
+ call xvv_error (s_badtype)
+ }
+ default:
+ call xvv_error (s_badtype)
+ }
+
+ # Free old operand value.
+ if (freeval)
+ call mfree (vp, old_type)
+ }
+end
+
+
+# XVV_INITOP -- Initialize an operand, providing storage for an operand value
+# of the given size and type.
+
+procedure xvv_initop (o, o_len, o_type)
+
+pointer o #I pointer to operand structure
+int o_len #I length of operand (zero if scalar)
+int o_type #I datatype of operand
+
+begin
+ O_LEN(o) = 0
+ call xvv_makeop (o, o_len, o_type)
+end
+
+
+# XVV_MAKEOP -- Set up the operand structure. If the operand structure has
+# already been initialized and array storage allocated, free the old array.
+
+procedure xvv_makeop (o, o_len, o_type)
+
+pointer o #I pointer to operand structure
+int o_len #I length of operand (zero if scalar)
+int o_type #I datatype of operand
+
+errchk malloc
+
+begin
+ # Free old array storage if any.
+ if (O_TYPE(o) != 0 && O_LEN(o) > 0)
+ if (and (O_FLAGS(o), O_FREEVAL) != 0) {
+ if (O_TYPE(o) == TY_BOOL)
+ call mfree (O_VALP(o), TY_INT)
+ else
+ call mfree (O_VALP(o), O_TYPE(o))
+ O_LEN(o) = 0
+ }
+
+ # Set new operand type.
+ O_TYPE(o) = o_type
+
+ # Allocate array storage if nonscalar operand.
+ if (o_len > 0) {
+ if (o_type == TY_BOOL)
+ call malloc (O_VALP(o), o_len, TY_INT)
+ else
+ call malloc (O_VALP(o), o_len, o_type)
+ O_LEN(o) = o_len
+ }
+
+ O_FLAGS(o) = O_FREEVAL
+end
+
+
+# XVV_FREEOP -- Reinitialize an operand structure, i.e., free any associated
+# array storage and clear the operand datatype field, but do not free the
+# operand structure itself (which may be only a segment of an array and not
+# a separately allocated structure).
+
+procedure xvv_freeop (o)
+
+pointer o #I pointer to operand structure
+
+begin
+ # Free old array storage if any.
+ if (O_TYPE(o) != 0 && O_LEN(o) > 0)
+ if (and (O_FLAGS(o), O_FREEVAL) != 0) {
+ if (O_TYPE(o) == TY_BOOL)
+ call mfree (O_VALP(o), TY_INT)
+ else
+ call mfree (O_VALP(o), O_TYPE(o))
+ O_LEN(o) = 0
+ }
+
+ # Either free operand struct or clear the operand type to mark
+ # operand invalid.
+
+ if (and (O_FLAGS(o), O_FREEOP) != 0)
+ call mfree (o, TY_STRUCT)
+ else
+ O_TYPE(o) = 0
+end
+
+
+# XVV_LOADSYMBOLS -- Load a list of symbol names into a symbol table. Each
+# symbol is tagged with an integer code corresponding to its sequence number
+# in the symbol list.
+
+pointer procedure xvv_loadsymbols (s)
+
+char s[ARB] #I symbol list "|sym1|sym2|...|"
+
+int delim, symnum, ip
+pointer sp, symname, st, sym, op
+pointer stopen(), stenter()
+
+begin
+ call smark (sp)
+ call salloc (symname, SZ_FNAME, TY_CHAR)
+
+ st = stopen ("evvexpr", LEN_INDEX, LEN_STAB, LEN_SBUF)
+ delim = s[1]
+ symnum = 0
+
+ for (ip=2; s[ip] != EOS; ip=ip+1) {
+ op = symname
+ while (s[ip] != delim && s[ip] != EOS) {
+ Memc[op] = s[ip]
+ op = op + 1
+ ip = ip + 1
+ }
+ Memc[op] = EOS
+ symnum = symnum + 1
+
+ if (op > symname && IS_ALPHA(Memc[symname])) {
+ sym = stenter (st, Memc[symname], LEN_SYM)
+ SYM_CODE(sym) = symnum
+ }
+ }
+
+ call sfree (sp)
+ return (st)
+end
+
+
+# XVV_NULL -- Return a null value to be used when a computation cannot be
+# performed and range checking is enabled. Perhaps we should permit a user
+# specified value here, however this doesn't really work in an expression
+# evaluator since the value generated may be used in subsequent calculations
+# and hence may change. If more careful treatment of out of range values
+# is needed a conditional expression can be used in which case the value
+# we return here is ignored (but still needed to avoid a hardware exception
+# when computing a vector).
+
+
+short procedure xvv_nulls (ignore)
+short ignore #I ignored
+begin
+ return (0)
+end
+
+int procedure xvv_nulli (ignore)
+int ignore #I ignored
+begin
+ return (0)
+end
+
+long procedure xvv_nulll (ignore)
+long ignore #I ignored
+begin
+ return (0)
+end
+
+real procedure xvv_nullr (ignore)
+real ignore #I ignored
+begin
+ return (0.0)
+end
+
+double procedure xvv_nulld (ignore)
+double ignore #I ignored
+begin
+ return (0.0D0)
+end
+
+define YYNPROD 39
+define YYLAST 303
+# line 1 "/iraf/iraf/lib/yaccpar.x"
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# Parser for yacc output, translated to the IRAF SPP language. The contents
+# of this file form the bulk of the source of the parser produced by Yacc.
+# Yacc recognizes several macros in the yaccpar input source and replaces
+# them as follows:
+# A user suppled "global" definitions and declarations
+# B parser tables
+# C user supplied actions (reductions)
+# The remainder of the yaccpar code is not changed.
+
+define yystack_ 10 # statement labels for gotos
+define yynewstate_ 20
+define yydefault_ 30
+define yyerrlab_ 40
+define yyabort_ 50
+
+define YYFLAG (-1000) # defs used in user actions
+define YYERROR goto yyerrlab_
+define YYACCEPT return (OK)
+define YYABORT return (ERR)
+
+
+# YYPARSE -- Parse the input stream, returning OK if the source is
+# syntactically acceptable (i.e., if compilation is successful),
+# otherwise ERR. The parameters YYMAXDEPTH and YYOPLEN must be
+# supplied by the caller in the %{ ... %} section of the Yacc source.
+# The token value stack is a dynamically allocated array of operand
+# structures, with the length and makeup of the operand structure being
+# application dependent.
+
+int procedure yyparse (fd, yydebug, yylex)
+
+int fd # stream to be parsed
+bool yydebug # print debugging information?
+int yylex() # user-supplied lexical input function
+extern yylex()
+
+short yys[YYMAXDEPTH] # parser stack -- stacks tokens
+pointer yyv # pointer to token value stack
+pointer yyval # value returned by action
+pointer yylval # value of token
+int yyps # token stack pointer
+pointer yypv # value stack pointer
+int yychar # current input token number
+int yyerrflag # error recovery flag
+int yynerrs # number of errors
+
+short yyj, yym # internal variables
+pointer yysp, yypvt
+short yystate, yyn
+int yyxi, i
+errchk salloc, yylex
+
+
+# XVV_PARSE -- SPP/Yacc parser for the evaluation of an expression passed as
+# a text string. Expression evaluation is carried out as the expression is
+# parsed, rather than being broken into separate compile and execute stages.
+# There is only one statement in this grammar, the expression. Our function
+# is to reduce an expression to a single value of type bool, string, int,
+# or real.
+
+pointer ap
+bool streq()
+errchk zcall3, xvv_error1, xvv_unop, xvv_binop, xvv_boolop
+errchk xvv_quest, xvv_callfcn, xvv_addarg
+include "evvexpr.com"
+
+short yyexca[96]
+data (yyexca(i),i= 1, 8) / -1, 1, 0, -1, -2, 0, -1, 5/
+data (yyexca(i),i= 9, 16) / 40, 33, -2, 5, -1, 6, 40, 32/
+data (yyexca(i),i= 17, 24) / -2, 6, -1, 76, 269, 0, 270, 0/
+data (yyexca(i),i= 25, 32) / 271, 0, 283, 0, -2, 22, -1, 77/
+data (yyexca(i),i= 33, 40) / 269, 0, 270, 0, 271, 0, 283, 0/
+data (yyexca(i),i= 41, 48) / -2, 23, -1, 78, 269, 0, 270, 0/
+data (yyexca(i),i= 49, 56) / 271, 0, 283, 0, -2, 24, -1, 79/
+data (yyexca(i),i= 57, 64) / 269, 0, 270, 0, 271, 0, 283, 0/
+data (yyexca(i),i= 65, 72) / -2, 25, -1, 80, 272, 0, 273, 0/
+data (yyexca(i),i= 73, 80) / 274, 0, -2, 26, -1, 81, 272, 0/
+data (yyexca(i),i= 81, 88) / 273, 0, 274, 0, -2, 27, -1, 82/
+data (yyexca(i),i= 89, 96) / 272, 0, 273, 0, 274, 0, -2, 28/
+short yyact[303]
+data (yyact(i),i= 1, 8) / 15, 16, 17, 18, 19, 20, 33, 86/
+data (yyact(i),i= 9, 16) / 26, 27, 28, 30, 32, 31, 21, 22/
+data (yyact(i),i= 17, 24) / 62, 23, 24, 25, 19, 34, 29, 15/
+data (yyact(i),i= 25, 32) / 16, 17, 18, 19, 20, 33, 38, 26/
+data (yyact(i),i= 33, 40) / 27, 28, 30, 32, 31, 21, 22, 60/
+data (yyact(i),i= 41, 48) / 23, 24, 25, 12, 11, 29, 15, 16/
+data (yyact(i),i= 49, 56) / 17, 18, 19, 20, 12, 2, 26, 27/
+data (yyact(i),i= 57, 64) / 28, 30, 32, 31, 12, 1, 0, 23/
+data (yyact(i),i= 65, 72) / 24, 25, 0, 14, 29, 15, 16, 17/
+data (yyact(i),i= 73, 80) / 18, 19, 20, 0, 0, 26, 27, 28/
+data (yyact(i),i= 81, 88) / 30, 32, 31, 0, 15, 16, 17, 18/
+data (yyact(i),i= 89, 96) / 19, 20, 0, 29, 26, 27, 28, 15/
+data (yyact(i),i= 97,104) / 16, 17, 18, 19, 20, 15, 16, 17/
+data (yyact(i),i=105,112) / 18, 19, 29, 17, 18, 19, 4, 0/
+data (yyact(i),i=113,120) / 84, 0, 40, 85, 0, 0, 0, 35/
+data (yyact(i),i=121,128) / 36, 37, 0, 39, 0, 0, 0, 0/
+data (yyact(i),i=129,136) / 0, 0, 41, 42, 43, 44, 45, 46/
+data (yyact(i),i=137,144) / 47, 48, 49, 50, 51, 52, 53, 54/
+data (yyact(i),i=145,152) / 55, 56, 57, 58, 59, 61, 0, 63/
+data (yyact(i),i=153,160) / 65, 66, 67, 68, 69, 70, 71, 72/
+data (yyact(i),i=161,168) / 73, 74, 75, 76, 77, 78, 79, 80/
+data (yyact(i),i=169,176) / 81, 82, 83, 0, 0, 0, 0, 0/
+data (yyact(i),i=177,184) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=185,192) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=193,200) / 0, 0, 0, 0, 0, 0, 89, 90/
+data (yyact(i),i=201,208) / 87, 88, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=209,216) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=217,224) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=225,232) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yyact(i),i=233,240) / 0, 0, 0, 0, 15, 16, 17, 18/
+data (yyact(i),i=241,248) / 19, 20, 33, 0, 26, 27, 28, 30/
+data (yyact(i),i=249,256) / 32, 31, 21, 22, 0, 23, 24, 25/
+data (yyact(i),i=257,264) / 0, 0, 29, 0, 5, 6, 64, 0/
+data (yyact(i),i=265,272) / 0, 8, 0, 0, 3, 5, 6, 0/
+data (yyact(i),i=273,280) / 0, 0, 8, 0, 0, 5, 6, 0/
+data (yyact(i),i=281,288) / 9, 0, 8, 13, 10, 7, 0, 0/
+data (yyact(i),i=289,296) / 0, 9, 0, 0, 0, 10, 7, 0/
+data (yyact(i),i=297,303) / 0, 9, 0, 0, 0, 10, 7/
+short yypact[91]
+data (yypact(i),i= 1, 8) / 12,-1000, 23,-1000,-238,-1000,-1000,-236/
+data (yypact(i),i= 9, 16) / 20, 20, 20, -10, 20,-1000,-1000,-1000/
+data (yypact(i),i= 17, 24) /-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i= 25, 32) /-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000/
+data (yypact(i),i= 33, 40) /-1000,-1000,-1000,-245,-245,-245, 20, -25/
+data (yypact(i),i= 41, 48) / 3, 3, 3, 3, 3, 3, 3, 3/
+data (yypact(i),i= 49, 56) / 3, 3, 3, 3, 3, 3, 3, 3/
+data (yypact(i),i= 57, 64) / 3, 3, 3, 3, 71,-238,-1000,-238/
+data (yypact(i),i= 65, 72) /-1000,-156,-156,-245,-245,-1000,-160,-215/
+data (yypact(i),i= 73, 80) /-215,-192,-192,-192,-166,-166,-166,-166/
+data (yypact(i),i= 81, 88) /-177,-177,-177,-261,-1000,-1000,-1000, 3/
+data (yypact(i),i= 89, 91) / 3,-238,-238/
+short yypgo[7]
+data (yypgo(i),i= 1, 7) / 0, 61, 53, 110, 114, 44, 39/
+short yyr1[39]
+data (yyr1(i),i= 1, 8) / 0, 1, 1, 2, 2, 3, 3, 3/
+data (yyr1(i),i= 9, 16) / 3, 3, 3, 3, 3, 3, 3, 3/
+data (yyr1(i),i= 17, 24) / 3, 3, 3, 3, 3, 3, 3, 3/
+data (yyr1(i),i= 25, 32) / 3, 3, 3, 3, 3, 3, 3, 3/
+data (yyr1(i),i= 33, 39) / 5, 5, 6, 6, 6, 4, 4/
+short yyr2[39]
+data (yyr2(i),i= 1, 8) / 0, 2, 1, 1, 4, 1, 1, 2/
+data (yyr2(i),i= 9, 16) / 2, 2, 2, 4, 4, 4, 4, 4/
+data (yyr2(i),i= 17, 24) / 4, 4, 4, 4, 4, 4, 4, 4/
+data (yyr2(i),i= 25, 32) / 4, 4, 4, 4, 4, 7, 4, 3/
+data (yyr2(i),i= 33, 39) / 1, 1, 0, 1, 4, 0, 2/
+short yychk[91]
+data (yychk(i),i= 1, 8) /-1000, -1, -2, 256, -3, 257, 258, 282/
+data (yychk(i),i= 9, 16) / 262, 277, 281, -5, 40, 260, 44, 261/
+data (yychk(i),i= 17, 24) / 262, 263, 264, 265, 266, 275, 276, 278/
+data (yychk(i),i= 25, 32) / 279, 280, 269, 270, 271, 283, 272, 274/
+data (yychk(i),i= 33, 40) / 273, 267, 257, -3, -3, -3, 40, -3/
+data (yychk(i),i= 41, 48) / -4, -4, -4, -4, -4, -4, -4, -4/
+data (yychk(i),i= 49, 56) / -4, -4, -4, -4, -4, -4, -4, -4/
+data (yychk(i),i= 57, 64) / -4, -4, -4, -4, -6, -3, 41, -3/
+data (yychk(i),i= 65, 72) / 259, -3, -3, -3, -3, -3, -3, -3/
+data (yychk(i),i= 73, 80) / -3, -3, -3, -3, -3, -3, -3, -3/
+data (yychk(i),i= 81, 88) / -3, -3, -3, -3, 41, 44, 268, -4/
+data (yychk(i),i= 89, 91) / -4, -3, -3/
+short yydef[91]
+data (yydef(i),i= 1, 8) / 0, -2, 0, 2, 3, -2, -2, 0/
+data (yydef(i),i= 9, 16) / 0, 0, 0, 0, 0, 1, 37, 37/
+data (yydef(i),i= 17, 24) / 37, 37, 37, 37, 37, 37, 37, 37/
+data (yydef(i),i= 25, 32) / 37, 37, 37, 37, 37, 37, 37, 37/
+data (yydef(i),i= 33, 40) / 37, 37, 7, 8, 9, 10, 34, 0/
+data (yydef(i),i= 41, 48) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yydef(i),i= 49, 56) / 0, 0, 0, 0, 0, 0, 0, 0/
+data (yydef(i),i= 57, 64) / 0, 0, 0, 0, 0, 35, 31, 4/
+data (yydef(i),i= 65, 72) / 38, 11, 12, 13, 14, 15, 16, 17/
+data (yydef(i),i= 73, 80) / 18, 19, 20, 21, -2, -2, -2, -2/
+data (yydef(i),i= 81, 88) / -2, -2, -2, 0, 30, 37, 37, 0/
+data (yydef(i),i= 89, 91) / 0, 36, 29/
+
+begin
+ call smark (yysp)
+ call salloc (yyv, (YYMAXDEPTH+2) * YYOPLEN, TY_STRUCT)
+
+ # Initialization. The first element of the dynamically allocated
+ # token value stack (yyv) is used for yyval, the second for yylval,
+ # and the actual stack starts with the third element.
+
+ yystate = 0
+ yychar = -1
+ yynerrs = 0
+ yyerrflag = 0
+ yyps = 0
+ yyval = yyv
+ yylval = yyv + YYOPLEN
+ yypv = yylval
+
+yystack_
+ # SHIFT -- Put a state and value onto the stack. The token and
+ # value stacks are logically the same stack, implemented as two
+ # separate arrays.
+
+ if (yydebug) {
+ call printf ("state %d, char 0%o\n")
+ call pargs (yystate)
+ call pargi (yychar)
+ }
+ yyps = yyps + 1
+ yypv = yypv + YYOPLEN
+ if (yyps > YYMAXDEPTH) {
+ call sfree (yysp)
+ call eprintf ("yacc stack overflow\n")
+ return (ERR)
+ }
+ yys[yyps] = yystate
+ YYMOVE (yyval, yypv)
+
+yynewstate_
+ # Process the new state.
+ yyn = yypact[yystate+1]
+
+ if (yyn <= YYFLAG)
+ goto yydefault_ # simple state
+
+ # The variable "yychar" is the lookahead token.
+ if (yychar < 0) {
+ yychar = yylex (fd, yylval)
+ if (yychar < 0)
+ yychar = 0
+ }
+ yyn = yyn + yychar
+ if (yyn < 0 || yyn >= YYLAST)
+ goto yydefault_
+
+ yyn = yyact[yyn+1]
+ if (yychk[yyn+1] == yychar) { # valid shift
+ yychar = -1
+ YYMOVE (yylval, yyval)
+ yystate = yyn
+ if (yyerrflag > 0)
+ yyerrflag = yyerrflag - 1
+ goto yystack_
+ }
+
+yydefault_
+ # Default state action.
+
+ yyn = yydef[yystate+1]
+ if (yyn == -2) {
+ if (yychar < 0) {
+ yychar = yylex (fd, yylval)
+ if (yychar < 0)
+ yychar = 0
+ }
+
+ # Look through exception table.
+ yyxi = 1
+ while ((yyexca[yyxi] != (-1)) || (yyexca[yyxi+1] != yystate))
+ yyxi = yyxi + 2
+ for (yyxi=yyxi+2; yyexca[yyxi] >= 0; yyxi=yyxi+2) {
+ if (yyexca[yyxi] == yychar)
+ break
+ }
+
+ yyn = yyexca[yyxi+1]
+ if (yyn < 0) {
+ call sfree (yysp)
+ return (OK) # ACCEPT -- all done
+ }
+ }
+
+
+ # SYNTAX ERROR -- resume parsing if possible.
+
+ if (yyn == 0) {
+ switch (yyerrflag) {
+ case 0, 1, 2:
+ if (yyerrflag == 0) { # brand new error
+ call eprintf ("syntax error\n")
+yyerrlab_
+ yynerrs = yynerrs + 1
+ # fall through...
+ }
+
+ # case 1:
+ # case 2: incompletely recovered error ... try again
+ yyerrflag = 3
+
+ # Find a state where "error" is a legal shift action.
+ while (yyps >= 1) {
+ yyn = yypact[yys[yyps]+1] + YYERRCODE
+ if ((yyn >= 0) && (yyn < YYLAST) &&
+ (yychk[yyact[yyn+1]+1] == YYERRCODE)) {
+ # Simulate a shift of "error".
+ yystate = yyact[yyn+1]
+ goto yystack_
+ }
+ yyn = yypact[yys[yyps]+1]
+
+ # The current yyps has no shift on "error", pop stack.
+ if (yydebug) {
+ call printf ("error recovery pops state %d, ")
+ call pargs (yys[yyps])
+ call printf ("uncovers %d\n")
+ call pargs (yys[yyps-1])
+ }
+ yyps = yyps - 1
+ yypv = yypv - YYOPLEN
+ }
+
+ # ABORT -- There is no state on the stack with an error shift.
+yyabort_
+ call sfree (yysp)
+ return (ERR)
+
+
+ case 3: # No shift yet; clobber input char.
+
+ if (yydebug) {
+ call printf ("error recovery discards char %d\n")
+ call pargi (yychar)
+ }
+
+ if (yychar == 0)
+ goto yyabort_ # don't discard EOF, quit
+ yychar = -1
+ goto yynewstate_ # try again in the same state
+ }
+ }
+
+
+ # REDUCE -- Reduction by production yyn.
+
+ if (yydebug) {
+ call printf ("reduce %d\n")
+ call pargs (yyn)
+ }
+ yyps = yyps - yyr2[yyn+1]
+ yypvt = yypv
+ yypv = yypv - yyr2[yyn+1] * YYOPLEN
+ YYMOVE (yypv + YYOPLEN, yyval)
+ yym = yyn
+
+ # Consult goto table to find next state.
+ yyn = yyr1[yyn+1]
+ yyj = yypgo[yyn+1] + yys[yyps] + 1
+ if (yyj >= YYLAST)
+ yystate = yyact[yypgo[yyn+1]+1]
+ else {
+ yystate = yyact[yyj+1]
+ if (yychk[yystate+1] != -yyn)
+ yystate = yyact[yypgo[yyn+1]+1]
+ }
+
+ # Perform action associated with the grammar rule, if any.
+ switch (yym) {
+
+case 1:
+# line 266 "evvexpr.y"
+{
+ # Normal exit. Move the final expression value operand
+ # into the operand structure pointed to by the global
+ # variable ev_oval.
+
+ YYMOVE (yypvt-YYOPLEN, ev_oval)
+ call sfree (yysp)
+ return (OK)
+ }
+case 2:
+# line 275 "evvexpr.y"
+{
+ call error (1, "syntax error")
+ }
+case 3:
+# line 280 "evvexpr.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 4:
+# line 283 "evvexpr.y"
+{
+ YYMOVE (yypvt, yyval)
+ call xvv_freeop (yypvt-3*YYOPLEN)
+ }
+case 5:
+# line 289 "evvexpr.y"
+{
+ # Numeric constant.
+ YYMOVE (yypvt, yyval)
+ }
+case 6:
+# line 293 "evvexpr.y"
+{
+ # The boolean constants "yes" and "no" are implemented
+ # as reserved operands.
+
+ call xvv_initop (yyval, 0, TY_BOOL)
+ if (streq (O_VALC(yypvt), "yes")) {
+ O_VALI(yyval) = YES
+ } else if (streq (O_VALC(yypvt), "no")) {
+ O_VALI(yyval) = NO
+ } else if (ev_getop != NULL) {
+ call zcall3 (ev_getop,ev_getop_data, O_VALC(yypvt), yyval)
+ if (O_TYPE(yyval) <= 0)
+ call xvv_error1 ("unknown operand `%s'",
+ O_VALC(yypvt))
+ } else
+ call xvv_error1 ("illegal operand `%s'", O_VALC(yypvt))
+ call xvv_freeop (yypvt)
+ }
+case 7:
+# line 311 "evvexpr.y"
+{
+ # e.g., @"param"
+ if (ev_getop != NULL) {
+ call zcall3 (ev_getop,ev_getop_data, O_VALC(yypvt), yyval)
+ if (O_TYPE(yyval) <= 0)
+ call xvv_error1 ("unknown operand `%s'",
+ O_VALC(yypvt-YYOPLEN))
+ } else
+ call xvv_error1 ("illegal operand `%s'", O_VALC(yypvt))
+ call xvv_freeop (yypvt)
+ }
+case 8:
+# line 322 "evvexpr.y"
+{
+ # Unary arithmetic minus.
+ call xvv_unop (MINUS, yypvt, yyval)
+ }
+case 9:
+# line 326 "evvexpr.y"
+{
+ # Logical not.
+ call xvv_unop (LNOT, yypvt, yyval)
+ }
+case 10:
+# line 330 "evvexpr.y"
+{
+ # Boolean not.
+ call xvv_unop (BNOT, yypvt, yyval)
+ }
+case 11:
+# line 334 "evvexpr.y"
+{
+ # Addition.
+ call xvv_binop (PLUS, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 12:
+# line 338 "evvexpr.y"
+{
+ # Subtraction.
+ call xvv_binop (MINUS, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 13:
+# line 342 "evvexpr.y"
+{
+ # Multiplication.
+ call xvv_binop (STAR, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 14:
+# line 346 "evvexpr.y"
+{
+ # Division.
+ call xvv_binop (SLASH, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 15:
+# line 350 "evvexpr.y"
+{
+ # Exponentiation.
+ call xvv_binop (EXPON, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 16:
+# line 354 "evvexpr.y"
+{
+ # Concatenate two operands.
+ call xvv_binop (CONCAT, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 17:
+# line 358 "evvexpr.y"
+{
+ # Logical and.
+ call xvv_boolop (LAND, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 18:
+# line 362 "evvexpr.y"
+{
+ # Logical or.
+ call xvv_boolop (LOR, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 19:
+# line 366 "evvexpr.y"
+{
+ # Boolean and.
+ call xvv_binop (BAND, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 20:
+# line 370 "evvexpr.y"
+{
+ # Boolean or.
+ call xvv_binop (BOR, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 21:
+# line 374 "evvexpr.y"
+{
+ # Boolean xor.
+ call xvv_binop (BXOR, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 22:
+# line 378 "evvexpr.y"
+{
+ # Boolean less than.
+ call xvv_boolop (LT, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 23:
+# line 382 "evvexpr.y"
+{
+ # Boolean greater than.
+ call xvv_boolop (GT, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 24:
+# line 386 "evvexpr.y"
+{
+ # Boolean less than or equal.
+ call xvv_boolop (LE, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 25:
+# line 390 "evvexpr.y"
+{
+ # Boolean greater than or equal.
+ call xvv_boolop (GE, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 26:
+# line 394 "evvexpr.y"
+{
+ # Boolean equal.
+ call xvv_boolop (EQ, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 27:
+# line 398 "evvexpr.y"
+{
+ # String pattern-equal.
+ call xvv_boolop (SE, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 28:
+# line 402 "evvexpr.y"
+{
+ # Boolean not equal.
+ call xvv_boolop (NE, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 29:
+# line 406 "evvexpr.y"
+{
+ # Conditional expression.
+ call xvv_quest (yypvt-6*YYOPLEN, yypvt-3*YYOPLEN, yypvt, yyval)
+ }
+case 30:
+# line 410 "evvexpr.y"
+{
+ # Call an intrinsic or external function.
+ ap = O_VALP(yypvt-YYOPLEN)
+ call xvv_callfcn (O_VALC(yypvt-3*YYOPLEN),
+ A_ARGP(ap,1), A_NARGS(ap), yyval)
+ call xvv_freeop (yypvt-3*YYOPLEN)
+ call xvv_freeop (yypvt-YYOPLEN)
+ }
+case 31:
+# line 418 "evvexpr.y"
+{
+ YYMOVE (yypvt-YYOPLEN, yyval)
+ }
+case 32:
+# line 424 "evvexpr.y"
+{
+ YYMOVE (yypvt, yyval)
+ }
+case 33:
+# line 427 "evvexpr.y"
+{
+ if (O_TYPE(yypvt) != TY_CHAR)
+ call error (1, "illegal function name")
+ YYMOVE (yypvt, yyval)
+ }
+case 34:
+# line 435 "evvexpr.y"
+{
+ # Empty.
+ call xvv_startarglist (NULL, yyval)
+ }
+case 35:
+# line 439 "evvexpr.y"
+{
+ # First arg; start a nonnull list.
+ call xvv_startarglist (yypvt, yyval)
+ }
+case 36:
+# line 443 "evvexpr.y"
+{
+ # Add an argument to an existing list.
+ call xvv_addarg (yypvt, yypvt-3*YYOPLEN, yyval)
+ } }
+
+ goto yystack_ # stack new state and value
+end