xref: /onnv-gate/usr/src/cmd/sh/cmd.c (revision 527)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*527Schin 
23*527Schin /*
24*527Schin  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
25*527Schin  * Use is subject to license terms.
26*527Schin  */
27*527Schin 
280Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
290Sstevel@tonic-gate /*	  All Rights Reserved  	*/
300Sstevel@tonic-gate 
31*527Schin #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate  * UNIX shell
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include	"defs.h"
370Sstevel@tonic-gate #include	"sym.h"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static struct ionod *	inout();
40*527Schin static void	chkword(void);
41*527Schin static void	chksym(int);
420Sstevel@tonic-gate static struct trenod *	term();
430Sstevel@tonic-gate static struct trenod *	makelist();
440Sstevel@tonic-gate static struct trenod *	list();
450Sstevel@tonic-gate static struct regnod *	syncase();
460Sstevel@tonic-gate static struct trenod *	item();
470Sstevel@tonic-gate static int	skipnl();
48*527Schin static void	prsym(int);
49*527Schin static void	synbad(void);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /* ======== storage allocation for functions ======== */
530Sstevel@tonic-gate 
540Sstevel@tonic-gate unsigned char *
550Sstevel@tonic-gate getstor(asize)
560Sstevel@tonic-gate 	int asize;
570Sstevel@tonic-gate {
580Sstevel@tonic-gate 	if (fndef)
590Sstevel@tonic-gate 		return((unsigned char *)alloc(asize));
600Sstevel@tonic-gate 	else
610Sstevel@tonic-gate 		return(getstak(asize));
620Sstevel@tonic-gate }
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /* ========	command line decoding	========*/
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 
700Sstevel@tonic-gate struct trenod *
710Sstevel@tonic-gate makefork(flgs, i)
720Sstevel@tonic-gate 	int	flgs;
730Sstevel@tonic-gate 	struct trenod *i;
740Sstevel@tonic-gate {
75*527Schin 	struct forknod *t;
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	t = (struct forknod *)getstor(sizeof(struct forknod));
780Sstevel@tonic-gate 	t->forktyp = flgs|TFORK;
790Sstevel@tonic-gate 	t->forktre = i;
800Sstevel@tonic-gate 	t->forkio = 0;
810Sstevel@tonic-gate 	return((struct trenod *)t);
820Sstevel@tonic-gate }
830Sstevel@tonic-gate 
840Sstevel@tonic-gate static struct trenod *
850Sstevel@tonic-gate makelist(type, i, r)
860Sstevel@tonic-gate 	int	type;
870Sstevel@tonic-gate 	struct trenod *i, *r;
880Sstevel@tonic-gate {
89*527Schin 	struct lstnod *t;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	if (i == 0 || r == 0)
920Sstevel@tonic-gate 		synbad();
930Sstevel@tonic-gate 	else
940Sstevel@tonic-gate 	{
950Sstevel@tonic-gate 		t = (struct lstnod *)getstor(sizeof(struct lstnod));
960Sstevel@tonic-gate 		t->lsttyp = type;
970Sstevel@tonic-gate 		t->lstlef = i;
980Sstevel@tonic-gate 		t->lstrit = r;
990Sstevel@tonic-gate 	}
1000Sstevel@tonic-gate 	return((struct trenod *)t);
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate /*
1040Sstevel@tonic-gate  * cmd
1050Sstevel@tonic-gate  *	empty
1060Sstevel@tonic-gate  *	list
1070Sstevel@tonic-gate  *	list & [ cmd ]
1080Sstevel@tonic-gate  *	list [ ; cmd ]
1090Sstevel@tonic-gate  */
1100Sstevel@tonic-gate struct trenod *
1110Sstevel@tonic-gate cmd(sym, flg)
112*527Schin 	int	sym;
1130Sstevel@tonic-gate 	int		flg;
1140Sstevel@tonic-gate {
115*527Schin 	struct trenod *i, *e;
1160Sstevel@tonic-gate 	i = list(flg);
1170Sstevel@tonic-gate 	if (wdval == NL)
1180Sstevel@tonic-gate 	{
1190Sstevel@tonic-gate 		if (flg & NLFLG)
1200Sstevel@tonic-gate 		{
1210Sstevel@tonic-gate 			wdval = ';';
1220Sstevel@tonic-gate 			chkpr();
1230Sstevel@tonic-gate 		}
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 	else if (i == 0 && (flg & MTFLG) == 0)
1260Sstevel@tonic-gate 		synbad();
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	switch (wdval)
1290Sstevel@tonic-gate 	{
1300Sstevel@tonic-gate 	case '&':
1310Sstevel@tonic-gate 		if (i)
1320Sstevel@tonic-gate 			i = makefork(FAMP, i);
1330Sstevel@tonic-gate 		else
1340Sstevel@tonic-gate 			synbad();
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	case ';':
1370Sstevel@tonic-gate 		if (e = cmd(sym, flg | MTFLG))
1380Sstevel@tonic-gate 			i = makelist(TLST, i, e);
1390Sstevel@tonic-gate 		else if (i == 0)
1400Sstevel@tonic-gate 			synbad();
1410Sstevel@tonic-gate 		break;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	case EOFSYM:
1440Sstevel@tonic-gate 		if (sym == NL)
1450Sstevel@tonic-gate 			break;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	default:
1480Sstevel@tonic-gate 		if (sym)
1490Sstevel@tonic-gate 			chksym(sym);
1500Sstevel@tonic-gate 	}
1510Sstevel@tonic-gate 	return(i);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate  * list
1560Sstevel@tonic-gate  *	term
1570Sstevel@tonic-gate  *	list && term
1580Sstevel@tonic-gate  *	list || term
1590Sstevel@tonic-gate  */
1600Sstevel@tonic-gate static struct trenod *
1610Sstevel@tonic-gate list(flg)
1620Sstevel@tonic-gate {
163*527Schin 	struct trenod *r;
164*527Schin 	int		b;
1650Sstevel@tonic-gate 	r = term(flg);
1660Sstevel@tonic-gate 	while (r && ((b = (wdval == ANDFSYM)) || wdval == ORFSYM))
1670Sstevel@tonic-gate 		r = makelist((b ? TAND : TORF), r, term(NLFLG));
1680Sstevel@tonic-gate 	return(r);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate /*
1720Sstevel@tonic-gate  * term
1730Sstevel@tonic-gate  *	item
1740Sstevel@tonic-gate  *	item |^ term
1750Sstevel@tonic-gate  */
1760Sstevel@tonic-gate static struct trenod *
1770Sstevel@tonic-gate term(flg)
1780Sstevel@tonic-gate {
179*527Schin 	struct trenod *t;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	reserv++;
1820Sstevel@tonic-gate 	if (flg & NLFLG)
1830Sstevel@tonic-gate 		skipnl();
1840Sstevel@tonic-gate 	else
1850Sstevel@tonic-gate 		word();
1860Sstevel@tonic-gate 	if ((t = item(TRUE)) && (wdval == '^' || wdval == '|'))
1870Sstevel@tonic-gate 	{
1880Sstevel@tonic-gate 		struct trenod	*left;
1890Sstevel@tonic-gate 		struct trenod	*right;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 		left = makefork(FPOU, t);
1920Sstevel@tonic-gate 		right = makefork(FPIN, term(NLFLG));
1930Sstevel@tonic-gate 		return(makefork(0, makelist(TFIL, left, right)));
1940Sstevel@tonic-gate 	}
1950Sstevel@tonic-gate 	else
1960Sstevel@tonic-gate 		return(t);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate static struct regnod *
2010Sstevel@tonic-gate syncase(esym)
202*527Schin int	esym;
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate 	skipnl();
2050Sstevel@tonic-gate 	if (wdval == esym)
2060Sstevel@tonic-gate 		return(0);
2070Sstevel@tonic-gate 	else
2080Sstevel@tonic-gate 	{
209*527Schin 		struct regnod *r =
210*527Schin 		    (struct regnod *)getstor(sizeof (struct regnod));
211*527Schin 		struct argnod *argp;
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 		r->regptr = 0;
2140Sstevel@tonic-gate 		for (;;)
2150Sstevel@tonic-gate 		{
2160Sstevel@tonic-gate 			if (fndef)
2170Sstevel@tonic-gate 			{
2180Sstevel@tonic-gate 				argp= wdarg;
2190Sstevel@tonic-gate 				wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
2200Sstevel@tonic-gate 				movstr(argp->argval, wdarg->argval);
2210Sstevel@tonic-gate 			}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 			wdarg->argnxt = r->regptr;
2240Sstevel@tonic-gate 			r->regptr = wdarg;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 			/* 'in' is not a reserved word in this case */
2270Sstevel@tonic-gate 			if (wdval == INSYM){
2280Sstevel@tonic-gate 				wdval = 0;
2290Sstevel@tonic-gate 			}
2300Sstevel@tonic-gate 			if (wdval || (word() != ')' && wdval != '|'))
2310Sstevel@tonic-gate 				synbad();
2320Sstevel@tonic-gate 			if (wdval == '|')
2330Sstevel@tonic-gate 				word();
2340Sstevel@tonic-gate 			else
2350Sstevel@tonic-gate 				break;
2360Sstevel@tonic-gate 		}
2370Sstevel@tonic-gate 		r->regcom = cmd(0, NLFLG | MTFLG);
2380Sstevel@tonic-gate 		if (wdval == ECSYM)
2390Sstevel@tonic-gate 			r->regnxt = syncase(esym);
2400Sstevel@tonic-gate 		else
2410Sstevel@tonic-gate 		{
2420Sstevel@tonic-gate 			chksym(esym);
2430Sstevel@tonic-gate 			r->regnxt = 0;
2440Sstevel@tonic-gate 		}
2450Sstevel@tonic-gate 		return(r);
2460Sstevel@tonic-gate 	}
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate /*
2500Sstevel@tonic-gate  * item
2510Sstevel@tonic-gate  *
2520Sstevel@tonic-gate  *	( cmd ) [ < in  ] [ > out ]
2530Sstevel@tonic-gate  *	word word* [ < in ] [ > out ]
2540Sstevel@tonic-gate  *	if ... then ... else ... fi
2550Sstevel@tonic-gate  *	for ... while ... do ... done
2560Sstevel@tonic-gate  *	case ... in ... esac
2570Sstevel@tonic-gate  *	begin ... end
2580Sstevel@tonic-gate  */
2590Sstevel@tonic-gate static struct trenod *
2600Sstevel@tonic-gate item(flag)
2610Sstevel@tonic-gate 	BOOL	flag;
2620Sstevel@tonic-gate {
263*527Schin 	struct trenod *r;
264*527Schin 	struct ionod *io;
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	if (flag)
2670Sstevel@tonic-gate 		io = inout((struct ionod *)0);
2680Sstevel@tonic-gate 	else
2690Sstevel@tonic-gate 		io = 0;
2700Sstevel@tonic-gate 	switch (wdval)
2710Sstevel@tonic-gate 	{
2720Sstevel@tonic-gate 	case CASYM:
2730Sstevel@tonic-gate 		{
274*527Schin 			struct swnod *t;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 			t = (struct swnod *)getstor(sizeof(struct swnod));
2770Sstevel@tonic-gate 			r = (struct trenod *)t;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 			chkword();
2800Sstevel@tonic-gate 			if (fndef)
2810Sstevel@tonic-gate 				t->swarg = make(wdarg->argval);
2820Sstevel@tonic-gate 			else
2830Sstevel@tonic-gate 				t->swarg = wdarg->argval;
2840Sstevel@tonic-gate 			skipnl();
2850Sstevel@tonic-gate 			chksym(INSYM | BRSYM);
2860Sstevel@tonic-gate 			t->swlst = syncase(wdval == INSYM ? ESSYM : KTSYM);
2870Sstevel@tonic-gate 			t->swtyp = TSW;
2880Sstevel@tonic-gate 			break;
2890Sstevel@tonic-gate 		}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	case IFSYM:
2920Sstevel@tonic-gate 		{
293*527Schin 			int	w;
294*527Schin 			struct ifnod *t;
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 			t = (struct ifnod *)getstor(sizeof(struct ifnod));
2970Sstevel@tonic-gate 			r = (struct trenod *)t;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 			t->iftyp = TIF;
3000Sstevel@tonic-gate 			t->iftre = cmd(THSYM, NLFLG);
3010Sstevel@tonic-gate 			t->thtre = cmd(ELSYM | FISYM | EFSYM, NLFLG);
3020Sstevel@tonic-gate 			t->eltre = ((w = wdval) == ELSYM ? cmd(FISYM, NLFLG) : (w == EFSYM ? (wdval = IFSYM, item(0)) : 0));
3030Sstevel@tonic-gate 			if (w == EFSYM)
3040Sstevel@tonic-gate 				return(r);
3050Sstevel@tonic-gate 			break;
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	case FORSYM:
3090Sstevel@tonic-gate 		{
310*527Schin 			struct fornod *t;
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 			t = (struct fornod *)getstor(sizeof(struct fornod));
3130Sstevel@tonic-gate 			r = (struct trenod *)t;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 			t->fortyp = TFOR;
3160Sstevel@tonic-gate 			t->forlst = 0;
3170Sstevel@tonic-gate 			chkword();
3180Sstevel@tonic-gate 			if (fndef)
3190Sstevel@tonic-gate 				t->fornam = make(wdarg->argval);
3200Sstevel@tonic-gate 			else
3210Sstevel@tonic-gate 				t->fornam = wdarg->argval;
3220Sstevel@tonic-gate 			if (skipnl() == INSYM)
3230Sstevel@tonic-gate 			{
3240Sstevel@tonic-gate 				chkword();
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 				nohash++;
3270Sstevel@tonic-gate 				t->forlst = (struct comnod *)item(0);
3280Sstevel@tonic-gate 				nohash--;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 				if (wdval != NL && wdval != ';')
3310Sstevel@tonic-gate 					synbad();
3320Sstevel@tonic-gate 				if (wdval == NL)
3330Sstevel@tonic-gate 					chkpr();
3340Sstevel@tonic-gate 				skipnl();
3350Sstevel@tonic-gate 			}
3360Sstevel@tonic-gate 			chksym(DOSYM | BRSYM);
3370Sstevel@tonic-gate 			t->fortre = cmd(wdval == DOSYM ? ODSYM : KTSYM, NLFLG);
3380Sstevel@tonic-gate 			break;
3390Sstevel@tonic-gate 		}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	case WHSYM:
3420Sstevel@tonic-gate 	case UNSYM:
3430Sstevel@tonic-gate 		{
344*527Schin 			struct whnod *t;
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 			t = (struct whnod *)getstor(sizeof(struct whnod));
3470Sstevel@tonic-gate 			r = (struct trenod *)t;
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 			t->whtyp = (wdval == WHSYM ? TWH : TUN);
3500Sstevel@tonic-gate 			t->whtre = cmd(DOSYM, NLFLG);
3510Sstevel@tonic-gate 			t->dotre = cmd(ODSYM, NLFLG);
3520Sstevel@tonic-gate 			break;
3530Sstevel@tonic-gate 		}
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	case BRSYM:
3560Sstevel@tonic-gate 		r = cmd(KTSYM, NLFLG);
3570Sstevel@tonic-gate 		break;
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	case '(':
3600Sstevel@tonic-gate 		{
361*527Schin 			struct parnod *p;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 			p = (struct parnod *)getstor(sizeof(struct parnod));
3640Sstevel@tonic-gate 			p->partre = cmd(')', NLFLG);
3650Sstevel@tonic-gate 			p->partyp = TPAR;
3660Sstevel@tonic-gate 			r = makefork(0, p);
3670Sstevel@tonic-gate 			break;
3680Sstevel@tonic-gate 		}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	default:
3710Sstevel@tonic-gate 		if (io == 0)
3720Sstevel@tonic-gate 			return(0);
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	case 0:
3750Sstevel@tonic-gate 		{
376*527Schin 			struct comnod *t;
377*527Schin 			struct argnod *argp;
378*527Schin 			struct argnod **argtail;
379*527Schin 			struct argnod **argset = 0;
3800Sstevel@tonic-gate 			int	keywd = 1;
3810Sstevel@tonic-gate 			unsigned char	*com;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 			if ((wdval != NL) && ((peekn = skipwc()) == '('))
3840Sstevel@tonic-gate 			{
3850Sstevel@tonic-gate 				struct fndnod *f;
3860Sstevel@tonic-gate 				struct ionod  *saveio;
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 				saveio = iotemp;
3890Sstevel@tonic-gate 				peekn = 0;
3900Sstevel@tonic-gate 				if (skipwc() != ')')
3910Sstevel@tonic-gate 					synbad();
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 				f = (struct fndnod *)getstor(sizeof(struct fndnod));
3940Sstevel@tonic-gate 				r = (struct trenod *)f;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 				f->fndtyp = TFND;
3970Sstevel@tonic-gate 				if (fndef)
3980Sstevel@tonic-gate 					f->fndnam = make(wdarg->argval);
3990Sstevel@tonic-gate 				else
4000Sstevel@tonic-gate 					f->fndnam = wdarg->argval;
4010Sstevel@tonic-gate 				reserv++;
4020Sstevel@tonic-gate 				fndef++;
4030Sstevel@tonic-gate 				skipnl();
4040Sstevel@tonic-gate 				f->fndval = (struct trenod *)item(0);
4050Sstevel@tonic-gate 				fndef--;
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 				if (iotemp != saveio)
4080Sstevel@tonic-gate 				{
4090Sstevel@tonic-gate 					struct ionod 	*ioptr = iotemp;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 					while (ioptr->iolst != saveio)
4120Sstevel@tonic-gate 						ioptr = ioptr->iolst;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 					ioptr->iolst = fiotemp;
4150Sstevel@tonic-gate 					fiotemp = iotemp;
4160Sstevel@tonic-gate 					iotemp = saveio;
4170Sstevel@tonic-gate 				}
4180Sstevel@tonic-gate 				return(r);
4190Sstevel@tonic-gate 			}
4200Sstevel@tonic-gate 			else
4210Sstevel@tonic-gate 			{
4220Sstevel@tonic-gate 				t = (struct comnod *)getstor(sizeof(struct comnod));
4230Sstevel@tonic-gate 				r = (struct trenod *)t;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 				t->comio = io; /*initial io chain*/
4260Sstevel@tonic-gate 				argtail = &(t->comarg);
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 				while (wdval == 0)
4290Sstevel@tonic-gate 				{
4300Sstevel@tonic-gate 					if (fndef)
4310Sstevel@tonic-gate 					{
4320Sstevel@tonic-gate 						argp = wdarg;
4330Sstevel@tonic-gate 						wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
4340Sstevel@tonic-gate 						movstr(argp->argval, wdarg->argval);
4350Sstevel@tonic-gate 					}
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 					argp = wdarg;
4380Sstevel@tonic-gate 					if (wdset && keywd)
4390Sstevel@tonic-gate 					{
4400Sstevel@tonic-gate 						argp->argnxt = (struct argnod *)argset;
4410Sstevel@tonic-gate 						argset = (struct argnod **)argp;
4420Sstevel@tonic-gate 					}
4430Sstevel@tonic-gate 					else
4440Sstevel@tonic-gate 					{
4450Sstevel@tonic-gate 						*argtail = argp;
4460Sstevel@tonic-gate 						argtail = &(argp->argnxt);
4470Sstevel@tonic-gate 						keywd = flags & keyflg;
4480Sstevel@tonic-gate 					}
4490Sstevel@tonic-gate 					word();
4500Sstevel@tonic-gate 					if (flag)
4510Sstevel@tonic-gate 					{
4520Sstevel@tonic-gate 						if (io)
4530Sstevel@tonic-gate 						{
4540Sstevel@tonic-gate 							while(io->ionxt)
4550Sstevel@tonic-gate 								io = io->ionxt;
4560Sstevel@tonic-gate 							io->ionxt = inout((struct ionod *)0);
4570Sstevel@tonic-gate 						}
4580Sstevel@tonic-gate 						else
4590Sstevel@tonic-gate 							t->comio = io = inout((struct ionod *)0);
4600Sstevel@tonic-gate  					}
4610Sstevel@tonic-gate 				}
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 				t->comtyp = TCOM;
4640Sstevel@tonic-gate 				t->comset = (struct argnod *)argset;
4650Sstevel@tonic-gate 				*argtail = 0;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 				if (nohash == 0 && (fndef == 0 || (flags & hashflg)))
4680Sstevel@tonic-gate 				{
4690Sstevel@tonic-gate 					if (t->comarg)
4700Sstevel@tonic-gate 					{
4710Sstevel@tonic-gate 						com = t->comarg->argval;
4720Sstevel@tonic-gate 						if (*com && *com != DOLLAR)
4730Sstevel@tonic-gate 							pathlook(com, 0, t->comset);
4740Sstevel@tonic-gate 					}
4750Sstevel@tonic-gate 				}
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 				return(r);
4780Sstevel@tonic-gate 			}
4790Sstevel@tonic-gate 		}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 	reserv++;
4830Sstevel@tonic-gate 	word();
4840Sstevel@tonic-gate 	if (io = inout(io))
4850Sstevel@tonic-gate 	{
4860Sstevel@tonic-gate 		r = makefork(0,r);
4870Sstevel@tonic-gate 		r->treio = io;
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 	return(r);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate static int
4940Sstevel@tonic-gate skipnl()
4950Sstevel@tonic-gate {
4960Sstevel@tonic-gate 	while ((reserv++, word() == NL))
4970Sstevel@tonic-gate 		chkpr();
4980Sstevel@tonic-gate 	return(wdval);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate static struct ionod *
5020Sstevel@tonic-gate inout(lastio)
5030Sstevel@tonic-gate 	struct ionod *lastio;
5040Sstevel@tonic-gate {
505*527Schin 	int	iof;
506*527Schin 	struct ionod *iop;
507*527Schin 	unsigned int	c;
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	iof = wdnum;
5100Sstevel@tonic-gate 	switch (wdval)
5110Sstevel@tonic-gate 	{
5120Sstevel@tonic-gate 	case DOCSYM:	/*	<<	*/
5130Sstevel@tonic-gate 		iof |= IODOC;
5140Sstevel@tonic-gate 		break;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 	case APPSYM:	/*	>>	*/
5170Sstevel@tonic-gate 	case '>':
5180Sstevel@tonic-gate 		if (wdnum == 0)
5190Sstevel@tonic-gate 			iof |= 1;
5200Sstevel@tonic-gate 		iof |= IOPUT;
5210Sstevel@tonic-gate 		if (wdval == APPSYM)
5220Sstevel@tonic-gate 		{
5230Sstevel@tonic-gate 			iof |= IOAPP;
5240Sstevel@tonic-gate 			break;
5250Sstevel@tonic-gate 		}
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	case '<':
5280Sstevel@tonic-gate 		if ((c = nextwc()) == '&')
5290Sstevel@tonic-gate 			iof |= IOMOV;
5300Sstevel@tonic-gate 		else if (c == '>')
5310Sstevel@tonic-gate 			iof |= IORDW;
5320Sstevel@tonic-gate 		else
5330Sstevel@tonic-gate 			peekn = c | MARK;
5340Sstevel@tonic-gate 		break;
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	default:
5370Sstevel@tonic-gate 		return(lastio);
5380Sstevel@tonic-gate 	}
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	chkword();
5410Sstevel@tonic-gate 	iop = (struct ionod *)getstor(sizeof(struct ionod));
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	if (fndef)
5440Sstevel@tonic-gate 		iop->ioname = (char *) make(wdarg->argval);
5450Sstevel@tonic-gate 	else
5460Sstevel@tonic-gate 		iop->ioname = (char *) (wdarg->argval);
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	iop->iolink = 0;
5490Sstevel@tonic-gate 	iop->iofile = iof;
5500Sstevel@tonic-gate 	if (iof & IODOC)
5510Sstevel@tonic-gate 	{
5520Sstevel@tonic-gate 		iop->iolst = iopend;
5530Sstevel@tonic-gate 		iopend = iop;
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 	word();
5560Sstevel@tonic-gate 	iop->ionxt = inout(lastio);
5570Sstevel@tonic-gate 	return(iop);
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate 
560*527Schin static void
561*527Schin chkword(void)
5620Sstevel@tonic-gate {
5630Sstevel@tonic-gate 	if (word())
5640Sstevel@tonic-gate 		synbad();
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate 
567*527Schin static void
568*527Schin chksym(int sym)
5690Sstevel@tonic-gate {
570*527Schin 	int	x = sym & wdval;
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	if (((x & SYMFLG) ? x : sym) != wdval)
5730Sstevel@tonic-gate 		synbad();
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate 
576*527Schin static void
577*527Schin prsym(int sym)
5780Sstevel@tonic-gate {
5790Sstevel@tonic-gate 	if (sym & SYMFLG)
5800Sstevel@tonic-gate 	{
581*527Schin 		const struct sysnod *sp = reserved;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 		while (sp->sysval && sp->sysval != sym)
5840Sstevel@tonic-gate 			sp++;
5850Sstevel@tonic-gate 		prs(sp->sysnam);
5860Sstevel@tonic-gate 	}
5870Sstevel@tonic-gate 	else if (sym == EOFSYM)
5880Sstevel@tonic-gate 		prs(endoffile);
5890Sstevel@tonic-gate 	else
5900Sstevel@tonic-gate 	{
5910Sstevel@tonic-gate 		if (sym & SYMREP)
5920Sstevel@tonic-gate 			prc(sym);
5930Sstevel@tonic-gate 		if (sym == NL)
5940Sstevel@tonic-gate 			prs("newline or ;");
5950Sstevel@tonic-gate 		else
5960Sstevel@tonic-gate 			prc(sym);
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate 
600*527Schin static void
601*527Schin synbad(void)
6020Sstevel@tonic-gate {
6030Sstevel@tonic-gate 	prp();
6040Sstevel@tonic-gate 	prs(synmsg);
6050Sstevel@tonic-gate 	if ((flags & ttyflg) == 0)
6060Sstevel@tonic-gate 	{
6070Sstevel@tonic-gate 		prs(atline);
6080Sstevel@tonic-gate 		prn(standin->flin);
6090Sstevel@tonic-gate 	}
6100Sstevel@tonic-gate 	prs(colon);
6110Sstevel@tonic-gate 	prc(LQ);
6120Sstevel@tonic-gate 	if (wdval)
6130Sstevel@tonic-gate 		prsym(wdval);
6140Sstevel@tonic-gate 	else
6150Sstevel@tonic-gate 		prs_cntl(wdarg->argval);
6160Sstevel@tonic-gate 	prc(RQ);
6170Sstevel@tonic-gate 	prs(unexpected);
6180Sstevel@tonic-gate 	newline();
6190Sstevel@tonic-gate 	exitsh(SYNBAD);
6200Sstevel@tonic-gate }
621