Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libdss/cxeval.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* C expression library evaluator
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include "cxlib.h"
29
30
/*
31
* called once before the first cxeval()
32
* there can be multiple cxbeg ... cxeval ... cxend sequences
33
*/
34
35
int
36
cxbeg(Cx_t* cx, register Cxexpr_t* expr, const char* method)
37
{
38
Opt_t opt;
39
int r;
40
char* oid;
41
char* s;
42
char id[64];
43
44
if (expr->begun)
45
return 0;
46
expr->begun = 1;
47
if (expr->query->head)
48
goto head;
49
do
50
{
51
expr->queried = expr->selected = 0;
52
if (expr->pass && cxbeg(cx, expr->pass, method))
53
return -1;
54
if (expr->fail && cxbeg(cx, expr->fail, method))
55
return -1;
56
if (expr->group)
57
{
58
if (cxbeg(cx, expr->group, method))
59
return -1;
60
}
61
else if (method && expr->query->method && !strmatch(expr->query->method, method))
62
{
63
if (cx->disc->errorf)
64
(*cx->disc->errorf)(cx, cx->disc, 2, "%s: %s: method %s expected", expr->query->name, method, expr->query->method);
65
return -1;
66
}
67
else if (expr->query->beg)
68
{
69
head:
70
oid = error_info.id;
71
if (!(s = strchr(oid, ':')))
72
s = oid + strlen(oid);
73
sfsprintf(error_info.id = id, sizeof(id), "%-.*s::%s", s - oid, oid, expr->argv[0]);
74
opt = opt_info;
75
opt_info.index = 0;
76
cx->state->header = (Cxheader_t*)expr->query;
77
cx->expr = expr;
78
r = (*expr->query->beg)(cx, expr, expr->argv, cx->disc);
79
opt_info = opt;
80
error_info.id = oid;
81
if (r)
82
return -1;
83
if (expr->query->head)
84
return 0;
85
}
86
} while (expr = expr->next);
87
return 0;
88
}
89
90
/*
91
* called once after the last cxeval()
92
* there can be multiple cxbeg ... cxeval ... cxend sequences
93
*/
94
95
int
96
cxend(Cx_t* cx, register Cxexpr_t* expr)
97
{
98
if (!expr->begun)
99
return 0;
100
expr->begun = 0;
101
do
102
{
103
if (expr->group)
104
{
105
if (cxend(cx, expr->group))
106
return -1;
107
}
108
else if (expr->query->end)
109
{
110
cx->expr = expr;
111
if ((*expr->query->end)(cx, expr, NiL, cx->disc))
112
return -1;
113
}
114
if (expr->pass && cxend(cx, expr->pass))
115
return -1;
116
if (expr->fail && cxend(cx, expr->fail))
117
return -1;
118
} while (expr = expr->next);
119
return 0;
120
}
121
122
/*
123
* execute program at pc
124
*/
125
126
static int
127
execute(Cx_t* cx, Cxexpr_t* expr, register Cxinstruction_t* pc, void* data, Cxoperand_t* rv, Cxdisc_t* disc)
128
{
129
register Cxoperand_t* sp;
130
register Cxcallout_f f;
131
register Cxoperand_t* so;
132
Cxinstruction_t* pe = pc;
133
Cxoperand_t r;
134
int i;
135
136
sp = expr->stack + 1;
137
sp->type = (sp-1)->type = cx->state->type_void;
138
sp->refs = (sp-1)->refs = 0;
139
for (;;)
140
{
141
r.type = pc->type;
142
r.refs = 0;
143
cx->jump = 1;
144
if (cx->test & 0x0100)
145
cxcodetrace(cx, "eval", pc, pc - pe + 1, expr->stack, sp);
146
if ((i = (*pc->callout)(cx, pc, &r, sp-1, sp, data, disc)) < 0)
147
{
148
if (i < -1)
149
return -1;
150
break;
151
}
152
so = sp;
153
sp += pc->pp;
154
*sp = r;
155
if (expr->reclaim)
156
while (--so > sp)
157
if (!so->refs && (f = cxcallout(cx, CX_DEL, so->type, cx->state->type_void, disc)) && (*f)(cx, pc, &r, NiL, so, data, disc))
158
break;
159
pc += cx->jump;
160
}
161
if (cx->returnf && pc->op == CX_END && (pc-1)->op != CX_SET)
162
{
163
(*cx->returnf)(cx, pc, &r, sp-1, sp, data, disc);
164
if (expr->reclaim && !sp->refs && (f = cxcallout(cx, CX_DEL, sp->type, cx->state->type_void, disc)))
165
{
166
(*f)(cx, pc, &r, NiL, sp, data, disc);
167
sp->type = cx->state->type_number;
168
sp->value.number = 0;
169
}
170
}
171
*rv = *sp;
172
return rv->value.number > 0;
173
}
174
175
/*
176
* evaluate expr
177
*/
178
179
static int
180
eval(Cx_t* cx, register Cxexpr_t* expr, void* data, Cxoperand_t* rv)
181
{
182
int r;
183
int t;
184
185
r = 0;
186
do
187
{
188
expr->queried++;
189
cx->expr = expr;
190
if ((t = expr->group ? eval(cx, expr->group, data, rv) : expr->query->sel ? (*expr->query->sel)(cx, expr, data, cx->disc) : expr->query->prog ? execute(cx, expr, expr->query->prog, data, rv, cx->disc) : 1) < 0)
191
return t;
192
if (t)
193
{
194
expr->selected++;
195
cx->expr = expr;
196
if (expr->query->act && (t = (*expr->query->act)(cx, expr, data, cx->disc)) < 0)
197
return t;
198
if (expr->pass && (t = eval(cx, expr->pass, data, rv)) < 0)
199
return t;
200
}
201
else if (expr->fail && (t = eval(cx, expr->fail, data, rv)) < 0)
202
return t;
203
if (t)
204
r = 1;
205
} while (expr = expr->next);
206
return r;
207
}
208
209
/*
210
* evaluate expr
211
*/
212
213
int
214
cxeval(Cx_t* cx, register Cxexpr_t* expr, void* data, Cxoperand_t* rv)
215
{
216
int r;
217
218
if (!cx->evaluating++)
219
vmclear(cx->em);
220
if ((r = eval(cx, expr, data, rv)) < -1)
221
r = -(r + 2);
222
cx->evaluating--;
223
return r;
224
}
225
226