nodes.c.pat revision 196634
144743Smarkm/*-
244743Smarkm * Copyright (c) 1991, 1993
344743Smarkm *	The Regents of the University of California.  All rights reserved.
444743Smarkm *
544743Smarkm * This code is derived from software contributed to Berkeley by
644743Smarkm * Kenneth Almquist.
744743Smarkm *
856977Sshin * Redistribution and use in source and binary forms, with or without
956977Sshin * modification, are permitted provided that the following conditions
1044743Smarkm * are met:
1144743Smarkm * 1. Redistributions of source code must retain the above copyright
1244743Smarkm *    notice, this list of conditions and the following disclaimer.
1344743Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1444743Smarkm *    notice, this list of conditions and the following disclaimer in the
1544743Smarkm *    documentation and/or other materials provided with the distribution.
1644743Smarkm * 4. Neither the name of the University nor the names of its contributors
1744743Smarkm *    may be used to endorse or promote products derived from this software
1844743Smarkm *    without specific prior written permission.
1944743Smarkm *
2044743Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2144743Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2244743Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2344743Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2444743Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2544743Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2644743Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2744743Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2844743Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2944743Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3044743Smarkm * SUCH DAMAGE.
3144743Smarkm *
3244743Smarkm *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
3344743Smarkm * $FreeBSD: head/bin/sh/nodes.c.pat 196634 2009-08-28 22:41:25Z jilles $
3444743Smarkm */
3544743Smarkm
3644743Smarkm#include <sys/param.h>
3744743Smarkm#include <stdlib.h>
3844743Smarkm#include <stddef.h>
3944743Smarkm/*
4044743Smarkm * Routine for dealing with parsed shell commands.
4144743Smarkm */
4244743Smarkm
4344743Smarkm#include "shell.h"
4444743Smarkm#include "nodes.h"
4544743Smarkm#include "memalloc.h"
4644743Smarkm#include "mystring.h"
4744743Smarkm
4844743Smarkm
4944743SmarkmSTATIC int     funcblocksize;	/* size of structures in function */
5044743SmarkmSTATIC int     funcstringsize;	/* size of strings in node */
5144743SmarkmSTATIC pointer funcblock;	/* block to allocate function from */
5244743SmarkmSTATIC char   *funcstring;	/* block to allocate strings from */
5344743Smarkm
5444743Smarkm%SIZES
5544743Smarkm
5644743Smarkm
5744743SmarkmSTATIC void calcsize(union node *);
5844743SmarkmSTATIC void sizenodelist(struct nodelist *);
5944743SmarkmSTATIC union node *copynode(union node *);
6044743SmarkmSTATIC struct nodelist *copynodelist(struct nodelist *);
6144743SmarkmSTATIC char *nodesavestr(char *);
6244743Smarkm
6344743Smarkm
6444743Smarkmstruct funcdef {
6544743Smarkm	unsigned int refcount;
6644743Smarkm	union node n;
6744743Smarkm};
6844743Smarkm
6944743Smarkm/*
7044743Smarkm * Make a copy of a parse tree.
7144743Smarkm */
7244743Smarkm
7344743Smarkmstruct funcdef *
7444743Smarkmcopyfunc(union node *n)
7544743Smarkm{
7644743Smarkm	struct funcdef *fn;
7744743Smarkm
7844743Smarkm	if (n == NULL)
7944743Smarkm		return NULL;
8044743Smarkm	funcblocksize = offsetof(struct funcdef, n);
8144743Smarkm	funcstringsize = 0;
8244743Smarkm	calcsize(n);
8344743Smarkm	fn = ckmalloc(funcblocksize + funcstringsize);
8444743Smarkm	fn->refcount = 1;
8544743Smarkm	funcblock = (char *)fn + offsetof(struct funcdef, n);
8644743Smarkm	funcstring = (char *)fn + funcblocksize;
8744743Smarkm	copynode(n);
8844743Smarkm	return fn;
8944743Smarkm}
9044743Smarkm
9144743Smarkm
9244743Smarkmunion node *
9344743Smarkmgetfuncnode(struct funcdef *fn)
9444743Smarkm{
9544743Smarkm	return fn == NULL ? NULL : &fn->n;
9644743Smarkm}
9744743Smarkm
9844743Smarkm
9944743SmarkmSTATIC void
10044743Smarkmcalcsize(union node *n)
10144743Smarkm{
10244743Smarkm	%CALCSIZE
10344743Smarkm}
10444743Smarkm
10544743Smarkm
10644743Smarkm
10744743SmarkmSTATIC void
10844743Smarkmsizenodelist(struct nodelist *lp)
10944743Smarkm{
11044743Smarkm	while (lp) {
11144743Smarkm		funcblocksize += ALIGN(sizeof(struct nodelist));
11244743Smarkm		calcsize(lp->n);
11344743Smarkm		lp = lp->next;
11444743Smarkm	}
11544743Smarkm}
11644743Smarkm
11744743Smarkm
11844743Smarkm
11944743SmarkmSTATIC union node *
12044743Smarkmcopynode(union node *n)
12144743Smarkm{
12244743Smarkm	union node *new;
12344743Smarkm
12444743Smarkm	%COPY
12544743Smarkm	return new;
12644743Smarkm}
12744743Smarkm
12844743Smarkm
12944743SmarkmSTATIC struct nodelist *
13044743Smarkmcopynodelist(struct nodelist *lp)
13144743Smarkm{
13244743Smarkm	struct nodelist *start;
13344743Smarkm	struct nodelist **lpp;
13444743Smarkm
13544743Smarkm	lpp = &start;
13644743Smarkm	while (lp) {
13744743Smarkm		*lpp = funcblock;
13844743Smarkm		funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
13944743Smarkm		(*lpp)->n = copynode(lp->n);
14044743Smarkm		lp = lp->next;
14144743Smarkm		lpp = &(*lpp)->next;
14244743Smarkm	}
14344743Smarkm	*lpp = NULL;
14444743Smarkm	return start;
14544743Smarkm}
14644743Smarkm
14744743Smarkm
14844743Smarkm
14944743SmarkmSTATIC char *
15044743Smarkmnodesavestr(char *s)
15144743Smarkm{
15244743Smarkm	char *p = s;
15344743Smarkm	char *q = funcstring;
15444743Smarkm	char   *rtn = funcstring;
15544743Smarkm
15644743Smarkm	while ((*q++ = *p++) != '\0')
15744743Smarkm		continue;
15844743Smarkm	funcstring = q;
15944743Smarkm	return rtn;
16044743Smarkm}
16144743Smarkm
16244743Smarkm
16344743Smarkmvoid
16444743Smarkmreffunc(struct funcdef *fn)
16544743Smarkm{
16644743Smarkm	if (fn)
16744743Smarkm		fn->refcount++;
16844743Smarkm}
16944743Smarkm
17044743Smarkm
17156977Sshin/*
17256977Sshin * Decrement the reference count of a function definition, freeing it
17356977Sshin * if it falls to 0.
17444743Smarkm */
17556977Sshin
17644743Smarkmvoid
17744743Smarkmunreffunc(struct funcdef *fn)
17856977Sshin{
17956977Sshin	if (fn) {
18056977Sshin		fn->refcount--;
18156977Sshin		if (fn->refcount > 0)
18256977Sshin			return;
18356977Sshin		ckfree(fn);
18444743Smarkm	}
18544743Smarkm}
18656977Sshin