1 /* 2 * This file was generated by the mknodes program. 3 */ 4 5 /*- 6 * Copyright (c) 1991, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Kenneth Almquist. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 37 * $FreeBSD$ 38 */ 39 40 #include <sys/param.h> 41 #include <stdlib.h> 42 #include <stddef.h> 43 /* 44 * Routine for dealing with parsed shell commands. 45 */ 46 47 #include "shell.h" 48 #include "nodes.h" 49 #include "memalloc.h" 50 #include "mystring.h" 51 52 53 static int funcblocksize; /* size of structures in function */ 54 static int funcstringsize; /* size of strings in node */ 55 static pointer funcblock; /* block to allocate function from */ 56 static char *funcstring; /* block to allocate strings from */ 57 58 static const short nodesize[27] = { 59 ALIGN(sizeof (struct nbinary)), 60 ALIGN(sizeof (struct ncmd)), 61 ALIGN(sizeof (struct npipe)), 62 ALIGN(sizeof (struct nredir)), 63 ALIGN(sizeof (struct nredir)), 64 ALIGN(sizeof (struct nredir)), 65 ALIGN(sizeof (struct nbinary)), 66 ALIGN(sizeof (struct nbinary)), 67 ALIGN(sizeof (struct nif)), 68 ALIGN(sizeof (struct nbinary)), 69 ALIGN(sizeof (struct nbinary)), 70 ALIGN(sizeof (struct nfor)), 71 ALIGN(sizeof (struct ncase)), 72 ALIGN(sizeof (struct nclist)), 73 ALIGN(sizeof (struct nclist)), 74 ALIGN(sizeof (struct narg)), 75 ALIGN(sizeof (struct narg)), 76 ALIGN(sizeof (struct nfile)), 77 ALIGN(sizeof (struct nfile)), 78 ALIGN(sizeof (struct nfile)), 79 ALIGN(sizeof (struct nfile)), 80 ALIGN(sizeof (struct nfile)), 81 ALIGN(sizeof (struct ndup)), 82 ALIGN(sizeof (struct ndup)), 83 ALIGN(sizeof (struct nhere)), 84 ALIGN(sizeof (struct nhere)), 85 ALIGN(sizeof (struct nnot)), 86 }; 87 88 89 static void calcsize(union node *); 90 static void sizenodelist(struct nodelist *); 91 static union node *copynode(union node *); 92 static struct nodelist *copynodelist(struct nodelist *); 93 static char *nodesavestr(const char *); 94 95 96 struct funcdef { 97 unsigned int refcount; 98 union node n; 99 }; 100 101 /* 102 * Make a copy of a parse tree. 103 */ 104 105 struct funcdef * 106 copyfunc(union node *n) 107 { 108 struct funcdef *fn; 109 110 if (n == NULL) 111 return NULL; 112 funcblocksize = offsetof(struct funcdef, n); 113 funcstringsize = 0; 114 calcsize(n); 115 fn = ckmalloc(funcblocksize + funcstringsize); 116 fn->refcount = 1; 117 funcblock = (char *)fn + offsetof(struct funcdef, n); 118 funcstring = (char *)fn + funcblocksize; 119 copynode(n); 120 return fn; 121 } 122 123 124 union node * 125 getfuncnode(struct funcdef *fn) 126 { 127 return fn == NULL ? NULL : &fn->n; 128 } 129 130 131 static void 132 calcsize(union node *n) 133 { 134 if (n == NULL) 135 return; 136 funcblocksize += nodesize[n->type]; 137 switch (n->type) { 138 case NSEMI: 139 case NAND: 140 case NOR: 141 case NWHILE: 142 case NUNTIL: 143 calcsize(n->nbinary.ch2); 144 calcsize(n->nbinary.ch1); 145 break; 146 case NCMD: 147 calcsize(n->ncmd.redirect); 148 calcsize(n->ncmd.args); 149 break; 150 case NPIPE: 151 sizenodelist(n->npipe.cmdlist); 152 break; 153 case NREDIR: 154 case NBACKGND: 155 case NSUBSHELL: 156 calcsize(n->nredir.redirect); 157 calcsize(n->nredir.n); 158 break; 159 case NIF: 160 calcsize(n->nif.elsepart); 161 calcsize(n->nif.ifpart); 162 calcsize(n->nif.test); 163 break; 164 case NFOR: 165 funcstringsize += strlen(n->nfor.var) + 1; 166 calcsize(n->nfor.body); 167 calcsize(n->nfor.args); 168 break; 169 case NCASE: 170 calcsize(n->ncase.cases); 171 calcsize(n->ncase.expr); 172 break; 173 case NCLIST: 174 case NCLISTFALLTHRU: 175 calcsize(n->nclist.body); 176 calcsize(n->nclist.pattern); 177 calcsize(n->nclist.next); 178 break; 179 case NDEFUN: 180 case NARG: 181 sizenodelist(n->narg.backquote); 182 funcstringsize += strlen(n->narg.text) + 1; 183 calcsize(n->narg.next); 184 break; 185 case NTO: 186 case NFROM: 187 case NFROMTO: 188 case NAPPEND: 189 case NCLOBBER: 190 calcsize(n->nfile.fname); 191 calcsize(n->nfile.next); 192 break; 193 case NTOFD: 194 case NFROMFD: 195 calcsize(n->ndup.vname); 196 calcsize(n->ndup.next); 197 break; 198 case NHERE: 199 case NXHERE: 200 calcsize(n->nhere.doc); 201 calcsize(n->nhere.next); 202 break; 203 case NNOT: 204 calcsize(n->nnot.com); 205 break; 206 }; 207 } 208 209 210 211 static void 212 sizenodelist(struct nodelist *lp) 213 { 214 while (lp) { 215 funcblocksize += ALIGN(sizeof(struct nodelist)); 216 calcsize(lp->n); 217 lp = lp->next; 218 } 219 } 220 221 222 223 static union node * 224 copynode(union node *n) 225 { 226 union node *new; 227 228 if (n == NULL) 229 return NULL; 230 new = funcblock; 231 funcblock = (char *)funcblock + nodesize[n->type]; 232 switch (n->type) { 233 case NSEMI: 234 case NAND: 235 case NOR: 236 case NWHILE: 237 case NUNTIL: 238 new->nbinary.ch2 = copynode(n->nbinary.ch2); 239 new->nbinary.ch1 = copynode(n->nbinary.ch1); 240 break; 241 case NCMD: 242 new->ncmd.redirect = copynode(n->ncmd.redirect); 243 new->ncmd.args = copynode(n->ncmd.args); 244 break; 245 case NPIPE: 246 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); 247 new->npipe.backgnd = n->npipe.backgnd; 248 break; 249 case NREDIR: 250 case NBACKGND: 251 case NSUBSHELL: 252 new->nredir.redirect = copynode(n->nredir.redirect); 253 new->nredir.n = copynode(n->nredir.n); 254 break; 255 case NIF: 256 new->nif.elsepart = copynode(n->nif.elsepart); 257 new->nif.ifpart = copynode(n->nif.ifpart); 258 new->nif.test = copynode(n->nif.test); 259 break; 260 case NFOR: 261 new->nfor.var = nodesavestr(n->nfor.var); 262 new->nfor.body = copynode(n->nfor.body); 263 new->nfor.args = copynode(n->nfor.args); 264 break; 265 case NCASE: 266 new->ncase.cases = copynode(n->ncase.cases); 267 new->ncase.expr = copynode(n->ncase.expr); 268 break; 269 case NCLIST: 270 case NCLISTFALLTHRU: 271 new->nclist.body = copynode(n->nclist.body); 272 new->nclist.pattern = copynode(n->nclist.pattern); 273 new->nclist.next = copynode(n->nclist.next); 274 break; 275 case NDEFUN: 276 case NARG: 277 new->narg.backquote = copynodelist(n->narg.backquote); 278 new->narg.text = nodesavestr(n->narg.text); 279 new->narg.next = copynode(n->narg.next); 280 break; 281 case NTO: 282 case NFROM: 283 case NFROMTO: 284 case NAPPEND: 285 case NCLOBBER: 286 new->nfile.fname = copynode(n->nfile.fname); 287 new->nfile.next = copynode(n->nfile.next); 288 new->nfile.fd = n->nfile.fd; 289 break; 290 case NTOFD: 291 case NFROMFD: 292 new->ndup.vname = copynode(n->ndup.vname); 293 new->ndup.dupfd = n->ndup.dupfd; 294 new->ndup.next = copynode(n->ndup.next); 295 new->ndup.fd = n->ndup.fd; 296 break; 297 case NHERE: 298 case NXHERE: 299 new->nhere.doc = copynode(n->nhere.doc); 300 new->nhere.next = copynode(n->nhere.next); 301 new->nhere.fd = n->nhere.fd; 302 break; 303 case NNOT: 304 new->nnot.com = copynode(n->nnot.com); 305 break; 306 }; 307 new->type = n->type; 308 return new; 309 } 310 311 312 static struct nodelist * 313 copynodelist(struct nodelist *lp) 314 { 315 struct nodelist *start; 316 struct nodelist **lpp; 317 318 lpp = &start; 319 while (lp) { 320 *lpp = funcblock; 321 funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist)); 322 (*lpp)->n = copynode(lp->n); 323 lp = lp->next; 324 lpp = &(*lpp)->next; 325 } 326 *lpp = NULL; 327 return start; 328 } 329 330 331 332 static char * 333 nodesavestr(const char *s) 334 { 335 const char *p = s; 336 char *q = funcstring; 337 char *rtn = funcstring; 338 339 while ((*q++ = *p++) != '\0') 340 continue; 341 funcstring = q; 342 return rtn; 343 } 344 345 346 void 347 reffunc(struct funcdef *fn) 348 { 349 if (fn) 350 fn->refcount++; 351 } 352 353 354 /* 355 * Decrement the reference count of a function definition, freeing it 356 * if it falls to 0. 357 */ 358 359 void 360 unreffunc(struct funcdef *fn) 361 { 362 if (fn) { 363 fn->refcount--; 364 if (fn->refcount > 0) 365 return; 366 ckfree(fn); 367 } 368 } 369