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