source: trunk/third/tcsh/sh.parse.c @ 12039

Revision 12039, 13.8 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/sh.parse.c,v 1.1.1.2 1998-10-03 21:10:05 danw 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
39RCSID("$Id: sh.parse.c,v 1.1.1.2 1998-10-03 21:10:05 danw Exp $")
40
41/*
42 * C shell
43 */
44static  void             asyntax __P((struct wordent *, struct wordent *));
45static  void             asyn0   __P((struct wordent *, struct wordent *));
46static  void             asyn3   __P((struct wordent *, struct wordent *));
47static  struct wordent  *freenod __P((struct wordent *, struct wordent *));
48static  struct command  *syn0    __P((struct wordent *, struct wordent *, int));
49static  struct command  *syn1    __P((struct wordent *, struct wordent *, int));
50static  struct command  *syn1a   __P((struct wordent *, struct wordent *, int));
51static  struct command  *syn1b   __P((struct wordent *, struct wordent *, int));
52static  struct command  *syn2    __P((struct wordent *, struct wordent *, int));
53static  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 */
63static int aleft;
64extern int hleft;
65void
66alias(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
85static void
86asyntax(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
98static void
99asyn0(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
141static void
142asyn3(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
192static struct wordent *
193freenod(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 */
218struct command *
219syntax(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 */
237static struct command *
238syn0(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 */
307static struct command *
308syn1(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 */
351static struct command *
352syn1a(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 */
395static struct command *
396syn1b(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 */
438static struct command *
439syn2(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
482static 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 */
492static struct command *
493syn3(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;
507again:
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
673void
674freesyn(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}
Note: See TracBrowser for help on using the repository browser.