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