fix to do writes in memory properly
[unix-history] / usr / src / old / sh / cmd.c
CommitLineData
bfed0c1d
KM
1/* cmd.c 4.1 82/05/07 */
2
3#
4/*
5 * UNIX shell
6 *
7 * S. R. Bourne
8 * Bell Telephone Laboratories
9 *
10 */
11
12#include "defs.h"
13#include "sym.h"
14
15PROC IOPTR inout();
16PROC VOID chkword();
17PROC VOID chksym();
18PROC TREPTR term();
19PROC TREPTR makelist();
20PROC TREPTR list();
21PROC REGPTR syncase();
22PROC TREPTR item();
23PROC VOID skipnl();
24PROC VOID prsym();
25PROC VOID synbad();
26
27
28/* ======== command line decoding ========*/
29
30
31
32
33TREPTR makefork(flgs, i)
34 INT flgs;
35 TREPTR i;
36{
37 REG TREPTR t;
38
39 t=getstak(FORKTYPE);
40 t->forktyp=flgs|TFORK; t->forktre=i; t->forkio=0;
41 return(t);
42}
43
44LOCAL TREPTR makelist(type,i,r)
45 INT type;
46 TREPTR i, r;
47{
48 REG TREPTR t;
49
50 IF i==0 ORF r==0
51 THEN synbad();
52 ELSE t = getstak(LSTTYPE);
53 t->lsttyp = type;
54 t->lstlef = i; t->lstrit = r;
55 FI
56 return(t);
57}
58
59/*
60 * cmd
61 * empty
62 * list
63 * list & [ cmd ]
64 * list [ ; cmd ]
65 */
66
67TREPTR cmd(sym,flg)
68 REG INT sym;
69 INT flg;
70{
71 REG TREPTR i, e;
72
73 i = list(flg);
74
75 IF wdval==NL
76 THEN IF flg&NLFLG
77 THEN wdval=';'; chkpr(NL);
78 FI
79 ELIF i==0 ANDF (flg&MTFLG)==0
80 THEN synbad();
81 FI
82
83 SWITCH wdval IN
84
85 case '&':
86 IF i
87 THEN i = makefork(FINT|FPRS|FAMP, i);
88 ELSE synbad();
89 FI
90
91 case ';':
92 IF e=cmd(sym,flg|MTFLG)
93 THEN i=makelist(TLST, i, e);
94 FI
95 break;
96
97 case EOFSYM:
98 IF sym==NL
99 THEN break;
100 FI
101
102 default:
103 IF sym
104 THEN chksym(sym);
105 FI
106
107 ENDSW
108 return(i);
109}
110
111/*
112 * list
113 * term
114 * list && term
115 * list || term
116 */
117
118LOCAL TREPTR list(flg)
119{
120 REG TREPTR r;
121 REG INT b;
122
123 r = term(flg);
124 WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM)
125 DO r = makelist((b ? TAND : TORF), r, term(NLFLG));
126 OD
127 return(r);
128}
129
130/*
131 * term
132 * item
133 * item |^ term
134 */
135
136LOCAL TREPTR term(flg)
137{
138 REG TREPTR t;
139
140 reserv++;
141 IF flg&NLFLG
142 THEN skipnl();
143 ELSE word();
144 FI
145
146 IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|')
147 THEN return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG))));
148 ELSE return(t);
149 FI
150}
151
152LOCAL REGPTR syncase(esym)
153 REG INT esym;
154{
155 skipnl();
156 IF wdval==esym
157 THEN return(0);
158 ELSE REG REGPTR r=getstak(REGTYPE);
159 r->regptr=0;
160 LOOP wdarg->argnxt=r->regptr;
161 r->regptr=wdarg;
162 IF wdval ORF ( word()!=')' ANDF wdval!='|' )
163 THEN synbad();
164 FI
165 IF wdval=='|'
166 THEN word();
167 ELSE break;
168 FI
169 POOL
170 r->regcom=cmd(0,NLFLG|MTFLG);
171 IF wdval==ECSYM
172 THEN r->regnxt=syncase(esym);
173 ELSE chksym(esym);
174 r->regnxt=0;
175 FI
176 return(r);
177 FI
178}
179
180/*
181 * item
182 *
183 * ( cmd ) [ < in ] [ > out ]
184 * word word* [ < in ] [ > out ]
185 * if ... then ... else ... fi
186 * for ... while ... do ... done
187 * case ... in ... esac
188 * begin ... end
189 */
190
191LOCAL TREPTR item(flag)
192 BOOL flag;
193{
194 REG TREPTR t;
195 REG IOPTR io;
196
197 IF flag
198 THEN io=inout((IOPTR)0);
199 ELSE io=0;
200 FI
201
202 SWITCH wdval IN
203
204 case CASYM:
205 BEGIN
206 t=getstak(SWTYPE);
207 chkword();
208 t->swarg=wdarg->argval;
209 skipnl(); chksym(INSYM|BRSYM);
210 t->swlst=syncase(wdval==INSYM?ESSYM:KTSYM);
211 t->swtyp=TSW;
212 break;
213 END
214
215 case IFSYM:
216 BEGIN
217 REG INT w;
218 t=getstak(IFTYPE);
219 t->iftyp=TIF;
220 t->iftre=cmd(THSYM,NLFLG);
221 t->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG);
222 t->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0));
223 IF w==EFSYM THEN return(t) FI
224 break;
225 END
226
227 case FORSYM:
228 BEGIN
229 t=getstak(FORTYPE);
230 t->fortyp=TFOR;
231 t->forlst=0;
232 chkword();
233 t->fornam=wdarg->argval;
234 IF skipnl()==INSYM
235 THEN chkword();
236 t->forlst=item(0);
237 IF wdval!=NL ANDF wdval!=';'
238 THEN synbad();
239 FI
240 chkpr(wdval); skipnl();
241 FI
242 chksym(DOSYM|BRSYM);
243 t->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG);
244 break;
245 END
246
247 case WHSYM:
248 case UNSYM:
249 BEGIN
250 t=getstak(WHTYPE);
251 t->whtyp=(wdval==WHSYM ? TWH : TUN);
252 t->whtre = cmd(DOSYM,NLFLG);
253 t->dotre = cmd(ODSYM,NLFLG);
254 break;
255 END
256
257 case BRSYM:
258 t=cmd(KTSYM,NLFLG);
259 break;
260
261 case '(':
262 BEGIN
263 REG PARPTR p;
264 p=getstak(PARTYPE);
265 p->partre=cmd(')',NLFLG);
266 p->partyp=TPAR;
267 t=makefork(0,p);
268 break;
269 END
270
271 default:
272 IF io==0
273 THEN return(0);
274 FI
275
276 case 0:
277 BEGIN
278 REG ARGPTR argp;
279 REG ARGPTR *argtail;
280 REG ARGPTR *argset=0;
281 INT keywd=1;
282 t=getstak(COMTYPE);
283 t->comio=io; /*initial io chain*/
284 argtail = &(t->comarg);
285 WHILE wdval==0
286 DO argp = wdarg;
287 IF wdset ANDF keywd
288 THEN argp->argnxt=argset; argset=argp;
289 ELSE *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg;
290 FI
291 word();
292 IF flag
293 THEN t->comio=inout(t->comio);
294 FI
295 OD
296
297 t->comtyp=TCOM; t->comset=argset; *argtail=0;
298 return(t);
299 END
300
301 ENDSW
302 reserv++; word();
303 IF io=inout(io)
304 THEN t=makefork(0,t); t->treio=io;
305 FI
306 return(t);
307}
308
309
310LOCAL VOID skipnl()
311{
312 WHILE (reserv++, word()==NL) DO chkpr(NL) OD
313 return(wdval);
314}
315
316LOCAL IOPTR inout(lastio)
317 IOPTR lastio;
318{
319 REG INT iof;
320 REG IOPTR iop;
321 REG CHAR c;
322
323 iof=wdnum;
324
325 SWITCH wdval IN
326
327 case DOCSYM:
328 iof |= IODOC; break;
329
330 case APPSYM:
331 case '>':
332 IF wdnum==0 THEN iof |= 1 FI
333 iof |= IOPUT;
334 IF wdval==APPSYM
335 THEN iof |= IOAPP; break;
336 FI
337
338 case '<':
339 IF (c=nextc(0))=='&'
340 THEN iof |= IOMOV;
341 ELIF c=='>'
342 THEN iof |= IORDW;
343 ELSE peekc=c|MARK;
344 FI
345 break;
346
347 default:
348 return(lastio);
349 ENDSW
350
351 chkword();
352 iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof;
353 IF iof&IODOC
354 THEN iop->iolst=iopend; iopend=iop;
355 FI
356 word(); iop->ionxt=inout(lastio);
357 return(iop);
358}
359
360LOCAL VOID chkword()
361{
362 IF word()
363 THEN synbad();
364 FI
365}
366
367LOCAL VOID chksym(sym)
368{
369 REG INT x = sym&wdval;
370 IF ((x&SYMFLG) ? x : sym) != wdval
371 THEN synbad();
372 FI
373}
374
375LOCAL VOID prsym(sym)
376{
377 IF sym&SYMFLG
378 THEN REG SYSPTR sp=reserved;
379 WHILE sp->sysval
380 ANDF sp->sysval!=sym
381 DO sp++ OD
382 prs(sp->sysnam);
383 ELIF sym==EOFSYM
384 THEN prs(endoffile);
385 ELSE IF sym&SYMREP THEN prc(sym) FI
386 IF sym==NL
387 THEN prs("newline");
388 ELSE prc(sym);
389 FI
390 FI
391}
392
393LOCAL VOID synbad()
394{
395 prp(); prs(synmsg);
396 IF (flags&ttyflg)==0
397 THEN prs(atline); prn(standin->flin);
398 FI
399 prs(colon);
400 prc(LQ);
401 IF wdval
402 THEN prsym(wdval);
403 ELSE prs(wdarg->argval);
404 FI
405 prc(RQ); prs(unexpected);
406 newline();
407 exitsh(SYNBAD);
408}