4.4BSD/usr/src/contrib/rc-1.4/tree.c
/* tree.c: functions for manipulating parse-trees. (create, copy, delete) */
#include "rc.h"
/* make a new node, pass it back to yyparse. Used to generate the parsetree. */
extern Node *mk(int /*nodetype*/ t,...) {
va_list ap;
Node *n;
va_start(ap, t);
switch (t) {
default:
panic("unexpected node in mk");
/* NOTREACHED */
case nDup:
n = nalloc(offsetof(Node, u[3]));
n->u[0].i = va_arg(ap, int);
n->u[1].i = va_arg(ap, int);
n->u[2].i = va_arg(ap, int);
break;
case nWord: case nQword:
n = nalloc(offsetof(Node, u[2]));
n->u[0].s = va_arg(ap, char *);
n->u[1].s = va_arg(ap, char *);
break;
case nBang: case nNowait:
case nCount: case nFlat: case nRmfn: case nSubshell:
case nVar: case nCase:
n = nalloc(offsetof(Node, u[1]));
n->u[0].p = va_arg(ap, Node *);
break;
case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat:
case nElse: case nEpilog: case nIf: case nNewfn: case nCbody:
case nOrelse: case nPre: case nArgs: case nSwitch:
case nMatch: case nVarsub: case nWhile: case nLappend:
n = nalloc(offsetof(Node, u[2]));
n->u[0].p = va_arg(ap, Node *);
n->u[1].p = va_arg(ap, Node *);
break;
case nForin:
n = nalloc(offsetof(Node, u[3]));
n->u[0].p = va_arg(ap, Node *);
n->u[1].p = va_arg(ap, Node *);
n->u[2].p = va_arg(ap, Node *);
break;
case nPipe:
n = nalloc(offsetof(Node, u[4]));
n->u[0].i = va_arg(ap, int);
n->u[1].i = va_arg(ap, int);
n->u[2].p = va_arg(ap, Node *);
n->u[3].p = va_arg(ap, Node *);
break;
case nRedir:
case nNmpipe:
n = nalloc(offsetof(Node, u[3]));
n->u[0].i = va_arg(ap, int);
n->u[1].i = va_arg(ap, int);
n->u[2].p = va_arg(ap, Node *);
break;
}
n->type = t;
va_end(ap);
return n;
}
/* copy a tree to malloc space. Used when storing the definition of a function */
extern Node *treecpy(Node *s, void *(*alloc)(size_t)) {
Node *n;
if (s == NULL)
return NULL;
switch (s->type) {
default:
panic("unexpected node in treecpy");
/* NOTREACHED */
case nDup:
n = (*alloc)(offsetof(Node, u[3]));
n->u[0].i = s->u[0].i;
n->u[1].i = s->u[1].i;
n->u[2].i = s->u[2].i;
break;
case nWord: case nQword:
n = (*alloc)(offsetof(Node, u[2]));
n->u[0].s = strcpy((char *) (*alloc)(strlen(s->u[0].s) + 1), s->u[0].s);
if (s->u[1].s != NULL) {
size_t i = strlen(s->u[0].s);
n->u[1].s = (*alloc)(i);
memcpy(n->u[1].s, s->u[1].s, i);
} else
n->u[1].s = NULL;
break;
case nBang: case nNowait: case nCase:
case nCount: case nFlat: case nRmfn: case nSubshell: case nVar:
n = (*alloc)(offsetof(Node, u[1]));
n->u[0].p = treecpy(s->u[0].p, alloc);
break;
case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat:
case nElse: case nEpilog: case nIf: case nNewfn: case nCbody:
case nOrelse: case nPre: case nArgs: case nSwitch:
case nMatch: case nVarsub: case nWhile: case nLappend:
n = (*alloc)(offsetof(Node, u[2]));
n->u[0].p = treecpy(s->u[0].p, alloc);
n->u[1].p = treecpy(s->u[1].p, alloc);
break;
case nForin:
n = (*alloc)(offsetof(Node, u[3]));
n->u[0].p = treecpy(s->u[0].p, alloc);
n->u[1].p = treecpy(s->u[1].p, alloc);
n->u[2].p = treecpy(s->u[2].p, alloc);
break;
case nPipe:
n = (*alloc)(offsetof(Node, u[4]));
n->u[0].i = s->u[0].i;
n->u[1].i = s->u[1].i;
n->u[2].p = treecpy(s->u[2].p, alloc);
n->u[3].p = treecpy(s->u[3].p, alloc);
break;
case nRedir:
case nNmpipe:
n = (*alloc)(offsetof(Node, u[3]));
n->u[0].i = s->u[0].i;
n->u[1].i = s->u[1].i;
n->u[2].p = treecpy(s->u[2].p, alloc);
break;
}
n->type = s->type;
return n;
}
/* free a function definition that is no longer needed */
extern void treefree(Node *s) {
if (s == NULL)
return;
switch (s->type) {
default:
panic("unexpected node in treefree");
/* NOTREACHED */
case nDup:
break;
case nWord: case nQword:
efree(s->u[0].s);
efree(s->u[1].s);
break;
case nBang: case nNowait:
case nCount: case nFlat: case nRmfn:
case nSubshell: case nVar: case nCase:
treefree(s->u[0].p);
break;
case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat:
case nElse: case nEpilog: case nIf: case nNewfn:
case nOrelse: case nPre: case nArgs: case nCbody:
case nSwitch: case nMatch: case nVarsub: case nWhile:
case nLappend:
treefree(s->u[1].p);
treefree(s->u[0].p);
break;
case nForin:
treefree(s->u[2].p);
treefree(s->u[1].p);
treefree(s->u[0].p);
break;
case nPipe:
treefree(s->u[2].p);
treefree(s->u[3].p);
break;
case nRedir:
case nNmpipe:
treefree(s->u[2].p);
}
efree(s);
}