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