Plan 9's rc.

not a clear win over byron's,
but at least it has the right syntax.
diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c
new file mode 100644
index 0000000..9bf76d8
--- /dev/null
+++ b/src/cmd/rc/tree.c
@@ -0,0 +1,114 @@
+#include "rc.h"
+#include "exec.h"
+#include "io.h"
+#include "fns.h"
+tree *treenodes;
+/*
+ * create and clear a new tree node, and add it
+ * to the node list.
+ */
+tree *newtree(void){
+	tree *t=new(tree);
+	t->iskw=0;
+	t->str=0;
+	t->child[0]=t->child[1]=t->child[2]=0;
+	t->next=treenodes;
+	treenodes=t;
+	return t;
+}
+void freenodes(void){
+	tree *t, *u;
+	for(t=treenodes;t;t=u){
+		u=t->next;
+		if(t->str) efree(t->str);
+		efree((char *)t);
+	}
+	treenodes=0;
+}
+tree *tree1(int type, tree *c0)
+{
+	return tree3(type, c0, (tree *)0, (tree *)0);
+}
+tree *tree2(int type, tree *c0, tree *c1)
+{
+	return tree3(type, c0, c1, (tree *)0);
+}
+tree *tree3(int type, tree *c0, tree *c1, tree *c2)
+{
+	tree *t;
+	if(type==';'){
+		if(c0==0) return c1;
+		if(c1==0) return c0;
+	}
+	t=newtree();
+	t->type=type;
+	t->child[0]=c0;
+	t->child[1]=c1;
+	t->child[2]=c2;
+	return t;
+}
+tree *mung1(tree *t, tree *c0)
+{
+	t->child[0]=c0;
+	return t;
+}
+tree *mung2(tree *t, tree *c0, tree *c1)
+{
+	t->child[0]=c0;
+	t->child[1]=c1;
+	return t;
+}
+tree *mung3(tree *t, tree *c0, tree *c1, tree *c2)
+{
+	t->child[0]=c0;
+	t->child[1]=c1;
+	t->child[2]=c2;
+	return t;
+}
+tree *epimung(tree *comp, tree *epi)
+{
+	tree *p;
+	if(epi==0) return comp;
+	for(p=epi;p->child[1];p=p->child[1]);
+	p->child[1]=comp;
+	return epi;
+}
+/*
+ * Add a SIMPLE node at the root of t and percolate all the redirections
+ * up to the root.
+ */
+tree *simplemung(tree *t)
+{
+	tree *u;
+	struct io *s;
+	t=tree1(SIMPLE, t);
+	s=openstr();
+	pfmt(s, "%t", t);
+	t->str=strdup(s->strp);
+	closeio(s);
+	for(u=t->child[0];u->type==ARGLIST;u=u->child[0]){
+		if(u->child[1]->type==DUP
+		|| u->child[1]->type==REDIR){
+			u->child[1]->child[1]=t;
+			t=u->child[1];
+			u->child[1]=0;
+		}
+	}
+	return t;
+}
+tree *token(char *str, int type)
+{
+	tree *t=newtree();
+	t->type=type;
+	t->str=strdup(str);
+	return t;
+}
+void freetree(tree *p)
+{
+	if(p==0) return;	
+	freetree(p->child[0]);
+	freetree(p->child[1]);
+	freetree(p->child[2]);
+	if(p->str) efree(p->str);
+	efree((char *)p);
+}