nodes.c.pat revision 249235
1169695Skan/*-
2169695Skan * Copyright (c) 1991, 1993
3169695Skan *	The Regents of the University of California.  All rights reserved.
4169695Skan *
5169695Skan * This code is derived from software contributed to Berkeley by
6169695Skan * Kenneth Almquist.
7169695Skan *
8169695Skan * Redistribution and use in source and binary forms, with or without
9169695Skan * modification, are permitted provided that the following conditions
10169695Skan * are met:
11169695Skan * 1. Redistributions of source code must retain the above copyright
12169695Skan *    notice, this list of conditions and the following disclaimer.
13169695Skan * 2. Redistributions in binary form must reproduce the above copyright
14169695Skan *    notice, this list of conditions and the following disclaimer in the
15169695Skan *    documentation and/or other materials provided with the distribution.
16169695Skan * 4. Neither the name of the University nor the names of its contributors
17169695Skan *    may be used to endorse or promote products derived from this software
18169695Skan *    without specific prior written permission.
19169695Skan *
20169695Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23169695Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24169695Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25169695Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26169695Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27169695Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28169695Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29169695Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30169695Skan * SUCH DAMAGE.
31169695Skan *
32169695Skan *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
33169695Skan * $FreeBSD: head/bin/sh/nodes.c.pat 249235 2013-04-07 16:28:36Z jilles $
34169695Skan */
35169695Skan
36169695Skan#include <sys/param.h>
37169695Skan#include <stdlib.h>
38169695Skan#include <stddef.h>
39169695Skan/*
40169695Skan * Routine for dealing with parsed shell commands.
41169695Skan */
42169695Skan
43169695Skan#include "shell.h"
44169695Skan#include "nodes.h"
45169695Skan#include "memalloc.h"
46169695Skan#include "mystring.h"
47169695Skan
48169695Skan
49169695Skanstatic int     funcblocksize;	/* size of structures in function */
50169695Skanstatic int     funcstringsize;	/* size of strings in node */
51169695Skanstatic pointer funcblock;	/* block to allocate function from */
52169695Skanstatic char   *funcstring;	/* block to allocate strings from */
53169695Skan
54169695Skan%SIZES
55169695Skan
56169695Skan
57169695Skanstatic void calcsize(union node *);
58169695Skanstatic void sizenodelist(struct nodelist *);
59169695Skanstatic union node *copynode(union node *);
60169695Skanstatic struct nodelist *copynodelist(struct nodelist *);
61169695Skanstatic char *nodesavestr(const char *);
62169695Skan
63169695Skan
64169695Skanstruct funcdef {
65169695Skan	unsigned int refcount;
66169695Skan	union node n;
67169695Skan};
68169695Skan
69169695Skan/*
70169695Skan * Make a copy of a parse tree.
71169695Skan */
72169695Skan
73169695Skanstruct funcdef *
74169695Skancopyfunc(union node *n)
75169695Skan{
76169695Skan	struct funcdef *fn;
77169695Skan
78169695Skan	if (n == NULL)
79169695Skan		return NULL;
80169695Skan	funcblocksize = offsetof(struct funcdef, n);
81169695Skan	funcstringsize = 0;
82169695Skan	calcsize(n);
83169695Skan	fn = ckmalloc(funcblocksize + funcstringsize);
84169695Skan	fn->refcount = 1;
85169695Skan	funcblock = (char *)fn + offsetof(struct funcdef, n);
86169695Skan	funcstring = (char *)fn + funcblocksize;
87169695Skan	copynode(n);
88169695Skan	return fn;
89169695Skan}
90169695Skan
91169695Skan
92169695Skanunion node *
93169695Skangetfuncnode(struct funcdef *fn)
94169695Skan{
95169695Skan	return fn == NULL ? NULL : &fn->n;
96169695Skan}
97169695Skan
98169695Skan
99169695Skanstatic void
100169695Skancalcsize(union node *n)
101169695Skan{
102169695Skan	%CALCSIZE
103169695Skan}
104169695Skan
105169695Skan
106169695Skan
107169695Skanstatic void
108169695Skansizenodelist(struct nodelist *lp)
109169695Skan{
110169695Skan	while (lp) {
111169695Skan		funcblocksize += ALIGN(sizeof(struct nodelist));
112169695Skan		calcsize(lp->n);
113169695Skan		lp = lp->next;
114169695Skan	}
115169695Skan}
116169695Skan
117169695Skan
118169695Skan
119169695Skanstatic union node *
120169695Skancopynode(union node *n)
121169695Skan{
122169695Skan	union node *new;
123169695Skan
124169695Skan	%COPY
125169695Skan	return new;
126169695Skan}
127169695Skan
128169695Skan
129169695Skanstatic struct nodelist *
130169695Skancopynodelist(struct nodelist *lp)
131169695Skan{
132169695Skan	struct nodelist *start;
133169695Skan	struct nodelist **lpp;
134169695Skan
135169695Skan	lpp = &start;
136169695Skan	while (lp) {
137169695Skan		*lpp = funcblock;
138169695Skan		funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
139169695Skan		(*lpp)->n = copynode(lp->n);
140169695Skan		lp = lp->next;
141169695Skan		lpp = &(*lpp)->next;
142169695Skan	}
143169695Skan	*lpp = NULL;
144169695Skan	return start;
145169695Skan}
146169695Skan
147169695Skan
148169695Skan
149169695Skanstatic char *
150169695Skannodesavestr(const char *s)
151169695Skan{
152169695Skan	const char *p = s;
153169695Skan	char *q = funcstring;
154169695Skan	char   *rtn = funcstring;
155169695Skan
156169695Skan	while ((*q++ = *p++) != '\0')
157169695Skan		continue;
158169695Skan	funcstring = q;
159169695Skan	return rtn;
160169695Skan}
161169695Skan
162169695Skan
163169695Skanvoid
164169695Skanreffunc(struct funcdef *fn)
165169695Skan{
166169695Skan	if (fn)
167169695Skan		fn->refcount++;
168169695Skan}
169169695Skan
170169695Skan
171169695Skan/*
172169695Skan * Decrement the reference count of a function definition, freeing it
173169695Skan * if it falls to 0.
174169695Skan */
175169695Skan
176169695Skanvoid
177169695Skanunreffunc(struct funcdef *fn)
178169695Skan{
179169695Skan	if (fn) {
180169695Skan		fn->refcount--;
181169695Skan		if (fn->refcount > 0)
182169695Skan			return;
183169695Skan		ckfree(fn);
184169695Skan	}
185169695Skan}
186169695Skan