parse.c revision 1.10 1 /* $NetBSD: parse.c,v 1.10 1998/07/28 11:41:45 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.10 1998/07/28 11:41:45 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 asyntax(lex->next, lex);
102 resexit(osetexit);
103 }
104
105 static void
106 asyntax(p1, p2)
107 struct wordent *p1, *p2;
108 {
109 while (p1 != p2)
110 if (any(";&\n", p1->word[0]))
111 p1 = p1->next;
112 else {
113 asyn0(p1, p2);
114 return;
115 }
116 }
117
118 static void
119 asyn0(p1, p2)
120 struct wordent *p1;
121 struct wordent *p2;
122 {
123 struct wordent *p;
124 int l = 0;
125
126 for (p = p1; p != p2; p = p->next)
127 switch (p->word[0]) {
128
129 case '(':
130 l++;
131 continue;
132
133 case ')':
134 l--;
135 if (l < 0)
136 stderror(ERR_TOOMANYRP);
137 continue;
138
139 case '>':
140 if (p->next != p2 && eq(p->next->word, STRand))
141 p = p->next;
142 continue;
143
144 case '&':
145 case '|':
146 case ';':
147 case '\n':
148 if (l != 0)
149 continue;
150 asyn3(p1, p);
151 asyntax(p->next, p2);
152 return;
153 }
154 if (l == 0)
155 asyn3(p1, p2);
156 }
157
158 static void
159 asyn3(p1, p2)
160 struct wordent *p1;
161 struct wordent *p2;
162 {
163 struct varent *ap;
164 struct wordent alout;
165 bool redid;
166
167 if (p1 == p2)
168 return;
169 if (p1->word[0] == '(') {
170 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
171 if (p2 == p1)
172 return;
173 if (p2 == p1->next)
174 return;
175 asyn0(p1->next, p2);
176 return;
177 }
178 ap = adrof1(p1->word, &aliases);
179 if (ap == 0)
180 return;
181 alhistp = p1->prev;
182 alhistt = p2;
183 alvec = ap->vec;
184 redid = lex(&alout);
185 alhistp = alhistt = 0;
186 alvec = 0;
187 if (seterr) {
188 freelex(&alout);
189 stderror(ERR_OLD);
190 }
191 if (p1->word[0] && eq(p1->word, alout.next->word)) {
192 Char *cp = alout.next->word;
193
194 alout.next->word = Strspl(STRQNULL, cp);
195 xfree((ptr_t) cp);
196 }
197 p1 = freenod(p1, redid ? p2 : p1->next);
198 if (alout.next != &alout) {
199 p1->next->prev = alout.prev->prev;
200 alout.prev->prev->next = p1->next;
201 alout.next->prev = p1;
202 p1->next = alout.next;
203 xfree((ptr_t) alout.prev->word);
204 xfree((ptr_t) (alout.prev));
205 }
206 reset(); /* throw! */
207 }
208
209 static struct wordent *
210 freenod(p1, p2)
211 struct wordent *p1, *p2;
212 {
213 struct wordent *retp = p1->prev;
214
215 while (p1 != p2) {
216 xfree((ptr_t) p1->word);
217 p1 = p1->next;
218 xfree((ptr_t) (p1->prev));
219 }
220 retp->next = p2;
221 p2->prev = retp;
222 return (retp);
223 }
224
225 #define PHERE 1
226 #define PIN 2
227 #define POUT 4
228 #define PERR 8
229
230 /*
231 * syntax
232 * empty
233 * syn0
234 */
235 struct command *
236 syntax(p1, p2, flags)
237 struct wordent *p1, *p2;
238 int flags;
239 {
240
241 while (p1 != p2)
242 if (any(";&\n", p1->word[0]))
243 p1 = p1->next;
244 else
245 return (syn0(p1, p2, flags));
246 return (0);
247 }
248
249 /*
250 * syn0
251 * syn1
252 * syn1 & syntax
253 */
254 static struct command *
255 syn0(p1, p2, flags)
256 struct wordent *p1, *p2;
257 int flags;
258 {
259 struct wordent *p;
260 struct command *t, *t1;
261 int l;
262
263 l = 0;
264 for (p = p1; p != p2; p = p->next)
265 switch (p->word[0]) {
266
267 case '(':
268 l++;
269 continue;
270
271 case ')':
272 l--;
273 if (l < 0)
274 seterror(ERR_TOOMANYRP);
275 continue;
276
277 case '|':
278 if (p->word[1] == '|')
279 continue;
280 /* FALLTHROUGH */
281
282 case '>':
283 if (p->next != p2 && eq(p->next->word, STRand))
284 p = p->next;
285 continue;
286
287 case '&':
288 if (l != 0)
289 break;
290 if (p->word[1] == '&')
291 continue;
292 t1 = syn1(p1, p, flags);
293 if (t1->t_dtyp == NODE_LIST ||
294 t1->t_dtyp == NODE_AND ||
295 t1->t_dtyp == NODE_OR) {
296 t = (struct command *) xcalloc(1, sizeof(*t));
297 t->t_dtyp = NODE_PAREN;
298 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
299 t->t_dspr = t1;
300 t1 = t;
301 }
302 else
303 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
304 t = (struct command *) xcalloc(1, sizeof(*t));
305 t->t_dtyp = NODE_LIST;
306 t->t_dflg = 0;
307 t->t_dcar = t1;
308 t->t_dcdr = syntax(p, p2, flags);
309 return (t);
310 }
311 if (l == 0)
312 return (syn1(p1, p2, flags));
313 seterror(ERR_TOOMANYLP);
314 return (0);
315 }
316
317 /*
318 * syn1
319 * syn1a
320 * syn1a ; syntax
321 */
322 static struct command *
323 syn1(p1, p2, flags)
324 struct wordent *p1, *p2;
325 int flags;
326 {
327 struct wordent *p;
328 struct command *t;
329 int l;
330
331 l = 0;
332 for (p = p1; p != p2; p = p->next)
333 switch (p->word[0]) {
334
335 case '(':
336 l++;
337 continue;
338
339 case ')':
340 l--;
341 continue;
342
343 case ';':
344 case '\n':
345 if (l != 0)
346 break;
347 t = (struct command *) xcalloc(1, sizeof(*t));
348 t->t_dtyp = NODE_LIST;
349 t->t_dcar = syn1a(p1, p, flags);
350 t->t_dcdr = syntax(p->next, p2, flags);
351 if (t->t_dcdr == 0)
352 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
353 return (t);
354 }
355 return (syn1a(p1, p2, flags));
356 }
357
358 /*
359 * syn1a
360 * syn1b
361 * syn1b || syn1a
362 */
363 static struct command *
364 syn1a(p1, p2, flags)
365 struct wordent *p1, *p2;
366 int flags;
367 {
368 struct wordent *p;
369 struct command *t;
370 int l = 0;
371
372 for (p = p1; p != p2; p = p->next)
373 switch (p->word[0]) {
374
375 case '(':
376 l++;
377 continue;
378
379 case ')':
380 l--;
381 continue;
382
383 case '|':
384 if (p->word[1] != '|')
385 continue;
386 if (l == 0) {
387 t = (struct command *) xcalloc(1, sizeof(*t));
388 t->t_dtyp = NODE_OR;
389 t->t_dcar = syn1b(p1, p, flags);
390 t->t_dcdr = syn1a(p->next, p2, flags);
391 t->t_dflg = 0;
392 return (t);
393 }
394 continue;
395 }
396 return (syn1b(p1, p2, flags));
397 }
398
399 /*
400 * syn1b
401 * syn2
402 * syn2 && syn1b
403 */
404 static struct command *
405 syn1b(p1, p2, flags)
406 struct wordent *p1, *p2;
407 int flags;
408 {
409 struct wordent *p;
410 struct command *t;
411 int l = 0;
412
413 for (p = p1; p != p2; p = p->next)
414 switch (p->word[0]) {
415
416 case '(':
417 l++;
418 continue;
419
420 case ')':
421 l--;
422 continue;
423
424 case '&':
425 if (p->word[1] == '&' && l == 0) {
426 t = (struct command *) xcalloc(1, sizeof(*t));
427 t->t_dtyp = NODE_AND;
428 t->t_dcar = syn2(p1, p, flags);
429 t->t_dcdr = syn1b(p->next, p2, flags);
430 t->t_dflg = 0;
431 return (t);
432 }
433 continue;
434 }
435 return (syn2(p1, p2, flags));
436 }
437
438 /*
439 * syn2
440 * syn3
441 * syn3 | syn2
442 * syn3 |& syn2
443 */
444 static struct command *
445 syn2(p1, p2, flags)
446 struct wordent *p1, *p2;
447 int flags;
448 {
449 struct wordent *p, *pn;
450 struct command *t;
451 int l = 0;
452 int f;
453
454 for (p = p1; p != p2; p = p->next)
455 switch (p->word[0]) {
456
457 case '(':
458 l++;
459 continue;
460
461 case ')':
462 l--;
463 continue;
464
465 case '|':
466 if (l != 0)
467 continue;
468 t = (struct command *) xcalloc(1, sizeof(*t));
469 f = flags | POUT;
470 pn = p->next;
471 if (pn != p2 && pn->word[0] == '&') {
472 f |= PERR;
473 t->t_dflg |= F_STDERR;
474 }
475 t->t_dtyp = NODE_PIPE;
476 t->t_dcar = syn3(p1, p, f);
477 if (pn != p2 && pn->word[0] == '&')
478 p = pn;
479 t->t_dcdr = syn2(p->next, p2, flags | PIN);
480 return (t);
481 }
482 return (syn3(p1, p2, flags));
483 }
484
485 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
486
487 /*
488 * syn3
489 * ( syn0 ) [ < in ] [ > out ]
490 * word word* [ < in ] [ > out ]
491 * KEYWORD ( word* ) word* [ < in ] [ > out ]
492 *
493 * KEYWORD = (@ exit foreach if set switch test while)
494 */
495 static struct command *
496 syn3(p1, p2, flags)
497 struct wordent *p1, *p2;
498 int flags;
499 {
500 struct wordent *p;
501 struct wordent *lp, *rp;
502 struct command *t;
503 int l;
504 Char **av;
505 int n, c;
506 bool specp = 0;
507
508 if (p1 != p2) {
509 p = p1;
510 again:
511 switch (srchx(p->word)) {
512
513 case T_ELSE:
514 p = p->next;
515 if (p != p2)
516 goto again;
517 break;
518
519 case T_EXIT:
520 case T_FOREACH:
521 case T_IF:
522 case T_LET:
523 case T_SET:
524 case T_SWITCH:
525 case T_WHILE:
526 specp = 1;
527 break;
528 }
529 }
530 n = 0;
531 l = 0;
532 for (p = p1; p != p2; p = p->next)
533 switch (p->word[0]) {
534
535 case '(':
536 if (specp)
537 n++;
538 l++;
539 continue;
540
541 case ')':
542 if (specp)
543 n++;
544 l--;
545 continue;
546
547 case '>':
548 case '<':
549 if (l != 0) {
550 if (specp)
551 n++;
552 continue;
553 }
554 if (p->next == p2)
555 continue;
556 if (any(RELPAR, p->next->word[0]))
557 continue;
558 n--;
559 continue;
560
561 default:
562 if (!specp && l != 0)
563 continue;
564 n++;
565 continue;
566 }
567 if (n < 0)
568 n = 0;
569 t = (struct command *) xcalloc(1, sizeof(*t));
570 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
571 t->t_dcom = av;
572 n = 0;
573 if (p2->word[0] == ')')
574 t->t_dflg = F_NOFORK;
575 lp = 0;
576 rp = 0;
577 l = 0;
578 for (p = p1; p != p2; p = p->next) {
579 c = p->word[0];
580 switch (c) {
581
582 case '(':
583 if (l == 0) {
584 if (lp != 0 && !specp)
585 seterror(ERR_BADPLP);
586 lp = p->next;
587 }
588 l++;
589 goto savep;
590
591 case ')':
592 l--;
593 if (l == 0)
594 rp = p;
595 goto savep;
596
597 case '>':
598 if (l != 0)
599 goto savep;
600 if (p->word[1] == '>')
601 t->t_dflg |= F_APPEND;
602 if (p->next != p2 && eq(p->next->word, STRand)) {
603 t->t_dflg |= F_STDERR, p = p->next;
604 if (flags & (POUT | PERR)) {
605 seterror(ERR_OUTRED);
606 continue;
607 }
608 }
609 if (p->next != p2 && eq(p->next->word, STRbang))
610 t->t_dflg |= F_OVERWRITE, p = p->next;
611 if (p->next == p2) {
612 seterror(ERR_MISRED);
613 continue;
614 }
615 p = p->next;
616 if (any(RELPAR, p->word[0])) {
617 seterror(ERR_MISRED);
618 continue;
619 }
620 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
621 seterror(ERR_OUTRED);
622 else
623 t->t_drit = Strsave(p->word);
624 continue;
625
626 case '<':
627 if (l != 0)
628 goto savep;
629 if (p->word[1] == '<')
630 t->t_dflg |= F_READ;
631 if (p->next == p2) {
632 seterror(ERR_MISRED);
633 continue;
634 }
635 p = p->next;
636 if (any(RELPAR, p->word[0])) {
637 seterror(ERR_MISRED);
638 continue;
639 }
640 if ((flags & PHERE) && (t->t_dflg & F_READ))
641 seterror(ERR_REDPAR);
642 else if ((flags & PIN) || t->t_dlef)
643 seterror(ERR_INRED);
644 else
645 t->t_dlef = Strsave(p->word);
646 continue;
647
648 savep:
649 if (!specp)
650 continue;
651 /* FALLTHROUGH */
652
653 default:
654 if (l != 0 && !specp)
655 continue;
656 if (seterr == 0)
657 av[n] = Strsave(p->word);
658 n++;
659 continue;
660 }
661 }
662 if (lp != 0 && !specp) {
663 if (n != 0)
664 seterror(ERR_BADPLPS);
665 t->t_dtyp = NODE_PAREN;
666 t->t_dspr = syn0(lp, rp, PHERE);
667 }
668 else {
669 if (n == 0)
670 seterror(ERR_NULLCOM);
671 t->t_dtyp = NODE_COMMAND;
672 }
673 return (t);
674 }
675
676 void
677 freesyn(t)
678 struct command *t;
679 {
680 Char **v;
681
682 if (t == 0)
683 return;
684 switch (t->t_dtyp) {
685
686 case NODE_COMMAND:
687 for (v = t->t_dcom; *v; v++)
688 xfree((ptr_t) * v);
689 xfree((ptr_t) (t->t_dcom));
690 xfree((ptr_t) t->t_dlef);
691 xfree((ptr_t) t->t_drit);
692 break;
693 case NODE_PAREN:
694 freesyn(t->t_dspr);
695 xfree((ptr_t) t->t_dlef);
696 xfree((ptr_t) t->t_drit);
697 break;
698
699 case NODE_AND:
700 case NODE_OR:
701 case NODE_PIPE:
702 case NODE_LIST:
703 freesyn(t->t_dcar), freesyn(t->t_dcdr);
704 break;
705 }
706 xfree((ptr_t) t);
707 }
708