Home | History | Annotate | Download | only in csh
      1 /*
      2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
      7 /*	  All Rights Reserved  	*/
      8 
      9 /*
     10  * Copyright (c) 1980 Regents of the University of California.
     11  * All rights reserved. The Berkeley Software License Agreement
     12  * specifies the terms and conditions for redistribution.
     13  */
     14 
     15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     16 
     17 #include "sh.h"
     18 #include "sh.tconst.h"
     19 
     20 /*
     21  * C shell
     22  */
     23 
     24 void	asyntax(struct wordent *, struct wordent *);
     25 void	asyn0(struct wordent *, struct wordent *);
     26 void	asyn3(struct wordent *, struct wordent *);
     27 void	chr_blkfree(char **);
     28 struct command	*syn0(struct wordent *, struct wordent *, int);
     29 struct command	*syn1(struct wordent *, struct wordent *, int);
     30 struct command	*syn1a(struct wordent *, struct wordent *, int);
     31 struct command	*syn1b(struct wordent *, struct wordent *, int);
     32 struct command	*syn2(struct wordent *, struct wordent *, int);
     33 struct command	*syn3(struct wordent *, struct wordent *, int);
     34 struct wordent	*freenod(struct wordent *, struct wordent *);
     35 
     36 /*
     37  * Perform aliasing on the word list lex
     38  * Do a (very rudimentary) parse to separate into commands.
     39  * If word 0 of a command has an alias, do it.
     40  * Repeat a maximum of 20 times.
     41  */
     42 void
     43 alias(struct wordent *lex)
     44 {
     45 	int aleft = 21;
     46 	jmp_buf osetexit;
     47 
     48 #ifdef TRACE
     49 	tprintf("TRACE- alias()\n");
     50 #endif
     51 	getexit(osetexit);
     52 	setexit();
     53 	if (haderr) {
     54 		resexit(osetexit);
     55 		reset();
     56 	}
     57 	if (--aleft == 0)
     58 		error("Alias loop");
     59 	asyntax(lex->next, lex);
     60 	resexit(osetexit);
     61 }
     62 
     63 void
     64 asyntax(struct wordent *p1, struct wordent *p2)
     65 {
     66 #ifdef TRACE
     67 	tprintf("TRACE- asyntax()\n");
     68 #endif
     69 
     70 	while (p1 != p2)
     71 		/* if (any(p1->word[0], ";&\n")) */  /* For char -> tchar */
     72 		if (p1->word[0] == ';' ||
     73 		    p1->word[0] == '&' ||
     74 		    p1->word[0] == '\n')
     75 			p1 = p1->next;
     76 		else {
     77 			asyn0(p1, p2);
     78 			return;
     79 		}
     80 }
     81 
     82 void
     83 asyn0(struct wordent *p1, struct wordent *p2)
     84 {
     85 	struct wordent *p;
     86 	int l = 0;
     87 
     88 #ifdef TRACE
     89 	tprintf("TRACE- asyn0()\n");
     90 #endif
     91 	for (p = p1; p != p2; p = p->next)
     92 		switch (p->word[0]) {
     93 
     94 		case '(':
     95 			l++;
     96 			continue;
     97 
     98 		case ')':
     99 			l--;
    100 			if (l < 0)
    101 				error("Too many )'s");
    102 			continue;
    103 
    104 		case '>':
    105 			if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/))
    106 				p = p->next;
    107 			continue;
    108 
    109 		case '&':
    110 		case '|':
    111 		case ';':
    112 		case '\n':
    113 			if (l != 0)
    114 				continue;
    115 			asyn3(p1, p);
    116 			asyntax(p->next, p2);
    117 			return;
    118 		}
    119 	if (l == 0)
    120 		asyn3(p1, p2);
    121 }
    122 
    123 void
    124 asyn3(struct wordent *p1, struct wordent *p2)
    125 {
    126 	struct varent *ap;
    127 	struct wordent alout;
    128 	bool redid;
    129 
    130 #ifdef TRACE
    131 	tprintf("TRACE- asyn3()\n");
    132 #endif
    133 	if (p1 == p2)
    134 		return;
    135 	if (p1->word[0] == '(') {
    136 		for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
    137 			if (p2 == p1)
    138 				return;
    139 		if (p2 == p1->next)
    140 			return;
    141 		asyn0(p1->next, p2);
    142 		return;
    143 	}
    144 	ap = adrof1(p1->word, &aliases);
    145 	if (ap == 0)
    146 		return;
    147 	alhistp = p1->prev;
    148 	alhistt = p2;
    149 	alvec = ap->vec;
    150 	redid = lex(&alout);
    151 	alhistp = alhistt = 0;
    152 	alvec = 0;
    153 	if (err) {
    154 		freelex(&alout);
    155 		error("%s", gettext(err));
    156 	}
    157 	if (p1->word[0] && eq(p1->word, alout.next->word)) {
    158 		tchar *cp = alout.next->word;
    159 
    160 		alout.next->word = strspl(S_TOPBIT /* "\200" */, cp);
    161 		xfree(cp);
    162 	}
    163 	p1 = freenod(p1, redid ? p2 : p1->next);
    164 	if (alout.next != &alout) {
    165 		p1->next->prev = alout.prev->prev;
    166 		alout.prev->prev->next = p1->next;
    167 		alout.next->prev = p1;
    168 		p1->next = alout.next;
    169 		xfree(alout.prev->word);
    170 		xfree(alout.prev);
    171 	}
    172 	reset();		/* throw! */
    173 }
    174 
    175 struct wordent *
    176 freenod(struct wordent *p1, struct wordent *p2)
    177 {
    178 	struct wordent *retp = p1->prev;
    179 
    180 #ifdef TRACE
    181 	tprintf("TRACE- freenod()\n");
    182 #endif
    183 	while (p1 != p2) {
    184 		xfree(p1->word);
    185 		p1 = p1->next;
    186 		xfree(p1->prev);
    187 	}
    188 	retp->next = p2;
    189 	p2->prev = retp;
    190 	return (retp);
    191 }
    192 
    193 #define	PHERE	1
    194 #define	PIN	2
    195 #define	POUT	4
    196 #define	PDIAG	8
    197 
    198 /*
    199  * syntax
    200  *	empty
    201  *	syn0
    202  */
    203 struct command *
    204 syntax(struct wordent *p1, struct wordent *p2, int flags)
    205 {
    206 #ifdef TRACE
    207 	tprintf("TRACE- syntax()\n");
    208 #endif
    209 
    210 	while (p1 != p2)
    211 		/* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */
    212 		if (p1->word[0] == ';' ||
    213 		    p1->word[0] == '&' ||
    214 		    p1->word[0] == '\n')
    215 			p1 = p1->next;
    216 		else
    217 			return (syn0(p1, p2, flags));
    218 	return (0);
    219 }
    220 
    221 /*
    222  * syn0
    223  *	syn1
    224  *	syn1 & syntax
    225  */
    226 struct command *
    227 syn0(struct wordent *p1, struct wordent *p2, int flags)
    228 {
    229 	struct wordent *p;
    230 	struct command *t, *t1;
    231 	int l;
    232 
    233 #ifdef TRACE
    234 	tprintf("TRACE- syn0()\n");
    235 #endif
    236 	l = 0;
    237 	for (p = p1; p != p2; p = p->next)
    238 		switch (p->word[0]) {
    239 
    240 		case '(':
    241 			l++;
    242 			continue;
    243 
    244 		case ')':
    245 			l--;
    246 			if (l < 0)
    247 				seterr("Too many )'s");
    248 			continue;
    249 
    250 		case '|':
    251 			if (p->word[1] == '|')
    252 				continue;
    253 			/* fall into ... */
    254 
    255 		case '>':
    256 			if (p->next != p2 && eq(p->next->word, S_AND /* "&" */))
    257 				p = p->next;
    258 			continue;
    259 
    260 		case '&':
    261 			if (l != 0)
    262 				break;
    263 			if (p->word[1] == '&')
    264 				continue;
    265 			t1 = syn1(p1, p, flags);
    266 			if (t1->t_dtyp == TLST ||
    267 			    t1->t_dtyp == TAND ||
    268 			    t1->t_dtyp == TOR) {
    269 				t = (struct command *)xcalloc(1, sizeof (*t));
    270 				t->t_dtyp = TPAR;
    271 				t->t_dflg = FAND|FINT;
    272 				t->t_dspr = t1;
    273 				t1 = t;
    274 			} else
    275 				t1->t_dflg |= FAND|FINT;
    276 			t = (struct command *)xcalloc(1, sizeof (*t));
    277 			t->t_dtyp = TLST;
    278 			t->t_dflg = 0;
    279 			t->t_dcar = t1;
    280 			t->t_dcdr = syntax(p, p2, flags);
    281 			return (t);
    282 		}
    283 	if (l == 0)
    284 		return (syn1(p1, p2, flags));
    285 	seterr("Too many ('s");
    286 	return (0);
    287 }
    288 
    289 /*
    290  * syn1
    291  *	syn1a
    292  *	syn1a ; syntax
    293  */
    294 struct command *
    295 syn1(struct wordent *p1, struct wordent *p2, int flags)
    296 {
    297 	struct wordent *p;
    298 	struct command *t;
    299 	int l;
    300 
    301 #ifdef TRACE
    302 	tprintf("TRACE- syn1()\n");
    303 #endif
    304 	l = 0;
    305 	for (p = p1; p != p2; p = p->next)
    306 		switch (p->word[0]) {
    307 
    308 		case '(':
    309 			l++;
    310 			continue;
    311 
    312 		case ')':
    313 			l--;
    314 			continue;
    315 
    316 		case ';':
    317 		case '\n':
    318 			if (l != 0)
    319 				break;
    320 			t = (struct command *)xcalloc(1, sizeof (*t));
    321 			t->t_dtyp = TLST;
    322 			t->t_dcar = syn1a(p1, p, flags);
    323 			t->t_dcdr = syntax(p->next, p2, flags);
    324 			if (t->t_dcdr == 0)
    325 				t->t_dcdr = t->t_dcar, t->t_dcar = 0;
    326 			return (t);
    327 		}
    328 	return (syn1a(p1, p2, flags));
    329 }
    330 
    331 /*
    332  * syn1a
    333  *	syn1b
    334  *	syn1b || syn1a
    335  */
    336 struct command *
    337 syn1a(struct wordent *p1, struct wordent *p2, int flags)
    338 {
    339 	struct wordent *p;
    340 	struct command *t;
    341 	int l = 0;
    342 
    343 #ifdef TRACE
    344 	tprintf("TRACE- syn1a()\n");
    345 #endif
    346 	for (p = p1; p != p2; p = p->next)
    347 		switch (p->word[0]) {
    348 
    349 		case '(':
    350 			l++;
    351 			continue;
    352 
    353 		case ')':
    354 			l--;
    355 			continue;
    356 
    357 		case '|':
    358 			if (p->word[1] != '|')
    359 				continue;
    360 			if (l == 0) {
    361 				t = (struct command *)xcalloc(1, sizeof (*t));
    362 				t->t_dtyp = TOR;
    363 				t->t_dcar = syn1b(p1, p, flags);
    364 				t->t_dcdr = syn1a(p->next, p2, flags);
    365 				t->t_dflg = 0;
    366 				return (t);
    367 			}
    368 			continue;
    369 		}
    370 	return (syn1b(p1, p2, flags));
    371 }
    372 
    373 /*
    374  * syn1b
    375  *	syn2
    376  *	syn2 && syn1b
    377  */
    378 struct command *
    379 syn1b(struct wordent *p1, struct wordent *p2, int flags)
    380 {
    381 	struct wordent *p;
    382 	struct command *t;
    383 	int l = 0;
    384 
    385 #ifdef TRACE
    386 	tprintf("TRACE- syn1b()\n");
    387 #endif
    388 	l = 0;
    389 	for (p = p1; p != p2; p = p->next)
    390 		switch (p->word[0]) {
    391 
    392 		case '(':
    393 			l++;
    394 			continue;
    395 
    396 		case ')':
    397 			l--;
    398 			continue;
    399 
    400 		case '&':
    401 			if (p->word[1] == '&' && l == 0) {
    402 				t = (struct command *)xcalloc(1, sizeof (*t));
    403 				t->t_dtyp = TAND;
    404 				t->t_dcar = syn2(p1, p, flags);
    405 				t->t_dcdr = syn1b(p->next, p2, flags);
    406 				t->t_dflg = 0;
    407 				return (t);
    408 			}
    409 			continue;
    410 		}
    411 	return (syn2(p1, p2, flags));
    412 }
    413 
    414 /*
    415  * syn2
    416  *	syn3
    417  *	syn3 | syn2
    418  *	syn3 |& syn2
    419  */
    420 struct command *
    421 syn2(struct wordent *p1, struct wordent *p2, int flags)
    422 {
    423 	struct wordent *p, *pn;
    424 	struct command *t;
    425 	int l = 0;
    426 	int f;
    427 
    428 #ifdef TRACE
    429 	tprintf("TRACE- syn2()\n");
    430 #endif
    431 	for (p = p1; p != p2; p = p->next)
    432 		switch (p->word[0]) {
    433 
    434 		case '(':
    435 			l++;
    436 			continue;
    437 
    438 		case ')':
    439 			l--;
    440 			continue;
    441 
    442 		case '|':
    443 			if (l != 0)
    444 				continue;
    445 			t = (struct command *)xcalloc(1, sizeof (*t));
    446 			f = flags | POUT;
    447 			pn = p->next;
    448 			if (pn != p2 && pn->word[0] == '&') {
    449 				f |= PDIAG;
    450 				t->t_dflg |= FDIAG;
    451 			}
    452 			t->t_dtyp = TFIL;
    453 			t->t_dcar = syn3(p1, p, f);
    454 			if (pn != p2 && pn->word[0] == '&')
    455 				p = pn;
    456 			t->t_dcdr = syn2(p->next, p2, flags | PIN);
    457 			return (t);
    458 		}
    459 	return (syn3(p1, p2, flags));
    460 }
    461 
    462 tchar RELPAR[] = {'<', '>', '(', ')', 0};	/* "<>()" */
    463 
    464 /*
    465  * syn3
    466  *	( syn0 ) [ < in  ] [ > out ]
    467  *	word word* [ < in ] [ > out ]
    468  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
    469  *
    470  *	KEYWORD = (@ exit foreach if set switch test while)
    471  */
    472 struct command *
    473 syn3(struct wordent *p1, struct wordent *p2, int flags)
    474 {
    475 	struct wordent *p;
    476 	struct wordent *lp, *rp;
    477 	struct command *t;
    478 	int l;
    479 	tchar **av;
    480 	int n, c;
    481 	bool specp = 0;
    482 
    483 #ifdef TRACE
    484 	tprintf("TRACE- syn3()\n");
    485 #endif
    486 	if (p1 != p2) {
    487 		p = p1;
    488 again:
    489 		switch (srchx(p->word)) {
    490 
    491 		case ZELSE:
    492 			p = p->next;
    493 			if (p != p2)
    494 				goto again;
    495 			break;
    496 
    497 		case ZEXIT:
    498 		case ZFOREACH:
    499 		case ZIF:
    500 		case ZLET:
    501 		case ZSET:
    502 		case ZSWITCH:
    503 		case ZWHILE:
    504 			specp = 1;
    505 			break;
    506 		}
    507 	}
    508 	n = 0;
    509 	l = 0;
    510 	for (p = p1; p != p2; p = p->next)
    511 		switch (p->word[0]) {
    512 
    513 		case '(':
    514 			if (specp)
    515 				n++;
    516 			l++;
    517 			continue;
    518 
    519 		case ')':
    520 			if (specp)
    521 				n++;
    522 			l--;
    523 			continue;
    524 
    525 		case '>':
    526 		case '<':
    527 			if (l != 0) {
    528 				if (specp)
    529 					n++;
    530 				continue;
    531 			}
    532 			if (p->next == p2)
    533 				continue;
    534 			if (any(p->next->word[0], RELPAR))
    535 				continue;
    536 			n--;
    537 			continue;
    538 
    539 		default:
    540 			if (!specp && l != 0)
    541 				continue;
    542 			n++;
    543 			continue;
    544 		}
    545 	if (n < 0)
    546 		n = 0;
    547 	t = (struct command *)xcalloc(1, sizeof (*t));
    548 	av =  (tchar **)xcalloc((unsigned)(n + 1), sizeof (tchar **));
    549 	t->t_dcom = av;
    550 	n = 0;
    551 	if (p2->word[0] == ')')
    552 		t->t_dflg = FPAR;
    553 	lp = 0;
    554 	rp = 0;
    555 	l = 0;
    556 	for (p = p1; p != p2; p = p->next) {
    557 		c = p->word[0];
    558 		switch (c) {
    559 
    560 		case '(':
    561 			if (l == 0) {
    562 				if (lp != 0 && !specp)
    563 					seterr("Badly placed (");
    564 				lp = p->next;
    565 			}
    566 			l++;
    567 			goto savep;
    568 
    569 		case ')':
    570 			l--;
    571 			if (l == 0)
    572 				rp = p;
    573 			goto savep;
    574 
    575 		case '>':
    576 			if (l != 0)
    577 				goto savep;
    578 			if (p->word[1] == '>')
    579 				t->t_dflg |= FCAT;
    580 			if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) {
    581 				t->t_dflg |= FDIAG, p = p->next;
    582 				if (flags & (POUT|PDIAG))
    583 					goto badout;
    584 			}
    585 			if (p->next != p2 && eq(p->next->word, S_EXAS /* "!" */))
    586 				t->t_dflg |= FANY, p = p->next;
    587 			if (p->next == p2) {
    588 missfile:
    589 				seterr("Missing name for redirect");
    590 				continue;
    591 			}
    592 			p = p->next;
    593 			if (any(p->word[0], RELPAR))
    594 				goto missfile;
    595 			if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
    596 badout:
    597 				seterr("Ambiguous output redirect");
    598 			else
    599 				t->t_drit = savestr(p->word);
    600 			continue;
    601 
    602 		case '<':
    603 			if (l != 0)
    604 				goto savep;
    605 			if (p->word[1] == '<')
    606 				t->t_dflg |= FHERE;
    607 			if (p->next == p2)
    608 				goto missfile;
    609 			p = p->next;
    610 			if (any(p->word[0], RELPAR))
    611 				goto missfile;
    612 			if ((flags & PHERE) && (t->t_dflg & FHERE))
    613 				seterr("Can't << within ()'s");
    614 			else if ((flags & PIN) || t->t_dlef)
    615 				seterr("Ambiguous input redirect");
    616 			else
    617 				t->t_dlef = savestr(p->word);
    618 			continue;
    619 
    620 savep:
    621 			if (!specp)
    622 				continue;
    623 		default:
    624 			if (l != 0 && !specp)
    625 				continue;
    626 			if (err == 0)
    627 				av[n] = savestr(p->word);
    628 			n++;
    629 			continue;
    630 		}
    631 	}
    632 	if (lp != 0 && !specp) {
    633 		if (n != 0)
    634 			seterr("Badly placed ()'s");
    635 		t->t_dtyp = TPAR;
    636 		t->t_dspr = syn0(lp, rp, PHERE);
    637 	} else {
    638 		if (n == 0)
    639 			seterr("Invalid null command");
    640 		t->t_dtyp = TCOM;
    641 	}
    642 	return (t);
    643 }
    644 
    645 void
    646 freesyn(struct command *t)
    647 {
    648 #ifdef TRACE
    649 	tprintf("TRACE- freesyn()\n");
    650 #endif
    651 	if (t == 0)
    652 		return;
    653 	switch (t->t_dtyp) {
    654 
    655 	case TCOM:
    656 		blkfree(t->t_dcom);
    657 		if (t->cfname)
    658 			xfree(t->cfname);
    659 		if (t->cargs)
    660 			chr_blkfree(t->cargs);
    661 		goto lr;
    662 
    663 	case TPAR:
    664 		freesyn(t->t_dspr);
    665 		/* fall into ... */
    666 
    667 lr:
    668 		xfree(t->t_dlef);
    669 		xfree(t->t_drit);
    670 		break;
    671 
    672 	case TAND:
    673 	case TOR:
    674 	case TFIL:
    675 	case TLST:
    676 		freesyn(t->t_dcar), freesyn(t->t_dcdr);
    677 		break;
    678 	}
    679 	xfree(t);
    680 }
    681 
    682 
    683 void
    684 chr_blkfree(char **vec)
    685 {
    686 	char **av;
    687 
    688 	for (av = vec; *av; av++)
    689 		xfree(*av);
    690 	xfree(vec);
    691 }
    692