Home | History | Annotate | Line # | Download | only in csh
parse.c revision 1.7
      1 /*	$NetBSD: parse.c,v 1.7 1997/01/13 17:53:27 tls Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1980, 1991, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #ifndef lint
     37 #if 0
     38 static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 5/31/93";
     39 #else
     40 static char rcsid[] = "$NetBSD: parse.c,v 1.7 1997/01/13 17:53:27 tls Exp $";
     41 #endif
     42 #endif /* not lint */
     43 
     44 #include <sys/types.h>
     45 #include <stdlib.h>
     46 #include <string.h>
     47 #if __STDC__
     48 # include <stdarg.h>
     49 #else
     50 # include <varargs.h>
     51 #endif
     52 
     53 #include "csh.h"
     54 #include "extern.h"
     55 
     56 static void	 asyntax __P((struct wordent *, struct wordent *));
     57 static void	 asyn0 __P((struct wordent *, struct wordent *));
     58 static void	 asyn3 __P((struct wordent *, struct wordent *));
     59 static struct wordent
     60 		*freenod __P((struct wordent *, struct wordent *));
     61 static struct command
     62 		*syn0 __P((struct wordent *, struct wordent *, int));
     63 static struct command
     64 		*syn1 __P((struct wordent *, struct wordent *, int));
     65 static struct command
     66 		*syn1a __P((struct wordent *, struct wordent *, int));
     67 static struct command
     68 		*syn1b __P((struct wordent *, struct wordent *, int));
     69 static struct command
     70 		*syn2 __P((struct wordent *, struct wordent *, int));
     71 static struct command
     72 		*syn3 __P((struct wordent *, struct wordent *, int));
     73 
     74 #define ALEFT	21		/* max of 20 alias expansions	 */
     75 #define HLEFT	11		/* max of 10 history expansions	 */
     76 /*
     77  * Perform aliasing on the word list lex
     78  * Do a (very rudimentary) parse to separate into commands.
     79  * If word 0 of a command has an alias, do it.
     80  * Repeat a maximum of 20 times.
     81  */
     82 static int aleft;
     83 extern int hleft;
     84 void
     85 alias(lex)
     86     struct wordent *lex;
     87 {
     88     jmp_buf osetexit;
     89 
     90     aleft = ALEFT;
     91     hleft = HLEFT;
     92     getexit(osetexit);
     93     (void) setexit();
     94     if (haderr) {
     95 	resexit(osetexit);
     96 	reset();
     97     }
     98     if (--aleft == 0)
     99 	stderror(ERR_ALIASLOOP);
    100     asyntax(lex->next, lex);
    101     resexit(osetexit);
    102 }
    103 
    104 static void
    105 asyntax(p1, p2)
    106     struct wordent *p1, *p2;
    107 {
    108     while (p1 != p2)
    109 	if (any(";&\n", p1->word[0]))
    110 	    p1 = p1->next;
    111 	else {
    112 	    asyn0(p1, p2);
    113 	    return;
    114 	}
    115 }
    116 
    117 static void
    118 asyn0(p1, p2)
    119     struct wordent *p1;
    120     struct wordent *p2;
    121 {
    122     struct wordent *p;
    123     int l = 0;
    124 
    125     for (p = p1; p != p2; p = p->next)
    126 	switch (p->word[0]) {
    127 
    128 	case '(':
    129 	    l++;
    130 	    continue;
    131 
    132 	case ')':
    133 	    l--;
    134 	    if (l < 0)
    135 		stderror(ERR_TOOMANYRP);
    136 	    continue;
    137 
    138 	case '>':
    139 	    if (p->next != p2 && eq(p->next->word, STRand))
    140 		p = p->next;
    141 	    continue;
    142 
    143 	case '&':
    144 	case '|':
    145 	case ';':
    146 	case '\n':
    147 	    if (l != 0)
    148 		continue;
    149 	    asyn3(p1, p);
    150 	    asyntax(p->next, p2);
    151 	    return;
    152 	}
    153     if (l == 0)
    154 	asyn3(p1, p2);
    155 }
    156 
    157 static void
    158 asyn3(p1, p2)
    159     struct wordent *p1;
    160     struct wordent *p2;
    161 {
    162     struct varent *ap;
    163     struct wordent alout;
    164     bool redid;
    165 
    166     if (p1 == p2)
    167 	return;
    168     if (p1->word[0] == '(') {
    169 	for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
    170 	    if (p2 == p1)
    171 		return;
    172 	if (p2 == p1->next)
    173 	    return;
    174 	asyn0(p1->next, p2);
    175 	return;
    176     }
    177     ap = adrof1(p1->word, &aliases);
    178     if (ap == 0)
    179 	return;
    180     alhistp = p1->prev;
    181     alhistt = p2;
    182     alvec = ap->vec;
    183     redid = lex(&alout);
    184     alhistp = alhistt = 0;
    185     alvec = 0;
    186     if (seterr) {
    187 	freelex(&alout);
    188 	stderror(ERR_OLD);
    189     }
    190     if (p1->word[0] && eq(p1->word, alout.next->word)) {
    191 	Char   *cp = alout.next->word;
    192 
    193 	alout.next->word = Strspl(STRQNULL, cp);
    194 	xfree((ptr_t) cp);
    195     }
    196     p1 = freenod(p1, redid ? p2 : p1->next);
    197     if (alout.next != &alout) {
    198 	p1->next->prev = alout.prev->prev;
    199 	alout.prev->prev->next = p1->next;
    200 	alout.next->prev = p1;
    201 	p1->next = alout.next;
    202 	xfree((ptr_t) alout.prev->word);
    203 	xfree((ptr_t) (alout.prev));
    204     }
    205     reset();			/* throw! */
    206 }
    207 
    208 static struct wordent *
    209 freenod(p1, p2)
    210     struct wordent *p1, *p2;
    211 {
    212     struct wordent *retp = p1->prev;
    213 
    214     while (p1 != p2) {
    215 	xfree((ptr_t) p1->word);
    216 	p1 = p1->next;
    217 	xfree((ptr_t) (p1->prev));
    218     }
    219     retp->next = p2;
    220     p2->prev = retp;
    221     return (retp);
    222 }
    223 
    224 #define	PHERE	1
    225 #define	PIN	2
    226 #define	POUT	4
    227 #define	PERR	8
    228 
    229 /*
    230  * syntax
    231  *	empty
    232  *	syn0
    233  */
    234 struct command *
    235 syntax(p1, p2, flags)
    236     struct wordent *p1, *p2;
    237     int     flags;
    238 {
    239 
    240     while (p1 != p2)
    241 	if (any(";&\n", p1->word[0]))
    242 	    p1 = p1->next;
    243 	else
    244 	    return (syn0(p1, p2, flags));
    245     return (0);
    246 }
    247 
    248 /*
    249  * syn0
    250  *	syn1
    251  *	syn1 & syntax
    252  */
    253 static struct command *
    254 syn0(p1, p2, flags)
    255     struct wordent *p1, *p2;
    256     int     flags;
    257 {
    258     struct wordent *p;
    259     struct command *t, *t1;
    260     int     l;
    261 
    262     l = 0;
    263     for (p = p1; p != p2; p = p->next)
    264 	switch (p->word[0]) {
    265 
    266 	case '(':
    267 	    l++;
    268 	    continue;
    269 
    270 	case ')':
    271 	    l--;
    272 	    if (l < 0)
    273 		seterror(ERR_TOOMANYRP);
    274 	    continue;
    275 
    276 	case '|':
    277 	    if (p->word[1] == '|')
    278 		continue;
    279 	    /* fall into ... */
    280 
    281 	case '>':
    282 	    if (p->next != p2 && eq(p->next->word, STRand))
    283 		p = p->next;
    284 	    continue;
    285 
    286 	case '&':
    287 	    if (l != 0)
    288 		break;
    289 	    if (p->word[1] == '&')
    290 		continue;
    291 	    t1 = syn1(p1, p, flags);
    292 	    if (t1->t_dtyp == NODE_LIST ||
    293 		t1->t_dtyp == NODE_AND ||
    294 		t1->t_dtyp == NODE_OR) {
    295 		t = (struct command *) xcalloc(1, sizeof(*t));
    296 		t->t_dtyp = NODE_PAREN;
    297 		t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
    298 		t->t_dspr = t1;
    299 		t1 = t;
    300 	    }
    301 	    else
    302 		t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
    303 	    t = (struct command *) xcalloc(1, sizeof(*t));
    304 	    t->t_dtyp = NODE_LIST;
    305 	    t->t_dflg = 0;
    306 	    t->t_dcar = t1;
    307 	    t->t_dcdr = syntax(p, p2, flags);
    308 	    return (t);
    309 	}
    310     if (l == 0)
    311 	return (syn1(p1, p2, flags));
    312     seterror(ERR_TOOMANYLP);
    313     return (0);
    314 }
    315 
    316 /*
    317  * syn1
    318  *	syn1a
    319  *	syn1a ; syntax
    320  */
    321 static struct command *
    322 syn1(p1, p2, flags)
    323     struct wordent *p1, *p2;
    324     int     flags;
    325 {
    326     struct wordent *p;
    327     struct command *t;
    328     int     l;
    329 
    330     l = 0;
    331     for (p = p1; p != p2; p = p->next)
    332 	switch (p->word[0]) {
    333 
    334 	case '(':
    335 	    l++;
    336 	    continue;
    337 
    338 	case ')':
    339 	    l--;
    340 	    continue;
    341 
    342 	case ';':
    343 	case '\n':
    344 	    if (l != 0)
    345 		break;
    346 	    t = (struct command *) xcalloc(1, sizeof(*t));
    347 	    t->t_dtyp = NODE_LIST;
    348 	    t->t_dcar = syn1a(p1, p, flags);
    349 	    t->t_dcdr = syntax(p->next, p2, flags);
    350 	    if (t->t_dcdr == 0)
    351 		t->t_dcdr = t->t_dcar, t->t_dcar = 0;
    352 	    return (t);
    353 	}
    354     return (syn1a(p1, p2, flags));
    355 }
    356 
    357 /*
    358  * syn1a
    359  *	syn1b
    360  *	syn1b || syn1a
    361  */
    362 static struct command *
    363 syn1a(p1, p2, flags)
    364     struct wordent *p1, *p2;
    365     int     flags;
    366 {
    367     struct wordent *p;
    368     struct command *t;
    369     int l = 0;
    370 
    371     for (p = p1; p != p2; p = p->next)
    372 	switch (p->word[0]) {
    373 
    374 	case '(':
    375 	    l++;
    376 	    continue;
    377 
    378 	case ')':
    379 	    l--;
    380 	    continue;
    381 
    382 	case '|':
    383 	    if (p->word[1] != '|')
    384 		continue;
    385 	    if (l == 0) {
    386 		t = (struct command *) xcalloc(1, sizeof(*t));
    387 		t->t_dtyp = NODE_OR;
    388 		t->t_dcar = syn1b(p1, p, flags);
    389 		t->t_dcdr = syn1a(p->next, p2, flags);
    390 		t->t_dflg = 0;
    391 		return (t);
    392 	    }
    393 	    continue;
    394 	}
    395     return (syn1b(p1, p2, flags));
    396 }
    397 
    398 /*
    399  * syn1b
    400  *	syn2
    401  *	syn2 && syn1b
    402  */
    403 static struct command *
    404 syn1b(p1, p2, flags)
    405     struct wordent *p1, *p2;
    406     int     flags;
    407 {
    408     struct wordent *p;
    409     struct command *t;
    410     int l = 0;
    411 
    412     for (p = p1; p != p2; p = p->next)
    413 	switch (p->word[0]) {
    414 
    415 	case '(':
    416 	    l++;
    417 	    continue;
    418 
    419 	case ')':
    420 	    l--;
    421 	    continue;
    422 
    423 	case '&':
    424 	    if (p->word[1] == '&' && l == 0) {
    425 		t = (struct command *) xcalloc(1, sizeof(*t));
    426 		t->t_dtyp = NODE_AND;
    427 		t->t_dcar = syn2(p1, p, flags);
    428 		t->t_dcdr = syn1b(p->next, p2, flags);
    429 		t->t_dflg = 0;
    430 		return (t);
    431 	    }
    432 	    continue;
    433 	}
    434     return (syn2(p1, p2, flags));
    435 }
    436 
    437 /*
    438  * syn2
    439  *	syn3
    440  *	syn3 | syn2
    441  *	syn3 |& syn2
    442  */
    443 static struct command *
    444 syn2(p1, p2, flags)
    445     struct wordent *p1, *p2;
    446     int     flags;
    447 {
    448     struct wordent *p, *pn;
    449     struct command *t;
    450     int l = 0;
    451     int     f;
    452 
    453     for (p = p1; p != p2; p = p->next)
    454 	switch (p->word[0]) {
    455 
    456 	case '(':
    457 	    l++;
    458 	    continue;
    459 
    460 	case ')':
    461 	    l--;
    462 	    continue;
    463 
    464 	case '|':
    465 	    if (l != 0)
    466 		continue;
    467 	    t = (struct command *) xcalloc(1, sizeof(*t));
    468 	    f = flags | POUT;
    469 	    pn = p->next;
    470 	    if (pn != p2 && pn->word[0] == '&') {
    471 		f |= PERR;
    472 		t->t_dflg |= F_STDERR;
    473 	    }
    474 	    t->t_dtyp = NODE_PIPE;
    475 	    t->t_dcar = syn3(p1, p, f);
    476 	    if (pn != p2 && pn->word[0] == '&')
    477 		p = pn;
    478 	    t->t_dcdr = syn2(p->next, p2, flags | PIN);
    479 	    return (t);
    480 	}
    481     return (syn3(p1, p2, flags));
    482 }
    483 
    484 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
    485 
    486 /*
    487  * syn3
    488  *	( syn0 ) [ < in  ] [ > out ]
    489  *	word word* [ < in ] [ > out ]
    490  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
    491  *
    492  *	KEYWORD = (@ exit foreach if set switch test while)
    493  */
    494 static struct command *
    495 syn3(p1, p2, flags)
    496     struct wordent *p1, *p2;
    497     int     flags;
    498 {
    499     struct wordent *p;
    500     struct wordent *lp, *rp;
    501     struct command *t;
    502     int l;
    503     Char  **av;
    504     int     n, c;
    505     bool    specp = 0;
    506 
    507     if (p1 != p2) {
    508 	p = p1;
    509 again:
    510 	switch (srchx(p->word)) {
    511 
    512 	case T_ELSE:
    513 	    p = p->next;
    514 	    if (p != p2)
    515 		goto again;
    516 	    break;
    517 
    518 	case T_EXIT:
    519 	case T_FOREACH:
    520 	case T_IF:
    521 	case T_LET:
    522 	case T_SET:
    523 	case T_SWITCH:
    524 	case T_WHILE:
    525 	    specp = 1;
    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 & (POUT | PERR)) {
    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 & POUT) && ((flags & PERR) == 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 & PHERE) && (t->t_dflg & F_READ))
    640 		seterror(ERR_REDPAR);
    641 	    else if ((flags & PIN) || 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, PHERE);
    664     }
    665     else {
    666 	if (n == 0)
    667 	    seterror(ERR_NULLCOM);
    668 	t->t_dtyp = NODE_COMMAND;
    669     }
    670     return (t);
    671 }
    672 
    673 void
    674 freesyn(t)
    675     struct command *t;
    676 {
    677     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     }
    703     xfree((ptr_t) t);
    704 }
    705