parse.c revision 1.9 1 /* $NetBSD: parse.c,v 1.9 1998/07/28 02:23:39 mycroft Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: parse.c,v 1.9 1998/07/28 02:23:39 mycroft Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <sys/types.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #if __STDC__
49 # include <stdarg.h>
50 #else
51 # include <varargs.h>
52 #endif
53
54 #include "csh.h"
55 #include "extern.h"
56
57 static void asyntax __P((struct wordent *, struct wordent *));
58 static void asyn0 __P((struct wordent *, struct wordent *));
59 static void asyn3 __P((struct wordent *, struct wordent *));
60 static struct wordent
61 *freenod __P((struct wordent *, struct wordent *));
62 static struct command
63 *syn0 __P((struct wordent *, struct wordent *, int));
64 static struct command
65 *syn1 __P((struct wordent *, struct wordent *, int));
66 static struct command
67 *syn1a __P((struct wordent *, struct wordent *, int));
68 static struct command
69 *syn1b __P((struct wordent *, struct wordent *, int));
70 static struct command
71 *syn2 __P((struct wordent *, struct wordent *, int));
72 static struct command
73 *syn3 __P((struct wordent *, struct wordent *, int));
74
75 #define ALEFT 21 /* max of 20 alias expansions */
76 #define HLEFT 11 /* max of 10 history expansions */
77 /*
78 * Perform aliasing on the word list lex
79 * Do a (very rudimentary) parse to separate into commands.
80 * If word 0 of a command has an alias, do it.
81 * Repeat a maximum of 20 times.
82 */
83 static int aleft;
84 extern int hleft;
85 void
86 alias(lex)
87 struct wordent *lex;
88 {
89 jmp_buf osetexit;
90
91 aleft = ALEFT;
92 hleft = HLEFT;
93 getexit(osetexit);
94 (void) setexit();
95 if (haderr) {
96 resexit(osetexit);
97 reset();
98 }
99 if (--aleft == 0) {
100 stderror(ERR_ALIASLOOP);
101 /* NOTREACHED */
102 }
103 asyntax(lex->next, lex);
104 resexit(osetexit);
105 }
106
107 static void
108 asyntax(p1, p2)
109 struct wordent *p1, *p2;
110 {
111 while (p1 != p2)
112 if (any(";&\n", p1->word[0]))
113 p1 = p1->next;
114 else {
115 asyn0(p1, p2);
116 return;
117 }
118 }
119
120 static void
121 asyn0(p1, p2)
122 struct wordent *p1;
123 struct wordent *p2;
124 {
125 struct wordent *p;
126 int l = 0;
127
128 for (p = p1; p != p2; p = p->next)
129 switch (p->word[0]) {
130
131 case '(':
132 l++;
133 continue;
134
135 case ')':
136 l--;
137 if (l < 0) {
138 stderror(ERR_TOOMANYRP);
139 /* NOTREACHED */
140 }
141 continue;
142
143 case '>':
144 if (p->next != p2 && eq(p->next->word, STRand))
145 p = p->next;
146 continue;
147
148 case '&':
149 case '|':
150 case ';':
151 case '\n':
152 if (l != 0)
153 continue;
154 asyn3(p1, p);
155 asyntax(p->next, p2);
156 return;
157 }
158 if (l == 0)
159 asyn3(p1, p2);
160 }
161
162 static void
163 asyn3(p1, p2)
164 struct wordent *p1;
165 struct wordent *p2;
166 {
167 struct varent *ap;
168 struct wordent alout;
169 bool redid;
170
171 if (p1 == p2)
172 return;
173 if (p1->word[0] == '(') {
174 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
175 if (p2 == p1)
176 return;
177 if (p2 == p1->next)
178 return;
179 asyn0(p1->next, p2);
180 return;
181 }
182 ap = adrof1(p1->word, &aliases);
183 if (ap == 0)
184 return;
185 alhistp = p1->prev;
186 alhistt = p2;
187 alvec = ap->vec;
188 redid = lex(&alout);
189 alhistp = alhistt = 0;
190 alvec = 0;
191 if (seterr) {
192 freelex(&alout);
193 stderror(ERR_OLD);
194 /* NOTREACHED */
195 }
196 if (p1->word[0] && eq(p1->word, alout.next->word)) {
197 Char *cp = alout.next->word;
198
199 alout.next->word = Strspl(STRQNULL, cp);
200 xfree((ptr_t) cp);
201 }
202 p1 = freenod(p1, redid ? p2 : p1->next);
203 if (alout.next != &alout) {
204 p1->next->prev = alout.prev->prev;
205 alout.prev->prev->next = p1->next;
206 alout.next->prev = p1;
207 p1->next = alout.next;
208 xfree((ptr_t) alout.prev->word);
209 xfree((ptr_t) (alout.prev));
210 }
211 reset(); /* throw! */
212 }
213
214 static struct wordent *
215 freenod(p1, p2)
216 struct wordent *p1, *p2;
217 {
218 struct wordent *retp = p1->prev;
219
220 while (p1 != p2) {
221 xfree((ptr_t) p1->word);
222 p1 = p1->next;
223 xfree((ptr_t) (p1->prev));
224 }
225 retp->next = p2;
226 p2->prev = retp;
227 return (retp);
228 }
229
230 #define PHERE 1
231 #define PIN 2
232 #define POUT 4
233 #define PERR 8
234
235 /*
236 * syntax
237 * empty
238 * syn0
239 */
240 struct command *
241 syntax(p1, p2, flags)
242 struct wordent *p1, *p2;
243 int flags;
244 {
245
246 while (p1 != p2)
247 if (any(";&\n", p1->word[0]))
248 p1 = p1->next;
249 else
250 return (syn0(p1, p2, flags));
251 return (0);
252 }
253
254 /*
255 * syn0
256 * syn1
257 * syn1 & syntax
258 */
259 static struct command *
260 syn0(p1, p2, flags)
261 struct wordent *p1, *p2;
262 int flags;
263 {
264 struct wordent *p;
265 struct command *t, *t1;
266 int l;
267
268 l = 0;
269 for (p = p1; p != p2; p = p->next)
270 switch (p->word[0]) {
271
272 case '(':
273 l++;
274 continue;
275
276 case ')':
277 l--;
278 if (l < 0)
279 seterror(ERR_TOOMANYRP);
280 continue;
281
282 case '|':
283 if (p->word[1] == '|')
284 continue;
285 /* FALLTHROUGH */
286
287 case '>':
288 if (p->next != p2 && eq(p->next->word, STRand))
289 p = p->next;
290 continue;
291
292 case '&':
293 if (l != 0)
294 break;
295 if (p->word[1] == '&')
296 continue;
297 t1 = syn1(p1, p, flags);
298 if (t1->t_dtyp == NODE_LIST ||
299 t1->t_dtyp == NODE_AND ||
300 t1->t_dtyp == NODE_OR) {
301 t = (struct command *) xcalloc(1, sizeof(*t));
302 t->t_dtyp = NODE_PAREN;
303 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
304 t->t_dspr = t1;
305 t1 = t;
306 }
307 else
308 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
309 t = (struct command *) xcalloc(1, sizeof(*t));
310 t->t_dtyp = NODE_LIST;
311 t->t_dflg = 0;
312 t->t_dcar = t1;
313 t->t_dcdr = syntax(p, p2, flags);
314 return (t);
315 }
316 if (l == 0)
317 return (syn1(p1, p2, flags));
318 seterror(ERR_TOOMANYLP);
319 return (0);
320 }
321
322 /*
323 * syn1
324 * syn1a
325 * syn1a ; syntax
326 */
327 static struct command *
328 syn1(p1, p2, flags)
329 struct wordent *p1, *p2;
330 int flags;
331 {
332 struct wordent *p;
333 struct command *t;
334 int l;
335
336 l = 0;
337 for (p = p1; p != p2; p = p->next)
338 switch (p->word[0]) {
339
340 case '(':
341 l++;
342 continue;
343
344 case ')':
345 l--;
346 continue;
347
348 case ';':
349 case '\n':
350 if (l != 0)
351 break;
352 t = (struct command *) xcalloc(1, sizeof(*t));
353 t->t_dtyp = NODE_LIST;
354 t->t_dcar = syn1a(p1, p, flags);
355 t->t_dcdr = syntax(p->next, p2, flags);
356 if (t->t_dcdr == 0)
357 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
358 return (t);
359 }
360 return (syn1a(p1, p2, flags));
361 }
362
363 /*
364 * syn1a
365 * syn1b
366 * syn1b || syn1a
367 */
368 static struct command *
369 syn1a(p1, p2, flags)
370 struct wordent *p1, *p2;
371 int flags;
372 {
373 struct wordent *p;
374 struct command *t;
375 int l = 0;
376
377 for (p = p1; p != p2; p = p->next)
378 switch (p->word[0]) {
379
380 case '(':
381 l++;
382 continue;
383
384 case ')':
385 l--;
386 continue;
387
388 case '|':
389 if (p->word[1] != '|')
390 continue;
391 if (l == 0) {
392 t = (struct command *) xcalloc(1, sizeof(*t));
393 t->t_dtyp = NODE_OR;
394 t->t_dcar = syn1b(p1, p, flags);
395 t->t_dcdr = syn1a(p->next, p2, flags);
396 t->t_dflg = 0;
397 return (t);
398 }
399 continue;
400 }
401 return (syn1b(p1, p2, flags));
402 }
403
404 /*
405 * syn1b
406 * syn2
407 * syn2 && syn1b
408 */
409 static struct command *
410 syn1b(p1, p2, flags)
411 struct wordent *p1, *p2;
412 int flags;
413 {
414 struct wordent *p;
415 struct command *t;
416 int l = 0;
417
418 for (p = p1; p != p2; p = p->next)
419 switch (p->word[0]) {
420
421 case '(':
422 l++;
423 continue;
424
425 case ')':
426 l--;
427 continue;
428
429 case '&':
430 if (p->word[1] == '&' && l == 0) {
431 t = (struct command *) xcalloc(1, sizeof(*t));
432 t->t_dtyp = NODE_AND;
433 t->t_dcar = syn2(p1, p, flags);
434 t->t_dcdr = syn1b(p->next, p2, flags);
435 t->t_dflg = 0;
436 return (t);
437 }
438 continue;
439 }
440 return (syn2(p1, p2, flags));
441 }
442
443 /*
444 * syn2
445 * syn3
446 * syn3 | syn2
447 * syn3 |& syn2
448 */
449 static struct command *
450 syn2(p1, p2, flags)
451 struct wordent *p1, *p2;
452 int flags;
453 {
454 struct wordent *p, *pn;
455 struct command *t;
456 int l = 0;
457 int f;
458
459 for (p = p1; p != p2; p = p->next)
460 switch (p->word[0]) {
461
462 case '(':
463 l++;
464 continue;
465
466 case ')':
467 l--;
468 continue;
469
470 case '|':
471 if (l != 0)
472 continue;
473 t = (struct command *) xcalloc(1, sizeof(*t));
474 f = flags | POUT;
475 pn = p->next;
476 if (pn != p2 && pn->word[0] == '&') {
477 f |= PERR;
478 t->t_dflg |= F_STDERR;
479 }
480 t->t_dtyp = NODE_PIPE;
481 t->t_dcar = syn3(p1, p, f);
482 if (pn != p2 && pn->word[0] == '&')
483 p = pn;
484 t->t_dcdr = syn2(p->next, p2, flags | PIN);
485 return (t);
486 }
487 return (syn3(p1, p2, flags));
488 }
489
490 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
491
492 /*
493 * syn3
494 * ( syn0 ) [ < in ] [ > out ]
495 * word word* [ < in ] [ > out ]
496 * KEYWORD ( word* ) word* [ < in ] [ > out ]
497 *
498 * KEYWORD = (@ exit foreach if set switch test while)
499 */
500 static struct command *
501 syn3(p1, p2, flags)
502 struct wordent *p1, *p2;
503 int flags;
504 {
505 struct wordent *p;
506 struct wordent *lp, *rp;
507 struct command *t;
508 int l;
509 Char **av;
510 int n, c;
511 bool specp = 0;
512
513 if (p1 != p2) {
514 p = p1;
515 again:
516 switch (srchx(p->word)) {
517
518 case T_ELSE:
519 p = p->next;
520 if (p != p2)
521 goto again;
522 break;
523
524 case T_EXIT:
525 case T_FOREACH:
526 case T_IF:
527 case T_LET:
528 case T_SET:
529 case T_SWITCH:
530 case T_WHILE:
531 specp = 1;
532 break;
533 }
534 }
535 n = 0;
536 l = 0;
537 for (p = p1; p != p2; p = p->next)
538 switch (p->word[0]) {
539
540 case '(':
541 if (specp)
542 n++;
543 l++;
544 continue;
545
546 case ')':
547 if (specp)
548 n++;
549 l--;
550 continue;
551
552 case '>':
553 case '<':
554 if (l != 0) {
555 if (specp)
556 n++;
557 continue;
558 }
559 if (p->next == p2)
560 continue;
561 if (any(RELPAR, p->next->word[0]))
562 continue;
563 n--;
564 continue;
565
566 default:
567 if (!specp && l != 0)
568 continue;
569 n++;
570 continue;
571 }
572 if (n < 0)
573 n = 0;
574 t = (struct command *) xcalloc(1, sizeof(*t));
575 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
576 t->t_dcom = av;
577 n = 0;
578 if (p2->word[0] == ')')
579 t->t_dflg = F_NOFORK;
580 lp = 0;
581 rp = 0;
582 l = 0;
583 for (p = p1; p != p2; p = p->next) {
584 c = p->word[0];
585 switch (c) {
586
587 case '(':
588 if (l == 0) {
589 if (lp != 0 && !specp)
590 seterror(ERR_BADPLP);
591 lp = p->next;
592 }
593 l++;
594 goto savep;
595
596 case ')':
597 l--;
598 if (l == 0)
599 rp = p;
600 goto savep;
601
602 case '>':
603 if (l != 0)
604 goto savep;
605 if (p->word[1] == '>')
606 t->t_dflg |= F_APPEND;
607 if (p->next != p2 && eq(p->next->word, STRand)) {
608 t->t_dflg |= F_STDERR, p = p->next;
609 if (flags & (POUT | PERR)) {
610 seterror(ERR_OUTRED);
611 continue;
612 }
613 }
614 if (p->next != p2 && eq(p->next->word, STRbang))
615 t->t_dflg |= F_OVERWRITE, p = p->next;
616 if (p->next == p2) {
617 seterror(ERR_MISRED);
618 continue;
619 }
620 p = p->next;
621 if (any(RELPAR, p->word[0])) {
622 seterror(ERR_MISRED);
623 continue;
624 }
625 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
626 seterror(ERR_OUTRED);
627 else
628 t->t_drit = Strsave(p->word);
629 continue;
630
631 case '<':
632 if (l != 0)
633 goto savep;
634 if (p->word[1] == '<')
635 t->t_dflg |= F_READ;
636 if (p->next == p2) {
637 seterror(ERR_MISRED);
638 continue;
639 }
640 p = p->next;
641 if (any(RELPAR, p->word[0])) {
642 seterror(ERR_MISRED);
643 continue;
644 }
645 if ((flags & PHERE) && (t->t_dflg & F_READ))
646 seterror(ERR_REDPAR);
647 else if ((flags & PIN) || t->t_dlef)
648 seterror(ERR_INRED);
649 else
650 t->t_dlef = Strsave(p->word);
651 continue;
652
653 savep:
654 if (!specp)
655 continue;
656 /* FALLTHROUGH */
657
658 default:
659 if (l != 0 && !specp)
660 continue;
661 if (seterr == 0)
662 av[n] = Strsave(p->word);
663 n++;
664 continue;
665 }
666 }
667 if (lp != 0 && !specp) {
668 if (n != 0)
669 seterror(ERR_BADPLPS);
670 t->t_dtyp = NODE_PAREN;
671 t->t_dspr = syn0(lp, rp, PHERE);
672 }
673 else {
674 if (n == 0)
675 seterror(ERR_NULLCOM);
676 t->t_dtyp = NODE_COMMAND;
677 }
678 return (t);
679 }
680
681 void
682 freesyn(t)
683 struct command *t;
684 {
685 Char **v;
686
687 if (t == 0)
688 return;
689 switch (t->t_dtyp) {
690
691 case NODE_COMMAND:
692 for (v = t->t_dcom; *v; v++)
693 xfree((ptr_t) * v);
694 xfree((ptr_t) (t->t_dcom));
695 xfree((ptr_t) t->t_dlef);
696 xfree((ptr_t) t->t_drit);
697 break;
698 case NODE_PAREN:
699 freesyn(t->t_dspr);
700 xfree((ptr_t) t->t_dlef);
701 xfree((ptr_t) t->t_drit);
702 break;
703
704 case NODE_AND:
705 case NODE_OR:
706 case NODE_PIPE:
707 case NODE_LIST:
708 freesyn(t->t_dcar), freesyn(t->t_dcdr);
709 break;
710 }
711 xfree((ptr_t) t);
712 }
713