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