add copyright
[unix-history] / usr / src / bin / csh / parse.c
CommitLineData
35371dec
EW
1#ifndef lint
2static char *sccsid = "@(#)parse.c 4.2 (Berkeley) %G%";
3#endif
0d061c44
BJ
4
5#include "sh.h"
6
7/*
8 * C shell
9 */
10
11/*
12 * Perform aliasing on the word list lex
13 * Do a (very rudimentary) parse to separate into commands.
14 * If word 0 of a command has an alias, do it.
15 * Repeat a maximum of 20 times.
16 */
17alias(lex)
18 register struct wordent *lex;
19{
20 int aleft = 21;
21 jmp_buf osetexit;
22
23 getexit(osetexit);
24 setexit();
25 if (haderr) {
26 resexit(osetexit);
27 reset();
28 }
29 if (--aleft == 0)
30 error("Alias loop");
31 asyntax(lex->next, lex);
32 resexit(osetexit);
33}
34
35asyntax(p1, p2)
36 register struct wordent *p1, *p2;
37{
38
39 while (p1 != p2)
40 if (any(p1->word[0], ";&\n"))
41 p1 = p1->next;
42 else {
43 asyn0(p1, p2);
44 return;
45 }
46}
47
48asyn0(p1, p2)
49 struct wordent *p1;
50 register struct wordent *p2;
51{
52 register struct wordent *p;
53 register int l = 0;
54
55 for (p = p1; p != p2; p = p->next)
56 switch (p->word[0]) {
57
58 case '(':
59 l++;
60 continue;
61
62 case ')':
63 l--;
64 if (l < 0)
65 error("Too many )'s");
66 continue;
67
68 case '>':
69 if (p->next != p2 && eq(p->next->word, "&"))
70 p = p->next;
71 continue;
72
73 case '&':
74 case '|':
75 case ';':
76 case '\n':
77 if (l != 0)
78 continue;
79 asyn3(p1, p);
80 asyntax(p->next, p2);
81 return;
82 }
83 if (l == 0)
84 asyn3(p1, p2);
85}
86
87asyn3(p1, p2)
88 struct wordent *p1;
89 register struct wordent *p2;
90{
91 register struct varent *ap;
92 struct wordent alout;
93 register bool redid;
94
95 if (p1 == p2)
96 return;
97 if (p1->word[0] == '(') {
98 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
99 if (p2 == p1)
100 return;
101 if (p2 == p1->next)
102 return;
103 asyn0(p1->next, p2);
104 return;
105 }
106 ap = adrof1(p1->word, &aliases);
107 if (ap == 0)
108 return;
109 alhistp = p1->prev;
110 alhistt = p2;
111 alvec = ap->vec;
112 redid = lex(&alout);
113 alhistp = alhistt = 0;
114 alvec = 0;
115 if (err) {
116 freelex(&alout);
117 error(err);
118 }
119 if (p1->word[0] && eq(p1->word, alout.next->word)) {
120 char *cp = alout.next->word;
121
122 alout.next->word = strspl("\200", cp);
35371dec 123 XFREE(cp)
0d061c44
BJ
124 }
125 p1 = freenod(p1, redid ? p2 : p1->next);
126 if (alout.next != &alout) {
127 p1->next->prev = alout.prev->prev;
128 alout.prev->prev->next = p1->next;
129 alout.next->prev = p1;
130 p1->next = alout.next;
35371dec
EW
131 XFREE(alout.prev->word)
132 XFREE((char *)alout.prev)
0d061c44
BJ
133 }
134 reset(); /* throw! */
135}
136
137struct wordent *
138freenod(p1, p2)
139 register struct wordent *p1, *p2;
140{
141 register struct wordent *retp = p1->prev;
142
143 while (p1 != p2) {
35371dec 144 XFREE(p1->word)
0d061c44 145 p1 = p1->next;
35371dec 146 XFREE((char *)p1->prev)
0d061c44
BJ
147 }
148 retp->next = p2;
149 p2->prev = retp;
150 return (retp);
151}
152
153#define PHERE 1
154#define PIN 2
155#define POUT 4
156#define PDIAG 8
157
158/*
159 * syntax
160 * empty
161 * syn0
162 */
163struct command *
164syntax(p1, p2, flags)
165 register struct wordent *p1, *p2;
166 int flags;
167{
168
169 while (p1 != p2)
170 if (any(p1->word[0], ";&\n"))
171 p1 = p1->next;
172 else
173 return (syn0(p1, p2, flags));
174 return (0);
175}
176
177/*
178 * syn0
179 * syn1
180 * syn1 & syntax
181 */
182struct command *
183syn0(p1, p2, flags)
184 struct wordent *p1, *p2;
185 int flags;
186{
187 register struct wordent *p;
188 register struct command *t, *t1;
189 int l;
190
191 l = 0;
192 for (p = p1; p != p2; p = p->next)
193 switch (p->word[0]) {
194
195 case '(':
196 l++;
197 continue;
198
199 case ')':
200 l--;
201 if (l < 0)
202 seterr("Too many )'s");
203 continue;
204
205 case '|':
206 if (p->word[1] == '|')
207 continue;
208 /* fall into ... */
209
210 case '>':
211 if (p->next != p2 && eq(p->next->word, "&"))
212 p = p->next;
213 continue;
214
215 case '&':
216 if (l != 0)
217 break;
218 if (p->word[1] == '&')
219 continue;
220 t1 = syn1(p1, p, flags);
221 if (t1->t_dtyp == TLST) {
222 t = (struct command *) calloc(1, sizeof (*t));
223 t->t_dtyp = TPAR;
224 t->t_dflg = FAND|FINT;
225 t->t_dspr = t1;
226 t1 = t;
227 } else
228 t1->t_dflg |= FAND|FINT;
229 t = (struct command *) calloc(1, sizeof (*t));
230 t->t_dtyp = TLST;
231 t->t_dflg = 0;
232 t->t_dcar = t1;
233 t->t_dcdr = syntax(p, p2, flags);
234 return(t);
235 }
236 if (l == 0)
237 return (syn1(p1, p2, flags));
238 seterr("Too many ('s");
239 return (0);
240}
241
242/*
243 * syn1
244 * syn1a
245 * syn1a ; syntax
246 */
247struct command *
248syn1(p1, p2, flags)
249 struct wordent *p1, *p2;
250 int flags;
251{
252 register struct wordent *p;
253 register struct command *t;
254 int l;
255
256 l = 0;
257 for (p = p1; p != p2; p = p->next)
258 switch (p->word[0]) {
259
260 case '(':
261 l++;
262 continue;
263
264 case ')':
265 l--;
266 continue;
267
268 case ';':
269 case '\n':
270 if (l != 0)
271 break;
272 t = (struct command *) calloc(1, sizeof (*t));
273 t->t_dtyp = TLST;
274 t->t_dcar = syn1a(p1, p, flags);
275 t->t_dcdr = syntax(p->next, p2, flags);
276 if (t->t_dcdr == 0)
277 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
278 return (t);
279 }
280 return (syn1a(p1, p2, flags));
281}
282
283/*
284 * syn1a
285 * syn1b
286 * syn1b || syn1a
287 */
288struct command *
289syn1a(p1, p2, flags)
290 struct wordent *p1, *p2;
291 int flags;
292{
293 register struct wordent *p;
294 register struct command *t;
295 register int l = 0;
296
297 for (p = p1; p != p2; p = p->next)
298 switch (p->word[0]) {
299
300 case '(':
301 l++;
302 continue;
303
304 case ')':
305 l--;
306 continue;
307
308 case '|':
309 if (p->word[1] != '|')
310 continue;
311 if (l == 0) {
312 t = (struct command *) calloc(1, sizeof (*t));
313 t->t_dtyp = TOR;
314 t->t_dcar = syn1b(p1, p, flags);
315 t->t_dcdr = syn1a(p->next, p2, flags);
316 t->t_dflg = 0;
317 return (t);
318 }
319 continue;
320 }
321 return (syn1b(p1, p2, flags));
322}
323
324/*
325 * syn1b
326 * syn2
327 * syn2 && syn1b
328 */
329struct command *
330syn1b(p1, p2, flags)
331 struct wordent *p1, *p2;
332 int flags;
333{
334 register struct wordent *p;
335 register struct command *t;
336 register int l = 0;
337
338 l = 0;
339 for (p = p1; p != p2; p = p->next)
340 switch (p->word[0]) {
341
342 case '(':
343 l++;
344 continue;
345
346 case ')':
347 l--;
348 continue;
349
350 case '&':
351 if (p->word[1] == '&' && l == 0) {
352 t = (struct command *) calloc(1, sizeof (*t));
353 t->t_dtyp = TAND;
354 t->t_dcar = syn2(p1, p, flags);
355 t->t_dcdr = syn1b(p->next, p2, flags);
356 t->t_dflg = 0;
357 return (t);
358 }
359 continue;
360 }
361 return (syn2(p1, p2, flags));
362}
363
364/*
365 * syn2
366 * syn3
367 * syn3 | syn2
368 * syn3 |& syn2
369 */
370struct command *
371syn2(p1, p2, flags)
372 struct wordent *p1, *p2;
373 int flags;
374{
375 register struct wordent *p, *pn;
376 register struct command *t;
377 register int l = 0;
378 int f;
379
380 for (p = p1; p != p2; p = p->next)
381 switch (p->word[0]) {
382
383 case '(':
384 l++;
385 continue;
386
387 case ')':
388 l--;
389 continue;
390
391 case '|':
392 if (l != 0)
393 continue;
394 t = (struct command *) calloc(1, sizeof (*t));
395 f = flags | POUT;
396 pn = p->next;
397 if (pn != p2 && pn->word[0] == '&') {
398 f |= PDIAG;
399 t->t_dflg |= FDIAG;
400 }
401 t->t_dtyp = TFIL;
402 t->t_dcar = syn3(p1, p, f);
403 if (pn != p2 && pn->word[0] == '&')
404 p = pn;
405 t->t_dcdr = syn2(p->next, p2, flags | PIN);
406 return (t);
407 }
408 return (syn3(p1, p2, flags));
409}
410
411char *RELPAR = "<>()";
412
413/*
414 * syn3
415 * ( syn0 ) [ < in ] [ > out ]
416 * word word* [ < in ] [ > out ]
417 * KEYWORD ( word* ) word* [ < in ] [ > out ]
418 *
419 * KEYWORD = (@ exit foreach if set switch test while)
420 */
421struct command *
422syn3(p1, p2, flags)
423 struct wordent *p1, *p2;
424 int flags;
425{
426 register struct wordent *p;
427 struct wordent *lp, *rp;
428 register struct command *t;
429 register int l;
430 char **av;
431 int n, c;
432 bool specp = 0;
433
434 if (p1 != p2) {
435 p = p1;
436again:
437 switch (srchx(p->word)) {
438
439 case ZELSE:
440 p = p->next;
441 if (p != p2)
442 goto again;
443 break;
444
445 case ZEXIT:
446 case ZFOREACH:
447 case ZIF:
448 case ZLET:
449 case ZSET:
450 case ZSWITCH:
451 case ZWHILE:
452 specp = 1;
453 break;
454 }
455 }
456 n = 0;
457 l = 0;
458 for (p = p1; p != p2; p = p->next)
459 switch (p->word[0]) {
460
461 case '(':
462 if (specp)
463 n++;
464 l++;
465 continue;
466
467 case ')':
468 if (specp)
469 n++;
470 l--;
471 continue;
472
473 case '>':
474 case '<':
475 if (l != 0) {
476 if (specp)
477 n++;
478 continue;
479 }
480 if (p->next == p2)
481 continue;
482 if (any(p->next->word[0], RELPAR))
483 continue;
484 n--;
485 continue;
486
487 default:
488 if (!specp && l != 0)
489 continue;
490 n++;
491 continue;
492 }
493 if (n < 0)
494 n = 0;
495 t = (struct command *) calloc(1, sizeof (*t));
35371dec 496 av = (char **) calloc((unsigned) (n + 1), sizeof (char **));
0d061c44
BJ
497 t->t_dcom = av;
498 n = 0;
499 if (p2->word[0] == ')')
500 t->t_dflg = FPAR;
501 lp = 0;
502 rp = 0;
503 l = 0;
504 for (p = p1; p != p2; p = p->next) {
505 c = p->word[0];
506 switch (c) {
507
508 case '(':
509 if (l == 0) {
510 if (lp != 0 && !specp)
511 seterr("Badly placed (");
512 lp = p->next;
513 }
514 l++;
515 goto savep;
516
517 case ')':
518 l--;
519 if (l == 0)
520 rp = p;
521 goto savep;
522
523 case '>':
524 if (l != 0)
525 goto savep;
526 if (p->word[1] == '>')
527 t->t_dflg |= FCAT;
528 if (p->next != p2 && eq(p->next->word, "&")) {
529 t->t_dflg |= FDIAG, p = p->next;
530 if (flags & (POUT|PDIAG))
531 goto badout;
532 }
533 if (p->next != p2 && eq(p->next->word, "!"))
534 t->t_dflg |= FANY, p = p->next;
535 if (p->next == p2) {
536missfile:
537 seterr("Missing name for redirect");
538 continue;
539 }
540 p = p->next;
541 if (any(p->word[0], RELPAR))
542 goto missfile;
543 if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
544badout:
545 seterr("Ambiguous output redirect");
546 else
547 t->t_drit = savestr(p->word);
548 continue;
549
550 case '<':
551 if (l != 0)
552 goto savep;
553 if (p->word[1] == '<')
554 t->t_dflg |= FHERE;
555 if (p->next == p2)
556 goto missfile;
557 p = p->next;
558 if (any(p->word[0], RELPAR))
559 goto missfile;
560 if ((flags & PHERE) && (t->t_dflg & FHERE))
561 seterr("Can't << within ()'s");
562 else if ((flags & PIN) || t->t_dlef)
563 seterr("Ambiguous input redirect");
564 else
565 t->t_dlef = savestr(p->word);
566 continue;
567
568savep:
569 if (!specp)
570 continue;
571 default:
572 if (l != 0 && !specp)
573 continue;
574 if (err == 0)
575 av[n] = savestr(p->word);
576 n++;
577 continue;
578 }
579 }
580 if (lp != 0 && !specp) {
581 if (n != 0)
582 seterr("Badly placed ()'s");
583 t->t_dtyp = TPAR;
584 t->t_dspr = syn0(lp, rp, PHERE);
585 } else {
586 if (n == 0)
587 seterr("Invalid null command");
588 t->t_dtyp = TCOM;
589 }
590 return (t);
591}
592
593freesyn(t)
594 register struct command *t;
595{
596 register char **v;
597
598 if (t == 0)
599 return;
600 switch (t->t_dtyp) {
601
602 case TCOM:
603 for (v = t->t_dcom; *v; v++)
35371dec
EW
604 XFREE(*v)
605 XFREE((char *)t->t_dcom)
0d061c44
BJ
606 goto lr;
607
608 case TPAR:
609 freesyn(t->t_dspr);
610 /* fall into ... */
611
612lr:
35371dec
EW
613 XFREE(t->t_dlef)
614 XFREE(t->t_drit)
0d061c44
BJ
615 break;
616
617 case TAND:
618 case TOR:
619 case TFIL:
620 case TLST:
621 freesyn(t->t_dcar), freesyn(t->t_dcdr);
622 break;
623 }
35371dec 624 XFREE((char *)t)
0d061c44 625}