]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcsh/sh.parse.c
This commit was generated by cvs2svn to compensate for changes in r94735,
[FreeBSD/FreeBSD.git] / contrib / tcsh / sh.parse.c
1 /* $Header: /src/pub/tcsh/sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $ */
2 /*
3  * sh.parse.c: Interpret a list of tokens
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 #include "sh.h"
38
39 RCSID("$Id: sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $")
40
41 /*
42  * C shell
43  */
44 static  void             asyntax __P((struct wordent *, struct wordent *));
45 static  void             asyn0   __P((struct wordent *, struct wordent *));
46 static  void             asyn3   __P((struct wordent *, struct wordent *));
47 static  struct wordent  *freenod __P((struct wordent *, struct wordent *));
48 static  struct command  *syn0    __P((struct wordent *, struct wordent *, int));
49 static  struct command  *syn1    __P((struct wordent *, struct wordent *, int));
50 static  struct command  *syn1a   __P((struct wordent *, struct wordent *, int));
51 static  struct command  *syn1b   __P((struct wordent *, struct wordent *, int));
52 static  struct command  *syn2    __P((struct wordent *, struct wordent *, int));
53 static  struct command  *syn3    __P((struct wordent *, struct wordent *, int));
54
55 #define ALEFT   51              /* max of 50 alias expansions    */
56 #define HLEFT   11              /* max of 10 history expansions */
57 /*
58  * Perform aliasing on the word list lexp
59  * Do a (very rudimentary) parse to separate into commands.
60  * If word 0 of a command has an alias, do it.
61  * Repeat a maximum of 50 times.
62  */
63 static int aleft;
64 extern int hleft;
65 void
66 alias(lexp)
67     register struct wordent *lexp;
68 {
69     jmp_buf_t osetexit;
70
71     aleft = ALEFT;
72     hleft = HLEFT;
73     getexit(osetexit);
74     (void) setexit();
75     if (haderr) {
76         resexit(osetexit);
77         reset();
78     }
79     if (--aleft == 0)
80         stderror(ERR_ALIASLOOP);
81     asyntax(lexp->next, lexp);
82     resexit(osetexit);
83 }
84
85 static void
86 asyntax(p1, p2)
87     register struct wordent *p1, *p2;
88 {
89     while (p1 != p2)
90         if (any(";&\n", p1->word[0]))
91             p1 = p1->next;
92         else {
93             asyn0(p1, p2);
94             return;
95         }
96 }
97
98 static void
99 asyn0(p1, p2)
100     struct wordent *p1;
101     register struct wordent *p2;
102 {
103     register struct wordent *p;
104     register int l = 0;
105
106     for (p = p1; p != p2; p = p->next)
107         switch (p->word[0]) {
108
109         case '(':
110             l++;
111             continue;
112
113         case ')':
114             l--;
115             if (l < 0)
116                 stderror(ERR_TOOMANYRP);
117             continue;
118
119         case '>':
120             if (p->next != p2 && eq(p->next->word, STRand))
121                 p = p->next;
122             continue;
123
124         case '&':
125         case '|':
126         case ';':
127         case '\n':
128             if (l != 0)
129                 continue;
130             asyn3(p1, p);
131             asyntax(p->next, p2);
132             return;
133
134         default:
135             break;
136         }
137     if (l == 0)
138         asyn3(p1, p2);
139 }
140
141 static void
142 asyn3(p1, p2)
143     struct wordent *p1;
144     register struct wordent *p2;
145 {
146     register struct varent *ap;
147     struct wordent alout;
148     register bool redid;
149
150     if (p1 == p2)
151         return;
152     if (p1->word[0] == '(') {
153         for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
154             if (p2 == p1)
155                 return;
156         if (p2 == p1->next)
157             return;
158         asyn0(p1->next, p2);
159         return;
160     }
161     ap = adrof1(p1->word, &aliases);
162     if (ap == 0)
163         return;
164     alhistp = p1->prev;
165     alhistt = p2;
166     alvec = ap->vec;
167     redid = lex(&alout);
168     alhistp = alhistt = 0;
169     alvec = 0;
170     if (seterr) {
171         freelex(&alout);
172         stderror(ERR_OLD);
173     }
174     if (p1->word[0] && eq(p1->word, alout.next->word)) {
175         Char   *cp = alout.next->word;
176
177         alout.next->word = Strspl(STRQNULL, cp);
178         xfree((ptr_t) cp);
179     }
180     p1 = freenod(p1, redid ? p2 : p1->next);
181     if (alout.next != &alout) {
182         p1->next->prev = alout.prev->prev;
183         alout.prev->prev->next = p1->next;
184         alout.next->prev = p1;
185         p1->next = alout.next;
186         xfree((ptr_t) alout.prev->word);
187         xfree((ptr_t) (alout.prev));
188     }
189     reset();                    /* throw! */
190 }
191
192 static struct wordent *
193 freenod(p1, p2)
194     register struct wordent *p1, *p2;
195 {
196     register struct wordent *retp = p1->prev;
197
198     while (p1 != p2) {
199         xfree((ptr_t) p1->word);
200         p1 = p1->next;
201         xfree((ptr_t) (p1->prev));
202     }
203     retp->next = p2;
204     p2->prev = retp;
205     return (retp);
206 }
207
208 #define P_HERE  1
209 #define P_IN    2
210 #define P_OUT   4
211 #define P_DIAG  8
212
213 /*
214  * syntax
215  *      empty
216  *      syn0
217  */
218 struct command *
219 syntax(p1, p2, flags)
220     register struct wordent *p1, *p2;
221     int     flags;
222 {
223
224     while (p1 != p2)
225         if (any(";&\n", p1->word[0]))
226             p1 = p1->next;
227         else
228             return (syn0(p1, p2, flags));
229     return (0);
230 }
231
232 /*
233  * syn0
234  *      syn1
235  *      syn1 & syntax
236  */
237 static struct command *
238 syn0(p1, p2, flags)
239     struct wordent *p1, *p2;
240     int     flags;
241 {
242     register struct wordent *p;
243     register struct command *t, *t1;
244     int     l;
245
246     l = 0;
247     for (p = p1; p != p2; p = p->next)
248         switch (p->word[0]) {
249
250         case '(':
251             l++;
252             continue;
253
254         case ')':
255             l--;
256             if (l < 0)
257                 seterror(ERR_TOOMANYRP);
258             continue;
259
260         case '|':
261             if (p->word[1] == '|')
262                 continue;
263             /*FALLTHROUGH*/
264
265         case '>':
266             if (p->next != p2 && eq(p->next->word, STRand))
267                 p = p->next;
268             continue;
269
270         case '&':
271             if (l != 0)
272                 break;
273             if (p->word[1] == '&')
274                 continue;
275             t1 = syn1(p1, p, flags);
276             if (t1->t_dtyp == NODE_LIST ||
277                 t1->t_dtyp == NODE_AND ||
278                 t1->t_dtyp == NODE_OR) {
279                 t = (struct command *) xcalloc(1, sizeof(*t));
280                 t->t_dtyp = NODE_PAREN;
281                 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
282                 t->t_dspr = t1;
283                 t1 = t;
284             }
285             else
286                 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
287             t = (struct command *) xcalloc(1, sizeof(*t));
288             t->t_dtyp = NODE_LIST;
289             t->t_dflg = 0;
290             t->t_dcar = t1;
291             t->t_dcdr = syntax(p, p2, flags);
292             return (t);
293         default:
294             break;
295         }
296     if (l == 0)
297         return (syn1(p1, p2, flags));
298     seterror(ERR_TOOMANYLP);
299     return (0);
300 }
301
302 /*
303  * syn1
304  *      syn1a
305  *      syn1a ; syntax
306  */
307 static struct command *
308 syn1(p1, p2, flags)
309     struct wordent *p1, *p2;
310     int     flags;
311 {
312     register struct wordent *p;
313     register struct command *t;
314     int     l;
315
316     l = 0;
317     for (p = p1; p != p2; p = p->next)
318         switch (p->word[0]) {
319
320         case '(':
321             l++;
322             continue;
323
324         case ')':
325             l--;
326             continue;
327
328         case ';':
329         case '\n':
330             if (l != 0)
331                 break;
332             t = (struct command *) xcalloc(1, sizeof(*t));
333             t->t_dtyp = NODE_LIST;
334             t->t_dcar = syn1a(p1, p, flags);
335             t->t_dcdr = syntax(p->next, p2, flags);
336             if (t->t_dcdr == 0)
337                 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
338             return (t);
339
340         default:
341             break;
342         }
343     return (syn1a(p1, p2, flags));
344 }
345
346 /*
347  * syn1a
348  *      syn1b
349  *      syn1b || syn1a
350  */
351 static struct command *
352 syn1a(p1, p2, flags)
353     struct wordent *p1, *p2;
354     int     flags;
355 {
356     register struct wordent *p;
357     register struct command *t;
358     register int l = 0;
359
360     for (p = p1; p != p2; p = p->next)
361         switch (p->word[0]) {
362
363         case '(':
364             l++;
365             continue;
366
367         case ')':
368             l--;
369             continue;
370
371         case '|':
372             if (p->word[1] != '|')
373                 continue;
374             if (l == 0) {
375                 t = (struct command *) xcalloc(1, sizeof(*t));
376                 t->t_dtyp = NODE_OR;
377                 t->t_dcar = syn1b(p1, p, flags);
378                 t->t_dcdr = syn1a(p->next, p2, flags);
379                 t->t_dflg = 0;
380                 return (t);
381             }
382             continue;
383
384         default:
385             break;
386         }
387     return (syn1b(p1, p2, flags));
388 }
389
390 /*
391  * syn1b
392  *      syn2
393  *      syn2 && syn1b
394  */
395 static struct command *
396 syn1b(p1, p2, flags)
397     struct wordent *p1, *p2;
398     int     flags;
399 {
400     register struct wordent *p;
401     register struct command *t;
402     register int l = 0;
403
404     for (p = p1; p != p2; p = p->next)
405         switch (p->word[0]) {
406
407         case '(':
408             l++;
409             continue;
410
411         case ')':
412             l--;
413             continue;
414
415         case '&':
416             if (p->word[1] == '&' && l == 0) {
417                 t = (struct command *) xcalloc(1, sizeof(*t));
418                 t->t_dtyp = NODE_AND;
419                 t->t_dcar = syn2(p1, p, flags);
420                 t->t_dcdr = syn1b(p->next, p2, flags);
421                 t->t_dflg = 0;
422                 return (t);
423             }
424             continue;
425
426         default:
427             break;
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 | P_OUT;
464             pn = p->next;
465             if (pn != p2 && pn->word[0] == '&') {
466                 f |= P_DIAG;
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 | P_IN);
474             return (t);
475
476         default:
477             break;
478         }
479     return (syn3(p1, p2, flags));
480 }
481
482 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
483
484 /*
485  * syn3
486  *      ( syn0 ) [ < in  ] [ > out ]
487  *      word word* [ < in ] [ > out ]
488  *      KEYWORD ( word* ) word* [ < in ] [ > out ]
489  *
490  *      KEYWORD = (@ exit foreach if set switch test while)
491  */
492 static struct command *
493 syn3(p1, p2, flags)
494     struct wordent *p1, *p2;
495     int     flags;
496 {
497     register struct wordent *p;
498     struct wordent *lp, *rp;
499     register struct command *t;
500     register int l;
501     Char  **av;
502     int     n, c;
503     bool    specp = 0;
504
505     if (p1 != p2) {
506         p = p1;
507 again:
508         switch (srchx(p->word)) {
509
510         case TC_ELSE:
511             p = p->next;
512             if (p != p2)
513                 goto again;
514             break;
515
516         case TC_EXIT:
517         case TC_FOREACH:
518         case TC_IF:
519         case TC_LET:
520         case TC_SET:
521         case TC_SWITCH:
522         case TC_WHILE:
523             specp = 1;
524             break;
525         default:
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 & (P_OUT | P_DIAG)) {
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 & P_OUT) && (flags & P_DIAG) == 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 & P_HERE) && (t->t_dflg & F_READ))
640                 seterror(ERR_REDPAR);
641             else if ((flags & P_IN) || 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, P_HERE);
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     register struct command *t;
676 {
677     register 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     default:
703         break;
704     }
705     xfree((ptr_t) t);
706 }