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 struct nodesize { 54 int blocksize; /* size of structures in function */ 55 int stringsize; /* size of strings in node */ 56 }; 57 58 struct nodecopystate { 59 pointer block; /* block to allocate function from */ 60 char *string; /* block to allocate strings from */ 61 }; 62 63 static const short nodesize[27] = { 64 ALIGN(sizeof (struct nbinary)), 65 ALIGN(sizeof (struct ncmd)), 66 ALIGN(sizeof (struct npipe)), 67 ALIGN(sizeof (struct nredir)), 68 ALIGN(sizeof (struct nredir)), 69 ALIGN(sizeof (struct nredir)), 70 ALIGN(sizeof (struct nbinary)), 71 ALIGN(sizeof (struct nbinary)), 72 ALIGN(sizeof (struct nif)), 73 ALIGN(sizeof (struct nbinary)), 74 ALIGN(sizeof (struct nbinary)), 75 ALIGN(sizeof (struct nfor)), 76 ALIGN(sizeof (struct ncase)), 77 ALIGN(sizeof (struct nclist)), 78 ALIGN(sizeof (struct nclist)), 79 ALIGN(sizeof (struct narg)), 80 ALIGN(sizeof (struct narg)), 81 ALIGN(sizeof (struct nfile)), 82 ALIGN(sizeof (struct nfile)), 83 ALIGN(sizeof (struct nfile)), 84 ALIGN(sizeof (struct nfile)), 85 ALIGN(sizeof (struct nfile)), 86 ALIGN(sizeof (struct ndup)), 87 ALIGN(sizeof (struct ndup)), 88 ALIGN(sizeof (struct nhere)), 89 ALIGN(sizeof (struct nhere)), 90 ALIGN(sizeof (struct nnot)), 91 }; 92 93 94 static void calcsize(union node *, struct nodesize *); 95 static void sizenodelist(struct nodelist *, struct nodesize *); 96 static union node *copynode(union node *, struct nodecopystate *); 97 static struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *); 98 static char *nodesavestr(const char *, struct nodecopystate *); 99 100 101 struct funcdef { 102 unsigned int refcount; 103 union node n; 104 }; 105 106 /* 107 * Make a copy of a parse tree. 108 */ 109 110 struct funcdef * 111 copyfunc(union node *n) 112 { 113 struct nodesize sz; 114 struct nodecopystate st; 115 struct funcdef *fn; 116 117 if (n == NULL) 118 return NULL; 119 sz.blocksize = offsetof(struct funcdef, n); 120 sz.stringsize = 0; 121 calcsize(n, &sz); 122 fn = ckmalloc(sz.blocksize + sz.stringsize); 123 fn->refcount = 1; 124 st.block = (char *)fn + offsetof(struct funcdef, n); 125 st.string = (char *)fn + sz.blocksize; 126 copynode(n, &st); 127 return fn; 128 } 129 130 131 union node * 132 getfuncnode(struct funcdef *fn) 133 { 134 return fn == NULL ? NULL : &fn->n; 135 } 136 137 138 static void 139 calcsize(union node *n, struct nodesize *result) 140 { 141 if (n == NULL) 142 return; 143 result->blocksize += nodesize[n->type]; 144 switch (n->type) { 145 case NSEMI: 146 case NAND: 147 case NOR: 148 case NWHILE: 149 case NUNTIL: 150 calcsize(n->nbinary.ch2, result); 151 calcsize(n->nbinary.ch1, result); 152 break; 153 case NCMD: 154 calcsize(n->ncmd.redirect, result); 155 calcsize(n->ncmd.args, result); 156 break; 157 case NPIPE: 158 sizenodelist(n->npipe.cmdlist, result); 159 break; 160 case NREDIR: 161 case NBACKGND: 162 case NSUBSHELL: 163 calcsize(n->nredir.redirect, result); 164 calcsize(n->nredir.n, result); 165 break; 166 case NIF: 167 calcsize(n->nif.elsepart, result); 168 calcsize(n->nif.ifpart, result); 169 calcsize(n->nif.test, result); 170 break; 171 case NFOR: 172 result->stringsize += strlen(n->nfor.var) + 1; 173 calcsize(n->nfor.body, result); 174 calcsize(n->nfor.args, result); 175 break; 176 case NCASE: 177 calcsize(n->ncase.cases, result); 178 calcsize(n->ncase.expr, result); 179 break; 180 case NCLIST: 181 case NCLISTFALLTHRU: 182 calcsize(n->nclist.body, result); 183 calcsize(n->nclist.pattern, result); 184 calcsize(n->nclist.next, result); 185 break; 186 case NDEFUN: 187 case NARG: 188 sizenodelist(n->narg.backquote, result); 189 result->stringsize += strlen(n->narg.text) + 1; 190 calcsize(n->narg.next, result); 191 break; 192 case NTO: 193 case NFROM: 194 case NFROMTO: 195 case NAPPEND: 196 case NCLOBBER: 197 calcsize(n->nfile.fname, result); 198 calcsize(n->nfile.next, result); 199 break; 200 case NTOFD: 201 case NFROMFD: 202 calcsize(n->ndup.vname, result); 203 calcsize(n->ndup.next, result); 204 break; 205 case NHERE: 206 case NXHERE: 207 calcsize(n->nhere.doc, result); 208 calcsize(n->nhere.next, result); 209 break; 210 case NNOT: 211 calcsize(n->nnot.com, result); 212 break; 213 }; 214 } 215 216 217 218 static void 219 sizenodelist(struct nodelist *lp, struct nodesize *result) 220 { 221 while (lp) { 222 result->blocksize += ALIGN(sizeof(struct nodelist)); 223 calcsize(lp->n, result); 224 lp = lp->next; 225 } 226 } 227 228 229 230 static union node * 231 copynode(union node *n, struct nodecopystate *state) 232 { 233 union node *new; 234 235 if (n == NULL) 236 return NULL; 237 new = state->block; 238 state->block = (char *)state->block + nodesize[n->type]; 239 switch (n->type) { 240 case NSEMI: 241 case NAND: 242 case NOR: 243 case NWHILE: 244 case NUNTIL: 245 new->nbinary.ch2 = copynode(n->nbinary.ch2, state); 246 new->nbinary.ch1 = copynode(n->nbinary.ch1, state); 247 break; 248 case NCMD: 249 new->ncmd.redirect = copynode(n->ncmd.redirect, state); 250 new->ncmd.args = copynode(n->ncmd.args, state); 251 break; 252 case NPIPE: 253 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist, state); 254 new->npipe.backgnd = n->npipe.backgnd; 255 break; 256 case NREDIR: 257 case NBACKGND: 258 case NSUBSHELL: 259 new->nredir.redirect = copynode(n->nredir.redirect, state); 260 new->nredir.n = copynode(n->nredir.n, state); 261 break; 262 case NIF: 263 new->nif.elsepart = copynode(n->nif.elsepart, state); 264 new->nif.ifpart = copynode(n->nif.ifpart, state); 265 new->nif.test = copynode(n->nif.test, state); 266 break; 267 case NFOR: 268 new->nfor.var = nodesavestr(n->nfor.var, state); 269 new->nfor.body = copynode(n->nfor.body, state); 270 new->nfor.args = copynode(n->nfor.args, state); 271 break; 272 case NCASE: 273 new->ncase.cases = copynode(n->ncase.cases, state); 274 new->ncase.expr = copynode(n->ncase.expr, state); 275 break; 276 case NCLIST: 277 case NCLISTFALLTHRU: 278 new->nclist.body = copynode(n->nclist.body, state); 279 new->nclist.pattern = copynode(n->nclist.pattern, state); 280 new->nclist.next = copynode(n->nclist.next, state); 281 break; 282 case NDEFUN: 283 case NARG: 284 new->narg.backquote = copynodelist(n->narg.backquote, state); 285 new->narg.text = nodesavestr(n->narg.text, state); 286 new->narg.next = copynode(n->narg.next, state); 287 break; 288 case NTO: 289 case NFROM: 290 case NFROMTO: 291 case NAPPEND: 292 case NCLOBBER: 293 new->nfile.fname = copynode(n->nfile.fname, state); 294 new->nfile.next = copynode(n->nfile.next, state); 295 new->nfile.fd = n->nfile.fd; 296 break; 297 case NTOFD: 298 case NFROMFD: 299 new->ndup.vname = copynode(n->ndup.vname, state); 300 new->ndup.dupfd = n->ndup.dupfd; 301 new->ndup.next = copynode(n->ndup.next, state); 302 new->ndup.fd = n->ndup.fd; 303 break; 304 case NHERE: 305 case NXHERE: 306 new->nhere.doc = copynode(n->nhere.doc, state); 307 new->nhere.next = copynode(n->nhere.next, state); 308 new->nhere.fd = n->nhere.fd; 309 break; 310 case NNOT: 311 new->nnot.com = copynode(n->nnot.com, state); 312 break; 313 }; 314 new->type = n->type; 315 return new; 316 } 317 318 319 static struct nodelist * 320 copynodelist(struct nodelist *lp, struct nodecopystate *state) 321 { 322 struct nodelist *start; 323 struct nodelist **lpp; 324 325 lpp = &start; 326 while (lp) { 327 *lpp = state->block; 328 state->block = (char *)state->block + 329 ALIGN(sizeof(struct nodelist)); 330 (*lpp)->n = copynode(lp->n, state); 331 lp = lp->next; 332 lpp = &(*lpp)->next; 333 } 334 *lpp = NULL; 335 return start; 336 } 337 338 339 340 static char * 341 nodesavestr(const char *s, struct nodecopystate *state) 342 { 343 const char *p = s; 344 char *q = state->string; 345 char *rtn = state->string; 346 347 while ((*q++ = *p++) != '\0') 348 continue; 349 state->string = q; 350 return rtn; 351 } 352 353 354 void 355 reffunc(struct funcdef *fn) 356 { 357 if (fn) 358 fn->refcount++; 359 } 360 361 362 /* 363 * Decrement the reference count of a function definition, freeing it 364 * if it falls to 0. 365 */ 366 367 void 368 unreffunc(struct funcdef *fn) 369 { 370 if (fn) { 371 fn->refcount--; 372 if (fn->refcount > 0) 373 return; 374 ckfree(fn); 375 } 376 } 377