page breaks for 4.4BSD manuals
[unix-history] / usr / src / bin / csh / parse.c
CommitLineData
ecc449eb 1/*-
ed72f0a0
KB
2 * Copyright (c) 1980, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
ecc449eb
KB
4 *
5 * %sccs.include.redist.c%
b79f4fa9
DF
6 */
7
35371dec 8#ifndef lint
ed72f0a0 9static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) %G%";
ecc449eb 10#endif /* not lint */
0d061c44 11
b9c4f741
KB
12#include <sys/types.h>
13#include <stdlib.h>
14#include <string.h>
4df6491c
CZ
15#if __STDC__
16# include <stdarg.h>
17#else
18# include <varargs.h>
19#endif
20
4d7b2685
KB
21#include "csh.h"
22#include "extern.h"
0d061c44 23
0aec749d
CZ
24static void asyntax __P((struct wordent *, struct wordent *));
25static void asyn0 __P((struct wordent *, struct wordent *));
26static void asyn3 __P((struct wordent *, struct wordent *));
27static struct wordent
28 *freenod __P((struct wordent *, struct wordent *));
29static struct command
30 *syn0 __P((struct wordent *, struct wordent *, int));
31static struct command
32 *syn1 __P((struct wordent *, struct wordent *, int));
33static struct command
34 *syn1a __P((struct wordent *, struct wordent *, int));
35static struct command
36 *syn1b __P((struct wordent *, struct wordent *, int));
37static struct command
38 *syn2 __P((struct wordent *, struct wordent *, int));
39static struct command
40 *syn3 __P((struct wordent *, struct wordent *, int));
6e37afca
KB
41
42#define ALEFT 21 /* max of 20 alias expansions */
43#define HLEFT 11 /* max of 10 history expansions */
0d061c44
BJ
44/*
45 * Perform aliasing on the word list lex
46 * Do a (very rudimentary) parse to separate into commands.
47 * If word 0 of a command has an alias, do it.
48 * Repeat a maximum of 20 times.
49 */
6e37afca
KB
50static int aleft;
51extern int hleft;
52void
0d061c44 53alias(lex)
6e37afca 54 register struct wordent *lex;
0d061c44 55{
6e37afca
KB
56 jmp_buf osetexit;
57
58 aleft = ALEFT;
59 hleft = HLEFT;
60 getexit(osetexit);
61 (void) setexit();
62 if (haderr) {
0d061c44 63 resexit(osetexit);
6e37afca
KB
64 reset();
65 }
66 if (--aleft == 0)
67 stderror(ERR_ALIASLOOP);
68 asyntax(lex->next, lex);
69 resexit(osetexit);
0d061c44
BJ
70}
71
6e37afca 72static void
0d061c44 73asyntax(p1, p2)
6e37afca 74 register struct wordent *p1, *p2;
0d061c44 75{
6e37afca
KB
76 while (p1 != p2)
77 if (any(";&\n", p1->word[0]))
78 p1 = p1->next;
79 else {
80 asyn0(p1, p2);
81 return;
82 }
0d061c44
BJ
83}
84
6e37afca 85static void
0d061c44 86asyn0(p1, p2)
6e37afca
KB
87 struct wordent *p1;
88 register struct wordent *p2;
0d061c44 89{
6e37afca
KB
90 register struct wordent *p;
91 register int l = 0;
92
93 for (p = p1; p != p2; p = p->next)
94 switch (p->word[0]) {
95
96 case '(':
97 l++;
98 continue;
99
100 case ')':
101 l--;
102 if (l < 0)
103 stderror(ERR_TOOMANYRP);
104 continue;
105
106 case '>':
107 if (p->next != p2 && eq(p->next->word, STRand))
108 p = p->next;
109 continue;
110
111 case '&':
112 case '|':
113 case ';':
114 case '\n':
115 if (l != 0)
116 continue;
117 asyn3(p1, p);
118 asyntax(p->next, p2);
119 return;
120 }
121 if (l == 0)
122 asyn3(p1, p2);
0d061c44
BJ
123}
124
6e37afca 125static void
0d061c44 126asyn3(p1, p2)
6e37afca
KB
127 struct wordent *p1;
128 register struct wordent *p2;
0d061c44 129{
6e37afca
KB
130 register struct varent *ap;
131 struct wordent alout;
132 register bool redid;
133
134 if (p1 == p2)
135 return;
136 if (p1->word[0] == '(') {
137 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
138 if (p2 == p1)
0d061c44 139 return;
6e37afca
KB
140 if (p2 == p1->next)
141 return;
142 asyn0(p1->next, p2);
143 return;
144 }
145 ap = adrof1(p1->word, &aliases);
146 if (ap == 0)
147 return;
148 alhistp = p1->prev;
149 alhistt = p2;
150 alvec = ap->vec;
151 redid = lex(&alout);
152 alhistp = alhistt = 0;
153 alvec = 0;
154 if (seterr) {
155 freelex(&alout);
156 stderror(ERR_OLD);
157 }
158 if (p1->word[0] && eq(p1->word, alout.next->word)) {
159 Char *cp = alout.next->word;
160
161 alout.next->word = Strspl(STRQNULL, cp);
162 xfree((ptr_t) cp);
163 }
164 p1 = freenod(p1, redid ? p2 : p1->next);
165 if (alout.next != &alout) {
166 p1->next->prev = alout.prev->prev;
167 alout.prev->prev->next = p1->next;
168 alout.next->prev = p1;
169 p1->next = alout.next;
170 xfree((ptr_t) alout.prev->word);
171 xfree((ptr_t) (alout.prev));
172 }
173 reset(); /* throw! */
0d061c44
BJ
174}
175
6e37afca 176static struct wordent *
0d061c44 177freenod(p1, p2)
6e37afca 178 register struct wordent *p1, *p2;
0d061c44 179{
6e37afca
KB
180 register struct wordent *retp = p1->prev;
181
182 while (p1 != p2) {
183 xfree((ptr_t) p1->word);
184 p1 = p1->next;
185 xfree((ptr_t) (p1->prev));
186 }
187 retp->next = p2;
188 p2->prev = retp;
189 return (retp);
0d061c44
BJ
190}
191
192#define PHERE 1
193#define PIN 2
194#define POUT 4
454c2aa3 195#define PERR 8
0d061c44
BJ
196
197/*
198 * syntax
199 * empty
200 * syn0
201 */
202struct command *
203syntax(p1, p2, flags)
6e37afca
KB
204 register struct wordent *p1, *p2;
205 int flags;
0d061c44
BJ
206{
207
6e37afca
KB
208 while (p1 != p2)
209 if (any(";&\n", p1->word[0]))
210 p1 = p1->next;
211 else
212 return (syn0(p1, p2, flags));
213 return (0);
0d061c44
BJ
214}
215
216/*
217 * syn0
218 * syn1
219 * syn1 & syntax
220 */
6e37afca 221static struct command *
0d061c44 222syn0(p1, p2, flags)
6e37afca
KB
223 struct wordent *p1, *p2;
224 int flags;
0d061c44 225{
6e37afca
KB
226 register struct wordent *p;
227 register struct command *t, *t1;
228 int l;
229
230 l = 0;
231 for (p = p1; p != p2; p = p->next)
232 switch (p->word[0]) {
233
234 case '(':
235 l++;
236 continue;
237
238 case ')':
239 l--;
240 if (l < 0)
241 seterror(ERR_TOOMANYRP);
242 continue;
243
244 case '|':
245 if (p->word[1] == '|')
246 continue;
247 /* fall into ... */
248
249 case '>':
250 if (p->next != p2 && eq(p->next->word, STRand))
251 p = p->next;
252 continue;
253
254 case '&':
255 if (l != 0)
256 break;
257 if (p->word[1] == '&')
258 continue;
259 t1 = syn1(p1, p, flags);
260 if (t1->t_dtyp == NODE_LIST ||
261 t1->t_dtyp == NODE_AND ||
262 t1->t_dtyp == NODE_OR) {
263 t = (struct command *) xcalloc(1, sizeof(*t));
264 t->t_dtyp = NODE_PAREN;
265 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
266 t->t_dspr = t1;
267 t1 = t;
268 }
269 else
270 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
271 t = (struct command *) xcalloc(1, sizeof(*t));
272 t->t_dtyp = NODE_LIST;
273 t->t_dflg = 0;
274 t->t_dcar = t1;
275 t->t_dcdr = syntax(p, p2, flags);
276 return (t);
277 }
278 if (l == 0)
279 return (syn1(p1, p2, flags));
280 seterror(ERR_TOOMANYLP);
281 return (0);
0d061c44
BJ
282}
283
284/*
285 * syn1
286 * syn1a
287 * syn1a ; syntax
288 */
6e37afca 289static struct command *
0d061c44 290syn1(p1, p2, flags)
6e37afca
KB
291 struct wordent *p1, *p2;
292 int flags;
0d061c44 293{
6e37afca
KB
294 register struct wordent *p;
295 register struct command *t;
296 int l;
297
298 l = 0;
299 for (p = p1; p != p2; p = p->next)
300 switch (p->word[0]) {
301
302 case '(':
303 l++;
304 continue;
305
306 case ')':
307 l--;
308 continue;
309
310 case ';':
311 case '\n':
312 if (l != 0)
313 break;
314 t = (struct command *) xcalloc(1, sizeof(*t));
315 t->t_dtyp = NODE_LIST;
316 t->t_dcar = syn1a(p1, p, flags);
317 t->t_dcdr = syntax(p->next, p2, flags);
318 if (t->t_dcdr == 0)
319 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
320 return (t);
321 }
322 return (syn1a(p1, p2, flags));
0d061c44
BJ
323}
324
325/*
326 * syn1a
327 * syn1b
328 * syn1b || syn1a
329 */
6e37afca 330static struct command *
0d061c44 331syn1a(p1, p2, flags)
6e37afca
KB
332 struct wordent *p1, *p2;
333 int flags;
0d061c44 334{
6e37afca
KB
335 register struct wordent *p;
336 register struct command *t;
337 register int l = 0;
338
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] != '|')
352 continue;
353 if (l == 0) {
354 t = (struct command *) xcalloc(1, sizeof(*t));
355 t->t_dtyp = NODE_OR;
356 t->t_dcar = syn1b(p1, p, flags);
357 t->t_dcdr = syn1a(p->next, p2, flags);
358 t->t_dflg = 0;
359 return (t);
360 }
361 continue;
362 }
363 return (syn1b(p1, p2, flags));
0d061c44
BJ
364}
365
366/*
367 * syn1b
368 * syn2
369 * syn2 && syn1b
370 */
6e37afca 371static struct command *
0d061c44 372syn1b(p1, p2, flags)
6e37afca
KB
373 struct wordent *p1, *p2;
374 int flags;
0d061c44 375{
6e37afca
KB
376 register struct wordent *p;
377 register struct command *t;
378 register int l = 0;
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 (p->word[1] == '&' && l == 0) {
393 t = (struct command *) xcalloc(1, sizeof(*t));
394 t->t_dtyp = NODE_AND;
395 t->t_dcar = syn2(p1, p, flags);
396 t->t_dcdr = syn1b(p->next, p2, flags);
397 t->t_dflg = 0;
398 return (t);
399 }
400 continue;
401 }
402 return (syn2(p1, p2, flags));
0d061c44
BJ
403}
404
405/*
406 * syn2
407 * syn3
408 * syn3 | syn2
409 * syn3 |& syn2
410 */
6e37afca 411static struct command *
0d061c44 412syn2(p1, p2, flags)
6e37afca
KB
413 struct wordent *p1, *p2;
414 int flags;
0d061c44 415{
6e37afca
KB
416 register struct wordent *p, *pn;
417 register struct command *t;
418 register int l = 0;
419 int f;
420
421 for (p = p1; p != p2; p = p->next)
422 switch (p->word[0]) {
423
424 case '(':
425 l++;
426 continue;
427
428 case ')':
429 l--;
430 continue;
431
432 case '|':
433 if (l != 0)
434 continue;
435 t = (struct command *) xcalloc(1, sizeof(*t));
436 f = flags | POUT;
437 pn = p->next;
438 if (pn != p2 && pn->word[0] == '&') {
454c2aa3 439 f |= PERR;
6e37afca
KB
440 t->t_dflg |= F_STDERR;
441 }
442 t->t_dtyp = NODE_PIPE;
443 t->t_dcar = syn3(p1, p, f);
444 if (pn != p2 && pn->word[0] == '&')
445 p = pn;
446 t->t_dcdr = syn2(p->next, p2, flags | PIN);
447 return (t);
448 }
449 return (syn3(p1, p2, flags));
0d061c44
BJ
450}
451
6e37afca 452static char RELPAR[] = {'<', '>', '(', ')', '\0'};
0d061c44
BJ
453
454/*
455 * syn3
456 * ( syn0 ) [ < in ] [ > out ]
457 * word word* [ < in ] [ > out ]
458 * KEYWORD ( word* ) word* [ < in ] [ > out ]
459 *
460 * KEYWORD = (@ exit foreach if set switch test while)
461 */
6e37afca 462static struct command *
0d061c44 463syn3(p1, p2, flags)
6e37afca
KB
464 struct wordent *p1, *p2;
465 int flags;
0d061c44 466{
6e37afca
KB
467 register struct wordent *p;
468 struct wordent *lp, *rp;
469 register struct command *t;
470 register int l;
471 Char **av;
472 int n, c;
473 bool specp = 0;
474
475 if (p1 != p2) {
476 p = p1;
0d061c44 477again:
6e37afca
KB
478 switch (srchx(p->word)) {
479
480 case T_ELSE:
481 p = p->next;
482 if (p != p2)
483 goto again;
484 break;
485
486 case T_EXIT:
487 case T_FOREACH:
488 case T_IF:
489 case T_LET:
490 case T_SET:
491 case T_SWITCH:
492 case T_WHILE:
493 specp = 1;
494 break;
0d061c44 495 }
6e37afca
KB
496 }
497 n = 0;
498 l = 0;
499 for (p = p1; p != p2; p = p->next)
500 switch (p->word[0]) {
501
502 case '(':
503 if (specp)
504 n++;
505 l++;
506 continue;
507
508 case ')':
509 if (specp)
510 n++;
511 l--;
512 continue;
513
514 case '>':
515 case '<':
516 if (l != 0) {
517 if (specp)
518 n++;
519 continue;
520 }
521 if (p->next == p2)
522 continue;
523 if (any(RELPAR, p->next->word[0]))
524 continue;
525 n--;
526 continue;
527
528 default:
529 if (!specp && l != 0)
530 continue;
531 n++;
532 continue;
533 }
534 if (n < 0)
0d061c44 535 n = 0;
6e37afca
KB
536 t = (struct command *) xcalloc(1, sizeof(*t));
537 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
538 t->t_dcom = av;
539 n = 0;
540 if (p2->word[0] == ')')
541 t->t_dflg = F_NOFORK;
542 lp = 0;
543 rp = 0;
544 l = 0;
545 for (p = p1; p != p2; p = p->next) {
546 c = p->word[0];
547 switch (c) {
548
549 case '(':
550 if (l == 0) {
551 if (lp != 0 && !specp)
552 seterror(ERR_BADPLP);
553 lp = p->next;
554 }
555 l++;
556 goto savep;
557
558 case ')':
559 l--;
560 if (l == 0)
561 rp = p;
562 goto savep;
563
564 case '>':
565 if (l != 0)
566 goto savep;
567 if (p->word[1] == '>')
568 t->t_dflg |= F_APPEND;
569 if (p->next != p2 && eq(p->next->word, STRand)) {
570 t->t_dflg |= F_STDERR, p = p->next;
454c2aa3 571 if (flags & (POUT | PERR)) {
6e37afca
KB
572 seterror(ERR_OUTRED);
573 continue;
0d061c44 574 }
6e37afca
KB
575 }
576 if (p->next != p2 && eq(p->next->word, STRbang))
577 t->t_dflg |= F_OVERWRITE, p = p->next;
578 if (p->next == p2) {
579 seterror(ERR_MISRED);
580 continue;
581 }
582 p = p->next;
583 if (any(RELPAR, p->word[0])) {
584 seterror(ERR_MISRED);
585 continue;
586 }
37999c01 587 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
6e37afca
KB
588 seterror(ERR_OUTRED);
589 else
590 t->t_drit = Strsave(p->word);
591 continue;
592
593 case '<':
594 if (l != 0)
595 goto savep;
596 if (p->word[1] == '<')
597 t->t_dflg |= F_READ;
598 if (p->next == p2) {
599 seterror(ERR_MISRED);
600 continue;
601 }
602 p = p->next;
603 if (any(RELPAR, p->word[0])) {
604 seterror(ERR_MISRED);
605 continue;
606 }
607 if ((flags & PHERE) && (t->t_dflg & F_READ))
608 seterror(ERR_REDPAR);
609 else if ((flags & PIN) || t->t_dlef)
610 seterror(ERR_INRED);
611 else
612 t->t_dlef = Strsave(p->word);
613 continue;
614
615 savep:
616 if (!specp)
617 continue;
618 default:
619 if (l != 0 && !specp)
620 continue;
621 if (seterr == 0)
622 av[n] = Strsave(p->word);
623 n++;
624 continue;
0d061c44 625 }
6e37afca
KB
626 }
627 if (lp != 0 && !specp) {
628 if (n != 0)
629 seterror(ERR_BADPLPS);
630 t->t_dtyp = NODE_PAREN;
631 t->t_dspr = syn0(lp, rp, PHERE);
632 }
633 else {
634 if (n == 0)
635 seterror(ERR_NULLCOM);
636 t->t_dtyp = NODE_COMMAND;
637 }
638 return (t);
0d061c44
BJ
639}
640
6e37afca 641void
0d061c44 642freesyn(t)
6e37afca 643 register struct command *t;
0d061c44 644{
6e37afca
KB
645 register Char **v;
646
647 if (t == 0)
648 return;
649 switch (t->t_dtyp) {
650
651 case NODE_COMMAND:
652 for (v = t->t_dcom; *v; v++)
653 xfree((ptr_t) * v);
654 xfree((ptr_t) (t->t_dcom));
655 xfree((ptr_t) t->t_dlef);
656 xfree((ptr_t) t->t_drit);
657 break;
658 case NODE_PAREN:
659 freesyn(t->t_dspr);
660 xfree((ptr_t) t->t_dlef);
661 xfree((ptr_t) t->t_drit);
662 break;
663
664 case NODE_AND:
665 case NODE_OR:
666 case NODE_PIPE:
667 case NODE_LIST:
668 freesyn(t->t_dcar), freesyn(t->t_dcdr);
669 break;
670 }
671 xfree((ptr_t) t);
0d061c44 672}