aboutsummaryrefslogtreecommitdiff
path: root/pkg/utilities/nttools/lib/tbleval.x
blob: c93826990bea386e7c72ba15befb56f70baeca1e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
include	<config.h>
include	<error.h>
include	<evexpr.h>
include	<xwhen.h>
include	"reloperr.h"

# TBL_EVAL -- Evaluate an arbitrary expression over table columns
#
# This procedure receives as input a table descriptor, an index array, and 
# a character string containing an algebraic expression. The terms in the 
# expression are column names. The expression is evaluated for each row in 
# the index array using the values from the indicated columns and the results 
# stored in the output array (aryptr). The array pointed to by nulptr 
# contains null flags. A null flag is set to true if any of the table elements
# in the expression is null or an arithmetic error ocurs during the 
# evaluation of the expression. Otherwise the null flag is set to false. 
# The type of the output array is determined by the type of the expression 
# unless all the elements are null, in which case the type input by the 
# calling routine is used. The two arrays pointed to by aryptr and nulptr 
# must be deallocated by the calling routine.
#
# B.Simon	29-Sept-87	First Code
# B.Simon	16-Dec-87	Changed to handle table subsets
# B.Simon	13-Apr-88	tbl_term, tbl_func moved to separate file

procedure tbl_eval (tp, nindex, index, expr, dtype, aryptr, nulptr)

pointer	tp		#  i: Table descriptor
int	nindex		#  i: Number of elements in index array
int	index[ARB]	#  i: Array of row indices
char	expr[ARB]	#  i: Expression to be evaluated
int	dtype		# io: Type of output array
pointer	aryptr		#  o: Array of output values
pointer	nulptr		#  o: Array of null flags
#--
include	"tblterm.com"

int	iary, status, junk
int	old_handler, tbl_term_adr, tbl_func_adr
pointer	op

string	badtype		"Character expressions not allowed"

int	locpr(), errcode()
pointer	evexpr()

extern	tbl_handler(), tbl_term(), tbl_func()

begin
	# Initialize output variables

	aryptr = NULL
	call malloc (nulptr, nindex, TY_BOOL)

	# Set up error handler to catch arithmetic errors

	call xwhen (X_ARITH, locpr(tbl_handler), old_handler)

	table = tp
	nterm = 0
	constant = true

	tbl_term_adr = locpr (tbl_term)
	tbl_func_adr = locpr (tbl_func)

	# Loop over all rows of the table

	do iary = 1, nindex {

	    irow = index[iary]
	    iterm = 0

	    # Execution will resume here when an arithmetic error occurs

	    call zsvjmp (jumpbuf, status)

	    if (status != OK) {
		Memb[nulptr+iary-1] = true

	    # Special case to speed up the evaluation of constant expressions

	    } else if (constant && (iary != 1)) {
		Memb[nulptr+iary-1] = false
		switch (dtype) {
		case TY_BOOL:
		    Memb[aryptr+iary-1] = Memb[aryptr]
		case TY_INT:
		    Memi[aryptr+iary-1] = Memi[aryptr]
		case TY_REAL:
		    Memr[aryptr+iary-1] = Memr[aryptr]
		}

	    # Evaluate the expression using the values in the current row

	    } else {
		iferr {
		    op = evexpr (expr, tbl_term_adr, tbl_func_adr)
		} then {

		    # Catch the error sent when a table element is null

		    if (errcode() == PUTNULL)
			Memb[nulptr+iary-1] = true
		    else {
			call mfree (nulptr, TY_BOOL)
			call xwhen (X_ARITH, old_handler, junk)
			call erract (EA_ERROR)
		    }

		# Usual case

		} else {

		    Memb[nulptr+iary-1] = false

		    # Determine array type from type of expression

		    if (aryptr == NULL) {
			if (O_TYPE(op) == TY_CHAR) {
			    call mfree (nulptr, TY_BOOL)
			    call xwhen (X_ARITH, old_handler, junk)
			    call error (SYNTAX, badtype)
			}
			dtype = O_TYPE(op)
			call calloc (aryptr, nindex, dtype)
		    }

		    # Assign the result of the expression to the output
		    # array

		    switch (dtype) {
		    case TY_BOOL:
			Memb[aryptr+iary-1] = O_VALB(op)
		    case TY_INT:
			Memi[aryptr+iary-1] = O_VALI(op)
		    case TY_REAL:
			Memr[aryptr+iary-1] = O_VALR(op)
		    }

		    call mfree (op, TY_STRUCT)	# Bug fix (BPS 04.20.93)
		}
	    }
	}

	# Allocate array when all results are null

	if (aryptr == NULL) {
	    if (dtype == TY_CHAR) {
		call mfree (nulptr, TY_BOOL)
		call xwhen (X_ARITH, old_handler, junk)
		call error (SYNTAX, badtype)
	    }
	    call calloc (aryptr, nindex, dtype)
	}
	# Restore old error handler

	call xwhen (X_ARITH, old_handler, junk)

end