2 c734c0e9 2021-08-03 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
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.
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.
17 c734c0e9 2021-08-03 op #include "compat.h"
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>
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"
30 c734c0e9 2021-08-03 op #define DEBUG 0
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);
35 d9d02161 2021-08-04 op static struct opstacks blocks = TAILQ_HEAD_INITIALIZER(blocks);
36 d9d02161 2021-08-04 op static struct opstacks args = TAILQ_HEAD_INITIALIZER(args);
38 c734c0e9 2021-08-03 op #define STACK_HEIGHT 16
39 c734c0e9 2021-08-03 op static struct value vstack[STACK_HEIGHT];
40 c734c0e9 2021-08-03 op static int stackh;
42 c734c0e9 2021-08-03 op static struct value v_false = {.type = V_NUM, .v = {.num = 0}};
43 c734c0e9 2021-08-03 op static struct value v_true = {.type = V_NUM, .v = {.num = 1}};
45 d9d02161 2021-08-04 op static inline struct opstack *
46 d9d02161 2021-08-04 op pushstack(struct opstacks *stack)
48 d9d02161 2021-08-04 op struct opstack *ops;
50 d9d02161 2021-08-04 op ops = xcalloc(1, sizeof(*ops));
51 d9d02161 2021-08-04 op TAILQ_INSERT_HEAD(stack, ops, entry);
55 d9d02161 2021-08-04 op static inline struct opstack *
56 d9d02161 2021-08-04 op peek(struct opstacks *stack)
58 d9d02161 2021-08-04 op if (TAILQ_EMPTY(stack))
59 d9d02161 2021-08-04 op errx(1, "%s: args underflow", __func__);
61 d9d02161 2021-08-04 op return TAILQ_FIRST(stack);
64 d9d02161 2021-08-04 op static inline struct op *
65 d9d02161 2021-08-04 op finalize(struct opstacks *stack, int *argc)
67 d9d02161 2021-08-04 op struct opstack *ops;
68 d9d02161 2021-08-04 op struct op *op;
70 d9d02161 2021-08-04 op if (TAILQ_EMPTY(stack))
71 d9d02161 2021-08-04 op errx(1, "%s: args underflow", __func__);
73 d9d02161 2021-08-04 op ops = peek(stack);
74 d9d02161 2021-08-04 op TAILQ_REMOVE(&args, ops, entry);
75 d9d02161 2021-08-04 op op = ops->base.next;
77 d9d02161 2021-08-04 op if (argc != NULL)
78 d9d02161 2021-08-04 op *argc = ops->counter;
84 d9d02161 2021-08-04 op static inline void
85 d9d02161 2021-08-04 op push(struct opstacks *stack, struct op *op)
87 d9d02161 2021-08-04 op struct opstack *ops;
89 d9d02161 2021-08-04 op ops = peek(stack);
90 d9d02161 2021-08-04 op if (ops->last == NULL) {
91 d9d02161 2021-08-04 op ops->base.next = op;
92 d9d02161 2021-08-04 op ops->last = op;
94 d9d02161 2021-08-04 op ops->last->next = op;
95 d9d02161 2021-08-04 op ops->last = op;
98 d9d02161 2021-08-04 op ops->counter++;
102 c734c0e9 2021-08-03 op global_set(char *sym, struct op *op)
104 c734c0e9 2021-08-03 op assert(op->type == OP_LITERAL);
108 c734c0e9 2021-08-03 op newop(int type)
110 c734c0e9 2021-08-03 op struct op *op;
112 f53af81c 2021-08-04 op op = xcalloc(1, sizeof(*op));
113 c734c0e9 2021-08-03 op op->type = type;
119 c734c0e9 2021-08-03 op free_op(struct op *op)
121 c734c0e9 2021-08-03 op /* TODO: probably more... */
126 c734c0e9 2021-08-03 op op_assign(char *sym, struct op *expr)
128 c734c0e9 2021-08-03 op struct op *op;
130 c734c0e9 2021-08-03 op op = newop(OP_ASSIGN);
131 c734c0e9 2021-08-03 op op->v.assign.name = sym;
132 c734c0e9 2021-08-03 op op->v.assign.expr = expr;
138 c734c0e9 2021-08-03 op op_assert(struct op *expr)
140 c734c0e9 2021-08-03 op struct op *op;
142 c734c0e9 2021-08-03 op op = newop(OP_ASSERT);
143 c734c0e9 2021-08-03 op op->v.assert = expr;
149 c734c0e9 2021-08-03 op op_var(char *sym)
151 c734c0e9 2021-08-03 op struct op *op;
153 c734c0e9 2021-08-03 op op = newop(OP_VAR);
154 c734c0e9 2021-08-03 op op->v.var = sym;
160 c734c0e9 2021-08-03 op op_lit_str(char *str)
162 c734c0e9 2021-08-03 op struct op *op;
164 c734c0e9 2021-08-03 op op = newop(OP_LITERAL);
165 c734c0e9 2021-08-03 op op->v.literal.type = V_NUM;
166 c734c0e9 2021-08-03 op op->v.literal.v.str = str;
172 c734c0e9 2021-08-03 op op_lit_num(uint64_t n)
174 c734c0e9 2021-08-03 op struct op *op;
176 c734c0e9 2021-08-03 op op = newop(OP_LITERAL);
177 c734c0e9 2021-08-03 op op->v.literal.type = V_NUM;
178 c734c0e9 2021-08-03 op op->v.literal.v.num = n;
184 c734c0e9 2021-08-03 op op_cmp_eq(struct op *a, struct op *b)
186 c734c0e9 2021-08-03 op struct op *op;
188 c734c0e9 2021-08-03 op op = newop(OP_CMP_EQ);
189 c734c0e9 2021-08-03 op op->v.cmp_eq.a = a;
190 c734c0e9 2021-08-03 op op->v.cmp_eq.b = b;
196 c734c0e9 2021-08-03 op op_cast(struct op *expr, int totype)
198 c734c0e9 2021-08-03 op struct op *op;
200 c734c0e9 2021-08-03 op op = newop(OP_CAST);
201 c734c0e9 2021-08-03 op op->v.cast.expr = expr;
202 c734c0e9 2021-08-03 op op->v.cast.totype = totype;
208 da4de0c1 2021-08-04 op ppf_val(FILE *f, struct value *val)
210 c734c0e9 2021-08-03 op switch (val->type) {
212 da4de0c1 2021-08-04 op fprintf(f, "%s", val->v.str);
215 da4de0c1 2021-08-04 op fprintf(f, "\"%s\"", val->v.str);
221 da4de0c1 2021-08-04 op fprintf(f, "%"PRIu64, val->v.num);
224 da4de0c1 2021-08-04 op fprintf(f, "<unknown value>");
230 da4de0c1 2021-08-04 op pp_val(struct value *val)
232 da4de0c1 2021-08-04 op ppf_val(stdout, val);
236 c734c0e9 2021-08-03 op val_trueish(struct value *a)
238 c734c0e9 2021-08-03 op return a->type == V_NUM && a->v.num;
241 c734c0e9 2021-08-03 op static inline int
242 c734c0e9 2021-08-03 op val_isnum(struct value *a)
244 c734c0e9 2021-08-03 op return a->type == V_NUM
245 c734c0e9 2021-08-03 op || a->type == V_U8
246 c734c0e9 2021-08-03 op || a->type == V_U16
247 c734c0e9 2021-08-03 op || a->type == V_U32;
251 c734c0e9 2021-08-03 op val_eq(struct value *a, struct value *b)
253 c734c0e9 2021-08-03 op if (val_isnum(a) && val_isnum(b))
254 c734c0e9 2021-08-03 op return a->v.num == b->v.num;
256 c734c0e9 2021-08-03 op if (a->type != b->type)
259 c734c0e9 2021-08-03 op switch (a->type) {
262 c734c0e9 2021-08-03 op return !strcmp(a->v.str, b->v.str);
268 da4de0c1 2021-08-04 op static inline const char *
269 da4de0c1 2021-08-04 op pp_totype(int totype)
272 da4de0c1 2021-08-04 op * Not all of these are valid cast type thought, including
273 da4de0c1 2021-08-04 op * every possibility only to aid debugging.
275 da4de0c1 2021-08-04 op switch (totype) {
276 da4de0c1 2021-08-04 op case V_STR: return "str";
277 da4de0c1 2021-08-04 op case V_SYM: return "sym";
278 da4de0c1 2021-08-04 op case V_NUM: return "num";
279 da4de0c1 2021-08-04 op case V_QID: return "qid";
280 da4de0c1 2021-08-04 op case V_U8: return "u8";
281 da4de0c1 2021-08-04 op case V_U16: return "u16";
282 da4de0c1 2021-08-04 op case V_U32: return "u32";
283 da4de0c1 2021-08-04 op default: return "unknown";
288 da4de0c1 2021-08-04 op val_cast(struct value *a, int totype)
292 da4de0c1 2021-08-04 op #define NUMCAST(v, totype, max) do { \
293 da4de0c1 2021-08-04 op if (v >= max) { \
294 da4de0c1 2021-08-04 op fprintf(stderr, "Can't cast %"PRIu64 \
295 da4de0c1 2021-08-04 op " to %s\n", v, pp_totype(totype)); \
296 da4de0c1 2021-08-04 op return EVAL_ERR; \
298 da4de0c1 2021-08-04 op a->type = totype; \
299 da4de0c1 2021-08-04 op return EVAL_OK; \
302 da4de0c1 2021-08-04 op if (!val_isnum(a)) {
303 da4de0c1 2021-08-04 op fprintf(stderr, "Can't cast ");
304 da4de0c1 2021-08-04 op ppf_val(stderr, a);
305 da4de0c1 2021-08-04 op fprintf(stderr, " to type %s\n", pp_totype(totype));
306 da4de0c1 2021-08-04 op return EVAL_ERR;
309 da4de0c1 2021-08-04 op v = a->v.num;
310 da4de0c1 2021-08-04 op switch (totype) {
311 da4de0c1 2021-08-04 op case V_U8: NUMCAST(v, totype, UINT8_MAX);
312 da4de0c1 2021-08-04 op case V_U16: NUMCAST(v, totype, UINT16_MAX);
313 da4de0c1 2021-08-04 op case V_U32: NUMCAST(v, totype, UINT32_MAX);
315 da4de0c1 2021-08-04 op fprintf(stderr, "Can't cast %"PRIu64" to %s\n",
316 da4de0c1 2021-08-04 op v, pp_totype(totype));
317 da4de0c1 2021-08-04 op return EVAL_ERR;
320 da4de0c1 2021-08-04 op #undef NUMCAST
324 c734c0e9 2021-08-03 op pp_op(struct op *op)
326 c734c0e9 2021-08-03 op switch (op->type) {
327 c734c0e9 2021-08-03 op case OP_ASSIGN:
328 c734c0e9 2021-08-03 op printf("%s = ", op->v.assign.name);
329 c734c0e9 2021-08-03 op pp_op(op->v.assign.expr);
331 c734c0e9 2021-08-03 op case OP_ASSERT:
332 c734c0e9 2021-08-03 op printf("assert ");
333 c734c0e9 2021-08-03 op pp_op(op->v.assert);
335 c734c0e9 2021-08-03 op case OP_FUNCALL:
336 c734c0e9 2021-08-03 op printf("funcall()");
338 c734c0e9 2021-08-03 op case OP_LITERAL:
339 c734c0e9 2021-08-03 op pp_val(&op->v.literal);
342 c734c0e9 2021-08-03 op printf("%s", op->v.var);
344 c734c0e9 2021-08-03 op case OP_CAST:
345 c734c0e9 2021-08-03 op pp_op(op->v.cast.expr);
347 c734c0e9 2021-08-03 op switch (op->v.cast.totype) {
348 c734c0e9 2021-08-03 op case V_U8: printf("u8"); break;
349 c734c0e9 2021-08-03 op case V_U16: printf("u16"); break;
350 c734c0e9 2021-08-03 op case V_U32: printf("u32"); break;
351 c734c0e9 2021-08-03 op case V_STR: printf("str"); break;
352 c734c0e9 2021-08-03 op default: printf("???"); break;
355 c734c0e9 2021-08-03 op case OP_CMP_EQ:
356 c734c0e9 2021-08-03 op pp_op(op->v.cmp_eq.a);
357 c734c0e9 2021-08-03 op printf(" == ");
358 c734c0e9 2021-08-03 op pp_op(op->v.cmp_eq.b);
361 c734c0e9 2021-08-03 op printf(" ???[%d] ", op->type);
366 c734c0e9 2021-08-03 op pp_block(struct op *op)
368 c734c0e9 2021-08-03 op while (op != NULL) {
369 c734c0e9 2021-08-03 op printf("> ");
371 c734c0e9 2021-08-03 op printf("\n");
373 c734c0e9 2021-08-03 op op = op->next;
377 c734c0e9 2021-08-03 op static inline void
378 c734c0e9 2021-08-03 op popv(struct value *v)
380 c734c0e9 2021-08-03 op if (stackh == 0)
381 c734c0e9 2021-08-03 op errx(1, "can't pop the stack: underflow");
382 c734c0e9 2021-08-03 op memcpy(v, &vstack[--stackh], sizeof(*v));
385 c734c0e9 2021-08-03 op printf("popping "); pp_val(v); printf("\n");
389 c734c0e9 2021-08-03 op static inline void
390 c734c0e9 2021-08-03 op pushv(struct value *v)
392 c734c0e9 2021-08-03 op if (stackh == STACK_HEIGHT)
393 c734c0e9 2021-08-03 op errx(1, "can't push the stack: overflow");
396 c734c0e9 2021-08-03 op printf("pushing "); pp_val(v); printf("\n");
399 c734c0e9 2021-08-03 op memcpy(&vstack[stackh++], v, sizeof(*v));
402 c734c0e9 2021-08-03 op static inline void
403 c734c0e9 2021-08-03 op pushbool(int n)
405 c734c0e9 2021-08-03 op pushv(n ? &v_true : &v_false);
409 c734c0e9 2021-08-03 op eval(struct op *op)
411 c734c0e9 2021-08-03 op struct value a, b;
412 c734c0e9 2021-08-03 op struct proc *proc;
413 c734c0e9 2021-08-03 op struct op *t;
418 c734c0e9 2021-08-03 op printf("\n");
421 c734c0e9 2021-08-03 op switch (op->type) {
422 c734c0e9 2021-08-03 op case OP_ASSIGN:
423 c734c0e9 2021-08-03 op printf("TODO: assignment\n");
426 c734c0e9 2021-08-03 op case OP_ASSERT:
427 333d8d7d 2021-08-04 op if ((ret = eval(op->v.assert)) != EVAL_OK)
430 c734c0e9 2021-08-03 op if (!val_trueish(&a)) {
431 c734c0e9 2021-08-03 op printf("assertion failed: ");
432 c734c0e9 2021-08-03 op pp_op(op->v.assert);
433 c734c0e9 2021-08-03 op printf("\n");
434 333d8d7d 2021-08-04 op return EVAL_ERR;
438 c734c0e9 2021-08-03 op case OP_FUNCALL:
439 c734c0e9 2021-08-03 op /* TODO: arity check! */
441 c734c0e9 2021-08-03 op for (i = 0; i < op->v.funcall.argc; ++i) {
442 c734c0e9 2021-08-03 op t = &op->v.funcall.argv[i];
443 333d8d7d 2021-08-04 op if ((ret = eval(t)) != EVAL_OK)
447 c734c0e9 2021-08-03 op proc = op->v.funcall.proc;
448 c734c0e9 2021-08-03 op if (proc->nativefn != NULL)
449 c734c0e9 2021-08-03 op proc->nativefn(i);
450 333d8d7d 2021-08-04 op else if ((ret = eval(proc->body)) != EVAL_OK)
454 c734c0e9 2021-08-03 op case OP_LITERAL:
455 c734c0e9 2021-08-03 op pushv(&op->v.literal);
459 c734c0e9 2021-08-03 op printf("TODO: load variable\n");
462 c734c0e9 2021-08-03 op case OP_CAST:
463 da4de0c1 2021-08-04 op if ((ret = eval(op->v.cast.expr)) != EVAL_OK)
466 da4de0c1 2021-08-04 op if ((ret = val_cast(&a, op->v.cast.totype)) != EVAL_OK)
471 c734c0e9 2021-08-03 op case OP_CMP_EQ:
472 333d8d7d 2021-08-04 op if ((ret = eval(op->v.cmp_eq.a)) != EVAL_OK)
474 333d8d7d 2021-08-04 op if ((ret = eval(op->v.cmp_eq.b)) != EVAL_OK)
479 c734c0e9 2021-08-03 op pushbool(val_eq(&a, &b));
484 e9f9c9b1 2021-08-04 op fprintf(stderr, "invalid op, aborting.\n");
488 c734c0e9 2021-08-03 op if (op->next)
489 c734c0e9 2021-08-03 op return eval(op->next);
490 333d8d7d 2021-08-04 op return EVAL_OK;
494 d9d02161 2021-08-04 op prepare_funcall(void)
496 d9d02161 2021-08-04 op pushstack(&args);
500 c734c0e9 2021-08-03 op push_arg(struct op *op)
502 d9d02161 2021-08-04 op push(&args, op);
506 d9d02161 2021-08-04 op op_funcall(struct proc *proc)
508 d9d02161 2021-08-04 op struct op *op, *argv;
511 d9d02161 2021-08-04 op argv = finalize(&args, &argc);
513 c734c0e9 2021-08-03 op op = newop(OP_FUNCALL);
514 c734c0e9 2021-08-03 op op->v.funcall.proc = proc;
515 d9d02161 2021-08-04 op op->v.funcall.argv = argv;
516 d9d02161 2021-08-04 op op->v.funcall.argc = argc;
522 c734c0e9 2021-08-03 op add_builtin_proc(const char *name, int (*fn)(int))
524 c734c0e9 2021-08-03 op struct proc *proc;
526 c734c0e9 2021-08-03 op proc = xcalloc(1, sizeof(*proc));
527 c734c0e9 2021-08-03 op proc->name = xstrdup(name);
528 c734c0e9 2021-08-03 op proc->nativefn = fn;
530 c734c0e9 2021-08-03 op TAILQ_INSERT_HEAD(&procs, proc, entry);
534 d9d02161 2021-08-04 op prepare_proc(void)
536 d9d02161 2021-08-04 op pushstack(&args);
540 c734c0e9 2021-08-03 op proc_setup_body(void)
542 d9d02161 2021-08-04 op struct opstack *argv;
543 d9d02161 2021-08-04 op struct op *op;
546 d9d02161 2021-08-04 op argv = peek(&args);
547 d9d02161 2021-08-04 op for (i = 0, op = argv->base.next; op != NULL; i++) {
549 d9d02161 2021-08-04 op * TODO: should free the whole list but.., we're gonna
550 d9d02161 2021-08-04 op * exit real soon(tm)!
552 c734c0e9 2021-08-03 op if (op->type != OP_VAR)
555 c8878182 2021-08-04 op op = op->next;
558 d9d02161 2021-08-04 op assert(i == argv->counter);
559 d9d02161 2021-08-04 op pushstack(&blocks);
564 d9d02161 2021-08-04 op proc_done(char *name)
566 d9d02161 2021-08-04 op struct proc *proc;
567 d9d02161 2021-08-04 op struct op *op, *next, *argv, *body;
570 d9d02161 2021-08-04 op argv = finalize(&args, &argc);
571 d9d02161 2021-08-04 op body = finalize(&blocks, NULL);
573 d9d02161 2021-08-04 op proc = xcalloc(1, sizeof(*proc));
574 d9d02161 2021-08-04 op proc->name = name;
575 d9d02161 2021-08-04 op proc->minargs = argc;
577 b99bdaa1 2021-08-04 op for (i = 0, op = argv; op != NULL; ++i) {
578 d9d02161 2021-08-04 op proc->args[i] = xstrdup(op->v.var);
580 d9d02161 2021-08-04 op next = op->next;
584 b99bdaa1 2021-08-04 op assert(i == argc);
586 d9d02161 2021-08-04 op proc->body = body;
588 d9d02161 2021-08-04 op TAILQ_INSERT_HEAD(&procs, proc, entry);
592 c734c0e9 2021-08-03 op block_push(struct op *op)
594 d9d02161 2021-08-04 op push(&blocks, op);
597 c734c0e9 2021-08-03 op struct proc *
598 c734c0e9 2021-08-03 op proc_by_name(const char *name)
600 c734c0e9 2021-08-03 op struct proc *p;
602 c734c0e9 2021-08-03 op TAILQ_FOREACH(p, &procs, entry) {
603 c734c0e9 2021-08-03 op if (!strcmp(p->name, name))
611 d9d02161 2021-08-04 op prepare_test(void)
613 d9d02161 2021-08-04 op pushstack(&blocks);
617 d9d02161 2021-08-04 op test_done(char *name, char *dir)
619 d9d02161 2021-08-04 op struct test *test;
621 d9d02161 2021-08-04 op test = xcalloc(1, sizeof(*test));
622 d9d02161 2021-08-04 op test->name = name;
623 d9d02161 2021-08-04 op test->dir = dir;
624 d9d02161 2021-08-04 op test->body = finalize(&blocks, NULL);
626 5e5c37b5 2021-08-04 op if (TAILQ_EMPTY(&tests))
627 5e5c37b5 2021-08-04 op TAILQ_INSERT_HEAD(&tests, test, entry);
629 5e5c37b5 2021-08-04 op TAILQ_INSERT_TAIL(&tests, test, entry);
633 c734c0e9 2021-08-03 op builtin_dummy(int argc)
635 c734c0e9 2021-08-03 op printf("dummy! yay!\n");
636 333d8d7d 2021-08-04 op return EVAL_OK;
640 c734c0e9 2021-08-03 op run_test(struct test *t)
643 c734c0e9 2021-08-03 op puts("=====================");
644 8e0ef4cb 2021-08-04 op pp_block(t->body);
645 c734c0e9 2021-08-03 op puts("=====================");
648 d9d02161 2021-08-04 op return eval(t->body);
652 c734c0e9 2021-08-03 op main(int argc, char **argv)
654 c734c0e9 2021-08-03 op struct test *t;
655 c734c0e9 2021-08-03 op int i, passed = 0, failed = 0, skipped = 0;
657 c734c0e9 2021-08-03 op log_init(1, LOG_DAEMON);
658 c734c0e9 2021-08-03 op log_setverbose(1);
660 c734c0e9 2021-08-03 op add_builtin_proc("dummy", builtin_dummy);
662 c734c0e9 2021-08-03 op for (i = 1; i < argc; ++i)
663 c734c0e9 2021-08-03 op loadfile(argv[i]);
666 c734c0e9 2021-08-03 op TAILQ_FOREACH(t, &tests, entry) {
667 e334da07 2021-08-04 op printf("===> running test \"%s\"... ", t->name);
668 e334da07 2021-08-04 op fflush(stdout);
670 e334da07 2021-08-04 op switch (run_test(t)) {
671 333d8d7d 2021-08-04 op case EVAL_OK:
672 e334da07 2021-08-04 op printf("ok!\n");
675 333d8d7d 2021-08-04 op case EVAL_ERR:
677 e334da07 2021-08-04 op /* we've already printed the failure */
678 e334da07 2021-08-04 op printf("\n");
680 333d8d7d 2021-08-04 op case EVAL_SKIP:
681 e334da07 2021-08-04 op printf("skipped!\n");
689 e334da07 2021-08-04 op printf("passed %d/%d\n", passed, i);
690 e334da07 2021-08-04 op printf("failed %d\n", failed);
691 e334da07 2021-08-04 op printf("skipped %d\n", skipped);
693 c734c0e9 2021-08-03 op return failed != 0;