acid
diff --git a/src/cmd/acid/util.c b/src/cmd/acid/util.c
new file mode 100644
index 0000000..a40416c
--- /dev/null
+++ b/src/cmd/acid/util.c
@@ -0,0 +1,344 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include <mach.h>
+#define Extern extern
+#include "acid.h"
+#include "y.tab.h"
+
+static int syren;
+
+Lsym*
+unique(char *buf, Symbol *s)
+{
+	Lsym *l;
+	int i, renamed;
+
+	renamed = 0;
+	strcpy(buf, s->name);
+	for(;;) {
+		l = look(buf);
+		if(l == 0 || (l->lexval == Tid && l->v->set == 0))
+			break;
+
+		if(syren == 0 && !quiet) {
+			print("Symbol renames:\n");
+			syren = 1;
+		}
+		i = strlen(buf)+1;
+		memmove(buf+1, buf, i);
+		buf[0] = '$';
+		renamed++;
+		if(renamed > 5 && !quiet) {
+			print("Too many renames; must be X source!\n");
+			break;
+		}
+	}
+	if(renamed && !quiet)
+		print("\t%s=%s %c/%Z\n", s->name, buf, s->type, s->loc);
+	if(l == 0)
+		l = enter(buf, Tid);
+	return l;	
+}
+
+void
+varsym(void)
+{
+	Lsym *l;
+	Fhdr *fp;
+
+	l = mkvar("symbols");
+	if(l->v->set)
+		return;
+
+	l->v->set = 1;
+	l->v->type = TLIST;
+	l->v->store.u.l = nil;
+
+	for(fp=fhdrlist; fp; fp=fp->next){
+		if(fp->ftype == FCORE)
+			continue;
+		addvarsym(fp);
+	}
+
+	if(l->v->store.u.l == nil)
+		print("no debugging symbols\n");
+}
+
+void
+addvarsym(Fhdr *fp)
+{
+	int i;
+	Symbol s;
+	Lsym *l;
+	String *file;
+	ulong v;
+	char buf[1024];
+	List *list, **tail, *tl;
+
+	if(fp == nil)
+		return;
+
+	l = look("symbols");
+	if(l == nil)
+		return;
+
+	l->v->set = 1;
+	l->v->type = TLIST;
+	tail = &l->v->store.u.l;
+	while(*tail)
+		tail = &(*tail)->next;
+
+	file = strnode(fp->filename);
+	for(i=0; findexsym(fp, i, &s)>=0; i++){
+		switch(s.type) {
+		case 'T':
+		case 'L':
+		case 'D':
+		case 'B':
+		case 'b':
+		case 'd':
+		case 'l':
+		case 't':
+			if(s.name[0] == '.')
+				continue;
+			if(s.loc.type != LADDR)
+				continue;
+			v = s.loc.addr;
+			tl = al(TLIST);
+			*tail = tl;
+			tail = &tl->next;
+
+			l = unique(buf, &s);
+			l->v->set = 1;
+			l->v->type = TINT;
+			l->v->store.u.ival = v;
+			if(l->v->store.comt == 0)
+				l->v->store.fmt = 'X';
+
+			/* Enter as list of { name, type, value, file } */
+			list = al(TSTRING);
+			tl->store.u.l = list;
+			list->store.u.string = strnode(buf);
+			list->store.fmt = 's';
+			list->next = al(TINT);
+			list = list->next;
+			list->store.fmt = 'c';
+			list->store.u.ival = s.type;
+			list->next = al(TINT);
+			list = list->next;
+			list->store.fmt = 'X';
+			list->store.u.ival = v;
+			list->next = al(TSTRING);
+			list = list->next;
+			list->store.fmt = 's';
+			list->store.u.string = file;
+		}
+	}
+	*tail = nil;
+}
+
+static int
+infile(List *list, char *file, char **name)
+{
+	/* name */
+	if(list->type != TSTRING)
+		return 0;
+	*name = list->store.u.string->string;
+	if(list->next == nil)
+		return 0;
+	list = list->next;
+
+	/* type character */
+	if(list->next == nil)
+		return 0;
+	list = list->next;
+
+	/* address */
+	if(list->next == nil)
+		return 0;
+	list = list->next;
+
+	/* file */
+	if(list->type != TSTRING)
+		return 0;
+	return strcmp(list->store.u.string->string, file) == 0;
+}
+
+void
+delvarsym(char *file)
+{
+	char *name;
+	Lsym *l;
+	List **lp, *p;
+
+	l = look("symbols");
+	if(l == nil)
+		return;
+
+	if(l->v->type != TLIST)
+		return;
+
+	for(lp=&l->v->store.u.l; *lp; lp=&(*lp)->next){
+		while(*lp){
+			p = *lp;
+			if(p->type != TLIST)
+				break;
+			if(!infile(p->store.u.l, file, &name))
+				break;
+			*lp = p->next;
+			/* XXX remove from hash tables */
+		}
+		if(*lp == nil)
+			break;
+	}
+}
+
+void
+varreg(void)
+{
+	Lsym *l;
+	Value *v;
+	Regdesc *r;
+	List **tail, *li;
+
+	l = mkvar("registers");
+	v = l->v;
+	v->set = 1;
+	v->type = TLIST;
+	v->store.u.l = 0;
+	tail = &v->store.u.l;
+
+	if(mach == nil)
+		return;
+
+	for(r = mach->reglist; r->name; r++) {
+		l = mkvar(r->name);
+		v = l->v;
+		v->set = 1;
+		v->store.u.ival = r->offset;
+		v->store.fmt = r->format;
+		v->type = TINT;
+
+		li = al(TSTRING);
+		li->store.u.string = strnode(r->name);
+		li->store.fmt = 's';
+		*tail = li;
+		tail = &li->next;
+	}
+
+	l = mkvar("bpinst");	/* Breakpoint text */
+	v = l->v;
+	v->type = TSTRING;
+	v->store.fmt = 's';
+	v->set = 1;
+	v->store.u.string = gmalloc(sizeof(String));
+	v->store.u.string->len = mach->bpsize;
+	v->store.u.string->string = gmalloc(mach->bpsize);
+	memmove(v->store.u.string->string, mach->bpinst, mach->bpsize);
+}
+
+void
+loadvars(void)
+{
+	Lsym *l;
+	Value *v;
+
+	l =  mkvar("proc");
+	v = l->v;
+	v->type = TINT;
+	v->store.fmt = 'X';
+	v->set = 1;
+	v->store.u.ival = 0;
+
+	l = mkvar("pid");		/* Current process */
+	v = l->v;
+	v->type = TINT;
+	v->store.fmt = 'D';
+	v->set = 1;
+	v->store.u.ival = 0;
+
+	mkvar("notes");			/* Pending notes */
+
+	l = mkvar("proclist");		/* Attached processes */
+	l->v->type = TLIST;
+}
+
+String*
+strnodlen(char *name, int len)
+{
+	String *s;
+
+	s = gmalloc(sizeof(String)+len+1);
+	s->string = (char*)s+sizeof(String);
+	s->len = len;
+	if(name != 0)
+		memmove(s->string, name, len);
+	s->string[len] = '\0';
+
+	s->gc.gclink = gcl;
+	gcl = (Gc*)s;
+
+	return s;
+}
+
+String*
+strnode(char *name)
+{
+	return strnodlen(name, strlen(name));
+}
+
+String*
+runenode(Rune *name)
+{
+	int len;
+	Rune *p;
+	String *s;
+
+	p = name;
+	for(len = 0; *p; p++)
+		len++;
+
+	len++;
+	len *= sizeof(Rune);
+	s = gmalloc(sizeof(String)+len);
+	s->string = (char*)s+sizeof(String);
+	s->len = len;
+	memmove(s->string, name, len);
+
+	s->gc.gclink = gcl;
+	gcl = (Gc*)s;
+
+	return s;
+}
+
+String*
+stradd(String *l, String *r)
+{
+	int len;
+	String *s;
+
+	len = l->len+r->len;
+	s = gmalloc(sizeof(String)+len+1);
+	s->gc.gclink = gcl;
+	gcl = (Gc*)s;
+	s->len = len;
+	s->string = (char*)s+sizeof(String);
+	memmove(s->string, l->string, l->len);
+	memmove(s->string+l->len, r->string, r->len);
+	s->string[s->len] = 0;
+	return s;
+}
+
+int
+scmp(String *sr, String *sl)
+{
+	if(sr->len != sl->len)
+		return 0;
+
+	if(memcmp(sr->string, sl->string, sl->len))
+		return 0;
+
+	return 1;
+}