xref: /titanic_53/usr/src/cmd/sh/macro.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * UNIX shell
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include	"defs.h"
36*7c478bd9Sstevel@tonic-gate #include	"sym.h"
37*7c478bd9Sstevel@tonic-gate #include	<wait.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate static unsigned char	quote;	/* used locally */
40*7c478bd9Sstevel@tonic-gate static unsigned char	quoted;	/* used locally */
41*7c478bd9Sstevel@tonic-gate static int getch();
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate static void
44*7c478bd9Sstevel@tonic-gate copyto(endch, trimflag)
45*7c478bd9Sstevel@tonic-gate int trimflag;  /* flag to check if argument will be trimmed */
46*7c478bd9Sstevel@tonic-gate register unsigned char	endch;
47*7c478bd9Sstevel@tonic-gate {
48*7c478bd9Sstevel@tonic-gate 	register unsigned int	c;
49*7c478bd9Sstevel@tonic-gate 	register unsigned int 	d;
50*7c478bd9Sstevel@tonic-gate 	register unsigned char *pc;
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate 	while ((c = getch(endch, trimflag)) != endch && c)
53*7c478bd9Sstevel@tonic-gate 		if (quote) {
54*7c478bd9Sstevel@tonic-gate 			if(c == '\\') { /* don't interpret next character */
55*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
56*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
57*7c478bd9Sstevel@tonic-gate 				pushstak(c);
58*7c478bd9Sstevel@tonic-gate 				d = readwc();
59*7c478bd9Sstevel@tonic-gate 				if(!escchar(d)) { /* both \ and following
60*7c478bd9Sstevel@tonic-gate 						     character are quoted if next
61*7c478bd9Sstevel@tonic-gate 						     character is not $, `, ", or \*/
62*7c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
63*7c478bd9Sstevel@tonic-gate 						growstak(staktop);
64*7c478bd9Sstevel@tonic-gate 					pushstak('\\');
65*7c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
66*7c478bd9Sstevel@tonic-gate 						growstak(staktop);
67*7c478bd9Sstevel@tonic-gate 					pushstak('\\');
68*7c478bd9Sstevel@tonic-gate 					pc = readw(d);
69*7c478bd9Sstevel@tonic-gate 					/* push entire multibyte char */
70*7c478bd9Sstevel@tonic-gate 					while(*pc) {
71*7c478bd9Sstevel@tonic-gate 						if (staktop >= brkend)
72*7c478bd9Sstevel@tonic-gate 							growstak(staktop);
73*7c478bd9Sstevel@tonic-gate 						pushstak(*pc++);
74*7c478bd9Sstevel@tonic-gate 					}
75*7c478bd9Sstevel@tonic-gate 				} else {
76*7c478bd9Sstevel@tonic-gate 					pc = readw(d);
77*7c478bd9Sstevel@tonic-gate 					/* d might be NULL */
78*7c478bd9Sstevel@tonic-gate 					/* Evenif d is NULL, we have to save it */
79*7c478bd9Sstevel@tonic-gate 					if (*pc) {
80*7c478bd9Sstevel@tonic-gate 						while (*pc) {
81*7c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
82*7c478bd9Sstevel@tonic-gate 								growstak(staktop);
83*7c478bd9Sstevel@tonic-gate 							pushstak(*pc++);
84*7c478bd9Sstevel@tonic-gate 						}
85*7c478bd9Sstevel@tonic-gate 					} else {
86*7c478bd9Sstevel@tonic-gate 						if (staktop >= brkend)
87*7c478bd9Sstevel@tonic-gate 							growstak(staktop);
88*7c478bd9Sstevel@tonic-gate 						pushstak(*pc);
89*7c478bd9Sstevel@tonic-gate 					}
90*7c478bd9Sstevel@tonic-gate 				}
91*7c478bd9Sstevel@tonic-gate 			} else { /* push escapes onto stack to quote characters */
92*7c478bd9Sstevel@tonic-gate 				pc = readw(c);
93*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
94*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
95*7c478bd9Sstevel@tonic-gate 				pushstak('\\');
96*7c478bd9Sstevel@tonic-gate 				while(*pc) {
97*7c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
98*7c478bd9Sstevel@tonic-gate 						growstak(staktop);
99*7c478bd9Sstevel@tonic-gate 					pushstak(*pc++);
100*7c478bd9Sstevel@tonic-gate 				}
101*7c478bd9Sstevel@tonic-gate 			}
102*7c478bd9Sstevel@tonic-gate 		} else if(c == '\\') {
103*7c478bd9Sstevel@tonic-gate 			c = readwc(); /* get character to be escaped */
104*7c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
105*7c478bd9Sstevel@tonic-gate 				growstak(staktop);
106*7c478bd9Sstevel@tonic-gate 			pushstak('\\');
107*7c478bd9Sstevel@tonic-gate 			pc = readw(c);
108*7c478bd9Sstevel@tonic-gate 			/* c might be NULL */
109*7c478bd9Sstevel@tonic-gate 			/* Evenif c is NULL, we have to save it */
110*7c478bd9Sstevel@tonic-gate 			if (*pc) {
111*7c478bd9Sstevel@tonic-gate 				while (*pc) {
112*7c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
113*7c478bd9Sstevel@tonic-gate 						growstak(staktop);
114*7c478bd9Sstevel@tonic-gate 					pushstak(*pc++);
115*7c478bd9Sstevel@tonic-gate 				}
116*7c478bd9Sstevel@tonic-gate 			} else {
117*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
118*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
119*7c478bd9Sstevel@tonic-gate 				pushstak(*pc);
120*7c478bd9Sstevel@tonic-gate 			}
121*7c478bd9Sstevel@tonic-gate 		} else {
122*7c478bd9Sstevel@tonic-gate 			pc = readw(c);
123*7c478bd9Sstevel@tonic-gate 			while (*pc) {
124*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
125*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
126*7c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
127*7c478bd9Sstevel@tonic-gate 			}
128*7c478bd9Sstevel@tonic-gate 		}
129*7c478bd9Sstevel@tonic-gate 	if (staktop >= brkend)
130*7c478bd9Sstevel@tonic-gate 			growstak(staktop);
131*7c478bd9Sstevel@tonic-gate 	zerostak();
132*7c478bd9Sstevel@tonic-gate 	if (c != endch)
133*7c478bd9Sstevel@tonic-gate 		error(badsub);
134*7c478bd9Sstevel@tonic-gate }
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate static
137*7c478bd9Sstevel@tonic-gate skipto(endch)
138*7c478bd9Sstevel@tonic-gate register unsigned char	endch;
139*7c478bd9Sstevel@tonic-gate {
140*7c478bd9Sstevel@tonic-gate 	/*
141*7c478bd9Sstevel@tonic-gate 	 * skip chars up to }
142*7c478bd9Sstevel@tonic-gate 	 */
143*7c478bd9Sstevel@tonic-gate 	register unsigned int	c;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	while ((c = readwc()) && c != endch)
146*7c478bd9Sstevel@tonic-gate 	{
147*7c478bd9Sstevel@tonic-gate 		switch (c)
148*7c478bd9Sstevel@tonic-gate 		{
149*7c478bd9Sstevel@tonic-gate 		case SQUOTE:
150*7c478bd9Sstevel@tonic-gate 			skipto(SQUOTE);
151*7c478bd9Sstevel@tonic-gate 			break;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 		case DQUOTE:
154*7c478bd9Sstevel@tonic-gate 			skipto(DQUOTE);
155*7c478bd9Sstevel@tonic-gate 			break;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 		case DOLLAR:
158*7c478bd9Sstevel@tonic-gate 			if (readwc() == BRACE)
159*7c478bd9Sstevel@tonic-gate 				skipto('}');
160*7c478bd9Sstevel@tonic-gate 		}
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	if (c != endch)
163*7c478bd9Sstevel@tonic-gate 		error(badsub);
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate static
167*7c478bd9Sstevel@tonic-gate int getch(endch, trimflag)
168*7c478bd9Sstevel@tonic-gate unsigned char	endch;
169*7c478bd9Sstevel@tonic-gate int trimflag; /* flag to check if an argument is going to be trimmed, here document
170*7c478bd9Sstevel@tonic-gate 		 output is never trimmed
171*7c478bd9Sstevel@tonic-gate 	 */
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	register unsigned int	d;
174*7c478bd9Sstevel@tonic-gate 	int atflag;  /* flag to check if $@ has already been seen within double
175*7c478bd9Sstevel@tonic-gate 		        quotes */
176*7c478bd9Sstevel@tonic-gate retry:
177*7c478bd9Sstevel@tonic-gate 	d = readwc();
178*7c478bd9Sstevel@tonic-gate 	if (!subchar(d))
179*7c478bd9Sstevel@tonic-gate 		return(d);
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	if (d == DOLLAR)
182*7c478bd9Sstevel@tonic-gate 	{
183*7c478bd9Sstevel@tonic-gate 		unsigned int c;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 		if ((c = readwc(), dolchar(c)))
186*7c478bd9Sstevel@tonic-gate 		{
187*7c478bd9Sstevel@tonic-gate 			struct namnod *n = (struct namnod *)NIL;
188*7c478bd9Sstevel@tonic-gate 			int		dolg = 0;
189*7c478bd9Sstevel@tonic-gate 			BOOL		bra;
190*7c478bd9Sstevel@tonic-gate 			BOOL		nulflg;
191*7c478bd9Sstevel@tonic-gate 			register unsigned char	*argp, *v;
192*7c478bd9Sstevel@tonic-gate 			unsigned char		idb[2];
193*7c478bd9Sstevel@tonic-gate 			unsigned char		*id = idb;
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 			if (bra = (c == BRACE))
196*7c478bd9Sstevel@tonic-gate 				c = readwc();
197*7c478bd9Sstevel@tonic-gate 			if (letter(c))
198*7c478bd9Sstevel@tonic-gate 			{
199*7c478bd9Sstevel@tonic-gate 				argp = (unsigned char *)relstak();
200*7c478bd9Sstevel@tonic-gate 				while (alphanum(c))
201*7c478bd9Sstevel@tonic-gate 				{
202*7c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
203*7c478bd9Sstevel@tonic-gate 						growstak(staktop);
204*7c478bd9Sstevel@tonic-gate 					pushstak(c);
205*7c478bd9Sstevel@tonic-gate 					c = readwc();
206*7c478bd9Sstevel@tonic-gate 				}
207*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
208*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
209*7c478bd9Sstevel@tonic-gate 				zerostak();
210*7c478bd9Sstevel@tonic-gate 				n = lookup(absstak(argp));
211*7c478bd9Sstevel@tonic-gate 				setstak(argp);
212*7c478bd9Sstevel@tonic-gate 				if (n->namflg & N_FUNCTN)
213*7c478bd9Sstevel@tonic-gate 					error(badsub);
214*7c478bd9Sstevel@tonic-gate 				v = n->namval;
215*7c478bd9Sstevel@tonic-gate 				id = (unsigned char *)n->namid;
216*7c478bd9Sstevel@tonic-gate 				peekc = c | MARK;
217*7c478bd9Sstevel@tonic-gate 			}
218*7c478bd9Sstevel@tonic-gate 			else if (digchar(c))
219*7c478bd9Sstevel@tonic-gate 			{
220*7c478bd9Sstevel@tonic-gate 				*id = c;
221*7c478bd9Sstevel@tonic-gate 				idb[1] = 0;
222*7c478bd9Sstevel@tonic-gate 				if (astchar(c))
223*7c478bd9Sstevel@tonic-gate 				{
224*7c478bd9Sstevel@tonic-gate 					if(c == '@' && !atflag && quote) {
225*7c478bd9Sstevel@tonic-gate 						quoted--;
226*7c478bd9Sstevel@tonic-gate 						atflag = 1;
227*7c478bd9Sstevel@tonic-gate 					}
228*7c478bd9Sstevel@tonic-gate 					dolg = 1;
229*7c478bd9Sstevel@tonic-gate 					c = '1';
230*7c478bd9Sstevel@tonic-gate 				}
231*7c478bd9Sstevel@tonic-gate 				c -= '0';
232*7c478bd9Sstevel@tonic-gate 				v = ((c == 0) ? cmdadr : ((int)c <= dolc) ? dolv[c] : (unsigned char *)(dolg = 0));
233*7c478bd9Sstevel@tonic-gate 			}
234*7c478bd9Sstevel@tonic-gate 			else if (c == '$')
235*7c478bd9Sstevel@tonic-gate 				v = pidadr;
236*7c478bd9Sstevel@tonic-gate 			else if (c == '!')
237*7c478bd9Sstevel@tonic-gate 				v = pcsadr;
238*7c478bd9Sstevel@tonic-gate 			else if (c == '#')
239*7c478bd9Sstevel@tonic-gate 			{
240*7c478bd9Sstevel@tonic-gate 				itos(dolc);
241*7c478bd9Sstevel@tonic-gate 				v = numbuf;
242*7c478bd9Sstevel@tonic-gate 			}
243*7c478bd9Sstevel@tonic-gate 			else if (c == '?')
244*7c478bd9Sstevel@tonic-gate 			{
245*7c478bd9Sstevel@tonic-gate 				itos(retval);
246*7c478bd9Sstevel@tonic-gate 				v = numbuf;
247*7c478bd9Sstevel@tonic-gate 			}
248*7c478bd9Sstevel@tonic-gate 			else if (c == '-')
249*7c478bd9Sstevel@tonic-gate 				v = flagadr;
250*7c478bd9Sstevel@tonic-gate 			else if (bra)
251*7c478bd9Sstevel@tonic-gate 				error(badsub);
252*7c478bd9Sstevel@tonic-gate 			else
253*7c478bd9Sstevel@tonic-gate 				goto retry;
254*7c478bd9Sstevel@tonic-gate 			c = readwc();
255*7c478bd9Sstevel@tonic-gate 			if (c == ':' && bra)	/* null and unset fix */
256*7c478bd9Sstevel@tonic-gate 			{
257*7c478bd9Sstevel@tonic-gate 				nulflg = 1;
258*7c478bd9Sstevel@tonic-gate 				c = readwc();
259*7c478bd9Sstevel@tonic-gate 			}
260*7c478bd9Sstevel@tonic-gate 			else
261*7c478bd9Sstevel@tonic-gate 				nulflg = 0;
262*7c478bd9Sstevel@tonic-gate 			if (!defchar(c) && bra)
263*7c478bd9Sstevel@tonic-gate 				error(badsub);
264*7c478bd9Sstevel@tonic-gate 			argp = 0;
265*7c478bd9Sstevel@tonic-gate 			if (bra)
266*7c478bd9Sstevel@tonic-gate 			{
267*7c478bd9Sstevel@tonic-gate 				if (c != '}')
268*7c478bd9Sstevel@tonic-gate 				{
269*7c478bd9Sstevel@tonic-gate 					argp = (unsigned char *)relstak();
270*7c478bd9Sstevel@tonic-gate 					if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c)))
271*7c478bd9Sstevel@tonic-gate 						copyto('}', trimflag);
272*7c478bd9Sstevel@tonic-gate 					else
273*7c478bd9Sstevel@tonic-gate 						skipto('}');
274*7c478bd9Sstevel@tonic-gate 					argp = absstak(argp);
275*7c478bd9Sstevel@tonic-gate 				}
276*7c478bd9Sstevel@tonic-gate 			}
277*7c478bd9Sstevel@tonic-gate 			else
278*7c478bd9Sstevel@tonic-gate 			{
279*7c478bd9Sstevel@tonic-gate 				peekc = c | MARK;
280*7c478bd9Sstevel@tonic-gate 				c = 0;
281*7c478bd9Sstevel@tonic-gate 			}
282*7c478bd9Sstevel@tonic-gate 			if (v && (!nulflg || *v))
283*7c478bd9Sstevel@tonic-gate 			{
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 				if (c != '+')
286*7c478bd9Sstevel@tonic-gate 				{
287*7c478bd9Sstevel@tonic-gate 					for (;;)
288*7c478bd9Sstevel@tonic-gate 					{
289*7c478bd9Sstevel@tonic-gate 						if (*v == 0 && quote) {
290*7c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
291*7c478bd9Sstevel@tonic-gate 								growstak(staktop);
292*7c478bd9Sstevel@tonic-gate 							pushstak('\\');
293*7c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
294*7c478bd9Sstevel@tonic-gate 								growstak(staktop);
295*7c478bd9Sstevel@tonic-gate 							pushstak('\0');
296*7c478bd9Sstevel@tonic-gate 						} else {
297*7c478bd9Sstevel@tonic-gate 							while (c = *v) {
298*7c478bd9Sstevel@tonic-gate 								wchar_t 	wc;
299*7c478bd9Sstevel@tonic-gate 								register int 	length;
300*7c478bd9Sstevel@tonic-gate 								if ((length = mbtowc(&wc, (char *)v, MB_LEN_MAX)) <= 0)
301*7c478bd9Sstevel@tonic-gate 									length = 1;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 								if(quote || (c == '\\' && trimflag)) {
304*7c478bd9Sstevel@tonic-gate 									if (staktop >= brkend)
305*7c478bd9Sstevel@tonic-gate 										growstak(staktop);
306*7c478bd9Sstevel@tonic-gate 									pushstak('\\');
307*7c478bd9Sstevel@tonic-gate 								}
308*7c478bd9Sstevel@tonic-gate 								while(length-- > 0) {
309*7c478bd9Sstevel@tonic-gate 									if (staktop >= brkend)
310*7c478bd9Sstevel@tonic-gate 										growstak(staktop);
311*7c478bd9Sstevel@tonic-gate 									pushstak(*v++);
312*7c478bd9Sstevel@tonic-gate 								}
313*7c478bd9Sstevel@tonic-gate 							}
314*7c478bd9Sstevel@tonic-gate 						}
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 						if (dolg == 0 || (++dolg > dolc))
317*7c478bd9Sstevel@tonic-gate 							break;
318*7c478bd9Sstevel@tonic-gate 						else /* $* and $@ expansion */
319*7c478bd9Sstevel@tonic-gate 						{
320*7c478bd9Sstevel@tonic-gate 							v = dolv[dolg];
321*7c478bd9Sstevel@tonic-gate 							if(*id == '*' && quote) {
322*7c478bd9Sstevel@tonic-gate /* push quoted space so that " $* " will not be broken into separate arguments */
323*7c478bd9Sstevel@tonic-gate 								if (staktop >= brkend)
324*7c478bd9Sstevel@tonic-gate 									growstak(staktop);
325*7c478bd9Sstevel@tonic-gate 								pushstak('\\');
326*7c478bd9Sstevel@tonic-gate 							}
327*7c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
328*7c478bd9Sstevel@tonic-gate 								growstak(staktop);
329*7c478bd9Sstevel@tonic-gate 							pushstak(' ');
330*7c478bd9Sstevel@tonic-gate 						}
331*7c478bd9Sstevel@tonic-gate 					}
332*7c478bd9Sstevel@tonic-gate 				}
333*7c478bd9Sstevel@tonic-gate 			}
334*7c478bd9Sstevel@tonic-gate 			else if (argp)
335*7c478bd9Sstevel@tonic-gate 			{
336*7c478bd9Sstevel@tonic-gate 				if (c == '?') {
337*7c478bd9Sstevel@tonic-gate 					if(trimflag)
338*7c478bd9Sstevel@tonic-gate 						trim(argp);
339*7c478bd9Sstevel@tonic-gate 					failed(id, *argp ? argp : (unsigned char *)badparam);
340*7c478bd9Sstevel@tonic-gate 				}
341*7c478bd9Sstevel@tonic-gate 				else if (c == '=')
342*7c478bd9Sstevel@tonic-gate 				{
343*7c478bd9Sstevel@tonic-gate 					if (n)
344*7c478bd9Sstevel@tonic-gate 					{
345*7c478bd9Sstevel@tonic-gate 						int strlngth = staktop - stakbot;
346*7c478bd9Sstevel@tonic-gate 						unsigned char *savptr = fixstak();
347*7c478bd9Sstevel@tonic-gate 						unsigned char *newargp;
348*7c478bd9Sstevel@tonic-gate 					/*
349*7c478bd9Sstevel@tonic-gate 					 * copy word onto stack, trim it, and then
350*7c478bd9Sstevel@tonic-gate 					 * do assignment
351*7c478bd9Sstevel@tonic-gate 					 */
352*7c478bd9Sstevel@tonic-gate 						usestak();
353*7c478bd9Sstevel@tonic-gate 						while(c = *argp) {
354*7c478bd9Sstevel@tonic-gate 							wchar_t 	wc;
355*7c478bd9Sstevel@tonic-gate 							register int 	len;
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 							if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
358*7c478bd9Sstevel@tonic-gate 								len = 1;
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 							if(c == '\\' && trimflag) {
361*7c478bd9Sstevel@tonic-gate 								argp++;
362*7c478bd9Sstevel@tonic-gate 								if (*argp == 0) {
363*7c478bd9Sstevel@tonic-gate 									argp++;
364*7c478bd9Sstevel@tonic-gate 									continue;
365*7c478bd9Sstevel@tonic-gate 								}
366*7c478bd9Sstevel@tonic-gate 								if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
367*7c478bd9Sstevel@tonic-gate 									len = 1;
368*7c478bd9Sstevel@tonic-gate 							}
369*7c478bd9Sstevel@tonic-gate 							while(len-- > 0) {
370*7c478bd9Sstevel@tonic-gate 								if (staktop >= brkend)
371*7c478bd9Sstevel@tonic-gate 									growstak(staktop);
372*7c478bd9Sstevel@tonic-gate 								pushstak(*argp++);
373*7c478bd9Sstevel@tonic-gate 							}
374*7c478bd9Sstevel@tonic-gate 						}
375*7c478bd9Sstevel@tonic-gate 						newargp = fixstak();
376*7c478bd9Sstevel@tonic-gate 						assign(n, newargp);
377*7c478bd9Sstevel@tonic-gate 						tdystak(savptr);
378*7c478bd9Sstevel@tonic-gate 						memcpy(stakbot, savptr, strlngth);
379*7c478bd9Sstevel@tonic-gate 						staktop = stakbot + strlngth;
380*7c478bd9Sstevel@tonic-gate 					}
381*7c478bd9Sstevel@tonic-gate 					else
382*7c478bd9Sstevel@tonic-gate 						error(badsub);
383*7c478bd9Sstevel@tonic-gate 				}
384*7c478bd9Sstevel@tonic-gate 			}
385*7c478bd9Sstevel@tonic-gate 			else if (flags & setflg)
386*7c478bd9Sstevel@tonic-gate 				failed(id, unset);
387*7c478bd9Sstevel@tonic-gate 			goto retry;
388*7c478bd9Sstevel@tonic-gate 		}
389*7c478bd9Sstevel@tonic-gate 		else
390*7c478bd9Sstevel@tonic-gate 			peekc = c | MARK;
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate 	else if (d == endch)
393*7c478bd9Sstevel@tonic-gate 		return(d);
394*7c478bd9Sstevel@tonic-gate 	else if (d == SQUOTE)
395*7c478bd9Sstevel@tonic-gate 	{
396*7c478bd9Sstevel@tonic-gate 		comsubst(trimflag);
397*7c478bd9Sstevel@tonic-gate 		goto retry;
398*7c478bd9Sstevel@tonic-gate 	}
399*7c478bd9Sstevel@tonic-gate 	else if (d == DQUOTE && trimflag)
400*7c478bd9Sstevel@tonic-gate 	{
401*7c478bd9Sstevel@tonic-gate 		if(!quote) {
402*7c478bd9Sstevel@tonic-gate 			atflag = 0;
403*7c478bd9Sstevel@tonic-gate 			quoted++;
404*7c478bd9Sstevel@tonic-gate 		}
405*7c478bd9Sstevel@tonic-gate 		quote ^= QUOTE;
406*7c478bd9Sstevel@tonic-gate 		goto retry;
407*7c478bd9Sstevel@tonic-gate 	}
408*7c478bd9Sstevel@tonic-gate 	return(d);
409*7c478bd9Sstevel@tonic-gate }
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate unsigned char *
412*7c478bd9Sstevel@tonic-gate macro(as)
413*7c478bd9Sstevel@tonic-gate unsigned char	*as;
414*7c478bd9Sstevel@tonic-gate {
415*7c478bd9Sstevel@tonic-gate 	/*
416*7c478bd9Sstevel@tonic-gate 	 * Strip "" and do $ substitution
417*7c478bd9Sstevel@tonic-gate 	 * Leaves result on top of stack
418*7c478bd9Sstevel@tonic-gate 	 */
419*7c478bd9Sstevel@tonic-gate 	register BOOL	savqu = quoted;
420*7c478bd9Sstevel@tonic-gate 	register unsigned char	savq = quote;
421*7c478bd9Sstevel@tonic-gate 	struct filehdr	fb;
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 	push(&fb);
424*7c478bd9Sstevel@tonic-gate 	estabf(as);
425*7c478bd9Sstevel@tonic-gate 	usestak();
426*7c478bd9Sstevel@tonic-gate 	quote = 0;
427*7c478bd9Sstevel@tonic-gate 	quoted = 0;
428*7c478bd9Sstevel@tonic-gate 	copyto(0, 1);
429*7c478bd9Sstevel@tonic-gate 	pop();
430*7c478bd9Sstevel@tonic-gate 	if (quoted && (stakbot == staktop)) {
431*7c478bd9Sstevel@tonic-gate 		if (staktop >= brkend)
432*7c478bd9Sstevel@tonic-gate 			growstak(staktop);
433*7c478bd9Sstevel@tonic-gate 		pushstak('\\');
434*7c478bd9Sstevel@tonic-gate 		if (staktop >= brkend)
435*7c478bd9Sstevel@tonic-gate 			growstak(staktop);
436*7c478bd9Sstevel@tonic-gate 		pushstak('\0');
437*7c478bd9Sstevel@tonic-gate /*
438*7c478bd9Sstevel@tonic-gate  * above is the fix for *'.c' bug
439*7c478bd9Sstevel@tonic-gate  */
440*7c478bd9Sstevel@tonic-gate 	}
441*7c478bd9Sstevel@tonic-gate 	quote = savq;
442*7c478bd9Sstevel@tonic-gate 	quoted = savqu;
443*7c478bd9Sstevel@tonic-gate 	return(fixstak());
444*7c478bd9Sstevel@tonic-gate }
445*7c478bd9Sstevel@tonic-gate /* Save file descriptor for command substitution */
446*7c478bd9Sstevel@tonic-gate int savpipe = -1;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate comsubst(trimflag)
449*7c478bd9Sstevel@tonic-gate int trimflag; /* used to determine if argument will later be trimmed */
450*7c478bd9Sstevel@tonic-gate {
451*7c478bd9Sstevel@tonic-gate 	/*
452*7c478bd9Sstevel@tonic-gate 	 * command substn
453*7c478bd9Sstevel@tonic-gate 	 */
454*7c478bd9Sstevel@tonic-gate 	struct fileblk	cb;
455*7c478bd9Sstevel@tonic-gate 	register unsigned int	d;
456*7c478bd9Sstevel@tonic-gate 	int strlngth = staktop - stakbot;
457*7c478bd9Sstevel@tonic-gate 	register unsigned char *oldstaktop;
458*7c478bd9Sstevel@tonic-gate 	unsigned char *savptr = fixstak();
459*7c478bd9Sstevel@tonic-gate 	unsigned char	*pc;
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	usestak();
462*7c478bd9Sstevel@tonic-gate 	while ((d = readwc()) != SQUOTE && d) {
463*7c478bd9Sstevel@tonic-gate 		if(d == '\\') {
464*7c478bd9Sstevel@tonic-gate 			d = readwc();
465*7c478bd9Sstevel@tonic-gate 			if(!escchar(d) || (d == '"' && !quote)) {
466*7c478bd9Sstevel@tonic-gate 		/* trim quotes for `, \, or " if command substitution is within
467*7c478bd9Sstevel@tonic-gate 		   double quotes */
468*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
469*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
470*7c478bd9Sstevel@tonic-gate 				pushstak('\\');
471*7c478bd9Sstevel@tonic-gate 			}
472*7c478bd9Sstevel@tonic-gate 		}
473*7c478bd9Sstevel@tonic-gate 		pc = readw(d);
474*7c478bd9Sstevel@tonic-gate 		/* d might be NULL */
475*7c478bd9Sstevel@tonic-gate 		if (*pc) {
476*7c478bd9Sstevel@tonic-gate 			while (*pc) {
477*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
478*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
479*7c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
480*7c478bd9Sstevel@tonic-gate 			}
481*7c478bd9Sstevel@tonic-gate 		} else {
482*7c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
483*7c478bd9Sstevel@tonic-gate 				growstak(staktop);
484*7c478bd9Sstevel@tonic-gate 			pushstak(*pc);
485*7c478bd9Sstevel@tonic-gate 		}
486*7c478bd9Sstevel@tonic-gate 	}
487*7c478bd9Sstevel@tonic-gate 	{
488*7c478bd9Sstevel@tonic-gate 		register unsigned char	*argc;
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 		argc = fixstak();
491*7c478bd9Sstevel@tonic-gate 		push(&cb);
492*7c478bd9Sstevel@tonic-gate 		estabf(argc);  /* read from string */
493*7c478bd9Sstevel@tonic-gate 	}
494*7c478bd9Sstevel@tonic-gate 	{
495*7c478bd9Sstevel@tonic-gate 		register struct trenod *t;
496*7c478bd9Sstevel@tonic-gate 		int		pv[2];
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 		/*
499*7c478bd9Sstevel@tonic-gate 		 * this is done like this so that the pipe
500*7c478bd9Sstevel@tonic-gate 		 * is open only when needed
501*7c478bd9Sstevel@tonic-gate 		 */
502*7c478bd9Sstevel@tonic-gate 	 	t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG ));
503*7c478bd9Sstevel@tonic-gate 		chkpipe(pv);
504*7c478bd9Sstevel@tonic-gate 		savpipe = pv[OTPIPE];
505*7c478bd9Sstevel@tonic-gate 		initf(pv[INPIPE]); /* read from pipe */
506*7c478bd9Sstevel@tonic-gate 		execute(t, XEC_NOSTOP, (int)(flags & errflg), 0, pv);
507*7c478bd9Sstevel@tonic-gate 		close(pv[OTPIPE]);
508*7c478bd9Sstevel@tonic-gate 		savpipe = -1;
509*7c478bd9Sstevel@tonic-gate 	}
510*7c478bd9Sstevel@tonic-gate 	tdystak(savptr);
511*7c478bd9Sstevel@tonic-gate 	memcpy(stakbot, savptr, strlngth);
512*7c478bd9Sstevel@tonic-gate 	oldstaktop = staktop = stakbot + strlngth;
513*7c478bd9Sstevel@tonic-gate 	while (d = readwc()) {
514*7c478bd9Sstevel@tonic-gate 		if(quote || (d == '\\' && trimflag)) {
515*7c478bd9Sstevel@tonic-gate 			register unsigned char *rest;
516*7c478bd9Sstevel@tonic-gate 			/* quote output from command subst. if within double
517*7c478bd9Sstevel@tonic-gate 			   quotes or backslash part of output */
518*7c478bd9Sstevel@tonic-gate 			rest = readw(d);
519*7c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
520*7c478bd9Sstevel@tonic-gate 				growstak(staktop);
521*7c478bd9Sstevel@tonic-gate 			pushstak('\\');
522*7c478bd9Sstevel@tonic-gate 			while(d = *rest++) {
523*7c478bd9Sstevel@tonic-gate 			/* Pick up all of multibyte character */
524*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
525*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
526*7c478bd9Sstevel@tonic-gate 				pushstak(d);
527*7c478bd9Sstevel@tonic-gate 			}
528*7c478bd9Sstevel@tonic-gate 		}
529*7c478bd9Sstevel@tonic-gate 		else {
530*7c478bd9Sstevel@tonic-gate 			pc = readw(d);
531*7c478bd9Sstevel@tonic-gate 			while (*pc) {
532*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
533*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
534*7c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
535*7c478bd9Sstevel@tonic-gate 			}
536*7c478bd9Sstevel@tonic-gate 		}
537*7c478bd9Sstevel@tonic-gate 	}
538*7c478bd9Sstevel@tonic-gate 	{
539*7c478bd9Sstevel@tonic-gate 		extern pid_t parent;
540*7c478bd9Sstevel@tonic-gate 		int stat;
541*7c478bd9Sstevel@tonic-gate 		register rc;
542*7c478bd9Sstevel@tonic-gate 		int	ret = 0;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 		while ((ret = waitpid(parent,&stat,0)) != parent) {
545*7c478bd9Sstevel@tonic-gate 			/* break out if waitpid(2) has failed */
546*7c478bd9Sstevel@tonic-gate 			if (ret == -1)
547*7c478bd9Sstevel@tonic-gate 				break;
548*7c478bd9Sstevel@tonic-gate 		}
549*7c478bd9Sstevel@tonic-gate 		if (WIFEXITED(stat))
550*7c478bd9Sstevel@tonic-gate 			rc = WEXITSTATUS(stat);
551*7c478bd9Sstevel@tonic-gate 		else
552*7c478bd9Sstevel@tonic-gate 			rc = (WTERMSIG(stat) | SIGFLG);
553*7c478bd9Sstevel@tonic-gate 		if (rc && (flags & errflg))
554*7c478bd9Sstevel@tonic-gate 			exitsh(rc);
555*7c478bd9Sstevel@tonic-gate 		exitval = rc;
556*7c478bd9Sstevel@tonic-gate 		flags |= eflag;
557*7c478bd9Sstevel@tonic-gate 		exitset();
558*7c478bd9Sstevel@tonic-gate 	}
559*7c478bd9Sstevel@tonic-gate 	while (oldstaktop != staktop)
560*7c478bd9Sstevel@tonic-gate 	{ /* strip off trailing newlines from command substitution only */
561*7c478bd9Sstevel@tonic-gate 		if ((*--staktop) != NL)
562*7c478bd9Sstevel@tonic-gate 		{
563*7c478bd9Sstevel@tonic-gate 			++staktop;
564*7c478bd9Sstevel@tonic-gate 			break;
565*7c478bd9Sstevel@tonic-gate 		} else if(quote)
566*7c478bd9Sstevel@tonic-gate 			staktop--; /* skip past backslashes if quoting */
567*7c478bd9Sstevel@tonic-gate 	}
568*7c478bd9Sstevel@tonic-gate 	pop();
569*7c478bd9Sstevel@tonic-gate }
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate #define CPYSIZ	512
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate subst(in, ot)
574*7c478bd9Sstevel@tonic-gate int	in, ot;
575*7c478bd9Sstevel@tonic-gate {
576*7c478bd9Sstevel@tonic-gate 	register unsigned int	c;
577*7c478bd9Sstevel@tonic-gate 	struct fileblk	fb;
578*7c478bd9Sstevel@tonic-gate 	register int	count = CPYSIZ;
579*7c478bd9Sstevel@tonic-gate 	unsigned char	*pc;
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	push(&fb);
582*7c478bd9Sstevel@tonic-gate 	initf(in);
583*7c478bd9Sstevel@tonic-gate 	/*
584*7c478bd9Sstevel@tonic-gate 	 * DQUOTE used to stop it from quoting
585*7c478bd9Sstevel@tonic-gate 	 */
586*7c478bd9Sstevel@tonic-gate 	while (c = (getch(DQUOTE, 0))) /* read characters from here document
587*7c478bd9Sstevel@tonic-gate 				       and interpret them */
588*7c478bd9Sstevel@tonic-gate 	{
589*7c478bd9Sstevel@tonic-gate 		if(c == '\\') {
590*7c478bd9Sstevel@tonic-gate 			c = readwc(); /* check if character in here document is
591*7c478bd9Sstevel@tonic-gate 					escaped */
592*7c478bd9Sstevel@tonic-gate 			if(!escchar(c) || c == '"') {
593*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
594*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
595*7c478bd9Sstevel@tonic-gate 				pushstak('\\');
596*7c478bd9Sstevel@tonic-gate 			}
597*7c478bd9Sstevel@tonic-gate 		}
598*7c478bd9Sstevel@tonic-gate 		pc = readw(c);
599*7c478bd9Sstevel@tonic-gate 		/* c might be NULL */
600*7c478bd9Sstevel@tonic-gate 		if (*pc) {
601*7c478bd9Sstevel@tonic-gate 			while (*pc) {
602*7c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
603*7c478bd9Sstevel@tonic-gate 					growstak(staktop);
604*7c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
605*7c478bd9Sstevel@tonic-gate 			}
606*7c478bd9Sstevel@tonic-gate 		} else {
607*7c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
608*7c478bd9Sstevel@tonic-gate 				growstak(staktop);
609*7c478bd9Sstevel@tonic-gate 			pushstak(*pc);
610*7c478bd9Sstevel@tonic-gate 		}
611*7c478bd9Sstevel@tonic-gate 		if (--count == 0)
612*7c478bd9Sstevel@tonic-gate 		{
613*7c478bd9Sstevel@tonic-gate 			flush(ot);
614*7c478bd9Sstevel@tonic-gate 			count = CPYSIZ;
615*7c478bd9Sstevel@tonic-gate 		}
616*7c478bd9Sstevel@tonic-gate 	}
617*7c478bd9Sstevel@tonic-gate 	flush(ot);
618*7c478bd9Sstevel@tonic-gate 	pop();
619*7c478bd9Sstevel@tonic-gate }
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate flush(ot)
622*7c478bd9Sstevel@tonic-gate {
623*7c478bd9Sstevel@tonic-gate 	write(ot, stakbot, staktop - stakbot);
624*7c478bd9Sstevel@tonic-gate 	if (flags & execpr)
625*7c478bd9Sstevel@tonic-gate 		write(output, stakbot, staktop - stakbot);
626*7c478bd9Sstevel@tonic-gate 	staktop = stakbot;
627*7c478bd9Sstevel@tonic-gate }
628