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