xref: /netbsd-src/bin/sh/nodes.c.pat (revision c7c0722af5685637af1038be53104003c3aad1cf)
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