Home | History | Annotate | Line # | Download | only in sh
nodes.c.pat revision 1.14
      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 */
     52 struct 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 */
     58 struct 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 
     68 STATIC void calcsize(union node *, struct nodesize *);
     69 STATIC void sizenodelist(struct nodelist *, struct nodesize *);
     70 STATIC union node *copynode(union node *, struct nodecopystate *);
     71 STATIC struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *);
     72 STATIC char *nodesavestr(char *, struct nodecopystate *);
     73 
     74 struct 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 
     84 struct funcdef *
     85 copyfunc(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 
    104 union node *
    105 getfuncnode(struct funcdef *fn)
    106 {
    107 	if (fn == NULL)
    108 		return NULL;
    109 	return &fn->n;
    110 }
    111 
    112 
    113 STATIC void
    114 calcsize(union node *n, struct nodesize *res)
    115 {
    116 	%CALCSIZE
    117 }
    118 
    119 
    120 
    121 STATIC void
    122 sizenodelist(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 
    133 STATIC union node *
    134 copynode(union node *n, struct nodecopystate *st)
    135 {
    136 	union node *new;
    137 
    138 	%COPY
    139 	return new;
    140 }
    141 
    142 
    143 STATIC struct nodelist *
    144 copynodelist(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 
    164 STATIC char *
    165 nodesavestr(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 
    184 void
    185 reffunc(struct funcdef *fn)
    186 {
    187 	if (fn != NULL)
    188 		fn->refcount++;
    189 }
    190 
    191 void
    192 unreffunc(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  */
    205 void
    206 freefunc(struct funcdef *fn)
    207 {
    208 	if (fn != NULL)
    209 		ckfree(fn);
    210 }
    211