1/* $NetBSD: nodes.c.pat,v 1.14 2018/06/22 11:04:55 kre Exp $ */ 2 3/*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 35 */ 36 37#include <stdlib.h> 38#include <stddef.h> 39 40/* 41 * Routine for dealing with parsed shell commands. 42 */ 43 44#include "shell.h" 45#include "nodes.h" 46#include "memalloc.h" 47#include "machdep.h" 48#include "mystring.h" 49 50 51/* used to accumulate sizes of nodes */ 52struct nodesize { 53 int bsize; /* size of structures in function */ 54 int ssize; /* size of strings in node */ 55}; 56 57/* provides resources for node copies */ 58struct nodecopystate { 59 pointer block; /* block to allocate function from */ 60 char *string; /* block to allocate strings from */ 61}; 62 63 64%SIZES 65 66 67 68STATIC void calcsize(union node *, struct nodesize *); 69STATIC void sizenodelist(struct nodelist *, struct nodesize *); 70STATIC union node *copynode(union node *, struct nodecopystate *); 71STATIC struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *); 72STATIC char *nodesavestr(char *, struct nodecopystate *); 73 74struct funcdef { 75 unsigned int refcount; 76 union node n; /* must be last */ 77}; 78 79 80/* 81 * Make a copy of a parse tree. 82 */ 83 84struct funcdef * 85copyfunc(union node *n) 86{ 87 struct nodesize sz; 88 struct nodecopystate st; 89 struct funcdef *fn; 90 91 if (n == NULL) 92 return NULL; 93 sz.bsize = offsetof(struct funcdef, n); 94 sz.ssize = 0; 95 calcsize(n, &sz); 96 fn = ckmalloc(sz.bsize + sz.ssize); 97 fn->refcount = 1; 98 st.block = (char *)fn + offsetof(struct funcdef, n); 99 st.string = (char *)fn + sz.bsize; 100 copynode(n, &st); 101 return fn; 102} 103 104union node * 105getfuncnode(struct funcdef *fn) 106{ 107 if (fn == NULL) 108 return NULL; 109 return &fn->n; 110} 111 112 113STATIC void 114calcsize(union node *n, struct nodesize *res) 115{ 116 %CALCSIZE 117} 118 119 120 121STATIC void 122sizenodelist(struct nodelist *lp, struct nodesize *res) 123{ 124 while (lp) { 125 res->bsize += SHELL_ALIGN(sizeof(struct nodelist)); 126 calcsize(lp->n, res); 127 lp = lp->next; 128 } 129} 130 131 132 133STATIC union node * 134copynode(union node *n, struct nodecopystate *st) 135{ 136 union node *new; 137 138 %COPY 139 return new; 140} 141 142 143STATIC struct nodelist * 144copynodelist(struct nodelist *lp, struct nodecopystate *st) 145{ 146 struct nodelist *start; 147 struct nodelist **lpp; 148 149 lpp = &start; 150 while (lp) { 151 *lpp = st->block; 152 st->block = (char *)st->block + 153 SHELL_ALIGN(sizeof(struct nodelist)); 154 (*lpp)->n = copynode(lp->n, st); 155 lp = lp->next; 156 lpp = &(*lpp)->next; 157 } 158 *lpp = NULL; 159 return start; 160} 161 162 163 164STATIC char * 165nodesavestr(char *s, struct nodecopystate *st) 166{ 167 register char *p = s; 168 register char *q = st->string; 169 char *rtn = st->string; 170 171 while ((*q++ = *p++) != 0) 172 continue; 173 st->string = q; 174 return rtn; 175} 176 177 178 179/* 180 * Handle making a reference to a function, and releasing it. 181 * Free the func code when there are no remaining references. 182 */ 183 184void 185reffunc(struct funcdef *fn) 186{ 187 if (fn != NULL) 188 fn->refcount++; 189} 190 191void 192unreffunc(struct funcdef *fn) 193{ 194 if (fn != NULL) { 195 if (--fn->refcount > 0) 196 return; 197 ckfree(fn); 198 } 199} 200 201/* 202 * this is used when we need to free the func, regardless of refcount 203 * which only happens when re-initing the shell for a SHELLPROC 204 */ 205void 206freefunc(struct funcdef *fn) 207{ 208 if (fn != NULL) 209 ckfree(fn); 210} 211