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