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