Blame


1 c734c0e9 2021-08-03 op /*
2 c734c0e9 2021-08-03 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 c734c0e9 2021-08-03 op *
4 c734c0e9 2021-08-03 op * Permission to use, copy, modify, and distribute this software for any
5 c734c0e9 2021-08-03 op * purpose with or without fee is hereby granted, provided that the above
6 c734c0e9 2021-08-03 op * copyright notice and this permission notice appear in all copies.
7 c734c0e9 2021-08-03 op *
8 c734c0e9 2021-08-03 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 c734c0e9 2021-08-03 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 c734c0e9 2021-08-03 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 c734c0e9 2021-08-03 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 c734c0e9 2021-08-03 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 c734c0e9 2021-08-03 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 c734c0e9 2021-08-03 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 c734c0e9 2021-08-03 op */
16 c734c0e9 2021-08-03 op
17 c734c0e9 2021-08-03 op #include "compat.h"
18 c734c0e9 2021-08-03 op
19 c734c0e9 2021-08-03 op #include <assert.h>
20 c734c0e9 2021-08-03 op #include <inttypes.h>
21 c734c0e9 2021-08-03 op #include <stdio.h>
22 c734c0e9 2021-08-03 op #include <stdlib.h>
23 c734c0e9 2021-08-03 op #include <string.h>
24 c734c0e9 2021-08-03 op #include <syslog.h>
25 c734c0e9 2021-08-03 op
26 c734c0e9 2021-08-03 op #include "utils.h"
27 c734c0e9 2021-08-03 op #include "script.h"
28 c734c0e9 2021-08-03 op #include "log.h"
29 c734c0e9 2021-08-03 op
30 c734c0e9 2021-08-03 op #define DEBUG 0
31 c734c0e9 2021-08-03 op
32 c734c0e9 2021-08-03 op static struct procs procs = TAILQ_HEAD_INITIALIZER(procs);
33 c734c0e9 2021-08-03 op static struct tests tests = TAILQ_HEAD_INITIALIZER(tests);
34 c734c0e9 2021-08-03 op
35 c734c0e9 2021-08-03 op static struct proc *curr_proc;
36 c734c0e9 2021-08-03 op static struct test *curr_test;
37 c734c0e9 2021-08-03 op
38 c734c0e9 2021-08-03 op static struct op *curr_block;
39 c734c0e9 2021-08-03 op
40 c734c0e9 2021-08-03 op static struct op *curr_argv;
41 c734c0e9 2021-08-03 op static int curr_argc;
42 c734c0e9 2021-08-03 op
43 c734c0e9 2021-08-03 op #define STACK_HEIGHT 16
44 c734c0e9 2021-08-03 op static struct value vstack[STACK_HEIGHT];
45 c734c0e9 2021-08-03 op static int stackh;
46 c734c0e9 2021-08-03 op
47 c734c0e9 2021-08-03 op static struct value v_false = {.type = V_NUM, .v = {.num = 0}};
48 c734c0e9 2021-08-03 op static struct value v_true = {.type = V_NUM, .v = {.num = 1}};
49 c734c0e9 2021-08-03 op
50 c734c0e9 2021-08-03 op void
51 c734c0e9 2021-08-03 op global_set(char *sym, struct op *op)
52 c734c0e9 2021-08-03 op {
53 c734c0e9 2021-08-03 op assert(op->type == OP_LITERAL);
54 c734c0e9 2021-08-03 op }
55 c734c0e9 2021-08-03 op
56 c734c0e9 2021-08-03 op struct op *
57 c734c0e9 2021-08-03 op newop(int type)
58 c734c0e9 2021-08-03 op {
59 c734c0e9 2021-08-03 op struct op *op;
60 c734c0e9 2021-08-03 op
61 c734c0e9 2021-08-03 op op = xcalloc(1, sizeof(*op));
62 c734c0e9 2021-08-03 op op->type = type;
63 c734c0e9 2021-08-03 op
64 c734c0e9 2021-08-03 op return op;
65 c734c0e9 2021-08-03 op }
66 c734c0e9 2021-08-03 op
67 c734c0e9 2021-08-03 op void
68 c734c0e9 2021-08-03 op free_op(struct op *op)
69 c734c0e9 2021-08-03 op {
70 c734c0e9 2021-08-03 op /* TODO: probably more... */
71 c734c0e9 2021-08-03 op free(op);
72 c734c0e9 2021-08-03 op }
73 c734c0e9 2021-08-03 op
74 c734c0e9 2021-08-03 op struct op *
75 c734c0e9 2021-08-03 op op_assign(char *sym, struct op *expr)
76 c734c0e9 2021-08-03 op {
77 c734c0e9 2021-08-03 op struct op *op;
78 c734c0e9 2021-08-03 op
79 c734c0e9 2021-08-03 op op = newop(OP_ASSIGN);
80 c734c0e9 2021-08-03 op op->v.assign.name = sym;
81 c734c0e9 2021-08-03 op op->v.assign.expr = expr;
82 c734c0e9 2021-08-03 op
83 c734c0e9 2021-08-03 op return op;
84 c734c0e9 2021-08-03 op }
85 c734c0e9 2021-08-03 op
86 c734c0e9 2021-08-03 op struct op *
87 c734c0e9 2021-08-03 op op_assert(struct op *expr)
88 c734c0e9 2021-08-03 op {
89 c734c0e9 2021-08-03 op struct op *op;
90 c734c0e9 2021-08-03 op
91 c734c0e9 2021-08-03 op op = newop(OP_ASSERT);
92 c734c0e9 2021-08-03 op op->v.assert = expr;
93 c734c0e9 2021-08-03 op
94 c734c0e9 2021-08-03 op return op;
95 c734c0e9 2021-08-03 op }
96 c734c0e9 2021-08-03 op
97 c734c0e9 2021-08-03 op struct op *
98 c734c0e9 2021-08-03 op op_var(char *sym)
99 c734c0e9 2021-08-03 op {
100 c734c0e9 2021-08-03 op struct op *op;
101 c734c0e9 2021-08-03 op
102 c734c0e9 2021-08-03 op op = newop(OP_VAR);
103 c734c0e9 2021-08-03 op op->v.var = sym;
104 c734c0e9 2021-08-03 op
105 c734c0e9 2021-08-03 op return op;
106 c734c0e9 2021-08-03 op }
107 c734c0e9 2021-08-03 op
108 c734c0e9 2021-08-03 op struct op *
109 c734c0e9 2021-08-03 op op_lit_str(char *str)
110 c734c0e9 2021-08-03 op {
111 c734c0e9 2021-08-03 op struct op *op;
112 c734c0e9 2021-08-03 op
113 c734c0e9 2021-08-03 op op = newop(OP_LITERAL);
114 c734c0e9 2021-08-03 op op->v.literal.type = V_NUM;
115 c734c0e9 2021-08-03 op op->v.literal.v.str = str;
116 c734c0e9 2021-08-03 op
117 c734c0e9 2021-08-03 op return op;
118 c734c0e9 2021-08-03 op }
119 c734c0e9 2021-08-03 op
120 c734c0e9 2021-08-03 op struct op *
121 c734c0e9 2021-08-03 op op_lit_num(uint64_t n)
122 c734c0e9 2021-08-03 op {
123 c734c0e9 2021-08-03 op struct op *op;
124 c734c0e9 2021-08-03 op
125 c734c0e9 2021-08-03 op op = newop(OP_LITERAL);
126 c734c0e9 2021-08-03 op op->v.literal.type = V_NUM;
127 c734c0e9 2021-08-03 op op->v.literal.v.num = n;
128 c734c0e9 2021-08-03 op
129 c734c0e9 2021-08-03 op return op;
130 c734c0e9 2021-08-03 op }
131 c734c0e9 2021-08-03 op
132 c734c0e9 2021-08-03 op struct op *
133 c734c0e9 2021-08-03 op op_cmp_eq(struct op *a, struct op *b)
134 c734c0e9 2021-08-03 op {
135 c734c0e9 2021-08-03 op struct op *op;
136 c734c0e9 2021-08-03 op
137 c734c0e9 2021-08-03 op op = newop(OP_CMP_EQ);
138 c734c0e9 2021-08-03 op op->v.cmp_eq.a = a;
139 c734c0e9 2021-08-03 op op->v.cmp_eq.b = b;
140 c734c0e9 2021-08-03 op
141 c734c0e9 2021-08-03 op return op;
142 c734c0e9 2021-08-03 op }
143 c734c0e9 2021-08-03 op
144 c734c0e9 2021-08-03 op struct op *
145 c734c0e9 2021-08-03 op op_cast(struct op *expr, int totype)
146 c734c0e9 2021-08-03 op {
147 c734c0e9 2021-08-03 op struct op *op;
148 c734c0e9 2021-08-03 op
149 c734c0e9 2021-08-03 op op = newop(OP_CAST);
150 c734c0e9 2021-08-03 op op->v.cast.expr = expr;
151 c734c0e9 2021-08-03 op op->v.cast.totype = totype;
152 c734c0e9 2021-08-03 op
153 c734c0e9 2021-08-03 op return op;
154 c734c0e9 2021-08-03 op }
155 c734c0e9 2021-08-03 op
156 c734c0e9 2021-08-03 op void
157 c734c0e9 2021-08-03 op pp_val(struct value *val)
158 c734c0e9 2021-08-03 op {
159 c734c0e9 2021-08-03 op switch (val->type) {
160 c734c0e9 2021-08-03 op case V_SYM:
161 c734c0e9 2021-08-03 op printf("%s", val->v.str);
162 c734c0e9 2021-08-03 op break;
163 c734c0e9 2021-08-03 op case V_STR:
164 c734c0e9 2021-08-03 op printf("\"%s\"", val->v.str);
165 c734c0e9 2021-08-03 op break;
166 c734c0e9 2021-08-03 op case V_NUM:
167 c734c0e9 2021-08-03 op case V_U8:
168 c734c0e9 2021-08-03 op case V_U16:
169 c734c0e9 2021-08-03 op case V_U32:
170 c734c0e9 2021-08-03 op printf("%"PRIu64, val->v.num);
171 c734c0e9 2021-08-03 op break;
172 c734c0e9 2021-08-03 op default:
173 c734c0e9 2021-08-03 op printf("<unknown value>");
174 c734c0e9 2021-08-03 op break;
175 c734c0e9 2021-08-03 op }
176 c734c0e9 2021-08-03 op }
177 c734c0e9 2021-08-03 op
178 c734c0e9 2021-08-03 op int
179 c734c0e9 2021-08-03 op val_trueish(struct value *a)
180 c734c0e9 2021-08-03 op {
181 c734c0e9 2021-08-03 op return a->type == V_NUM && a->v.num;
182 c734c0e9 2021-08-03 op }
183 c734c0e9 2021-08-03 op
184 c734c0e9 2021-08-03 op static inline int
185 c734c0e9 2021-08-03 op val_isnum(struct value *a)
186 c734c0e9 2021-08-03 op {
187 c734c0e9 2021-08-03 op return a->type == V_NUM
188 c734c0e9 2021-08-03 op || a->type == V_U8
189 c734c0e9 2021-08-03 op || a->type == V_U16
190 c734c0e9 2021-08-03 op || a->type == V_U32;
191 c734c0e9 2021-08-03 op }
192 c734c0e9 2021-08-03 op
193 c734c0e9 2021-08-03 op int
194 c734c0e9 2021-08-03 op val_eq(struct value *a, struct value *b)
195 c734c0e9 2021-08-03 op {
196 c734c0e9 2021-08-03 op if (val_isnum(a) && val_isnum(b))
197 c734c0e9 2021-08-03 op return a->v.num == b->v.num;
198 c734c0e9 2021-08-03 op
199 c734c0e9 2021-08-03 op if (a->type != b->type)
200 c734c0e9 2021-08-03 op return 0;
201 c734c0e9 2021-08-03 op
202 c734c0e9 2021-08-03 op switch (a->type) {
203 c734c0e9 2021-08-03 op case V_STR:
204 c734c0e9 2021-08-03 op case V_SYM:
205 c734c0e9 2021-08-03 op return !strcmp(a->v.str, b->v.str);
206 c734c0e9 2021-08-03 op }
207 c734c0e9 2021-08-03 op
208 c734c0e9 2021-08-03 op return 0;
209 c734c0e9 2021-08-03 op }
210 c734c0e9 2021-08-03 op
211 c734c0e9 2021-08-03 op void
212 c734c0e9 2021-08-03 op pp_op(struct op *op)
213 c734c0e9 2021-08-03 op {
214 c734c0e9 2021-08-03 op switch (op->type) {
215 c734c0e9 2021-08-03 op case OP_ASSIGN:
216 c734c0e9 2021-08-03 op printf("%s = ", op->v.assign.name);
217 c734c0e9 2021-08-03 op pp_op(op->v.assign.expr);
218 c734c0e9 2021-08-03 op break;
219 c734c0e9 2021-08-03 op case OP_ASSERT:
220 c734c0e9 2021-08-03 op printf("assert ");
221 c734c0e9 2021-08-03 op pp_op(op->v.assert);
222 c734c0e9 2021-08-03 op break;
223 c734c0e9 2021-08-03 op case OP_FUNCALL:
224 c734c0e9 2021-08-03 op printf("funcall()");
225 c734c0e9 2021-08-03 op break;
226 c734c0e9 2021-08-03 op case OP_LITERAL:
227 c734c0e9 2021-08-03 op pp_val(&op->v.literal);
228 c734c0e9 2021-08-03 op break;
229 c734c0e9 2021-08-03 op case OP_VAR:
230 c734c0e9 2021-08-03 op printf("%s", op->v.var);
231 c734c0e9 2021-08-03 op break;
232 c734c0e9 2021-08-03 op case OP_CAST:
233 c734c0e9 2021-08-03 op pp_op(op->v.cast.expr);
234 c734c0e9 2021-08-03 op printf(":");
235 c734c0e9 2021-08-03 op switch (op->v.cast.totype) {
236 c734c0e9 2021-08-03 op case V_U8: printf("u8"); break;
237 c734c0e9 2021-08-03 op case V_U16: printf("u16"); break;
238 c734c0e9 2021-08-03 op case V_U32: printf("u32"); break;
239 c734c0e9 2021-08-03 op case V_STR: printf("str"); break;
240 c734c0e9 2021-08-03 op default: printf("???"); break;
241 c734c0e9 2021-08-03 op }
242 c734c0e9 2021-08-03 op break;
243 c734c0e9 2021-08-03 op case OP_CMP_EQ:
244 c734c0e9 2021-08-03 op pp_op(op->v.cmp_eq.a);
245 c734c0e9 2021-08-03 op printf(" == ");
246 c734c0e9 2021-08-03 op pp_op(op->v.cmp_eq.b);
247 c734c0e9 2021-08-03 op break;
248 c734c0e9 2021-08-03 op default:
249 c734c0e9 2021-08-03 op printf(" ???[%d] ", op->type);
250 c734c0e9 2021-08-03 op }
251 c734c0e9 2021-08-03 op }
252 c734c0e9 2021-08-03 op
253 c734c0e9 2021-08-03 op void
254 c734c0e9 2021-08-03 op pp_block(struct op *op)
255 c734c0e9 2021-08-03 op {
256 c734c0e9 2021-08-03 op while (op != NULL) {
257 c734c0e9 2021-08-03 op printf("> ");
258 c734c0e9 2021-08-03 op pp_op(op);
259 c734c0e9 2021-08-03 op printf("\n");
260 c734c0e9 2021-08-03 op
261 c734c0e9 2021-08-03 op op = op->next;
262 c734c0e9 2021-08-03 op }
263 c734c0e9 2021-08-03 op }
264 c734c0e9 2021-08-03 op
265 c734c0e9 2021-08-03 op static inline void
266 c734c0e9 2021-08-03 op popv(struct value *v)
267 c734c0e9 2021-08-03 op {
268 c734c0e9 2021-08-03 op if (stackh == 0)
269 c734c0e9 2021-08-03 op errx(1, "can't pop the stack: underflow");
270 c734c0e9 2021-08-03 op memcpy(v, &vstack[--stackh], sizeof(*v));
271 c734c0e9 2021-08-03 op
272 c734c0e9 2021-08-03 op #if DEBUG
273 c734c0e9 2021-08-03 op printf("popping "); pp_val(v); printf("\n");
274 c734c0e9 2021-08-03 op #endif
275 c734c0e9 2021-08-03 op }
276 c734c0e9 2021-08-03 op
277 c734c0e9 2021-08-03 op static inline void
278 c734c0e9 2021-08-03 op pushv(struct value *v)
279 c734c0e9 2021-08-03 op {
280 c734c0e9 2021-08-03 op if (stackh == STACK_HEIGHT)
281 c734c0e9 2021-08-03 op errx(1, "can't push the stack: overflow");
282 c734c0e9 2021-08-03 op
283 c734c0e9 2021-08-03 op #if DEBUG
284 c734c0e9 2021-08-03 op printf("pushing "); pp_val(v); printf("\n");
285 c734c0e9 2021-08-03 op #endif
286 c734c0e9 2021-08-03 op
287 c734c0e9 2021-08-03 op memcpy(&vstack[stackh++], v, sizeof(*v));
288 c734c0e9 2021-08-03 op }
289 c734c0e9 2021-08-03 op
290 c734c0e9 2021-08-03 op static inline void
291 c734c0e9 2021-08-03 op pushbool(int n)
292 c734c0e9 2021-08-03 op {
293 c734c0e9 2021-08-03 op pushv(n ? &v_true : &v_false);
294 c734c0e9 2021-08-03 op }
295 c734c0e9 2021-08-03 op
296 c734c0e9 2021-08-03 op int
297 c734c0e9 2021-08-03 op eval(struct op *op)
298 c734c0e9 2021-08-03 op {
299 c734c0e9 2021-08-03 op struct value a, b;
300 c734c0e9 2021-08-03 op struct proc *proc;
301 c734c0e9 2021-08-03 op struct op *t;
302 c734c0e9 2021-08-03 op int i, ret;
303 c734c0e9 2021-08-03 op
304 c734c0e9 2021-08-03 op #if DEBUG
305 c734c0e9 2021-08-03 op pp_op(op);
306 c734c0e9 2021-08-03 op printf("\n");
307 c734c0e9 2021-08-03 op #endif
308 c734c0e9 2021-08-03 op
309 c734c0e9 2021-08-03 op switch (op->type) {
310 c734c0e9 2021-08-03 op case OP_ASSIGN:
311 c734c0e9 2021-08-03 op printf("TODO: assignment\n");
312 c734c0e9 2021-08-03 op break;
313 c734c0e9 2021-08-03 op
314 c734c0e9 2021-08-03 op case OP_ASSERT:
315 c734c0e9 2021-08-03 op if ((ret = eval(op->v.assert)) != TEST_PASSED)
316 c734c0e9 2021-08-03 op return ret;
317 c734c0e9 2021-08-03 op popv(&a);
318 c734c0e9 2021-08-03 op if (!val_trueish(&a)) {
319 c734c0e9 2021-08-03 op printf("assertion failed: ");
320 c734c0e9 2021-08-03 op pp_op(op->v.assert);
321 c734c0e9 2021-08-03 op printf("\n");
322 c734c0e9 2021-08-03 op return TEST_FAILED;
323 c734c0e9 2021-08-03 op }
324 c734c0e9 2021-08-03 op break;
325 c734c0e9 2021-08-03 op
326 c734c0e9 2021-08-03 op case OP_FUNCALL:
327 c734c0e9 2021-08-03 op /* TODO: arity check! */
328 c734c0e9 2021-08-03 op
329 c734c0e9 2021-08-03 op for (i = 0; i < op->v.funcall.argc; ++i) {
330 c734c0e9 2021-08-03 op t = &op->v.funcall.argv[i];
331 c734c0e9 2021-08-03 op if ((ret = eval(t)) != TEST_PASSED)
332 c734c0e9 2021-08-03 op return ret;
333 c734c0e9 2021-08-03 op }
334 c734c0e9 2021-08-03 op
335 c734c0e9 2021-08-03 op proc = op->v.funcall.proc;
336 c734c0e9 2021-08-03 op if (proc->nativefn != NULL)
337 c734c0e9 2021-08-03 op proc->nativefn(i);
338 c734c0e9 2021-08-03 op else if ((ret = eval(proc->body)) != TEST_PASSED)
339 c734c0e9 2021-08-03 op return ret;
340 c734c0e9 2021-08-03 op break;
341 c734c0e9 2021-08-03 op
342 c734c0e9 2021-08-03 op case OP_LITERAL:
343 c734c0e9 2021-08-03 op pushv(&op->v.literal);
344 c734c0e9 2021-08-03 op break;
345 c734c0e9 2021-08-03 op
346 c734c0e9 2021-08-03 op case OP_VAR:
347 c734c0e9 2021-08-03 op printf("TODO: load variable\n");
348 c734c0e9 2021-08-03 op break;
349 c734c0e9 2021-08-03 op
350 c734c0e9 2021-08-03 op case OP_CAST:
351 c734c0e9 2021-08-03 op printf("TODO: cast value\n");
352 c734c0e9 2021-08-03 op break;
353 c734c0e9 2021-08-03 op
354 c734c0e9 2021-08-03 op case OP_CMP_EQ:
355 c734c0e9 2021-08-03 op if ((ret = eval(op->v.cmp_eq.a)) != TEST_PASSED)
356 c734c0e9 2021-08-03 op return ret;
357 c734c0e9 2021-08-03 op if ((ret = eval(op->v.cmp_eq.b)) != TEST_PASSED)
358 c734c0e9 2021-08-03 op return ret;
359 c734c0e9 2021-08-03 op
360 c734c0e9 2021-08-03 op popv(&b);
361 c734c0e9 2021-08-03 op popv(&a);
362 c734c0e9 2021-08-03 op pushbool(val_eq(&a, &b));
363 c734c0e9 2021-08-03 op
364 c734c0e9 2021-08-03 op break;
365 c734c0e9 2021-08-03 op
366 c734c0e9 2021-08-03 op default:
367 c734c0e9 2021-08-03 op abort();
368 c734c0e9 2021-08-03 op }
369 c734c0e9 2021-08-03 op
370 c734c0e9 2021-08-03 op if (op->next)
371 c734c0e9 2021-08-03 op return eval(op->next);
372 c734c0e9 2021-08-03 op return TEST_PASSED;
373 c734c0e9 2021-08-03 op }
374 c734c0e9 2021-08-03 op
375 c734c0e9 2021-08-03 op void
376 c734c0e9 2021-08-03 op prepare_funcall(struct op *base)
377 c734c0e9 2021-08-03 op {
378 c734c0e9 2021-08-03 op if (curr_argv != NULL)
379 c734c0e9 2021-08-03 op err(1, "can't funcall during funcall");
380 c734c0e9 2021-08-03 op
381 c734c0e9 2021-08-03 op curr_argv = base;
382 c734c0e9 2021-08-03 op curr_argc = 0;
383 c734c0e9 2021-08-03 op }
384 c734c0e9 2021-08-03 op
385 c734c0e9 2021-08-03 op void
386 c734c0e9 2021-08-03 op push_arg(struct op *op)
387 c734c0e9 2021-08-03 op {
388 c734c0e9 2021-08-03 op curr_argv->next = op;
389 c734c0e9 2021-08-03 op curr_argv = op;
390 c734c0e9 2021-08-03 op curr_argc++;
391 c734c0e9 2021-08-03 op }
392 c734c0e9 2021-08-03 op
393 c734c0e9 2021-08-03 op struct op *
394 c734c0e9 2021-08-03 op op_funcall(struct proc *proc, struct op *base)
395 c734c0e9 2021-08-03 op {
396 c734c0e9 2021-08-03 op struct op *op;
397 c734c0e9 2021-08-03 op
398 c734c0e9 2021-08-03 op op = newop(OP_FUNCALL);
399 c734c0e9 2021-08-03 op op->v.funcall.proc = proc;
400 c734c0e9 2021-08-03 op op->v.funcall.argv = base->next;
401 c734c0e9 2021-08-03 op op->v.funcall.argc = curr_argc;
402 c734c0e9 2021-08-03 op
403 c734c0e9 2021-08-03 op curr_argv = NULL;
404 c734c0e9 2021-08-03 op
405 c734c0e9 2021-08-03 op return op;
406 c734c0e9 2021-08-03 op }
407 c734c0e9 2021-08-03 op
408 c734c0e9 2021-08-03 op void
409 c734c0e9 2021-08-03 op add_builtin_proc(const char *name, int (*fn)(int))
410 c734c0e9 2021-08-03 op {
411 c734c0e9 2021-08-03 op struct proc *proc;
412 c734c0e9 2021-08-03 op
413 c734c0e9 2021-08-03 op proc = xcalloc(1, sizeof(*proc));
414 c734c0e9 2021-08-03 op proc->name = xstrdup(name);
415 c734c0e9 2021-08-03 op proc->nativefn = fn;
416 c734c0e9 2021-08-03 op
417 c734c0e9 2021-08-03 op TAILQ_INSERT_HEAD(&procs, proc, entry);
418 c734c0e9 2021-08-03 op }
419 c734c0e9 2021-08-03 op
420 c734c0e9 2021-08-03 op void
421 c734c0e9 2021-08-03 op prepare_proc(char *name)
422 c734c0e9 2021-08-03 op {
423 c734c0e9 2021-08-03 op if (curr_proc != NULL)
424 c734c0e9 2021-08-03 op err(1, "can't recursively create a proc!");
425 c734c0e9 2021-08-03 op
426 c734c0e9 2021-08-03 op curr_proc = xcalloc(1, sizeof(*curr_proc));
427 c734c0e9 2021-08-03 op curr_proc->name = name;
428 c734c0e9 2021-08-03 op
429 c734c0e9 2021-08-03 op curr_argv = &curr_proc->tmp_args;
430 c734c0e9 2021-08-03 op
431 c734c0e9 2021-08-03 op curr_argv = NULL;
432 c734c0e9 2021-08-03 op curr_argc = 0;
433 c734c0e9 2021-08-03 op }
434 c734c0e9 2021-08-03 op
435 c734c0e9 2021-08-03 op void
436 c734c0e9 2021-08-03 op proc_setup_body(void)
437 c734c0e9 2021-08-03 op {
438 c734c0e9 2021-08-03 op struct op *next, *op = curr_proc->tmp_args.next;
439 c734c0e9 2021-08-03 op int i;
440 c734c0e9 2021-08-03 op
441 c734c0e9 2021-08-03 op i = 0;
442 c734c0e9 2021-08-03 op while (op != NULL) {
443 c734c0e9 2021-08-03 op if (op->type != OP_VAR)
444 c734c0e9 2021-08-03 op errx(1, "invalid argument in proc definition: "
445 c734c0e9 2021-08-03 op "got type %d but want OP_VAR", op->type);
446 c734c0e9 2021-08-03 op assert(i < curr_argc && curr_argc < MAXWELEM);
447 c734c0e9 2021-08-03 op curr_proc->args[i] = xstrdup(op->v.var);
448 c734c0e9 2021-08-03 op next = op->next;
449 c734c0e9 2021-08-03 op free_op(op);
450 c734c0e9 2021-08-03 op }
451 c734c0e9 2021-08-03 op
452 c734c0e9 2021-08-03 op curr_proc->minargs = curr_argc;
453 c734c0e9 2021-08-03 op }
454 c734c0e9 2021-08-03 op
455 c734c0e9 2021-08-03 op void
456 c734c0e9 2021-08-03 op proc_done(void)
457 c734c0e9 2021-08-03 op {
458 c734c0e9 2021-08-03 op TAILQ_INSERT_HEAD(&procs, curr_proc, entry);
459 c734c0e9 2021-08-03 op
460 c734c0e9 2021-08-03 op curr_proc = NULL;
461 c734c0e9 2021-08-03 op }
462 c734c0e9 2021-08-03 op
463 c734c0e9 2021-08-03 op void
464 c734c0e9 2021-08-03 op block_push(struct op *op)
465 c734c0e9 2021-08-03 op {
466 c734c0e9 2021-08-03 op if (curr_block == NULL) {
467 c734c0e9 2021-08-03 op curr_proc->body = op;
468 c734c0e9 2021-08-03 op curr_block = op;
469 c734c0e9 2021-08-03 op } else {
470 c734c0e9 2021-08-03 op curr_block->next = op;
471 c734c0e9 2021-08-03 op curr_block = op;
472 c734c0e9 2021-08-03 op }
473 c734c0e9 2021-08-03 op }
474 c734c0e9 2021-08-03 op
475 c734c0e9 2021-08-03 op struct proc *
476 c734c0e9 2021-08-03 op proc_by_name(const char *name)
477 c734c0e9 2021-08-03 op {
478 c734c0e9 2021-08-03 op struct proc *p;
479 c734c0e9 2021-08-03 op
480 c734c0e9 2021-08-03 op TAILQ_FOREACH(p, &procs, entry) {
481 c734c0e9 2021-08-03 op if (!strcmp(p->name, name))
482 c734c0e9 2021-08-03 op return p;
483 c734c0e9 2021-08-03 op }
484 c734c0e9 2021-08-03 op
485 c734c0e9 2021-08-03 op return NULL;
486 c734c0e9 2021-08-03 op }
487 c734c0e9 2021-08-03 op
488 c734c0e9 2021-08-03 op void
489 c734c0e9 2021-08-03 op prepare_test(char *name, char *dir)
490 c734c0e9 2021-08-03 op {
491 c734c0e9 2021-08-03 op assert(curr_test == NULL);
492 c734c0e9 2021-08-03 op
493 c734c0e9 2021-08-03 op prepare_proc(xstrdup("<test-internal>"));
494 c734c0e9 2021-08-03 op
495 c734c0e9 2021-08-03 op curr_test = xcalloc(1, sizeof(*curr_test));
496 c734c0e9 2021-08-03 op curr_test->name = name;
497 c734c0e9 2021-08-03 op curr_test->dir = dir;
498 c734c0e9 2021-08-03 op curr_test->proc = curr_proc;
499 c734c0e9 2021-08-03 op }
500 c734c0e9 2021-08-03 op
501 c734c0e9 2021-08-03 op void
502 c734c0e9 2021-08-03 op test_done(void)
503 c734c0e9 2021-08-03 op {
504 c734c0e9 2021-08-03 op TAILQ_INSERT_HEAD(&tests, curr_test, entry);
505 c734c0e9 2021-08-03 op curr_test = NULL;
506 c734c0e9 2021-08-03 op }
507 c734c0e9 2021-08-03 op
508 c734c0e9 2021-08-03 op static int
509 c734c0e9 2021-08-03 op builtin_dummy(int argc)
510 c734c0e9 2021-08-03 op {
511 c734c0e9 2021-08-03 op printf("dummy! yay!\n");
512 c734c0e9 2021-08-03 op return 0;
513 c734c0e9 2021-08-03 op }
514 c734c0e9 2021-08-03 op
515 c734c0e9 2021-08-03 op static int
516 c734c0e9 2021-08-03 op run_test(struct test *t)
517 c734c0e9 2021-08-03 op {
518 c734c0e9 2021-08-03 op #if DEBUG
519 c734c0e9 2021-08-03 op puts("=====================");
520 c734c0e9 2021-08-03 op pp_block(t->proc->body);
521 c734c0e9 2021-08-03 op puts("=====================");
522 c734c0e9 2021-08-03 op #endif
523 c734c0e9 2021-08-03 op
524 c734c0e9 2021-08-03 op return eval(t->proc->body);
525 c734c0e9 2021-08-03 op }
526 c734c0e9 2021-08-03 op
527 c734c0e9 2021-08-03 op int
528 c734c0e9 2021-08-03 op main(int argc, char **argv)
529 c734c0e9 2021-08-03 op {
530 c734c0e9 2021-08-03 op struct test *t;
531 c734c0e9 2021-08-03 op int i, passed = 0, failed = 0, skipped = 0;
532 c734c0e9 2021-08-03 op
533 c734c0e9 2021-08-03 op log_init(1, LOG_DAEMON);
534 c734c0e9 2021-08-03 op log_setverbose(1);
535 c734c0e9 2021-08-03 op
536 c734c0e9 2021-08-03 op add_builtin_proc("dummy", builtin_dummy);
537 c734c0e9 2021-08-03 op
538 c734c0e9 2021-08-03 op for (i = 1; i < argc; ++i)
539 c734c0e9 2021-08-03 op loadfile(argv[i]);
540 c734c0e9 2021-08-03 op
541 c734c0e9 2021-08-03 op TAILQ_FOREACH(t, &tests, entry) {
542 c734c0e9 2021-08-03 op switch (run_test(t)) {
543 c734c0e9 2021-08-03 op case TEST_PASSED: passed++; break;
544 c734c0e9 2021-08-03 op case TEST_FAILED: failed++; break;
545 c734c0e9 2021-08-03 op case TEST_SKIPPED: skipped++; break;
546 c734c0e9 2021-08-03 op }
547 c734c0e9 2021-08-03 op }
548 c734c0e9 2021-08-03 op
549 c734c0e9 2021-08-03 op printf("passed = %d\n", passed);
550 c734c0e9 2021-08-03 op printf("failed = %d\n", failed);
551 c734c0e9 2021-08-03 op printf("skipped = %d\n", skipped);
552 c734c0e9 2021-08-03 op
553 c734c0e9 2021-08-03 op return failed != 0;
554 c734c0e9 2021-08-03 op }