nodes.c.pat revision 1.14 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 */
52 struct 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 */
58 struct 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
68 STATIC void calcsize(union node *, struct nodesize *);
69 STATIC void sizenodelist(struct nodelist *, struct nodesize *);
70 STATIC union node *copynode(union node *, struct nodecopystate *);
71 STATIC struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *);
72 STATIC char *nodesavestr(char *, struct nodecopystate *);
73
74 struct 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
84 struct funcdef *
85 copyfunc(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
104 union node *
105 getfuncnode(struct funcdef *fn)
106 {
107 if (fn == NULL)
108 return NULL;
109 return &fn->n;
110 }
111
112
113 STATIC void
114 calcsize(union node *n, struct nodesize *res)
115 {
116 %CALCSIZE
117 }
118
119
120
121 STATIC void
122 sizenodelist(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
133 STATIC union node *
134 copynode(union node *n, struct nodecopystate *st)
135 {
136 union node *new;
137
138 %COPY
139 return new;
140 }
141
142
143 STATIC struct nodelist *
144 copynodelist(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
164 STATIC char *
165 nodesavestr(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
184 void
185 reffunc(struct funcdef *fn)
186 {
187 if (fn != NULL)
188 fn->refcount++;
189 }
190
191 void
192 unreffunc(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 */
205 void
206 freefunc(struct funcdef *fn)
207 {
208 if (fn != NULL)
209 ckfree(fn);
210 }
211