/* 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); }