xref: /titanic_51/usr/src/cmd/sh/macro.c (revision 965005c81e0f731867d47892b9fb677030b102df)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * UNIX shell
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include	"defs.h"
367c478bd9Sstevel@tonic-gate #include	"sym.h"
377c478bd9Sstevel@tonic-gate #include	<wait.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate static unsigned char	quote;	/* used locally */
407c478bd9Sstevel@tonic-gate static unsigned char	quoted;	/* used locally */
417c478bd9Sstevel@tonic-gate static int getch();
42*965005c8Schin static void comsubst(int);
43*965005c8Schin static void flush(int);
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate static void
46*965005c8Schin copyto(unsigned char endch, int trimflag)
47*965005c8Schin /* trimflag - flag to check if argument will be trimmed */
487c478bd9Sstevel@tonic-gate {
49*965005c8Schin 	unsigned int	c;
50*965005c8Schin 	unsigned int 	d;
51*965005c8Schin 	unsigned char *pc;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 	while ((c = getch(endch, trimflag)) != endch && c)
547c478bd9Sstevel@tonic-gate 		if (quote) {
557c478bd9Sstevel@tonic-gate 			if(c == '\\') { /* don't interpret next character */
567c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
577c478bd9Sstevel@tonic-gate 					growstak(staktop);
587c478bd9Sstevel@tonic-gate 				pushstak(c);
597c478bd9Sstevel@tonic-gate 				d = readwc();
607c478bd9Sstevel@tonic-gate 				if(!escchar(d)) { /* both \ and following
617c478bd9Sstevel@tonic-gate 						     character are quoted if next
627c478bd9Sstevel@tonic-gate 						     character is not $, `, ", or \*/
637c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
647c478bd9Sstevel@tonic-gate 						growstak(staktop);
657c478bd9Sstevel@tonic-gate 					pushstak('\\');
667c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
677c478bd9Sstevel@tonic-gate 						growstak(staktop);
687c478bd9Sstevel@tonic-gate 					pushstak('\\');
697c478bd9Sstevel@tonic-gate 					pc = readw(d);
707c478bd9Sstevel@tonic-gate 					/* push entire multibyte char */
717c478bd9Sstevel@tonic-gate 					while(*pc) {
727c478bd9Sstevel@tonic-gate 						if (staktop >= brkend)
737c478bd9Sstevel@tonic-gate 							growstak(staktop);
747c478bd9Sstevel@tonic-gate 						pushstak(*pc++);
757c478bd9Sstevel@tonic-gate 					}
767c478bd9Sstevel@tonic-gate 				} else {
777c478bd9Sstevel@tonic-gate 					pc = readw(d);
787c478bd9Sstevel@tonic-gate 					/* d might be NULL */
797c478bd9Sstevel@tonic-gate 					/* Evenif d is NULL, we have to save it */
807c478bd9Sstevel@tonic-gate 					if (*pc) {
817c478bd9Sstevel@tonic-gate 						while (*pc) {
827c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
837c478bd9Sstevel@tonic-gate 								growstak(staktop);
847c478bd9Sstevel@tonic-gate 							pushstak(*pc++);
857c478bd9Sstevel@tonic-gate 						}
867c478bd9Sstevel@tonic-gate 					} else {
877c478bd9Sstevel@tonic-gate 						if (staktop >= brkend)
887c478bd9Sstevel@tonic-gate 							growstak(staktop);
897c478bd9Sstevel@tonic-gate 						pushstak(*pc);
907c478bd9Sstevel@tonic-gate 					}
917c478bd9Sstevel@tonic-gate 				}
927c478bd9Sstevel@tonic-gate 			} else { /* push escapes onto stack to quote characters */
937c478bd9Sstevel@tonic-gate 				pc = readw(c);
947c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
957c478bd9Sstevel@tonic-gate 					growstak(staktop);
967c478bd9Sstevel@tonic-gate 				pushstak('\\');
977c478bd9Sstevel@tonic-gate 				while(*pc) {
987c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
997c478bd9Sstevel@tonic-gate 						growstak(staktop);
1007c478bd9Sstevel@tonic-gate 					pushstak(*pc++);
1017c478bd9Sstevel@tonic-gate 				}
1027c478bd9Sstevel@tonic-gate 			}
1037c478bd9Sstevel@tonic-gate 		} else if(c == '\\') {
1047c478bd9Sstevel@tonic-gate 			c = readwc(); /* get character to be escaped */
1057c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
1067c478bd9Sstevel@tonic-gate 				growstak(staktop);
1077c478bd9Sstevel@tonic-gate 			pushstak('\\');
1087c478bd9Sstevel@tonic-gate 			pc = readw(c);
1097c478bd9Sstevel@tonic-gate 			/* c might be NULL */
1107c478bd9Sstevel@tonic-gate 			/* Evenif c is NULL, we have to save it */
1117c478bd9Sstevel@tonic-gate 			if (*pc) {
1127c478bd9Sstevel@tonic-gate 				while (*pc) {
1137c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
1147c478bd9Sstevel@tonic-gate 						growstak(staktop);
1157c478bd9Sstevel@tonic-gate 					pushstak(*pc++);
1167c478bd9Sstevel@tonic-gate 				}
1177c478bd9Sstevel@tonic-gate 			} else {
1187c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
1197c478bd9Sstevel@tonic-gate 					growstak(staktop);
1207c478bd9Sstevel@tonic-gate 				pushstak(*pc);
1217c478bd9Sstevel@tonic-gate 			}
1227c478bd9Sstevel@tonic-gate 		} else {
1237c478bd9Sstevel@tonic-gate 			pc = readw(c);
1247c478bd9Sstevel@tonic-gate 			while (*pc) {
1257c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
1267c478bd9Sstevel@tonic-gate 					growstak(staktop);
1277c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
1287c478bd9Sstevel@tonic-gate 			}
1297c478bd9Sstevel@tonic-gate 		}
1307c478bd9Sstevel@tonic-gate 	if (staktop >= brkend)
1317c478bd9Sstevel@tonic-gate 			growstak(staktop);
1327c478bd9Sstevel@tonic-gate 	zerostak();
1337c478bd9Sstevel@tonic-gate 	if (c != endch)
1347c478bd9Sstevel@tonic-gate 		error(badsub);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate 
137*965005c8Schin static void
138*965005c8Schin skipto(unsigned char endch)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	/*
1417c478bd9Sstevel@tonic-gate 	 * skip chars up to }
1427c478bd9Sstevel@tonic-gate 	 */
143*965005c8Schin 	unsigned int	c;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	while ((c = readwc()) && c != endch)
1467c478bd9Sstevel@tonic-gate 	{
1477c478bd9Sstevel@tonic-gate 		switch (c)
1487c478bd9Sstevel@tonic-gate 		{
1497c478bd9Sstevel@tonic-gate 		case SQUOTE:
1507c478bd9Sstevel@tonic-gate 			skipto(SQUOTE);
1517c478bd9Sstevel@tonic-gate 			break;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 		case DQUOTE:
1547c478bd9Sstevel@tonic-gate 			skipto(DQUOTE);
1557c478bd9Sstevel@tonic-gate 			break;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 		case DOLLAR:
1587c478bd9Sstevel@tonic-gate 			if (readwc() == BRACE)
1597c478bd9Sstevel@tonic-gate 				skipto('}');
1607c478bd9Sstevel@tonic-gate 		}
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 	if (c != endch)
1637c478bd9Sstevel@tonic-gate 		error(badsub);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate static
1677c478bd9Sstevel@tonic-gate int getch(endch, trimflag)
1687c478bd9Sstevel@tonic-gate unsigned char	endch;
1697c478bd9Sstevel@tonic-gate int trimflag; /* flag to check if an argument is going to be trimmed, here document
1707c478bd9Sstevel@tonic-gate 		 output is never trimmed
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate {
173*965005c8Schin 	unsigned int	d;
1747c478bd9Sstevel@tonic-gate 	int atflag;  /* flag to check if $@ has already been seen within double
1757c478bd9Sstevel@tonic-gate 		        quotes */
1767c478bd9Sstevel@tonic-gate retry:
1777c478bd9Sstevel@tonic-gate 	d = readwc();
1787c478bd9Sstevel@tonic-gate 	if (!subchar(d))
1797c478bd9Sstevel@tonic-gate 		return(d);
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	if (d == DOLLAR)
1827c478bd9Sstevel@tonic-gate 	{
1837c478bd9Sstevel@tonic-gate 		unsigned int c;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 		if ((c = readwc(), dolchar(c)))
1867c478bd9Sstevel@tonic-gate 		{
1877c478bd9Sstevel@tonic-gate 			struct namnod *n = (struct namnod *)NIL;
1887c478bd9Sstevel@tonic-gate 			int		dolg = 0;
1897c478bd9Sstevel@tonic-gate 			BOOL		bra;
1907c478bd9Sstevel@tonic-gate 			BOOL		nulflg;
191*965005c8Schin 			unsigned char	*argp, *v;
1927c478bd9Sstevel@tonic-gate 			unsigned char		idb[2];
1937c478bd9Sstevel@tonic-gate 			unsigned char		*id = idb;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 			if (bra = (c == BRACE))
1967c478bd9Sstevel@tonic-gate 				c = readwc();
1977c478bd9Sstevel@tonic-gate 			if (letter(c))
1987c478bd9Sstevel@tonic-gate 			{
1997c478bd9Sstevel@tonic-gate 				argp = (unsigned char *)relstak();
2007c478bd9Sstevel@tonic-gate 				while (alphanum(c))
2017c478bd9Sstevel@tonic-gate 				{
2027c478bd9Sstevel@tonic-gate 					if (staktop >= brkend)
2037c478bd9Sstevel@tonic-gate 						growstak(staktop);
2047c478bd9Sstevel@tonic-gate 					pushstak(c);
2057c478bd9Sstevel@tonic-gate 					c = readwc();
2067c478bd9Sstevel@tonic-gate 				}
2077c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
2087c478bd9Sstevel@tonic-gate 					growstak(staktop);
2097c478bd9Sstevel@tonic-gate 				zerostak();
2107c478bd9Sstevel@tonic-gate 				n = lookup(absstak(argp));
2117c478bd9Sstevel@tonic-gate 				setstak(argp);
2127c478bd9Sstevel@tonic-gate 				if (n->namflg & N_FUNCTN)
2137c478bd9Sstevel@tonic-gate 					error(badsub);
2147c478bd9Sstevel@tonic-gate 				v = n->namval;
2157c478bd9Sstevel@tonic-gate 				id = (unsigned char *)n->namid;
2167c478bd9Sstevel@tonic-gate 				peekc = c | MARK;
2177c478bd9Sstevel@tonic-gate 			}
2187c478bd9Sstevel@tonic-gate 			else if (digchar(c))
2197c478bd9Sstevel@tonic-gate 			{
2207c478bd9Sstevel@tonic-gate 				*id = c;
2217c478bd9Sstevel@tonic-gate 				idb[1] = 0;
2227c478bd9Sstevel@tonic-gate 				if (astchar(c))
2237c478bd9Sstevel@tonic-gate 				{
2247c478bd9Sstevel@tonic-gate 					if(c == '@' && !atflag && quote) {
2257c478bd9Sstevel@tonic-gate 						quoted--;
2267c478bd9Sstevel@tonic-gate 						atflag = 1;
2277c478bd9Sstevel@tonic-gate 					}
2287c478bd9Sstevel@tonic-gate 					dolg = 1;
2297c478bd9Sstevel@tonic-gate 					c = '1';
2307c478bd9Sstevel@tonic-gate 				}
2317c478bd9Sstevel@tonic-gate 				c -= '0';
2327c478bd9Sstevel@tonic-gate 				v = ((c == 0) ? cmdadr : ((int)c <= dolc) ? dolv[c] : (unsigned char *)(dolg = 0));
2337c478bd9Sstevel@tonic-gate 			}
2347c478bd9Sstevel@tonic-gate 			else if (c == '$')
2357c478bd9Sstevel@tonic-gate 				v = pidadr;
2367c478bd9Sstevel@tonic-gate 			else if (c == '!')
2377c478bd9Sstevel@tonic-gate 				v = pcsadr;
2387c478bd9Sstevel@tonic-gate 			else if (c == '#')
2397c478bd9Sstevel@tonic-gate 			{
2407c478bd9Sstevel@tonic-gate 				itos(dolc);
2417c478bd9Sstevel@tonic-gate 				v = numbuf;
2427c478bd9Sstevel@tonic-gate 			}
2437c478bd9Sstevel@tonic-gate 			else if (c == '?')
2447c478bd9Sstevel@tonic-gate 			{
2457c478bd9Sstevel@tonic-gate 				itos(retval);
2467c478bd9Sstevel@tonic-gate 				v = numbuf;
2477c478bd9Sstevel@tonic-gate 			}
2487c478bd9Sstevel@tonic-gate 			else if (c == '-')
2497c478bd9Sstevel@tonic-gate 				v = flagadr;
2507c478bd9Sstevel@tonic-gate 			else if (bra)
2517c478bd9Sstevel@tonic-gate 				error(badsub);
2527c478bd9Sstevel@tonic-gate 			else
2537c478bd9Sstevel@tonic-gate 				goto retry;
2547c478bd9Sstevel@tonic-gate 			c = readwc();
2557c478bd9Sstevel@tonic-gate 			if (c == ':' && bra)	/* null and unset fix */
2567c478bd9Sstevel@tonic-gate 			{
2577c478bd9Sstevel@tonic-gate 				nulflg = 1;
2587c478bd9Sstevel@tonic-gate 				c = readwc();
2597c478bd9Sstevel@tonic-gate 			}
2607c478bd9Sstevel@tonic-gate 			else
2617c478bd9Sstevel@tonic-gate 				nulflg = 0;
2627c478bd9Sstevel@tonic-gate 			if (!defchar(c) && bra)
2637c478bd9Sstevel@tonic-gate 				error(badsub);
2647c478bd9Sstevel@tonic-gate 			argp = 0;
2657c478bd9Sstevel@tonic-gate 			if (bra)
2667c478bd9Sstevel@tonic-gate 			{
2677c478bd9Sstevel@tonic-gate 				if (c != '}')
2687c478bd9Sstevel@tonic-gate 				{
2697c478bd9Sstevel@tonic-gate 					argp = (unsigned char *)relstak();
2707c478bd9Sstevel@tonic-gate 					if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c)))
2717c478bd9Sstevel@tonic-gate 						copyto('}', trimflag);
2727c478bd9Sstevel@tonic-gate 					else
2737c478bd9Sstevel@tonic-gate 						skipto('}');
2747c478bd9Sstevel@tonic-gate 					argp = absstak(argp);
2757c478bd9Sstevel@tonic-gate 				}
2767c478bd9Sstevel@tonic-gate 			}
2777c478bd9Sstevel@tonic-gate 			else
2787c478bd9Sstevel@tonic-gate 			{
2797c478bd9Sstevel@tonic-gate 				peekc = c | MARK;
2807c478bd9Sstevel@tonic-gate 				c = 0;
2817c478bd9Sstevel@tonic-gate 			}
2827c478bd9Sstevel@tonic-gate 			if (v && (!nulflg || *v))
2837c478bd9Sstevel@tonic-gate 			{
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 				if (c != '+')
2867c478bd9Sstevel@tonic-gate 				{
2877c478bd9Sstevel@tonic-gate 					for (;;)
2887c478bd9Sstevel@tonic-gate 					{
2897c478bd9Sstevel@tonic-gate 						if (*v == 0 && quote) {
2907c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
2917c478bd9Sstevel@tonic-gate 								growstak(staktop);
2927c478bd9Sstevel@tonic-gate 							pushstak('\\');
2937c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
2947c478bd9Sstevel@tonic-gate 								growstak(staktop);
2957c478bd9Sstevel@tonic-gate 							pushstak('\0');
2967c478bd9Sstevel@tonic-gate 						} else {
2977c478bd9Sstevel@tonic-gate 							while (c = *v) {
2987c478bd9Sstevel@tonic-gate 								wchar_t 	wc;
299*965005c8Schin 								int 	length;
3007c478bd9Sstevel@tonic-gate 								if ((length = mbtowc(&wc, (char *)v, MB_LEN_MAX)) <= 0)
3017c478bd9Sstevel@tonic-gate 									length = 1;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 								if(quote || (c == '\\' && trimflag)) {
3047c478bd9Sstevel@tonic-gate 									if (staktop >= brkend)
3057c478bd9Sstevel@tonic-gate 										growstak(staktop);
3067c478bd9Sstevel@tonic-gate 									pushstak('\\');
3077c478bd9Sstevel@tonic-gate 								}
3087c478bd9Sstevel@tonic-gate 								while(length-- > 0) {
3097c478bd9Sstevel@tonic-gate 									if (staktop >= brkend)
3107c478bd9Sstevel@tonic-gate 										growstak(staktop);
3117c478bd9Sstevel@tonic-gate 									pushstak(*v++);
3127c478bd9Sstevel@tonic-gate 								}
3137c478bd9Sstevel@tonic-gate 							}
3147c478bd9Sstevel@tonic-gate 						}
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 						if (dolg == 0 || (++dolg > dolc))
3177c478bd9Sstevel@tonic-gate 							break;
3187c478bd9Sstevel@tonic-gate 						else /* $* and $@ expansion */
3197c478bd9Sstevel@tonic-gate 						{
3207c478bd9Sstevel@tonic-gate 							v = dolv[dolg];
3217c478bd9Sstevel@tonic-gate 							if(*id == '*' && quote) {
3227c478bd9Sstevel@tonic-gate /* push quoted space so that " $* " will not be broken into separate arguments */
3237c478bd9Sstevel@tonic-gate 								if (staktop >= brkend)
3247c478bd9Sstevel@tonic-gate 									growstak(staktop);
3257c478bd9Sstevel@tonic-gate 								pushstak('\\');
3267c478bd9Sstevel@tonic-gate 							}
3277c478bd9Sstevel@tonic-gate 							if (staktop >= brkend)
3287c478bd9Sstevel@tonic-gate 								growstak(staktop);
3297c478bd9Sstevel@tonic-gate 							pushstak(' ');
3307c478bd9Sstevel@tonic-gate 						}
3317c478bd9Sstevel@tonic-gate 					}
3327c478bd9Sstevel@tonic-gate 				}
3337c478bd9Sstevel@tonic-gate 			}
3347c478bd9Sstevel@tonic-gate 			else if (argp)
3357c478bd9Sstevel@tonic-gate 			{
3367c478bd9Sstevel@tonic-gate 				if (c == '?') {
3377c478bd9Sstevel@tonic-gate 					if(trimflag)
3387c478bd9Sstevel@tonic-gate 						trim(argp);
339*965005c8Schin 					failed(id, *argp ? (const char *)argp :
340*965005c8Schin 					    badparam);
3417c478bd9Sstevel@tonic-gate 				}
3427c478bd9Sstevel@tonic-gate 				else if (c == '=')
3437c478bd9Sstevel@tonic-gate 				{
3447c478bd9Sstevel@tonic-gate 					if (n)
3457c478bd9Sstevel@tonic-gate 					{
3467c478bd9Sstevel@tonic-gate 						int strlngth = staktop - stakbot;
3477c478bd9Sstevel@tonic-gate 						unsigned char *savptr = fixstak();
3487c478bd9Sstevel@tonic-gate 						unsigned char *newargp;
3497c478bd9Sstevel@tonic-gate 					/*
3507c478bd9Sstevel@tonic-gate 					 * copy word onto stack, trim it, and then
3517c478bd9Sstevel@tonic-gate 					 * do assignment
3527c478bd9Sstevel@tonic-gate 					 */
3537c478bd9Sstevel@tonic-gate 						usestak();
3547c478bd9Sstevel@tonic-gate 						while(c = *argp) {
3557c478bd9Sstevel@tonic-gate 							wchar_t 	wc;
356*965005c8Schin 							int 		len;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 							if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
3597c478bd9Sstevel@tonic-gate 								len = 1;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 							if(c == '\\' && trimflag) {
3627c478bd9Sstevel@tonic-gate 								argp++;
3637c478bd9Sstevel@tonic-gate 								if (*argp == 0) {
3647c478bd9Sstevel@tonic-gate 									argp++;
3657c478bd9Sstevel@tonic-gate 									continue;
3667c478bd9Sstevel@tonic-gate 								}
3677c478bd9Sstevel@tonic-gate 								if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
3687c478bd9Sstevel@tonic-gate 									len = 1;
3697c478bd9Sstevel@tonic-gate 							}
3707c478bd9Sstevel@tonic-gate 							while(len-- > 0) {
3717c478bd9Sstevel@tonic-gate 								if (staktop >= brkend)
3727c478bd9Sstevel@tonic-gate 									growstak(staktop);
3737c478bd9Sstevel@tonic-gate 								pushstak(*argp++);
3747c478bd9Sstevel@tonic-gate 							}
3757c478bd9Sstevel@tonic-gate 						}
3767c478bd9Sstevel@tonic-gate 						newargp = fixstak();
3777c478bd9Sstevel@tonic-gate 						assign(n, newargp);
3787c478bd9Sstevel@tonic-gate 						tdystak(savptr);
3797c478bd9Sstevel@tonic-gate 						memcpy(stakbot, savptr, strlngth);
3807c478bd9Sstevel@tonic-gate 						staktop = stakbot + strlngth;
3817c478bd9Sstevel@tonic-gate 					}
3827c478bd9Sstevel@tonic-gate 					else
3837c478bd9Sstevel@tonic-gate 						error(badsub);
3847c478bd9Sstevel@tonic-gate 				}
3857c478bd9Sstevel@tonic-gate 			}
3867c478bd9Sstevel@tonic-gate 			else if (flags & setflg)
3877c478bd9Sstevel@tonic-gate 				failed(id, unset);
3887c478bd9Sstevel@tonic-gate 			goto retry;
3897c478bd9Sstevel@tonic-gate 		}
3907c478bd9Sstevel@tonic-gate 		else
3917c478bd9Sstevel@tonic-gate 			peekc = c | MARK;
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 	else if (d == endch)
3947c478bd9Sstevel@tonic-gate 		return(d);
3957c478bd9Sstevel@tonic-gate 	else if (d == SQUOTE)
3967c478bd9Sstevel@tonic-gate 	{
3977c478bd9Sstevel@tonic-gate 		comsubst(trimflag);
3987c478bd9Sstevel@tonic-gate 		goto retry;
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 	else if (d == DQUOTE && trimflag)
4017c478bd9Sstevel@tonic-gate 	{
4027c478bd9Sstevel@tonic-gate 		if(!quote) {
4037c478bd9Sstevel@tonic-gate 			atflag = 0;
4047c478bd9Sstevel@tonic-gate 			quoted++;
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 		quote ^= QUOTE;
4077c478bd9Sstevel@tonic-gate 		goto retry;
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 	return(d);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate unsigned char *
4137c478bd9Sstevel@tonic-gate macro(as)
4147c478bd9Sstevel@tonic-gate unsigned char	*as;
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate 	/*
4177c478bd9Sstevel@tonic-gate 	 * Strip "" and do $ substitution
4187c478bd9Sstevel@tonic-gate 	 * Leaves result on top of stack
4197c478bd9Sstevel@tonic-gate 	 */
420*965005c8Schin 	BOOL	savqu = quoted;
421*965005c8Schin 	unsigned char	savq = quote;
4227c478bd9Sstevel@tonic-gate 	struct filehdr	fb;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	push(&fb);
4257c478bd9Sstevel@tonic-gate 	estabf(as);
4267c478bd9Sstevel@tonic-gate 	usestak();
4277c478bd9Sstevel@tonic-gate 	quote = 0;
4287c478bd9Sstevel@tonic-gate 	quoted = 0;
4297c478bd9Sstevel@tonic-gate 	copyto(0, 1);
4307c478bd9Sstevel@tonic-gate 	pop();
4317c478bd9Sstevel@tonic-gate 	if (quoted && (stakbot == staktop)) {
4327c478bd9Sstevel@tonic-gate 		if (staktop >= brkend)
4337c478bd9Sstevel@tonic-gate 			growstak(staktop);
4347c478bd9Sstevel@tonic-gate 		pushstak('\\');
4357c478bd9Sstevel@tonic-gate 		if (staktop >= brkend)
4367c478bd9Sstevel@tonic-gate 			growstak(staktop);
4377c478bd9Sstevel@tonic-gate 		pushstak('\0');
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate  * above is the fix for *'.c' bug
4407c478bd9Sstevel@tonic-gate  */
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 	quote = savq;
4437c478bd9Sstevel@tonic-gate 	quoted = savqu;
4447c478bd9Sstevel@tonic-gate 	return(fixstak());
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate /* Save file descriptor for command substitution */
4477c478bd9Sstevel@tonic-gate int savpipe = -1;
4487c478bd9Sstevel@tonic-gate 
449*965005c8Schin static void
450*965005c8Schin comsubst(int trimflag)
451*965005c8Schin /* trimflag - used to determine if argument will later be trimmed */
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * command substn
4557c478bd9Sstevel@tonic-gate 	 */
4567c478bd9Sstevel@tonic-gate 	struct fileblk	cb;
457*965005c8Schin 	unsigned int	d;
4587c478bd9Sstevel@tonic-gate 	int strlngth = staktop - stakbot;
459*965005c8Schin 	unsigned char *oldstaktop;
4607c478bd9Sstevel@tonic-gate 	unsigned char *savptr = fixstak();
4617c478bd9Sstevel@tonic-gate 	unsigned char	*pc;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	usestak();
4647c478bd9Sstevel@tonic-gate 	while ((d = readwc()) != SQUOTE && d) {
4657c478bd9Sstevel@tonic-gate 		if(d == '\\') {
4667c478bd9Sstevel@tonic-gate 			d = readwc();
4677c478bd9Sstevel@tonic-gate 			if(!escchar(d) || (d == '"' && !quote)) {
4687c478bd9Sstevel@tonic-gate 		/* trim quotes for `, \, or " if command substitution is within
4697c478bd9Sstevel@tonic-gate 		   double quotes */
4707c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
4717c478bd9Sstevel@tonic-gate 					growstak(staktop);
4727c478bd9Sstevel@tonic-gate 				pushstak('\\');
4737c478bd9Sstevel@tonic-gate 			}
4747c478bd9Sstevel@tonic-gate 		}
4757c478bd9Sstevel@tonic-gate 		pc = readw(d);
4767c478bd9Sstevel@tonic-gate 		/* d might be NULL */
4777c478bd9Sstevel@tonic-gate 		if (*pc) {
4787c478bd9Sstevel@tonic-gate 			while (*pc) {
4797c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
4807c478bd9Sstevel@tonic-gate 					growstak(staktop);
4817c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
4827c478bd9Sstevel@tonic-gate 			}
4837c478bd9Sstevel@tonic-gate 		} else {
4847c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
4857c478bd9Sstevel@tonic-gate 				growstak(staktop);
4867c478bd9Sstevel@tonic-gate 			pushstak(*pc);
4877c478bd9Sstevel@tonic-gate 		}
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 	{
490*965005c8Schin 		unsigned char	*argc;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 		argc = fixstak();
4937c478bd9Sstevel@tonic-gate 		push(&cb);
4947c478bd9Sstevel@tonic-gate 		estabf(argc);  /* read from string */
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate 	{
497*965005c8Schin 		struct trenod	*t;
4987c478bd9Sstevel@tonic-gate 		int		pv[2];
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		/*
5017c478bd9Sstevel@tonic-gate 		 * this is done like this so that the pipe
5027c478bd9Sstevel@tonic-gate 		 * is open only when needed
5037c478bd9Sstevel@tonic-gate 		 */
5047c478bd9Sstevel@tonic-gate 	 	t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG ));
5057c478bd9Sstevel@tonic-gate 		chkpipe(pv);
5067c478bd9Sstevel@tonic-gate 		savpipe = pv[OTPIPE];
5077c478bd9Sstevel@tonic-gate 		initf(pv[INPIPE]); /* read from pipe */
5087c478bd9Sstevel@tonic-gate 		execute(t, XEC_NOSTOP, (int)(flags & errflg), 0, pv);
5097c478bd9Sstevel@tonic-gate 		close(pv[OTPIPE]);
5107c478bd9Sstevel@tonic-gate 		savpipe = -1;
5117c478bd9Sstevel@tonic-gate 	}
5127c478bd9Sstevel@tonic-gate 	tdystak(savptr);
5137c478bd9Sstevel@tonic-gate 	memcpy(stakbot, savptr, strlngth);
5147c478bd9Sstevel@tonic-gate 	oldstaktop = staktop = stakbot + strlngth;
5157c478bd9Sstevel@tonic-gate 	while (d = readwc()) {
5167c478bd9Sstevel@tonic-gate 		if(quote || (d == '\\' && trimflag)) {
517*965005c8Schin 			unsigned char *rest;
5187c478bd9Sstevel@tonic-gate 			/* quote output from command subst. if within double
5197c478bd9Sstevel@tonic-gate 			   quotes or backslash part of output */
5207c478bd9Sstevel@tonic-gate 			rest = readw(d);
5217c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
5227c478bd9Sstevel@tonic-gate 				growstak(staktop);
5237c478bd9Sstevel@tonic-gate 			pushstak('\\');
5247c478bd9Sstevel@tonic-gate 			while(d = *rest++) {
5257c478bd9Sstevel@tonic-gate 			/* Pick up all of multibyte character */
5267c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
5277c478bd9Sstevel@tonic-gate 					growstak(staktop);
5287c478bd9Sstevel@tonic-gate 				pushstak(d);
5297c478bd9Sstevel@tonic-gate 			}
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 		else {
5327c478bd9Sstevel@tonic-gate 			pc = readw(d);
5337c478bd9Sstevel@tonic-gate 			while (*pc) {
5347c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
5357c478bd9Sstevel@tonic-gate 					growstak(staktop);
5367c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
5377c478bd9Sstevel@tonic-gate 			}
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 	}
5407c478bd9Sstevel@tonic-gate 	{
5417c478bd9Sstevel@tonic-gate 		extern pid_t parent;
5427c478bd9Sstevel@tonic-gate 		int stat;
543*965005c8Schin 		int rc;
5447c478bd9Sstevel@tonic-gate 		int	ret = 0;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		while ((ret = waitpid(parent,&stat,0)) != parent) {
5477c478bd9Sstevel@tonic-gate 			/* break out if waitpid(2) has failed */
5487c478bd9Sstevel@tonic-gate 			if (ret == -1)
5497c478bd9Sstevel@tonic-gate 				break;
5507c478bd9Sstevel@tonic-gate 		}
5517c478bd9Sstevel@tonic-gate 		if (WIFEXITED(stat))
5527c478bd9Sstevel@tonic-gate 			rc = WEXITSTATUS(stat);
5537c478bd9Sstevel@tonic-gate 		else
5547c478bd9Sstevel@tonic-gate 			rc = (WTERMSIG(stat) | SIGFLG);
5557c478bd9Sstevel@tonic-gate 		if (rc && (flags & errflg))
5567c478bd9Sstevel@tonic-gate 			exitsh(rc);
5577c478bd9Sstevel@tonic-gate 		exitval = rc;
5587c478bd9Sstevel@tonic-gate 		flags |= eflag;
5597c478bd9Sstevel@tonic-gate 		exitset();
5607c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 	while (oldstaktop != staktop)
5627c478bd9Sstevel@tonic-gate 	{ /* strip off trailing newlines from command substitution only */
5637c478bd9Sstevel@tonic-gate 		if ((*--staktop) != NL)
5647c478bd9Sstevel@tonic-gate 		{
5657c478bd9Sstevel@tonic-gate 			++staktop;
5667c478bd9Sstevel@tonic-gate 			break;
5677c478bd9Sstevel@tonic-gate 		} else if(quote)
5687c478bd9Sstevel@tonic-gate 			staktop--; /* skip past backslashes if quoting */
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 	pop();
5717c478bd9Sstevel@tonic-gate }
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate #define CPYSIZ	512
5747c478bd9Sstevel@tonic-gate 
575*965005c8Schin void
576*965005c8Schin subst(int in, int ot)
5777c478bd9Sstevel@tonic-gate {
578*965005c8Schin 	unsigned int	c;
5797c478bd9Sstevel@tonic-gate 	struct fileblk	fb;
580*965005c8Schin 	int	count = CPYSIZ;
5817c478bd9Sstevel@tonic-gate 	unsigned char	*pc;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	push(&fb);
5847c478bd9Sstevel@tonic-gate 	initf(in);
5857c478bd9Sstevel@tonic-gate 	/*
5867c478bd9Sstevel@tonic-gate 	 * DQUOTE used to stop it from quoting
5877c478bd9Sstevel@tonic-gate 	 */
5887c478bd9Sstevel@tonic-gate 	while (c = (getch(DQUOTE, 0))) /* read characters from here document
5897c478bd9Sstevel@tonic-gate 				       and interpret them */
5907c478bd9Sstevel@tonic-gate 	{
5917c478bd9Sstevel@tonic-gate 		if(c == '\\') {
5927c478bd9Sstevel@tonic-gate 			c = readwc(); /* check if character in here document is
5937c478bd9Sstevel@tonic-gate 					escaped */
5947c478bd9Sstevel@tonic-gate 			if(!escchar(c) || c == '"') {
5957c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
5967c478bd9Sstevel@tonic-gate 					growstak(staktop);
5977c478bd9Sstevel@tonic-gate 				pushstak('\\');
5987c478bd9Sstevel@tonic-gate 			}
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 		pc = readw(c);
6017c478bd9Sstevel@tonic-gate 		/* c might be NULL */
6027c478bd9Sstevel@tonic-gate 		if (*pc) {
6037c478bd9Sstevel@tonic-gate 			while (*pc) {
6047c478bd9Sstevel@tonic-gate 				if (staktop >= brkend)
6057c478bd9Sstevel@tonic-gate 					growstak(staktop);
6067c478bd9Sstevel@tonic-gate 				pushstak(*pc++);
6077c478bd9Sstevel@tonic-gate 			}
6087c478bd9Sstevel@tonic-gate 		} else {
6097c478bd9Sstevel@tonic-gate 			if (staktop >= brkend)
6107c478bd9Sstevel@tonic-gate 				growstak(staktop);
6117c478bd9Sstevel@tonic-gate 			pushstak(*pc);
6127c478bd9Sstevel@tonic-gate 		}
6137c478bd9Sstevel@tonic-gate 		if (--count == 0)
6147c478bd9Sstevel@tonic-gate 		{
6157c478bd9Sstevel@tonic-gate 			flush(ot);
6167c478bd9Sstevel@tonic-gate 			count = CPYSIZ;
6177c478bd9Sstevel@tonic-gate 		}
6187c478bd9Sstevel@tonic-gate 	}
6197c478bd9Sstevel@tonic-gate 	flush(ot);
6207c478bd9Sstevel@tonic-gate 	pop();
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate 
623*965005c8Schin static void
624*965005c8Schin flush(int ot)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate 	write(ot, stakbot, staktop - stakbot);
6277c478bd9Sstevel@tonic-gate 	if (flags & execpr)
6287c478bd9Sstevel@tonic-gate 		write(output, stakbot, staktop - stakbot);
6297c478bd9Sstevel@tonic-gate 	staktop = stakbot;
6307c478bd9Sstevel@tonic-gate }
631