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