+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "umpf.h"
+
+#define HASHSIZE 103
+#define MAGIC 19
+#define BUFSIZE 1024
+
+static struct list*
+new_var_hash(void)
+{
+ struct list* res;
+ int i;
+
+ res = xmalloc (HASHSIZE * sizeof(struct list));
+ for (i = 0; i < HASHSIZE; i++)
+ list_init(res + i);
+
+ return res;
+}
+
+static int
+get_bucket_number(char* name)
+{
+ unsigned int n = 0;
+ unsigned char* p = name;
+
+ while (*p != '\0'){
+ n = n * MAGIC + toupper(*p++);
+ }
+ n %= HASHSIZE;
+
+ return n;
+}
+
+/* if not found, variable with value "" is created */
+static int
+find_var(char* name, struct list* hash)
+{
+ int n;
+ struct variable *p;
+
+ n = get_bucket_number(name);
+ int nocase = isupper(*name);
+ LIST_FOREACH(p, hash + n)
+ if (!(nocase ? strcasecmp : strcmp)(p->name,name))
+ return p->varcode;
+
+ p = xmalloc(sizeof(struct variable));
+ p->name = xstrdup(name);
+ p->varcode = current_varcode++;
+ list_add_last(hash+n, &p->car);
+ return p->varcode;
+}
+
+void
+init(void)
+{
+ list_init(&input_code);
+ var_hash = new_var_hash();
+ const_tab = xmalloc(BUFSIZE);
+ cur_const_s = BUFSIZE;
+}
+
+static int
+store_const(char* c)
+{
+ if (cur_const_n >= cur_const_s) {
+ cur_const_s *= 2;
+ const_tab = xrealloc(const_tab, cur_const_s);
+ }
+
+ const_tab[cur_const_n] = c;
+
+ return -cur_const_n++;
+}
+
+static void
+new_instr(struct code c)
+{
+ struct code* p = xmalloc(sizeof(struct code));
+ *p = c;
+ list_add_last(&input_code, &p->car);
+}
+
+static void
+do_ass(struct tree* t)
+{
+ int var_l, var_r;
+ struct code ins;
+ var_l = find_var(t->pt.ass.left->pt.leaf.value, var_hash);
+
+ if (t->st == ST_LEAF) {
+ if (t->pt.leaf.type == L_VAR)
+ var_r = find_var(t->pt.leaf.value, var_hash);
+ else
+ var_r = store_const(t->pt.leaf.value);
+ ins.opc = SET;
+ ins.op1.i = var_l;
+ ins.op2.i = var_r;
+ new_instr(ins);
+ }
+}
+
+void
+compile(struct tree* t)
+{
+ if (!t)
+ return;
+ switch(t->st) {
+ case ST_BLOCK:
+ compile(t->pt.block.head);
+ compile(t->pt.block.tail);
+ break;
+ case ST_EMPTY:
+ break;
+ case ST_ASS:
+ do_ass(t);
+ break;
+ default:
+ die("compile: got to default");
+ }
+}
+
+void
+print_code(struct tree* t)
+{
+
+}