Blob


1 /*
2 * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #ifndef SCRIPT_H
18 #define SCRIPT_H
20 enum {
21 /* literals */
22 V_SYM,
23 V_STR,
24 V_NUM,
26 /* foreign */
27 V_MSG,
28 V_QIDVEC,
29 V_QID,
31 /* casted */
32 V_U8,
33 V_U16,
34 V_U32,
35 };
37 struct value {
38 int type;
39 union {
40 char *str;
41 int64_t num;
42 uint8_t u8;
43 uint16_t u16;
44 uint32_t u32;
45 struct {
46 uint8_t *msg;
47 size_t len;
48 } msg;
49 struct {
50 uint8_t *start;
51 size_t len;
52 } qidvec;
53 uint8_t qid[QIDSIZE];
54 } v;
55 };
57 enum {
58 OP_REST,
59 OP_ASSIGN,
60 OP_ASSERT,
61 OP_FUNCALL,
62 OP_LITERAL,
63 OP_VAR,
64 OP_CAST,
65 OP_CMP_EQ,
66 OP_CMP_LEQ,
67 OP_FACCESS,
68 OP_SFAIL,
69 OP_VARGS,
70 };
72 struct proc;
74 struct op {
75 struct op *next;
76 int type;
77 union {
78 struct {
79 char *name;
80 struct op *expr;
81 } assign;
82 struct op *assert;
83 struct {
84 struct proc *proc;
85 struct op *argv;
86 int argc;
87 } funcall;
88 struct value literal;
89 char *var;
90 struct {
91 struct op *expr;
92 int totype;
93 } cast;
94 struct {
95 struct op *a;
96 struct op *b;
97 } bin_cmp;
98 struct {
99 struct op *expr;
100 char *field;
101 } faccess;
102 struct {
103 char *msg;
104 struct op *expr;
105 } sfail;
106 } v;
107 };
109 TAILQ_HEAD(bindings, binding);
110 struct binding {
111 TAILQ_ENTRY(binding) entry;
112 char *name;
113 struct value val;
115 /*
116 * Hack to support varargs. We set a special variable named
117 * "..." that contains the list of ops that will evaluate to
118 * the arguments.
119 */
120 struct op *raw;
121 };
123 TAILQ_HEAD(envs, env);
124 struct env {
125 TAILQ_ENTRY(env) entry;
126 struct bindings bindings;
127 };
129 TAILQ_HEAD(opstacks, opstack);
130 struct opstack {
131 TAILQ_ENTRY(opstack) entry;
132 struct op base;
133 struct op *last;
134 int counter;
135 };
137 TAILQ_HEAD(procs, proc);
138 struct proc {
139 TAILQ_ENTRY(proc) entry;
140 char *name;
141 int minargs;
142 int vararg;
143 char *args[MAXWELEM];
144 struct op *body;
145 int (*nativefn)(int);
146 };
148 TAILQ_HEAD(tests, test);
149 struct test {
150 TAILQ_ENTRY(test) entry;
151 int shouldfail;
152 char *name;
153 struct op *body;
154 };
156 enum {
157 EVAL_OK,
158 EVAL_ERR,
159 EVAL_SKIP,
160 };
162 int global_set(char *, struct op *);
164 struct op *newop(int);
165 void free_op_rec(struct op *);
166 void free_op(struct op *);
167 struct op *op_rest(void);
168 struct op *op_assign(char *, struct op *);
169 struct op *op_assert(struct op *);
170 struct op *op_var(char *);
171 struct op *op_lit_str(char *);
172 struct op *op_lit_num(uint64_t);
173 struct op *op_cmp_eq(struct op *, struct op *);
174 struct op *op_cmp_leq(struct op *, struct op *);
175 struct op *op_cast(struct op *, int);
176 struct op *op_faccess(struct op *, char *);
177 struct op *op_sfail(struct op *, char *);
178 struct op *op_vargs(void);
180 void ppf_val(FILE *, const struct value *);
181 void pp_val(const struct value *);
182 const char *val_type(struct value *);
183 int val_trueish(struct value *);
184 int val_isnum(struct value *);
185 int64_t val_tonum(struct value *);
186 int val_eq(struct value *, struct value *);
187 int val_leq(struct value *, struct value *);
188 int val_cast(struct value *, int);
189 int val_faccess(struct value *, const char *, struct value *);
190 void pp_op(struct op *);
191 void pp_block(struct op *);
192 int eval(struct op *);
194 /* funcall */
195 void prepare_funcall(void);
196 void push_arg(struct op *);
197 struct op *op_funcall(struct proc *);
199 /* proc */
200 void add_builtin_proc(const char *name, int (*)(int), int, int);
201 void prepare_proc(void);
202 /* push_arg works on procs too */
203 int proc_setup_body(void);
204 void proc_done(char *name);
205 void block_push(struct op *);
206 struct proc *proc_by_name(const char *);
208 /* testing */
209 void prepare_test(void);
210 void test_done(int, char *);
212 /* np.y */
213 void loadfile(const char *);
215 #endif