xref: /onnv-gate/usr/src/cmd/sh/cmd.c (revision 9369:4df685ccc8c1)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52256Sna195498  * Common Development and Distribution License (the "License").
62256Sna195498  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21527Schin 
22527Schin /*
23*9369SNobutomo.Nakano@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24527Schin  * Use is subject to license terms.
25527Schin  */
26527Schin 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * UNIX shell
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include	"defs.h"
350Sstevel@tonic-gate #include	"sym.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate static struct ionod *	inout();
38527Schin static void	chkword(void);
39527Schin static void	chksym(int);
400Sstevel@tonic-gate static struct trenod *	term();
410Sstevel@tonic-gate static struct trenod *	makelist();
420Sstevel@tonic-gate static struct trenod *	list();
430Sstevel@tonic-gate static struct regnod *	syncase();
440Sstevel@tonic-gate static struct trenod *	item();
450Sstevel@tonic-gate static int	skipnl();
46527Schin static void	prsym(int);
47527Schin static void	synbad(void);
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /* ======== storage allocation for functions ======== */
510Sstevel@tonic-gate 
520Sstevel@tonic-gate unsigned char *
getstor(asize)530Sstevel@tonic-gate getstor(asize)
540Sstevel@tonic-gate 	int asize;
550Sstevel@tonic-gate {
560Sstevel@tonic-gate 	if (fndef)
570Sstevel@tonic-gate 		return((unsigned char *)alloc(asize));
580Sstevel@tonic-gate 	else
590Sstevel@tonic-gate 		return(getstak(asize));
600Sstevel@tonic-gate }
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /* ========	command line decoding	========*/
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 
680Sstevel@tonic-gate struct trenod *
makefork(flgs,i)690Sstevel@tonic-gate makefork(flgs, i)
700Sstevel@tonic-gate 	int	flgs;
710Sstevel@tonic-gate 	struct trenod *i;
720Sstevel@tonic-gate {
73527Schin 	struct forknod *t;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	t = (struct forknod *)getstor(sizeof(struct forknod));
760Sstevel@tonic-gate 	t->forktyp = flgs|TFORK;
770Sstevel@tonic-gate 	t->forktre = i;
780Sstevel@tonic-gate 	t->forkio = 0;
790Sstevel@tonic-gate 	return((struct trenod *)t);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate 
820Sstevel@tonic-gate static struct trenod *
makelist(type,i,r)830Sstevel@tonic-gate makelist(type, i, r)
840Sstevel@tonic-gate 	int	type;
850Sstevel@tonic-gate 	struct trenod *i, *r;
860Sstevel@tonic-gate {
87527Schin 	struct lstnod *t;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	if (i == 0 || r == 0)
900Sstevel@tonic-gate 		synbad();
910Sstevel@tonic-gate 	else
920Sstevel@tonic-gate 	{
930Sstevel@tonic-gate 		t = (struct lstnod *)getstor(sizeof(struct lstnod));
940Sstevel@tonic-gate 		t->lsttyp = type;
950Sstevel@tonic-gate 		t->lstlef = i;
960Sstevel@tonic-gate 		t->lstrit = r;
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	return((struct trenod *)t);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * cmd
1030Sstevel@tonic-gate  *	empty
1040Sstevel@tonic-gate  *	list
1050Sstevel@tonic-gate  *	list & [ cmd ]
1060Sstevel@tonic-gate  *	list [ ; cmd ]
1070Sstevel@tonic-gate  */
1080Sstevel@tonic-gate struct trenod *
cmd(sym,flg)1090Sstevel@tonic-gate cmd(sym, flg)
110527Schin 	int	sym;
1110Sstevel@tonic-gate 	int		flg;
1120Sstevel@tonic-gate {
113527Schin 	struct trenod *i, *e;
1140Sstevel@tonic-gate 	i = list(flg);
1150Sstevel@tonic-gate 	if (wdval == NL)
1160Sstevel@tonic-gate 	{
1170Sstevel@tonic-gate 		if (flg & NLFLG)
1180Sstevel@tonic-gate 		{
1190Sstevel@tonic-gate 			wdval = ';';
1200Sstevel@tonic-gate 			chkpr();
1210Sstevel@tonic-gate 		}
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 	else if (i == 0 && (flg & MTFLG) == 0)
1240Sstevel@tonic-gate 		synbad();
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	switch (wdval)
1270Sstevel@tonic-gate 	{
1280Sstevel@tonic-gate 	case '&':
1290Sstevel@tonic-gate 		if (i)
1300Sstevel@tonic-gate 			i = makefork(FAMP, i);
1310Sstevel@tonic-gate 		else
1320Sstevel@tonic-gate 			synbad();
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	case ';':
1350Sstevel@tonic-gate 		if (e = cmd(sym, flg | MTFLG))
1360Sstevel@tonic-gate 			i = makelist(TLST, i, e);
1370Sstevel@tonic-gate 		else if (i == 0)
1380Sstevel@tonic-gate 			synbad();
1390Sstevel@tonic-gate 		break;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	case EOFSYM:
1420Sstevel@tonic-gate 		if (sym == NL)
1430Sstevel@tonic-gate 			break;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	default:
1460Sstevel@tonic-gate 		if (sym)
1470Sstevel@tonic-gate 			chksym(sym);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 	return(i);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate /*
1530Sstevel@tonic-gate  * list
1540Sstevel@tonic-gate  *	term
1550Sstevel@tonic-gate  *	list && term
1560Sstevel@tonic-gate  *	list || term
1570Sstevel@tonic-gate  */
1580Sstevel@tonic-gate static struct trenod *
list(flg)1590Sstevel@tonic-gate list(flg)
1600Sstevel@tonic-gate {
161527Schin 	struct trenod *r;
162527Schin 	int		b;
1630Sstevel@tonic-gate 	r = term(flg);
1640Sstevel@tonic-gate 	while (r && ((b = (wdval == ANDFSYM)) || wdval == ORFSYM))
1650Sstevel@tonic-gate 		r = makelist((b ? TAND : TORF), r, term(NLFLG));
1660Sstevel@tonic-gate 	return(r);
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * term
1710Sstevel@tonic-gate  *	item
1720Sstevel@tonic-gate  *	item |^ term
1730Sstevel@tonic-gate  */
1740Sstevel@tonic-gate static struct trenod *
term(flg)1750Sstevel@tonic-gate term(flg)
1760Sstevel@tonic-gate {
177527Schin 	struct trenod *t;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	reserv++;
1800Sstevel@tonic-gate 	if (flg & NLFLG)
1810Sstevel@tonic-gate 		skipnl();
1820Sstevel@tonic-gate 	else
1830Sstevel@tonic-gate 		word();
1840Sstevel@tonic-gate 	if ((t = item(TRUE)) && (wdval == '^' || wdval == '|'))
1850Sstevel@tonic-gate 	{
1860Sstevel@tonic-gate 		struct trenod	*left;
1870Sstevel@tonic-gate 		struct trenod	*right;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 		left = makefork(FPOU, t);
1900Sstevel@tonic-gate 		right = makefork(FPIN, term(NLFLG));
1910Sstevel@tonic-gate 		return(makefork(0, makelist(TFIL, left, right)));
1920Sstevel@tonic-gate 	}
1930Sstevel@tonic-gate 	else
1940Sstevel@tonic-gate 		return(t);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate static struct regnod *
syncase(esym)1990Sstevel@tonic-gate syncase(esym)
200527Schin int	esym;
2010Sstevel@tonic-gate {
2020Sstevel@tonic-gate 	skipnl();
2030Sstevel@tonic-gate 	if (wdval == esym)
2040Sstevel@tonic-gate 		return(0);
2050Sstevel@tonic-gate 	else
2060Sstevel@tonic-gate 	{
207527Schin 		struct regnod *r =
208527Schin 		    (struct regnod *)getstor(sizeof (struct regnod));
209527Schin 		struct argnod *argp;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 		r->regptr = 0;
2120Sstevel@tonic-gate 		for (;;)
2130Sstevel@tonic-gate 		{
2140Sstevel@tonic-gate 			if (fndef)
2150Sstevel@tonic-gate 			{
2160Sstevel@tonic-gate 				argp= wdarg;
2170Sstevel@tonic-gate 				wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
2180Sstevel@tonic-gate 				movstr(argp->argval, wdarg->argval);
2190Sstevel@tonic-gate 			}
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 			wdarg->argnxt = r->regptr;
2220Sstevel@tonic-gate 			r->regptr = wdarg;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 			/* 'in' is not a reserved word in this case */
2250Sstevel@tonic-gate 			if (wdval == INSYM){
2260Sstevel@tonic-gate 				wdval = 0;
2270Sstevel@tonic-gate 			}
2280Sstevel@tonic-gate 			if (wdval || (word() != ')' && wdval != '|'))
2290Sstevel@tonic-gate 				synbad();
2300Sstevel@tonic-gate 			if (wdval == '|')
2310Sstevel@tonic-gate 				word();
2320Sstevel@tonic-gate 			else
2330Sstevel@tonic-gate 				break;
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 		r->regcom = cmd(0, NLFLG | MTFLG);
2360Sstevel@tonic-gate 		if (wdval == ECSYM)
2370Sstevel@tonic-gate 			r->regnxt = syncase(esym);
2380Sstevel@tonic-gate 		else
2390Sstevel@tonic-gate 		{
2400Sstevel@tonic-gate 			chksym(esym);
2410Sstevel@tonic-gate 			r->regnxt = 0;
2420Sstevel@tonic-gate 		}
2430Sstevel@tonic-gate 		return(r);
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate  * item
2490Sstevel@tonic-gate  *
2500Sstevel@tonic-gate  *	( cmd ) [ < in  ] [ > out ]
2510Sstevel@tonic-gate  *	word word* [ < in ] [ > out ]
2520Sstevel@tonic-gate  *	if ... then ... else ... fi
2530Sstevel@tonic-gate  *	for ... while ... do ... done
2540Sstevel@tonic-gate  *	case ... in ... esac
2550Sstevel@tonic-gate  *	begin ... end
2560Sstevel@tonic-gate  */
2570Sstevel@tonic-gate static struct trenod *
item(flag)2580Sstevel@tonic-gate item(flag)
2590Sstevel@tonic-gate 	BOOL	flag;
2600Sstevel@tonic-gate {
261527Schin 	struct trenod *r;
262527Schin 	struct ionod *io;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	if (flag)
2650Sstevel@tonic-gate 		io = inout((struct ionod *)0);
2660Sstevel@tonic-gate 	else
2670Sstevel@tonic-gate 		io = 0;
2680Sstevel@tonic-gate 	switch (wdval)
2690Sstevel@tonic-gate 	{
2700Sstevel@tonic-gate 	case CASYM:
2710Sstevel@tonic-gate 		{
272527Schin 			struct swnod *t;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 			t = (struct swnod *)getstor(sizeof(struct swnod));
2750Sstevel@tonic-gate 			r = (struct trenod *)t;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 			chkword();
2780Sstevel@tonic-gate 			if (fndef)
2790Sstevel@tonic-gate 				t->swarg = make(wdarg->argval);
2800Sstevel@tonic-gate 			else
2810Sstevel@tonic-gate 				t->swarg = wdarg->argval;
2820Sstevel@tonic-gate 			skipnl();
2830Sstevel@tonic-gate 			chksym(INSYM | BRSYM);
2840Sstevel@tonic-gate 			t->swlst = syncase(wdval == INSYM ? ESSYM : KTSYM);
2850Sstevel@tonic-gate 			t->swtyp = TSW;
2860Sstevel@tonic-gate 			break;
2870Sstevel@tonic-gate 		}
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	case IFSYM:
2900Sstevel@tonic-gate 		{
291527Schin 			int	w;
292527Schin 			struct ifnod *t;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 			t = (struct ifnod *)getstor(sizeof(struct ifnod));
2950Sstevel@tonic-gate 			r = (struct trenod *)t;
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 			t->iftyp = TIF;
2980Sstevel@tonic-gate 			t->iftre = cmd(THSYM, NLFLG);
2990Sstevel@tonic-gate 			t->thtre = cmd(ELSYM | FISYM | EFSYM, NLFLG);
3000Sstevel@tonic-gate 			t->eltre = ((w = wdval) == ELSYM ? cmd(FISYM, NLFLG) : (w == EFSYM ? (wdval = IFSYM, item(0)) : 0));
3010Sstevel@tonic-gate 			if (w == EFSYM)
3020Sstevel@tonic-gate 				return(r);
3030Sstevel@tonic-gate 			break;
3040Sstevel@tonic-gate 		}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	case FORSYM:
3070Sstevel@tonic-gate 		{
308527Schin 			struct fornod *t;
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 			t = (struct fornod *)getstor(sizeof(struct fornod));
3110Sstevel@tonic-gate 			r = (struct trenod *)t;
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 			t->fortyp = TFOR;
3140Sstevel@tonic-gate 			t->forlst = 0;
3150Sstevel@tonic-gate 			chkword();
3160Sstevel@tonic-gate 			if (fndef)
3170Sstevel@tonic-gate 				t->fornam = make(wdarg->argval);
3180Sstevel@tonic-gate 			else
3190Sstevel@tonic-gate 				t->fornam = wdarg->argval;
3200Sstevel@tonic-gate 			if (skipnl() == INSYM)
3210Sstevel@tonic-gate 			{
3220Sstevel@tonic-gate 				chkword();
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 				nohash++;
3250Sstevel@tonic-gate 				t->forlst = (struct comnod *)item(0);
3260Sstevel@tonic-gate 				nohash--;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 				if (wdval != NL && wdval != ';')
3290Sstevel@tonic-gate 					synbad();
3300Sstevel@tonic-gate 				if (wdval == NL)
3310Sstevel@tonic-gate 					chkpr();
3320Sstevel@tonic-gate 				skipnl();
3330Sstevel@tonic-gate 			}
3340Sstevel@tonic-gate 			chksym(DOSYM | BRSYM);
3350Sstevel@tonic-gate 			t->fortre = cmd(wdval == DOSYM ? ODSYM : KTSYM, NLFLG);
3360Sstevel@tonic-gate 			break;
3370Sstevel@tonic-gate 		}
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	case WHSYM:
3400Sstevel@tonic-gate 	case UNSYM:
3410Sstevel@tonic-gate 		{
342527Schin 			struct whnod *t;
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 			t = (struct whnod *)getstor(sizeof(struct whnod));
3450Sstevel@tonic-gate 			r = (struct trenod *)t;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 			t->whtyp = (wdval == WHSYM ? TWH : TUN);
3480Sstevel@tonic-gate 			t->whtre = cmd(DOSYM, NLFLG);
3490Sstevel@tonic-gate 			t->dotre = cmd(ODSYM, NLFLG);
3500Sstevel@tonic-gate 			break;
3510Sstevel@tonic-gate 		}
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	case BRSYM:
3540Sstevel@tonic-gate 		r = cmd(KTSYM, NLFLG);
3550Sstevel@tonic-gate 		break;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	case '(':
3580Sstevel@tonic-gate 		{
359527Schin 			struct parnod *p;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 			p = (struct parnod *)getstor(sizeof(struct parnod));
3620Sstevel@tonic-gate 			p->partre = cmd(')', NLFLG);
3630Sstevel@tonic-gate 			p->partyp = TPAR;
3640Sstevel@tonic-gate 			r = makefork(0, p);
3650Sstevel@tonic-gate 			break;
3660Sstevel@tonic-gate 		}
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	default:
3690Sstevel@tonic-gate 		if (io == 0)
3700Sstevel@tonic-gate 			return(0);
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	case 0:
3730Sstevel@tonic-gate 		{
374527Schin 			struct comnod *t;
375527Schin 			struct argnod *argp;
376527Schin 			struct argnod **argtail;
377527Schin 			struct argnod **argset = 0;
3780Sstevel@tonic-gate 			int	keywd = 1;
3790Sstevel@tonic-gate 			unsigned char	*com;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 			if ((wdval != NL) && ((peekn = skipwc()) == '('))
3820Sstevel@tonic-gate 			{
3830Sstevel@tonic-gate 				struct fndnod *f;
3840Sstevel@tonic-gate 				struct ionod  *saveio;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 				saveio = iotemp;
3870Sstevel@tonic-gate 				peekn = 0;
3880Sstevel@tonic-gate 				if (skipwc() != ')')
3890Sstevel@tonic-gate 					synbad();
3900Sstevel@tonic-gate 
391*9369SNobutomo.Nakano@Sun.COM 				/*
392*9369SNobutomo.Nakano@Sun.COM 				 * We increase fndef before calling getstor(),
393*9369SNobutomo.Nakano@Sun.COM 				 * so that getstor() uses malloc to allocate
394*9369SNobutomo.Nakano@Sun.COM 				 * memory instead of stack. This is necessary
395*9369SNobutomo.Nakano@Sun.COM 				 * since fndnod will be hung on np->namenv,
396*9369SNobutomo.Nakano@Sun.COM 				 * which persists over command executions.
397*9369SNobutomo.Nakano@Sun.COM 				 */
398*9369SNobutomo.Nakano@Sun.COM 				fndef++;
3990Sstevel@tonic-gate 				f = (struct fndnod *)getstor(sizeof(struct fndnod));
4000Sstevel@tonic-gate 				r = (struct trenod *)f;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 				f->fndtyp = TFND;
403*9369SNobutomo.Nakano@Sun.COM 				f->fndnam = make(wdarg->argval);
404*9369SNobutomo.Nakano@Sun.COM 				f->fndref = 0;
4050Sstevel@tonic-gate 				reserv++;
4060Sstevel@tonic-gate 				skipnl();
4070Sstevel@tonic-gate 				f->fndval = (struct trenod *)item(0);
4080Sstevel@tonic-gate 				fndef--;
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 				if (iotemp != saveio)
4110Sstevel@tonic-gate 				{
4120Sstevel@tonic-gate 					struct ionod 	*ioptr = iotemp;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 					while (ioptr->iolst != saveio)
4150Sstevel@tonic-gate 						ioptr = ioptr->iolst;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 					ioptr->iolst = fiotemp;
4180Sstevel@tonic-gate 					fiotemp = iotemp;
4190Sstevel@tonic-gate 					iotemp = saveio;
4200Sstevel@tonic-gate 				}
4210Sstevel@tonic-gate 				return(r);
4220Sstevel@tonic-gate 			}
4230Sstevel@tonic-gate 			else
4240Sstevel@tonic-gate 			{
4250Sstevel@tonic-gate 				t = (struct comnod *)getstor(sizeof(struct comnod));
4260Sstevel@tonic-gate 				r = (struct trenod *)t;
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 				t->comio = io; /*initial io chain*/
4290Sstevel@tonic-gate 				argtail = &(t->comarg);
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 				while (wdval == 0)
4320Sstevel@tonic-gate 				{
4330Sstevel@tonic-gate 					if (fndef)
4340Sstevel@tonic-gate 					{
4350Sstevel@tonic-gate 						argp = wdarg;
4360Sstevel@tonic-gate 						wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
4370Sstevel@tonic-gate 						movstr(argp->argval, wdarg->argval);
4380Sstevel@tonic-gate 					}
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 					argp = wdarg;
4410Sstevel@tonic-gate 					if (wdset && keywd)
4420Sstevel@tonic-gate 					{
4430Sstevel@tonic-gate 						argp->argnxt = (struct argnod *)argset;
4440Sstevel@tonic-gate 						argset = (struct argnod **)argp;
4450Sstevel@tonic-gate 					}
4460Sstevel@tonic-gate 					else
4470Sstevel@tonic-gate 					{
4480Sstevel@tonic-gate 						*argtail = argp;
4490Sstevel@tonic-gate 						argtail = &(argp->argnxt);
4500Sstevel@tonic-gate 						keywd = flags & keyflg;
4510Sstevel@tonic-gate 					}
4520Sstevel@tonic-gate 					word();
4530Sstevel@tonic-gate 					if (flag)
4540Sstevel@tonic-gate 					{
4550Sstevel@tonic-gate 						if (io)
4560Sstevel@tonic-gate 						{
4570Sstevel@tonic-gate 							while(io->ionxt)
4580Sstevel@tonic-gate 								io = io->ionxt;
4590Sstevel@tonic-gate 							io->ionxt = inout((struct ionod *)0);
4600Sstevel@tonic-gate 						}
4610Sstevel@tonic-gate 						else
4620Sstevel@tonic-gate 							t->comio = io = inout((struct ionod *)0);
4630Sstevel@tonic-gate  					}
4640Sstevel@tonic-gate 				}
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 				t->comtyp = TCOM;
4670Sstevel@tonic-gate 				t->comset = (struct argnod *)argset;
4680Sstevel@tonic-gate 				*argtail = 0;
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 				if (nohash == 0 && (fndef == 0 || (flags & hashflg)))
4710Sstevel@tonic-gate 				{
4720Sstevel@tonic-gate 					if (t->comarg)
4730Sstevel@tonic-gate 					{
4740Sstevel@tonic-gate 						com = t->comarg->argval;
4750Sstevel@tonic-gate 						if (*com && *com != DOLLAR)
4760Sstevel@tonic-gate 							pathlook(com, 0, t->comset);
4770Sstevel@tonic-gate 					}
4780Sstevel@tonic-gate 				}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 				return(r);
4810Sstevel@tonic-gate 			}
4820Sstevel@tonic-gate 		}
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	}
4850Sstevel@tonic-gate 	reserv++;
4860Sstevel@tonic-gate 	word();
4870Sstevel@tonic-gate 	if (io = inout(io))
4880Sstevel@tonic-gate 	{
4890Sstevel@tonic-gate 		r = makefork(0,r);
4900Sstevel@tonic-gate 		r->treio = io;
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate 	return(r);
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate static int
skipnl()4970Sstevel@tonic-gate skipnl()
4980Sstevel@tonic-gate {
4990Sstevel@tonic-gate 	while ((reserv++, word() == NL))
5000Sstevel@tonic-gate 		chkpr();
5010Sstevel@tonic-gate 	return(wdval);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate static struct ionod *
inout(lastio)5050Sstevel@tonic-gate inout(lastio)
5060Sstevel@tonic-gate 	struct ionod *lastio;
5070Sstevel@tonic-gate {
508527Schin 	int	iof;
509527Schin 	struct ionod *iop;
510527Schin 	unsigned int	c;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	iof = wdnum;
5130Sstevel@tonic-gate 	switch (wdval)
5140Sstevel@tonic-gate 	{
5150Sstevel@tonic-gate 	case DOCSYM:	/*	<<	*/
5165976Snakanon 		iof |= IODOC|IODOC_SUBST;
5170Sstevel@tonic-gate 		break;
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	case APPSYM:	/*	>>	*/
5200Sstevel@tonic-gate 	case '>':
5210Sstevel@tonic-gate 		if (wdnum == 0)
5220Sstevel@tonic-gate 			iof |= 1;
5230Sstevel@tonic-gate 		iof |= IOPUT;
5240Sstevel@tonic-gate 		if (wdval == APPSYM)
5250Sstevel@tonic-gate 		{
5260Sstevel@tonic-gate 			iof |= IOAPP;
5270Sstevel@tonic-gate 			break;
5280Sstevel@tonic-gate 		}
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	case '<':
5310Sstevel@tonic-gate 		if ((c = nextwc()) == '&')
5320Sstevel@tonic-gate 			iof |= IOMOV;
5330Sstevel@tonic-gate 		else if (c == '>')
5340Sstevel@tonic-gate 			iof |= IORDW;
5350Sstevel@tonic-gate 		else
5360Sstevel@tonic-gate 			peekn = c | MARK;
5370Sstevel@tonic-gate 		break;
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	default:
5400Sstevel@tonic-gate 		return(lastio);
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	chkword();
5440Sstevel@tonic-gate 	iop = (struct ionod *)getstor(sizeof(struct ionod));
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	if (fndef)
5470Sstevel@tonic-gate 		iop->ioname = (char *) make(wdarg->argval);
5480Sstevel@tonic-gate 	else
5490Sstevel@tonic-gate 		iop->ioname = (char *) (wdarg->argval);
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	iop->iolink = 0;
5520Sstevel@tonic-gate 	iop->iofile = iof;
5530Sstevel@tonic-gate 	if (iof & IODOC)
5540Sstevel@tonic-gate 	{
5550Sstevel@tonic-gate 		iop->iolst = iopend;
5560Sstevel@tonic-gate 		iopend = iop;
5570Sstevel@tonic-gate 	}
5580Sstevel@tonic-gate 	word();
5590Sstevel@tonic-gate 	iop->ionxt = inout(lastio);
5600Sstevel@tonic-gate 	return(iop);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
563527Schin static void
chkword(void)564527Schin chkword(void)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate 	if (word())
5670Sstevel@tonic-gate 		synbad();
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate 
570527Schin static void
chksym(int sym)571527Schin chksym(int sym)
5720Sstevel@tonic-gate {
573527Schin 	int	x = sym & wdval;
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	if (((x & SYMFLG) ? x : sym) != wdval)
5760Sstevel@tonic-gate 		synbad();
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate 
579527Schin static void
prsym(int sym)580527Schin prsym(int sym)
5810Sstevel@tonic-gate {
5820Sstevel@tonic-gate 	if (sym & SYMFLG)
5830Sstevel@tonic-gate 	{
584527Schin 		const struct sysnod *sp = reserved;
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 		while (sp->sysval && sp->sysval != sym)
5870Sstevel@tonic-gate 			sp++;
5880Sstevel@tonic-gate 		prs(sp->sysnam);
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 	else if (sym == EOFSYM)
5912256Sna195498 		prs(_gettext(endoffile));
5920Sstevel@tonic-gate 	else
5930Sstevel@tonic-gate 	{
5940Sstevel@tonic-gate 		if (sym & SYMREP)
5950Sstevel@tonic-gate 			prc(sym);
5960Sstevel@tonic-gate 		if (sym == NL)
5972256Sna195498 			prs(_gettext(nlorsemi));
5980Sstevel@tonic-gate 		else
5990Sstevel@tonic-gate 			prc(sym);
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
603527Schin static void
synbad(void)604527Schin synbad(void)
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate 	prp();
6072256Sna195498 	prs(_gettext(synmsg));
6080Sstevel@tonic-gate 	if ((flags & ttyflg) == 0)
6090Sstevel@tonic-gate 	{
6102256Sna195498 		prs(_gettext(atline));
6110Sstevel@tonic-gate 		prn(standin->flin);
6120Sstevel@tonic-gate 	}
6130Sstevel@tonic-gate 	prs(colon);
6140Sstevel@tonic-gate 	prc(LQ);
6150Sstevel@tonic-gate 	if (wdval)
6160Sstevel@tonic-gate 		prsym(wdval);
6170Sstevel@tonic-gate 	else
6180Sstevel@tonic-gate 		prs_cntl(wdarg->argval);
6190Sstevel@tonic-gate 	prc(RQ);
6202256Sna195498 	prs(_gettext(unexpected));
6210Sstevel@tonic-gate 	newline();
6220Sstevel@tonic-gate 	exitsh(SYNBAD);
6230Sstevel@tonic-gate }
624