1cbb07febSzrj /*
2cbb07febSzrj * This file was generated by the mknodes program.
3cbb07febSzrj */
4cbb07febSzrj
5cbb07febSzrj /*-
6cbb07febSzrj * Copyright (c) 1991, 1993
7cbb07febSzrj * The Regents of the University of California. All rights reserved.
8cbb07febSzrj *
9cbb07febSzrj * This code is derived from software contributed to Berkeley by
10cbb07febSzrj * Kenneth Almquist.
11cbb07febSzrj *
12cbb07febSzrj * Redistribution and use in source and binary forms, with or without
13cbb07febSzrj * modification, are permitted provided that the following conditions
14cbb07febSzrj * are met:
15cbb07febSzrj * 1. Redistributions of source code must retain the above copyright
16cbb07febSzrj * notice, this list of conditions and the following disclaimer.
17cbb07febSzrj * 2. Redistributions in binary form must reproduce the above copyright
18cbb07febSzrj * notice, this list of conditions and the following disclaimer in the
19cbb07febSzrj * documentation and/or other materials provided with the distribution.
20cbb07febSzrj * 3. Neither the name of the University nor the names of its contributors
21cbb07febSzrj * may be used to endorse or promote products derived from this software
22cbb07febSzrj * without specific prior written permission.
23cbb07febSzrj *
24cbb07febSzrj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25cbb07febSzrj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26cbb07febSzrj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27cbb07febSzrj * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28cbb07febSzrj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29cbb07febSzrj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30cbb07febSzrj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31cbb07febSzrj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32cbb07febSzrj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33cbb07febSzrj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34cbb07febSzrj * SUCH DAMAGE.
35cbb07febSzrj *
36cbb07febSzrj * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
37cbb07febSzrj * $FreeBSD$
38cbb07febSzrj */
39cbb07febSzrj
40cbb07febSzrj #include <sys/param.h>
41cbb07febSzrj #include <stdlib.h>
42cbb07febSzrj #include <stddef.h>
43cbb07febSzrj /*
44cbb07febSzrj * Routine for dealing with parsed shell commands.
45cbb07febSzrj */
46cbb07febSzrj
47cbb07febSzrj #include "shell.h"
48cbb07febSzrj #include "nodes.h"
49cbb07febSzrj #include "memalloc.h"
50cbb07febSzrj #include "mystring.h"
51cbb07febSzrj
52cbb07febSzrj
53*3e3895bfSKrzysztof Piecuch struct nodesize {
54*3e3895bfSKrzysztof Piecuch int blocksize; /* size of structures in function */
55*3e3895bfSKrzysztof Piecuch int stringsize; /* size of strings in node */
56*3e3895bfSKrzysztof Piecuch };
57*3e3895bfSKrzysztof Piecuch
58*3e3895bfSKrzysztof Piecuch struct nodecopystate {
59*3e3895bfSKrzysztof Piecuch pointer block; /* block to allocate function from */
60*3e3895bfSKrzysztof Piecuch char *string; /* block to allocate strings from */
61*3e3895bfSKrzysztof Piecuch };
62cbb07febSzrj
63cbb07febSzrj static const short nodesize[27] = {
64cbb07febSzrj ALIGN(sizeof (struct nbinary)),
65cbb07febSzrj ALIGN(sizeof (struct ncmd)),
66cbb07febSzrj ALIGN(sizeof (struct npipe)),
67cbb07febSzrj ALIGN(sizeof (struct nredir)),
68cbb07febSzrj ALIGN(sizeof (struct nredir)),
69cbb07febSzrj ALIGN(sizeof (struct nredir)),
70cbb07febSzrj ALIGN(sizeof (struct nbinary)),
71cbb07febSzrj ALIGN(sizeof (struct nbinary)),
72cbb07febSzrj ALIGN(sizeof (struct nif)),
73cbb07febSzrj ALIGN(sizeof (struct nbinary)),
74cbb07febSzrj ALIGN(sizeof (struct nbinary)),
75cbb07febSzrj ALIGN(sizeof (struct nfor)),
76cbb07febSzrj ALIGN(sizeof (struct ncase)),
77cbb07febSzrj ALIGN(sizeof (struct nclist)),
78cbb07febSzrj ALIGN(sizeof (struct nclist)),
79cbb07febSzrj ALIGN(sizeof (struct narg)),
80cbb07febSzrj ALIGN(sizeof (struct narg)),
81cbb07febSzrj ALIGN(sizeof (struct nfile)),
82cbb07febSzrj ALIGN(sizeof (struct nfile)),
83cbb07febSzrj ALIGN(sizeof (struct nfile)),
84cbb07febSzrj ALIGN(sizeof (struct nfile)),
85cbb07febSzrj ALIGN(sizeof (struct nfile)),
86cbb07febSzrj ALIGN(sizeof (struct ndup)),
87cbb07febSzrj ALIGN(sizeof (struct ndup)),
88cbb07febSzrj ALIGN(sizeof (struct nhere)),
89cbb07febSzrj ALIGN(sizeof (struct nhere)),
90cbb07febSzrj ALIGN(sizeof (struct nnot)),
91cbb07febSzrj };
92cbb07febSzrj
93cbb07febSzrj
94*3e3895bfSKrzysztof Piecuch static void calcsize(union node *, struct nodesize *);
95*3e3895bfSKrzysztof Piecuch static void sizenodelist(struct nodelist *, struct nodesize *);
96*3e3895bfSKrzysztof Piecuch static union node *copynode(union node *, struct nodecopystate *);
97*3e3895bfSKrzysztof Piecuch static struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *);
98*3e3895bfSKrzysztof Piecuch static char *nodesavestr(const char *, struct nodecopystate *);
99cbb07febSzrj
100cbb07febSzrj
101cbb07febSzrj struct funcdef {
102cbb07febSzrj unsigned int refcount;
103cbb07febSzrj union node n;
104cbb07febSzrj };
105cbb07febSzrj
106cbb07febSzrj /*
107cbb07febSzrj * Make a copy of a parse tree.
108cbb07febSzrj */
109cbb07febSzrj
110cbb07febSzrj struct funcdef *
copyfunc(union node * n)111cbb07febSzrj copyfunc(union node *n)
112cbb07febSzrj {
113*3e3895bfSKrzysztof Piecuch struct nodesize sz;
114*3e3895bfSKrzysztof Piecuch struct nodecopystate st;
115cbb07febSzrj struct funcdef *fn;
116cbb07febSzrj
117cbb07febSzrj if (n == NULL)
118cbb07febSzrj return NULL;
119*3e3895bfSKrzysztof Piecuch sz.blocksize = offsetof(struct funcdef, n);
120*3e3895bfSKrzysztof Piecuch sz.stringsize = 0;
121*3e3895bfSKrzysztof Piecuch calcsize(n, &sz);
122*3e3895bfSKrzysztof Piecuch fn = ckmalloc(sz.blocksize + sz.stringsize);
123cbb07febSzrj fn->refcount = 1;
124*3e3895bfSKrzysztof Piecuch st.block = (char *)fn + offsetof(struct funcdef, n);
125*3e3895bfSKrzysztof Piecuch st.string = (char *)fn + sz.blocksize;
126*3e3895bfSKrzysztof Piecuch copynode(n, &st);
127cbb07febSzrj return fn;
128cbb07febSzrj }
129cbb07febSzrj
130cbb07febSzrj
131cbb07febSzrj union node *
getfuncnode(struct funcdef * fn)132cbb07febSzrj getfuncnode(struct funcdef *fn)
133cbb07febSzrj {
134cbb07febSzrj return fn == NULL ? NULL : &fn->n;
135cbb07febSzrj }
136cbb07febSzrj
137cbb07febSzrj
138cbb07febSzrj static void
calcsize(union node * n,struct nodesize * result)139*3e3895bfSKrzysztof Piecuch calcsize(union node *n, struct nodesize *result)
140cbb07febSzrj {
141cbb07febSzrj if (n == NULL)
142cbb07febSzrj return;
143*3e3895bfSKrzysztof Piecuch result->blocksize += nodesize[n->type];
144cbb07febSzrj switch (n->type) {
145cbb07febSzrj case NSEMI:
146cbb07febSzrj case NAND:
147cbb07febSzrj case NOR:
148cbb07febSzrj case NWHILE:
149cbb07febSzrj case NUNTIL:
150*3e3895bfSKrzysztof Piecuch calcsize(n->nbinary.ch2, result);
151*3e3895bfSKrzysztof Piecuch calcsize(n->nbinary.ch1, result);
152cbb07febSzrj break;
153cbb07febSzrj case NCMD:
154*3e3895bfSKrzysztof Piecuch calcsize(n->ncmd.redirect, result);
155*3e3895bfSKrzysztof Piecuch calcsize(n->ncmd.args, result);
156cbb07febSzrj break;
157cbb07febSzrj case NPIPE:
158*3e3895bfSKrzysztof Piecuch sizenodelist(n->npipe.cmdlist, result);
159cbb07febSzrj break;
160cbb07febSzrj case NREDIR:
161cbb07febSzrj case NBACKGND:
162cbb07febSzrj case NSUBSHELL:
163*3e3895bfSKrzysztof Piecuch calcsize(n->nredir.redirect, result);
164*3e3895bfSKrzysztof Piecuch calcsize(n->nredir.n, result);
165cbb07febSzrj break;
166cbb07febSzrj case NIF:
167*3e3895bfSKrzysztof Piecuch calcsize(n->nif.elsepart, result);
168*3e3895bfSKrzysztof Piecuch calcsize(n->nif.ifpart, result);
169*3e3895bfSKrzysztof Piecuch calcsize(n->nif.test, result);
170cbb07febSzrj break;
171cbb07febSzrj case NFOR:
172*3e3895bfSKrzysztof Piecuch result->stringsize += strlen(n->nfor.var) + 1;
173*3e3895bfSKrzysztof Piecuch calcsize(n->nfor.body, result);
174*3e3895bfSKrzysztof Piecuch calcsize(n->nfor.args, result);
175cbb07febSzrj break;
176cbb07febSzrj case NCASE:
177*3e3895bfSKrzysztof Piecuch calcsize(n->ncase.cases, result);
178*3e3895bfSKrzysztof Piecuch calcsize(n->ncase.expr, result);
179cbb07febSzrj break;
180cbb07febSzrj case NCLIST:
181cbb07febSzrj case NCLISTFALLTHRU:
182*3e3895bfSKrzysztof Piecuch calcsize(n->nclist.body, result);
183*3e3895bfSKrzysztof Piecuch calcsize(n->nclist.pattern, result);
184*3e3895bfSKrzysztof Piecuch calcsize(n->nclist.next, result);
185cbb07febSzrj break;
186cbb07febSzrj case NDEFUN:
187cbb07febSzrj case NARG:
188*3e3895bfSKrzysztof Piecuch sizenodelist(n->narg.backquote, result);
189*3e3895bfSKrzysztof Piecuch result->stringsize += strlen(n->narg.text) + 1;
190*3e3895bfSKrzysztof Piecuch calcsize(n->narg.next, result);
191cbb07febSzrj break;
192cbb07febSzrj case NTO:
193cbb07febSzrj case NFROM:
194cbb07febSzrj case NFROMTO:
195cbb07febSzrj case NAPPEND:
196cbb07febSzrj case NCLOBBER:
197*3e3895bfSKrzysztof Piecuch calcsize(n->nfile.fname, result);
198*3e3895bfSKrzysztof Piecuch calcsize(n->nfile.next, result);
199cbb07febSzrj break;
200cbb07febSzrj case NTOFD:
201cbb07febSzrj case NFROMFD:
202*3e3895bfSKrzysztof Piecuch calcsize(n->ndup.vname, result);
203*3e3895bfSKrzysztof Piecuch calcsize(n->ndup.next, result);
204cbb07febSzrj break;
205cbb07febSzrj case NHERE:
206cbb07febSzrj case NXHERE:
207*3e3895bfSKrzysztof Piecuch calcsize(n->nhere.doc, result);
208*3e3895bfSKrzysztof Piecuch calcsize(n->nhere.next, result);
209cbb07febSzrj break;
210cbb07febSzrj case NNOT:
211*3e3895bfSKrzysztof Piecuch calcsize(n->nnot.com, result);
212cbb07febSzrj break;
213cbb07febSzrj };
214cbb07febSzrj }
215cbb07febSzrj
216cbb07febSzrj
217cbb07febSzrj
218cbb07febSzrj static void
sizenodelist(struct nodelist * lp,struct nodesize * result)219*3e3895bfSKrzysztof Piecuch sizenodelist(struct nodelist *lp, struct nodesize *result)
220cbb07febSzrj {
221cbb07febSzrj while (lp) {
222*3e3895bfSKrzysztof Piecuch result->blocksize += ALIGN(sizeof(struct nodelist));
223*3e3895bfSKrzysztof Piecuch calcsize(lp->n, result);
224cbb07febSzrj lp = lp->next;
225cbb07febSzrj }
226cbb07febSzrj }
227cbb07febSzrj
228cbb07febSzrj
229cbb07febSzrj
230cbb07febSzrj static union node *
copynode(union node * n,struct nodecopystate * state)231*3e3895bfSKrzysztof Piecuch copynode(union node *n, struct nodecopystate *state)
232cbb07febSzrj {
233cbb07febSzrj union node *new;
234cbb07febSzrj
235cbb07febSzrj if (n == NULL)
236cbb07febSzrj return NULL;
237*3e3895bfSKrzysztof Piecuch new = state->block;
238*3e3895bfSKrzysztof Piecuch state->block = (char *)state->block + nodesize[n->type];
239cbb07febSzrj switch (n->type) {
240cbb07febSzrj case NSEMI:
241cbb07febSzrj case NAND:
242cbb07febSzrj case NOR:
243cbb07febSzrj case NWHILE:
244cbb07febSzrj case NUNTIL:
245*3e3895bfSKrzysztof Piecuch new->nbinary.ch2 = copynode(n->nbinary.ch2, state);
246*3e3895bfSKrzysztof Piecuch new->nbinary.ch1 = copynode(n->nbinary.ch1, state);
247cbb07febSzrj break;
248cbb07febSzrj case NCMD:
249*3e3895bfSKrzysztof Piecuch new->ncmd.redirect = copynode(n->ncmd.redirect, state);
250*3e3895bfSKrzysztof Piecuch new->ncmd.args = copynode(n->ncmd.args, state);
251cbb07febSzrj break;
252cbb07febSzrj case NPIPE:
253*3e3895bfSKrzysztof Piecuch new->npipe.cmdlist = copynodelist(n->npipe.cmdlist, state);
254cbb07febSzrj new->npipe.backgnd = n->npipe.backgnd;
255cbb07febSzrj break;
256cbb07febSzrj case NREDIR:
257cbb07febSzrj case NBACKGND:
258cbb07febSzrj case NSUBSHELL:
259*3e3895bfSKrzysztof Piecuch new->nredir.redirect = copynode(n->nredir.redirect, state);
260*3e3895bfSKrzysztof Piecuch new->nredir.n = copynode(n->nredir.n, state);
261cbb07febSzrj break;
262cbb07febSzrj case NIF:
263*3e3895bfSKrzysztof Piecuch new->nif.elsepart = copynode(n->nif.elsepart, state);
264*3e3895bfSKrzysztof Piecuch new->nif.ifpart = copynode(n->nif.ifpart, state);
265*3e3895bfSKrzysztof Piecuch new->nif.test = copynode(n->nif.test, state);
266cbb07febSzrj break;
267cbb07febSzrj case NFOR:
268*3e3895bfSKrzysztof Piecuch new->nfor.var = nodesavestr(n->nfor.var, state);
269*3e3895bfSKrzysztof Piecuch new->nfor.body = copynode(n->nfor.body, state);
270*3e3895bfSKrzysztof Piecuch new->nfor.args = copynode(n->nfor.args, state);
271cbb07febSzrj break;
272cbb07febSzrj case NCASE:
273*3e3895bfSKrzysztof Piecuch new->ncase.cases = copynode(n->ncase.cases, state);
274*3e3895bfSKrzysztof Piecuch new->ncase.expr = copynode(n->ncase.expr, state);
275cbb07febSzrj break;
276cbb07febSzrj case NCLIST:
277cbb07febSzrj case NCLISTFALLTHRU:
278*3e3895bfSKrzysztof Piecuch new->nclist.body = copynode(n->nclist.body, state);
279*3e3895bfSKrzysztof Piecuch new->nclist.pattern = copynode(n->nclist.pattern, state);
280*3e3895bfSKrzysztof Piecuch new->nclist.next = copynode(n->nclist.next, state);
281cbb07febSzrj break;
282cbb07febSzrj case NDEFUN:
283cbb07febSzrj case NARG:
284*3e3895bfSKrzysztof Piecuch new->narg.backquote = copynodelist(n->narg.backquote, state);
285*3e3895bfSKrzysztof Piecuch new->narg.text = nodesavestr(n->narg.text, state);
286*3e3895bfSKrzysztof Piecuch new->narg.next = copynode(n->narg.next, state);
287cbb07febSzrj break;
288cbb07febSzrj case NTO:
289cbb07febSzrj case NFROM:
290cbb07febSzrj case NFROMTO:
291cbb07febSzrj case NAPPEND:
292cbb07febSzrj case NCLOBBER:
293*3e3895bfSKrzysztof Piecuch new->nfile.fname = copynode(n->nfile.fname, state);
294*3e3895bfSKrzysztof Piecuch new->nfile.next = copynode(n->nfile.next, state);
295cbb07febSzrj new->nfile.fd = n->nfile.fd;
296cbb07febSzrj break;
297cbb07febSzrj case NTOFD:
298cbb07febSzrj case NFROMFD:
299*3e3895bfSKrzysztof Piecuch new->ndup.vname = copynode(n->ndup.vname, state);
300cbb07febSzrj new->ndup.dupfd = n->ndup.dupfd;
301*3e3895bfSKrzysztof Piecuch new->ndup.next = copynode(n->ndup.next, state);
302cbb07febSzrj new->ndup.fd = n->ndup.fd;
303cbb07febSzrj break;
304cbb07febSzrj case NHERE:
305cbb07febSzrj case NXHERE:
306*3e3895bfSKrzysztof Piecuch new->nhere.doc = copynode(n->nhere.doc, state);
307*3e3895bfSKrzysztof Piecuch new->nhere.next = copynode(n->nhere.next, state);
308cbb07febSzrj new->nhere.fd = n->nhere.fd;
309cbb07febSzrj break;
310cbb07febSzrj case NNOT:
311*3e3895bfSKrzysztof Piecuch new->nnot.com = copynode(n->nnot.com, state);
312cbb07febSzrj break;
313cbb07febSzrj };
314cbb07febSzrj new->type = n->type;
315cbb07febSzrj return new;
316cbb07febSzrj }
317cbb07febSzrj
318cbb07febSzrj
319cbb07febSzrj static struct nodelist *
copynodelist(struct nodelist * lp,struct nodecopystate * state)320*3e3895bfSKrzysztof Piecuch copynodelist(struct nodelist *lp, struct nodecopystate *state)
321cbb07febSzrj {
322cbb07febSzrj struct nodelist *start;
323cbb07febSzrj struct nodelist **lpp;
324cbb07febSzrj
325cbb07febSzrj lpp = &start;
326cbb07febSzrj while (lp) {
327*3e3895bfSKrzysztof Piecuch *lpp = state->block;
328*3e3895bfSKrzysztof Piecuch state->block = (char *)state->block +
329*3e3895bfSKrzysztof Piecuch ALIGN(sizeof(struct nodelist));
330*3e3895bfSKrzysztof Piecuch (*lpp)->n = copynode(lp->n, state);
331cbb07febSzrj lp = lp->next;
332cbb07febSzrj lpp = &(*lpp)->next;
333cbb07febSzrj }
334cbb07febSzrj *lpp = NULL;
335cbb07febSzrj return start;
336cbb07febSzrj }
337cbb07febSzrj
338cbb07febSzrj
339cbb07febSzrj
340cbb07febSzrj static char *
nodesavestr(const char * s,struct nodecopystate * state)341*3e3895bfSKrzysztof Piecuch nodesavestr(const char *s, struct nodecopystate *state)
342cbb07febSzrj {
343cbb07febSzrj const char *p = s;
344*3e3895bfSKrzysztof Piecuch char *q = state->string;
345*3e3895bfSKrzysztof Piecuch char *rtn = state->string;
346cbb07febSzrj
347cbb07febSzrj while ((*q++ = *p++) != '\0')
348cbb07febSzrj continue;
349*3e3895bfSKrzysztof Piecuch state->string = q;
350cbb07febSzrj return rtn;
351cbb07febSzrj }
352cbb07febSzrj
353cbb07febSzrj
354cbb07febSzrj void
reffunc(struct funcdef * fn)355cbb07febSzrj reffunc(struct funcdef *fn)
356cbb07febSzrj {
357cbb07febSzrj if (fn)
358cbb07febSzrj fn->refcount++;
359cbb07febSzrj }
360cbb07febSzrj
361cbb07febSzrj
362cbb07febSzrj /*
363cbb07febSzrj * Decrement the reference count of a function definition, freeing it
364cbb07febSzrj * if it falls to 0.
365cbb07febSzrj */
366cbb07febSzrj
367cbb07febSzrj void
unreffunc(struct funcdef * fn)368cbb07febSzrj unreffunc(struct funcdef *fn)
369cbb07febSzrj {
370cbb07febSzrj if (fn) {
371cbb07febSzrj fn->refcount--;
372cbb07febSzrj if (fn->refcount > 0)
373cbb07febSzrj return;
374cbb07febSzrj ckfree(fn);
375cbb07febSzrj }
376cbb07febSzrj }
377