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 *
copyfunc(union node * n)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 *
getfuncnode(struct funcdef * fn)132 getfuncnode(struct funcdef *fn)
133 {
134 return fn == NULL ? NULL : &fn->n;
135 }
136
137
138 static void
calcsize(union node * n,struct nodesize * result)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
sizenodelist(struct nodelist * lp,struct nodesize * result)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 *
copynode(union node * n,struct nodecopystate * state)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 *
copynodelist(struct nodelist * lp,struct nodecopystate * state)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 *
nodesavestr(const char * s,struct nodecopystate * state)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
reffunc(struct funcdef * fn)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
unreffunc(struct funcdef * fn)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