14 res = xmalloc (HASHSIZE * sizeof(struct list));
15 for (i = 0; i < HASHSIZE; i++)
22 get_bucket_number(char* name)
25 unsigned char* p = name;
28 n = n * MAGIC + toupper(*p++);
35 /* return var struct or NULL if not found */
37 get_var_struct(char* name, enum var_type type, struct list* hash)
42 n = get_bucket_number(name);
43 LIST_FOREACH(p, hash + n)
44 if (!strcasecmp(p->name, name) && p->type == type)
51 find_var(char* name, enum var_type type, struct list* hash)
56 n = get_bucket_number(name);
57 LIST_FOREACH(p, hash + n)
58 if (!strcasecmp(p->name, name) && p->type == type)
61 p = xmalloc(sizeof(struct variable));
62 p->name = xstrdup(name);
63 p->varcode = current_varcode++;
65 list_add_last(hash+n, &p->car);
73 if (cur_const_n >= cur_const_s) {
75 const_tab = xrealloc(const_tab, cur_const_s);
78 const_tab[cur_const_n] = c;
80 return -cur_const_n++;
84 new_instr(struct code c, struct list* where)
86 struct code* p = xmalloc(sizeof(struct code));
89 list_add_last(where, &p->car);
91 list_add_last(&input_code, &p->car);
95 new_3par_instr(int opcode, int left, int right, int pref_var,
102 ins.u.tpop.r = right;
104 ins.u.tpop.res = pref_var;
106 ins.u.tpop.res = current_varcode++;;
107 new_instr(ins, where);
108 return ins.u.tpop.res;
111 /* return number of variable where lies result
112 * pref_var < 0 => no preference
115 evaluate(struct tree* t, int pref_var, struct list* where)
117 if (t->st == ST_LEAF) {
121 left = evaluate(t->pt.op.left, -1, where);
122 right = evaluate(t->pt.op.right, -1, where);
123 switch (t->pt.op.op) {
125 return new_3par_instr(OPC_CAT, left,
126 right, pref_var, where);
129 return new_3par_instr(OPC_PLUS, left,
130 right, pref_var, where);
133 return new_3par_instr(OPC_MINUS, left,
134 right, pref_var, where);
137 return new_3par_instr(OPC_MUL, left,
138 right, pref_var, where);
141 return new_3par_instr(OPC_DIV, left,
142 right, pref_var, where);
145 die("evaluate: Never can get here :)");
149 do_ass(struct tree* t, struct list* where)
153 var_l = t->pt.ass.left->pt.leaf.n;
154 var_r = evaluate(t->pt.ass.right, -1, where);
156 ins.opcode = OPC_SET;
159 new_instr(ins, where);
164 eval_cond(struct tree *t, int pref_var, struct list* where)
167 if (t->pt.cond.type == JUST_BOOL) {
168 if (t->pt.cond.left->st == ST_LEAF)
169 return t->pt.cond.left->pt.leaf.n;
170 if (t->pt.cond.left->st == ST_OP)
171 return evaluate(t->pt.cond.left, -1, where);
173 die("eval_cond: %d cannot be JUST_BOOL\n",
174 t->pt.cond.left->st);
176 if (t->pt.cond.type == OP_REL) {
177 left = evaluate(t->pt.cond.left, -1, where);
178 right = evaluate(t->pt.cond.right, -1, where);
180 switch (t->pt.cond.op) {
182 return new_3par_instr (OPC_GT, left,
183 right, pref_var, where);
186 return new_3par_instr (OPC_LT, left,
187 right, pref_var, where);
190 return new_3par_instr (OPC_LE, left,
191 right, pref_var, where);
194 return new_3par_instr (OPC_GE, left,
195 right, pref_var, where);
198 return new_3par_instr (OPC_NRE, left,
199 right, pref_var, where);
202 return new_3par_instr (OPC_RE, left,
203 right, pref_var, where);
206 return new_3par_instr (OPC_EQ, left,
207 right, pref_var, where);
210 return new_3par_instr (OPC_NEQ, left,
211 right, pref_var, where);
213 /* fixme: do more of them */
215 die("eval_cond: unknown relation op %c\n",
220 if (t->pt.cond.type == OP_BOOL) {
223 left = eval_cond(t->pt.cond.left, -1, where);
224 if (t->pt.cond.op != '!') /* ! is unary */
225 right = eval_cond(t->pt.cond.right, -1, where);
226 switch (t->pt.cond.op) {
228 return new_3par_instr (OPC_AND, left,
229 right, pref_var, where);
232 return new_3par_instr (OPC_OR, left,
233 right, pref_var, where);
236 return new_3par_instr (OPC_XOR, left,
237 right, pref_var, where);
240 ins.opcode = OPC_NOT;
241 ins.u.dpop.par = left;
243 ins.u.dpop.res = pref_var;
245 ins.u.dpop.res = current_varcode++;;
246 new_instr(ins, where);
247 return ins.u.dpop.res;
250 die("eval_cond: unknown boolean op %c\n",
255 die("eval_cond: unknown condition type");
259 do_if(struct tree *t, struct list* where)
262 struct code ins, nop, jmp;
263 struct list* if_branch = xmalloc(sizeof(struct list));
264 struct list* else_branch = xmalloc(sizeof(struct list));
266 list_init(if_branch);
267 list_init(else_branch);
268 nop.opcode = OPC_NOP;
269 jmp.opcode = OPC_JUMP;
271 c = eval_cond(t->pt.tif.c, -1, where);
273 compile(t->pt.tif.i, if_branch);
274 compile(t->pt.tif.e, else_branch);
275 new_instr(nop, else_branch);
276 jmp.u.jump.target = list_last(else_branch);
277 new_instr(jmp, if_branch);
278 new_instr(nop, if_branch);
280 ins.opcode = OPC_JUMP_UNLESS;
281 ins.u.jump_unless.cond = c;
282 ins.u.jump_unless.target = list_last(if_branch);
283 new_instr(ins, where);
284 list_cat(where, if_branch);
285 list_cat(where, else_branch);
292 do_arrow(struct tree* t, struct list* where)
298 if (t->pt.arrow.left == K_COPY)
299 ins.u.arrow.copy = 1;
301 ins.u.arrow.copy = 0;
302 switch (t->pt.arrow.right) {
304 ins.opcode = OPC_DELIVER;
307 ins.opcode = OPC_PIPE;
310 ins.opcode = OPC_MAIL;
313 ins.opcode = OPC_DISCARD;
316 ins.opcode = OPC_FILTER;
319 die("do_arrow: This cannot happen ;-)");
322 if (t->pt.arrow.right != K_DISCARD) {
323 v = evaluate(t->pt.arrow.s, -1, where);
324 ins.u.arrow.what = v;
327 new_instr(ins, where);
331 reset_temp_var_count(void)
333 if (current_varcode > max_varcode)
334 max_varcode = current_varcode;
335 current_varcode = temp_varcode_start;
339 compile(struct tree* t, struct list* where)
348 reset_temp_var_count();
349 compile(t->pt.block.head, where);
350 compile(t->pt.block.tail, where);
354 case ST_LEAF: //warn?
360 evaluate(t, -1, where); //emit warning?
366 eval_cond(t, -1, where); // warn?
371 die("compile: got to default, type: %d", t->st);
376 lookup_var_name(int id)
380 for (h=0; h<HASHSIZE; h++) {
382 LIST_FOREACH(p, var_hash + h)
383 if (p->varcode == id)
395 printf("Known constants:\n");
396 for (i=1; i<cur_const_n; i++)
397 printf("-%d\t\"%s\"\n", i, const_tab[i]);
400 printf("Known variables:\n");
401 // This is grossly inefficient...
402 for (i=0; i<temp_varcode_start; i++)
403 printf("%d\t%s\n", i, lookup_var_name(i));
406 LIST_FOREACH(p, &input_code) {
410 printf("SET %d %d\n", p->u.set.l, p->u.set.r);
413 printf("CAT %d %d %d\n", p->u.tpop.l,
414 p->u.tpop.r, p->u.tpop.res);
417 printf("JUMP %p\n", p->u.jump.target);
419 case OPC_JUMP_UNLESS:
420 printf("JUMP_UNLESS %d %p\n", p->u.jump_unless.cond, p->u.jump_unless.target);
423 printf("GT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
426 printf("LT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
429 printf("LE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
432 printf("GE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
435 printf("RE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
438 printf("NRE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
441 printf("NEQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
444 printf("EQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
447 printf("AND %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
450 printf("OR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
453 printf("XOR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
456 printf("PLUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
459 printf("MINUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
462 printf("MUL %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
465 printf("DIV %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
468 printf("NOT %d %d\n", p->u.dpop.par, p->u.dpop.res);
474 printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
477 printf("FILTER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
480 printf("DELIVER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
483 printf("MAIL %d %d\n", p->u.arrow.what, p->u.arrow.copy);
489 printf("not implemented, opcode: %d\n",