xref: /csrg-svn/old/sh/cmd.c (revision 34082)
114477Ssam #ifndef lint
2*34082Sbostic static char sccsid[] = "@(#)cmd.c	4.3 04/24/88";
314477Ssam #endif
46685Smckusick 
56685Smckusick #
66685Smckusick /*
76685Smckusick  * UNIX shell
86685Smckusick  *
96685Smckusick  * S. R. Bourne
106685Smckusick  * Bell Telephone Laboratories
116685Smckusick  *
126685Smckusick  */
136685Smckusick 
146685Smckusick #include	"defs.h"
156685Smckusick #include	"sym.h"
166685Smckusick 
176685Smckusick PROC IOPTR	inout();
186685Smckusick PROC VOID	chkword();
196685Smckusick PROC VOID	chksym();
206685Smckusick PROC TREPTR	term();
216685Smckusick PROC TREPTR	makelist();
226685Smckusick PROC TREPTR	list();
236685Smckusick PROC REGPTR	syncase();
246685Smckusick PROC TREPTR	item();
256685Smckusick PROC VOID	skipnl();
266685Smckusick PROC VOID	prsym();
276685Smckusick PROC VOID	synbad();
286685Smckusick 
296685Smckusick 
306685Smckusick /* ========	command line decoding	========*/
316685Smckusick 
326685Smckusick 
336685Smckusick 
346685Smckusick 
makefork(flgs,i)356685Smckusick TREPTR	makefork(flgs, i)
366685Smckusick 	INT		flgs;
376685Smckusick 	TREPTR		i;
386685Smckusick {
396685Smckusick 	REG TREPTR	t;
406685Smckusick 
416685Smckusick 	t=getstak(FORKTYPE);
42*34082Sbostic 	t->forknod.forktyp=flgs|TFORK;
43*34082Sbostic 	t->forknod.forktre=i;
44*34082Sbostic 	t->forknod.forkio=0;
456685Smckusick 	return(t);
466685Smckusick }
476685Smckusick 
makelist(type,i,r)486685Smckusick LOCAL TREPTR	makelist(type,i,r)
496685Smckusick 	INT		type;
506685Smckusick 	TREPTR		i, r;
516685Smckusick {
526685Smckusick 	REG TREPTR	t;
536685Smckusick 
546685Smckusick 	IF i==0 ORF r==0
556685Smckusick 	THEN	synbad();
566685Smckusick 	ELSE	t = getstak(LSTTYPE);
57*34082Sbostic 		t->lstnod.lsttyp = type;
58*34082Sbostic 		t->lstnod.lstlef = i;
59*34082Sbostic 		t->lstnod.lstrit = r;
606685Smckusick 	FI
616685Smckusick 	return(t);
626685Smckusick }
636685Smckusick 
646685Smckusick /*
656685Smckusick  * cmd
666685Smckusick  *	empty
676685Smckusick  *	list
686685Smckusick  *	list & [ cmd ]
696685Smckusick  *	list [ ; cmd ]
706685Smckusick  */
716685Smckusick 
cmd(sym,flg)726685Smckusick TREPTR	cmd(sym,flg)
736685Smckusick 	REG INT		sym;
746685Smckusick 	INT		flg;
756685Smckusick {
766685Smckusick 	REG TREPTR	i, e;
776685Smckusick 
786685Smckusick 	i = list(flg);
796685Smckusick 
806685Smckusick 	IF wdval==NL
816685Smckusick 	THEN	IF flg&NLFLG
826685Smckusick 		THEN	wdval=';'; chkpr(NL);
836685Smckusick 		FI
846685Smckusick 	ELIF i==0 ANDF (flg&MTFLG)==0
856685Smckusick 	THEN	synbad();
866685Smckusick 	FI
876685Smckusick 
886685Smckusick 	SWITCH wdval IN
896685Smckusick 
906685Smckusick 	    case '&':
916685Smckusick 		IF i
926685Smckusick 		THEN	i = makefork(FINT|FPRS|FAMP, i);
936685Smckusick 		ELSE	synbad();
946685Smckusick 		FI
956685Smckusick 
966685Smckusick 	    case ';':
976685Smckusick 		IF e=cmd(sym,flg|MTFLG)
986685Smckusick 		THEN	i=makelist(TLST, i, e);
996685Smckusick 		FI
1006685Smckusick 		break;
1016685Smckusick 
1026685Smckusick 	    case EOFSYM:
1036685Smckusick 		IF sym==NL
1046685Smckusick 		THEN	break;
1056685Smckusick 		FI
1066685Smckusick 
1076685Smckusick 	    default:
1086685Smckusick 		IF sym
1096685Smckusick 		THEN	chksym(sym);
1106685Smckusick 		FI
1116685Smckusick 
1126685Smckusick 	ENDSW
1136685Smckusick 	return(i);
1146685Smckusick }
1156685Smckusick 
1166685Smckusick /*
1176685Smckusick  * list
1186685Smckusick  *	term
1196685Smckusick  *	list && term
1206685Smckusick  *	list || term
1216685Smckusick  */
1226685Smckusick 
list(flg)1236685Smckusick LOCAL TREPTR	list(flg)
1246685Smckusick {
1256685Smckusick 	REG TREPTR	r;
1266685Smckusick 	REG INT		b;
1276685Smckusick 
1286685Smckusick 	r = term(flg);
1296685Smckusick 	WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM)
1306685Smckusick 	DO	r = makelist((b ? TAND : TORF), r, term(NLFLG));
1316685Smckusick 	OD
1326685Smckusick 	return(r);
1336685Smckusick }
1346685Smckusick 
1356685Smckusick /*
1366685Smckusick  * term
1376685Smckusick  *	item
1386685Smckusick  *	item |^ term
1396685Smckusick  */
1406685Smckusick 
term(flg)1416685Smckusick LOCAL TREPTR	term(flg)
1426685Smckusick {
1436685Smckusick 	REG TREPTR	t;
1446685Smckusick 
1456685Smckusick 	reserv++;
1466685Smckusick 	IF flg&NLFLG
1476685Smckusick 	THEN	skipnl();
1486685Smckusick 	ELSE	word();
1496685Smckusick 	FI
1506685Smckusick 
1516685Smckusick 	IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|')
1526685Smckusick 	THEN	return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG))));
1536685Smckusick 	ELSE	return(t);
1546685Smckusick 	FI
1556685Smckusick }
1566685Smckusick 
syncase(esym)1576685Smckusick LOCAL REGPTR	syncase(esym)
1586685Smckusick 	REG INT	esym;
1596685Smckusick {
1606685Smckusick 	skipnl();
1616685Smckusick 	IF wdval==esym
1626685Smckusick 	THEN	return(0);
1636685Smckusick 	ELSE	REG REGPTR	r=getstak(REGTYPE);
1646685Smckusick 		r->regptr=0;
1656685Smckusick 		LOOP wdarg->argnxt=r->regptr;
1666685Smckusick 		     r->regptr=wdarg;
1676685Smckusick 		     IF wdval ORF ( word()!=')' ANDF wdval!='|' )
1686685Smckusick 		     THEN synbad();
1696685Smckusick 		     FI
1706685Smckusick 		     IF wdval=='|'
1716685Smckusick 		     THEN word();
1726685Smckusick 		     ELSE break;
1736685Smckusick 		     FI
1746685Smckusick 		POOL
1756685Smckusick 		r->regcom=cmd(0,NLFLG|MTFLG);
1766685Smckusick 		IF wdval==ECSYM
1776685Smckusick 		THEN	r->regnxt=syncase(esym);
1786685Smckusick 		ELSE	chksym(esym);
1796685Smckusick 			r->regnxt=0;
1806685Smckusick 		FI
1816685Smckusick 		return(r);
1826685Smckusick 	FI
1836685Smckusick }
1846685Smckusick 
1856685Smckusick /*
1866685Smckusick  * item
1876685Smckusick  *
1886685Smckusick  *	( cmd ) [ < in  ] [ > out ]
1896685Smckusick  *	word word* [ < in ] [ > out ]
1906685Smckusick  *	if ... then ... else ... fi
1916685Smckusick  *	for ... while ... do ... done
1926685Smckusick  *	case ... in ... esac
1936685Smckusick  *	begin ... end
1946685Smckusick  */
1956685Smckusick 
item(flag)1966685Smckusick LOCAL TREPTR	item(flag)
1976685Smckusick 	BOOL		flag;
1986685Smckusick {
1996685Smckusick 	REG TREPTR	t;
2006685Smckusick 	REG IOPTR	io;
2016685Smckusick 
2026685Smckusick 	IF flag
2036685Smckusick 	THEN	io=inout((IOPTR)0);
2046685Smckusick 	ELSE	io=0;
2056685Smckusick 	FI
2066685Smckusick 
2076685Smckusick 	SWITCH wdval IN
2086685Smckusick 
2096685Smckusick 	    case CASYM:
2106685Smckusick 		BEGIN
2116685Smckusick 		   t=getstak(SWTYPE);
2126685Smckusick 		   chkword();
213*34082Sbostic 		   t->swnod.swarg=wdarg->argval;
2146685Smckusick 		   skipnl(); chksym(INSYM|BRSYM);
215*34082Sbostic 		   t->swnod.swlst=syncase(wdval==INSYM?ESSYM:KTSYM);
216*34082Sbostic 		   t->swnod.swtyp=TSW;
2176685Smckusick 		   break;
2186685Smckusick 		END
2196685Smckusick 
2206685Smckusick 	    case IFSYM:
2216685Smckusick 		BEGIN
2226685Smckusick 		   REG INT	w;
2236685Smckusick 		   t=getstak(IFTYPE);
224*34082Sbostic 		   t->ifnod.iftyp=TIF;
225*34082Sbostic 		   t->ifnod.iftre=cmd(THSYM,NLFLG);
226*34082Sbostic 		   t->ifnod.thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG);
227*34082Sbostic 		   t->ifnod.eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0));
2286685Smckusick 		   IF w==EFSYM THEN return(t) FI
2296685Smckusick 		   break;
2306685Smckusick 		END
2316685Smckusick 
2326685Smckusick 	    case FORSYM:
2336685Smckusick 		BEGIN
2346685Smckusick 		   t=getstak(FORTYPE);
235*34082Sbostic 		   t->fornod.fortyp=TFOR;
236*34082Sbostic 		   t->fornod.forlst=0;
2376685Smckusick 		   chkword();
238*34082Sbostic 		   t->fornod.fornam=wdarg->argval;
2396685Smckusick 		   IF skipnl()==INSYM
2406685Smckusick 		   THEN	chkword();
241*34082Sbostic 			t->fornod.forlst=item(0);
2426685Smckusick 			IF wdval!=NL ANDF wdval!=';'
2436685Smckusick 			THEN	synbad();
2446685Smckusick 			FI
2456685Smckusick 			chkpr(wdval); skipnl();
2466685Smckusick 		   FI
2476685Smckusick 		   chksym(DOSYM|BRSYM);
248*34082Sbostic 		   t->fornod.fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG);
2496685Smckusick 		   break;
2506685Smckusick 		END
2516685Smckusick 
2526685Smckusick 	    case WHSYM:
2536685Smckusick 	    case UNSYM:
2546685Smckusick 		BEGIN
2556685Smckusick 		   t=getstak(WHTYPE);
256*34082Sbostic 		   t->whnod.whtyp=(wdval==WHSYM ? TWH : TUN);
257*34082Sbostic 		   t->whnod.whtre = cmd(DOSYM,NLFLG);
258*34082Sbostic 		   t->whnod.dotre = cmd(ODSYM,NLFLG);
2596685Smckusick 		   break;
2606685Smckusick 		END
2616685Smckusick 
2626685Smckusick 	    case BRSYM:
2636685Smckusick 		t=cmd(KTSYM,NLFLG);
2646685Smckusick 		break;
2656685Smckusick 
2666685Smckusick 	    case '(':
2676685Smckusick 		BEGIN
2686685Smckusick 		   REG PARPTR	 p;
2696685Smckusick 		   p=getstak(PARTYPE);
2706685Smckusick 		   p->partre=cmd(')',NLFLG);
2716685Smckusick 		   p->partyp=TPAR;
2726685Smckusick 		   t=makefork(0,p);
2736685Smckusick 		   break;
2746685Smckusick 		END
2756685Smckusick 
2766685Smckusick 	    default:
2776685Smckusick 		IF io==0
2786685Smckusick 		THEN	return(0);
2796685Smckusick 		FI
2806685Smckusick 
2816685Smckusick 	    case 0:
2826685Smckusick 		BEGIN
2836685Smckusick 		   REG ARGPTR	argp;
2846685Smckusick 		   REG ARGPTR	*argtail;
2856685Smckusick 		   REG ARGPTR	*argset=0;
2866685Smckusick 		   INT		keywd=1;
2876685Smckusick 		   t=getstak(COMTYPE);
288*34082Sbostic 		   t->comnod.comio=io; /*initial io chain*/
289*34082Sbostic 		   argtail = &(t->comnod.comarg);
2906685Smckusick 		   WHILE wdval==0
2916685Smckusick 		   DO	argp = wdarg;
2926685Smckusick 			IF wdset ANDF keywd
2936685Smckusick 			THEN	argp->argnxt=argset; argset=argp;
2946685Smckusick 			ELSE	*argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg;
2956685Smckusick 			FI
2966685Smckusick 			word();
2976685Smckusick 			IF flag
298*34082Sbostic 			THEN t->comnod.comio=inout(t->comnod.comio);
2996685Smckusick 			FI
3006685Smckusick 		   OD
3016685Smckusick 
302*34082Sbostic 		   t->comnod.comtyp=TCOM; t->comnod.comset=argset; *argtail=0;
3036685Smckusick 		   return(t);
3046685Smckusick 		END
3056685Smckusick 
3066685Smckusick 	ENDSW
3076685Smckusick 	reserv++; word();
3086685Smckusick 	IF io=inout(io)
309*34082Sbostic 	THEN	t=makefork(0,t); t->treio.treio=io;
3106685Smckusick 	FI
3116685Smckusick 	return(t);
3126685Smckusick }
3136685Smckusick 
3146685Smckusick 
skipnl()3156685Smckusick LOCAL VOID	skipnl()
3166685Smckusick {
3176685Smckusick 	WHILE (reserv++, word()==NL) DO chkpr(NL) OD
3186685Smckusick 	return(wdval);
3196685Smckusick }
3206685Smckusick 
inout(lastio)3216685Smckusick LOCAL IOPTR	inout(lastio)
3226685Smckusick 	IOPTR		lastio;
3236685Smckusick {
3246685Smckusick 	REG INT		iof;
3256685Smckusick 	REG IOPTR	iop;
3266685Smckusick 	REG CHAR	c;
3276685Smckusick 
3286685Smckusick 	iof=wdnum;
3296685Smckusick 
3306685Smckusick 	SWITCH wdval IN
3316685Smckusick 
3326685Smckusick 	    case DOCSYM:
3336685Smckusick 		iof |= IODOC; break;
3346685Smckusick 
3356685Smckusick 	    case APPSYM:
3366685Smckusick 	    case '>':
3376685Smckusick 		IF wdnum==0 THEN iof |= 1 FI
3386685Smckusick 		iof |= IOPUT;
3396685Smckusick 		IF wdval==APPSYM
3406685Smckusick 		THEN	iof |= IOAPP; break;
3416685Smckusick 		FI
3426685Smckusick 
3436685Smckusick 	    case '<':
3446685Smckusick 		IF (c=nextc(0))=='&'
3456685Smckusick 		THEN	iof |= IOMOV;
3466685Smckusick 		ELIF c=='>'
3476685Smckusick 		THEN	iof |= IORDW;
3486685Smckusick 		ELSE	peekc=c|MARK;
3496685Smckusick 		FI
3506685Smckusick 		break;
3516685Smckusick 
3526685Smckusick 	    default:
3536685Smckusick 		return(lastio);
3546685Smckusick 	ENDSW
3556685Smckusick 
3566685Smckusick 	chkword();
3576685Smckusick 	iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof;
3586685Smckusick 	IF iof&IODOC
3596685Smckusick 	THEN iop->iolst=iopend; iopend=iop;
3606685Smckusick 	FI
3616685Smckusick 	word(); iop->ionxt=inout(lastio);
3626685Smckusick 	return(iop);
3636685Smckusick }
3646685Smckusick 
chkword()3656685Smckusick LOCAL VOID	chkword()
3666685Smckusick {
3676685Smckusick 	IF word()
3686685Smckusick 	THEN	synbad();
3696685Smckusick 	FI
3706685Smckusick }
3716685Smckusick 
chksym(sym)3726685Smckusick LOCAL VOID	chksym(sym)
3736685Smckusick {
3746685Smckusick 	REG INT		x = sym&wdval;
3756685Smckusick 	IF ((x&SYMFLG) ? x : sym) != wdval
3766685Smckusick 	THEN	synbad();
3776685Smckusick 	FI
3786685Smckusick }
3796685Smckusick 
prsym(sym)3806685Smckusick LOCAL VOID	prsym(sym)
3816685Smckusick {
3826685Smckusick 	IF sym&SYMFLG
3836685Smckusick 	THEN	REG SYSPTR	sp=reserved;
3846685Smckusick 		WHILE sp->sysval
3856685Smckusick 			ANDF sp->sysval!=sym
3866685Smckusick 		DO sp++ OD
3876685Smckusick 		prs(sp->sysnam);
3886685Smckusick 	ELIF sym==EOFSYM
3896685Smckusick 	THEN	prs(endoffile);
3906685Smckusick 	ELSE	IF sym&SYMREP THEN prc(sym) FI
3916685Smckusick 		IF sym==NL
3926685Smckusick 		THEN	prs("newline");
3936685Smckusick 		ELSE	prc(sym);
3946685Smckusick 		FI
3956685Smckusick 	FI
3966685Smckusick }
3976685Smckusick 
synbad()3986685Smckusick LOCAL VOID	synbad()
3996685Smckusick {
4006685Smckusick 	prp(); prs(synmsg);
4016685Smckusick 	IF (flags&ttyflg)==0
4026685Smckusick 	THEN	prs(atline); prn(standin->flin);
4036685Smckusick 	FI
4046685Smckusick 	prs(colon);
4056685Smckusick 	prc(LQ);
4066685Smckusick 	IF wdval
4076685Smckusick 	THEN	prsym(wdval);
4086685Smckusick 	ELSE	prs(wdarg->argval);
4096685Smckusick 	FI
4106685Smckusick 	prc(RQ); prs(unexpected);
4116685Smckusick 	newline();
4126685Smckusick 	exitsh(SYNBAD);
4136685Smckusick }
414