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