tree.c (5863B)
1 /* tree.c: functions for manipulating parse-trees. (create, copy, delete) */ 2 3 #include "rc.h" 4 5 #include "develop.h" 6 7 /* convert if followed by ifnot to else */ 8 static Node *desugar_ifnot(Node *n) { 9 if (n->type == nBody && n->u[1].p && n->u[1].p->type == nIfnot) { 10 /* (body (if c x) (if-not y)) => (body (if c (else x y))) */ 11 if (n->u[0].p->type == nIf && 12 n->u[0].p->u[1].p->type != nElse) { 13 Node *yes = n->u[0].p; 14 Node *no = n->u[1].p; 15 Node *els = nalloc(offsetof(Node, u[2])); 16 els->type = nElse; 17 els->u[1].p = no->u[0].p; 18 els->u[0].p = yes->u[1].p; 19 yes->u[1].p = els; 20 n->u[1].p = NULL; 21 } else goto fail; 22 } else if (n->type == nBody && 23 n->u[1].p && n->u[1].p->type == nBody && 24 n->u[1].p->u[0].p && 25 n->u[1].p->u[0].p->type == nIfnot) { 26 /* (body (if c x) (body (if-not y) z)) => 27 (body (if c (else x y)) z) */ 28 if (n->u[0].p->type == nIf && 29 n->u[0].p->u[1].p->type != nElse) { 30 Node *yes = n->u[0].p; 31 Node *no = n->u[1].p->u[0].p; 32 Node *els = nalloc(offsetof(Node, u[2])); 33 els->type = nElse; 34 els->u[1].p = no->u[0].p; 35 els->u[0].p = yes->u[1].p; 36 yes->u[1].p = els; 37 n->u[1].p = n->u[1].p->u[1].p; 38 } else goto fail; 39 } 40 41 return n; 42 fail: 43 rc_error("`if not' must follow `if'"); 44 return NULL; 45 } 46 47 /* make a new node, pass it back to yyparse. Used to generate the parsetree. */ 48 49 extern Node *mk(enum nodetype t,...) { 50 va_list ap; 51 Node *n; 52 va_start(ap, t); 53 switch (t) { 54 default: 55 panic("unexpected node in mk"); 56 /* NOTREACHED */ 57 case nDup: 58 n = nalloc(offsetof(Node, u[3])); 59 n->u[0].i = va_arg(ap, int); 60 n->u[1].i = va_arg(ap, int); 61 n->u[2].i = va_arg(ap, int); 62 break; 63 case nWord: 64 n = nalloc(offsetof(Node, u[3])); 65 n->u[0].s = va_arg(ap, char *); 66 n->u[1].s = va_arg(ap, char *); 67 n->u[2].i = va_arg(ap, int); 68 break; 69 case nBang: case nNowait: 70 case nCount: case nFlat: case nRmfn: case nSubshell: 71 case nVar: case nCase: case nIfnot: 72 n = nalloc(offsetof(Node, u[1])); 73 n->u[0].p = va_arg(ap, Node *); 74 break; 75 case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: 76 case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: 77 case nOrelse: case nPre: case nArgs: case nSwitch: 78 case nMatch: case nVarsub: case nWhile: case nLappend: 79 n = nalloc(offsetof(Node, u[2])); 80 n->u[0].p = va_arg(ap, Node *); 81 n->u[1].p = va_arg(ap, Node *); 82 break; 83 case nForin: 84 n = nalloc(offsetof(Node, u[3])); 85 n->u[0].p = va_arg(ap, Node *); 86 n->u[1].p = va_arg(ap, Node *); 87 n->u[2].p = va_arg(ap, Node *); 88 break; 89 case nPipe: 90 n = nalloc(offsetof(Node, u[4])); 91 n->u[0].i = va_arg(ap, int); 92 n->u[1].i = va_arg(ap, int); 93 n->u[2].p = va_arg(ap, Node *); 94 n->u[3].p = va_arg(ap, Node *); 95 break; 96 case nRedir: 97 case nNmpipe: 98 n = nalloc(offsetof(Node, u[3])); 99 n->u[0].i = va_arg(ap, int); 100 n->u[1].i = va_arg(ap, int); 101 n->u[2].p = va_arg(ap, Node *); 102 break; 103 } 104 n->type = t; 105 106 if (0 && RC_DEVELOP) { 107 tree_dump(n); 108 fprint(2, "---\n"); 109 } 110 n = desugar_ifnot(n); 111 va_end(ap); 112 return n; 113 } 114 115 /* copy a tree to malloc space. Used when storing the definition of a function */ 116 117 extern Node *treecpy(Node *s, void *(*alloc)(size_t)) { 118 Node *n; 119 if (s == NULL) 120 return NULL; 121 switch (s->type) { 122 default: 123 panic("unexpected node in treecpy"); 124 /* NOTREACHED */ 125 case nDup: 126 n = (*alloc)(offsetof(Node, u[3])); 127 n->u[0].i = s->u[0].i; 128 n->u[1].i = s->u[1].i; 129 n->u[2].i = s->u[2].i; 130 break; 131 case nWord: 132 n = (*alloc)(offsetof(Node, u[3])); 133 n->u[0].s = strcpy((char *) (*alloc)(strlen(s->u[0].s) + 1), s->u[0].s); 134 if (s->u[1].s != NULL) { 135 size_t i = strlen(s->u[0].s); 136 n->u[1].s = (*alloc)(i); 137 memcpy(n->u[1].s, s->u[1].s, i); 138 } else 139 n->u[1].s = NULL; 140 n->u[2].i = s->u[2].i; 141 break; 142 case nBang: case nNowait: case nCase: 143 case nCount: case nFlat: case nRmfn: case nSubshell: case nVar: 144 n = (*alloc)(offsetof(Node, u[1])); 145 n->u[0].p = treecpy(s->u[0].p, alloc); 146 break; 147 case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: 148 case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: 149 case nOrelse: case nPre: case nArgs: case nSwitch: 150 case nMatch: case nVarsub: case nWhile: case nLappend: 151 n = (*alloc)(offsetof(Node, u[2])); 152 n->u[0].p = treecpy(s->u[0].p, alloc); 153 n->u[1].p = treecpy(s->u[1].p, alloc); 154 break; 155 case nForin: 156 n = (*alloc)(offsetof(Node, u[3])); 157 n->u[0].p = treecpy(s->u[0].p, alloc); 158 n->u[1].p = treecpy(s->u[1].p, alloc); 159 n->u[2].p = treecpy(s->u[2].p, alloc); 160 break; 161 case nPipe: 162 n = (*alloc)(offsetof(Node, u[4])); 163 n->u[0].i = s->u[0].i; 164 n->u[1].i = s->u[1].i; 165 n->u[2].p = treecpy(s->u[2].p, alloc); 166 n->u[3].p = treecpy(s->u[3].p, alloc); 167 break; 168 case nRedir: 169 case nNmpipe: 170 n = (*alloc)(offsetof(Node, u[3])); 171 n->u[0].i = s->u[0].i; 172 n->u[1].i = s->u[1].i; 173 n->u[2].p = treecpy(s->u[2].p, alloc); 174 break; 175 } 176 n->type = s->type; 177 return n; 178 } 179 180 /* free a function definition that is no longer needed */ 181 182 extern void treefree(Node *s) { 183 if (s == NULL) 184 return; 185 switch (s->type) { 186 default: 187 panic("unexpected node in treefree"); 188 /* NOTREACHED */ 189 case nDup: 190 break; 191 case nWord: 192 efree(s->u[0].s); 193 efree(s->u[1].s); 194 break; 195 case nBang: case nNowait: 196 case nCount: case nFlat: case nRmfn: 197 case nSubshell: case nVar: case nCase: 198 treefree(s->u[0].p); 199 break; 200 case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: 201 case nElse: case nEpilog: case nIf: case nNewfn: 202 case nOrelse: case nPre: case nArgs: case nCbody: 203 case nSwitch: case nMatch: case nVarsub: case nWhile: 204 case nLappend: 205 treefree(s->u[1].p); 206 treefree(s->u[0].p); 207 break; 208 case nForin: 209 treefree(s->u[2].p); 210 treefree(s->u[1].p); 211 treefree(s->u[0].p); 212 break; 213 case nPipe: 214 treefree(s->u[2].p); 215 treefree(s->u[3].p); 216 break; 217 case nRedir: 218 case nNmpipe: 219 treefree(s->u[2].p); 220 } 221 efree(s); 222 }