Home | History | Annotate | Download | only in sh
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  * UNIX shell
     32  */
     33 
     34 #include	"defs.h"
     35 #include	"sym.h"
     36 
     37 static struct ionod *	inout();
     38 static void	chkword(void);
     39 static void	chksym(int);
     40 static struct trenod *	term();
     41 static struct trenod *	makelist();
     42 static struct trenod *	list();
     43 static struct regnod *	syncase();
     44 static struct trenod *	item();
     45 static int	skipnl();
     46 static void	prsym(int);
     47 static void	synbad(void);
     48 
     49 
     50 /* ======== storage allocation for functions ======== */
     51 
     52 unsigned char *
     53 getstor(asize)
     54 	int asize;
     55 {
     56 	if (fndef)
     57 		return((unsigned char *)alloc(asize));
     58 	else
     59 		return(getstak(asize));
     60 }
     61 
     62 
     63 /* ========	command line decoding	========*/
     64 
     65 
     66 
     67 
     68 struct trenod *
     69 makefork(flgs, i)
     70 	int	flgs;
     71 	struct trenod *i;
     72 {
     73 	struct forknod *t;
     74 
     75 	t = (struct forknod *)getstor(sizeof(struct forknod));
     76 	t->forktyp = flgs|TFORK;
     77 	t->forktre = i;
     78 	t->forkio = 0;
     79 	return((struct trenod *)t);
     80 }
     81 
     82 static struct trenod *
     83 makelist(type, i, r)
     84 	int	type;
     85 	struct trenod *i, *r;
     86 {
     87 	struct lstnod *t;
     88 
     89 	if (i == 0 || r == 0)
     90 		synbad();
     91 	else
     92 	{
     93 		t = (struct lstnod *)getstor(sizeof(struct lstnod));
     94 		t->lsttyp = type;
     95 		t->lstlef = i;
     96 		t->lstrit = r;
     97 	}
     98 	return((struct trenod *)t);
     99 }
    100 
    101 /*
    102  * cmd
    103  *	empty
    104  *	list
    105  *	list & [ cmd ]
    106  *	list [ ; cmd ]
    107  */
    108 struct trenod *
    109 cmd(sym, flg)
    110 	int	sym;
    111 	int		flg;
    112 {
    113 	struct trenod *i, *e;
    114 	i = list(flg);
    115 	if (wdval == NL)
    116 	{
    117 		if (flg & NLFLG)
    118 		{
    119 			wdval = ';';
    120 			chkpr();
    121 		}
    122 	}
    123 	else if (i == 0 && (flg & MTFLG) == 0)
    124 		synbad();
    125 
    126 	switch (wdval)
    127 	{
    128 	case '&':
    129 		if (i)
    130 			i = makefork(FAMP, i);
    131 		else
    132 			synbad();
    133 
    134 	case ';':
    135 		if (e = cmd(sym, flg | MTFLG))
    136 			i = makelist(TLST, i, e);
    137 		else if (i == 0)
    138 			synbad();
    139 		break;
    140 
    141 	case EOFSYM:
    142 		if (sym == NL)
    143 			break;
    144 
    145 	default:
    146 		if (sym)
    147 			chksym(sym);
    148 	}
    149 	return(i);
    150 }
    151 
    152 /*
    153  * list
    154  *	term
    155  *	list && term
    156  *	list || term
    157  */
    158 static struct trenod *
    159 list(flg)
    160 {
    161 	struct trenod *r;
    162 	int		b;
    163 	r = term(flg);
    164 	while (r && ((b = (wdval == ANDFSYM)) || wdval == ORFSYM))
    165 		r = makelist((b ? TAND : TORF), r, term(NLFLG));
    166 	return(r);
    167 }
    168 
    169 /*
    170  * term
    171  *	item
    172  *	item |^ term
    173  */
    174 static struct trenod *
    175 term(flg)
    176 {
    177 	struct trenod *t;
    178 
    179 	reserv++;
    180 	if (flg & NLFLG)
    181 		skipnl();
    182 	else
    183 		word();
    184 	if ((t = item(TRUE)) && (wdval == '^' || wdval == '|'))
    185 	{
    186 		struct trenod	*left;
    187 		struct trenod	*right;
    188 
    189 		left = makefork(FPOU, t);
    190 		right = makefork(FPIN, term(NLFLG));
    191 		return(makefork(0, makelist(TFIL, left, right)));
    192 	}
    193 	else
    194 		return(t);
    195 }
    196 
    197 
    198 static struct regnod *
    199 syncase(esym)
    200 int	esym;
    201 {
    202 	skipnl();
    203 	if (wdval == esym)
    204 		return(0);
    205 	else
    206 	{
    207 		struct regnod *r =
    208 		    (struct regnod *)getstor(sizeof (struct regnod));
    209 		struct argnod *argp;
    210 
    211 		r->regptr = 0;
    212 		for (;;)
    213 		{
    214 			if (fndef)
    215 			{
    216 				argp= wdarg;
    217 				wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
    218 				movstr(argp->argval, wdarg->argval);
    219 			}
    220 
    221 			wdarg->argnxt = r->regptr;
    222 			r->regptr = wdarg;
    223 
    224 			/* 'in' is not a reserved word in this case */
    225 			if (wdval == INSYM){
    226 				wdval = 0;
    227 			}
    228 			if (wdval || (word() != ')' && wdval != '|'))
    229 				synbad();
    230 			if (wdval == '|')
    231 				word();
    232 			else
    233 				break;
    234 		}
    235 		r->regcom = cmd(0, NLFLG | MTFLG);
    236 		if (wdval == ECSYM)
    237 			r->regnxt = syncase(esym);
    238 		else
    239 		{
    240 			chksym(esym);
    241 			r->regnxt = 0;
    242 		}
    243 		return(r);
    244 	}
    245 }
    246 
    247 /*
    248  * item
    249  *
    250  *	( cmd ) [ < in  ] [ > out ]
    251  *	word word* [ < in ] [ > out ]
    252  *	if ... then ... else ... fi
    253  *	for ... while ... do ... done
    254  *	case ... in ... esac
    255  *	begin ... end
    256  */
    257 static struct trenod *
    258 item(flag)
    259 	BOOL	flag;
    260 {
    261 	struct trenod *r;
    262 	struct ionod *io;
    263 
    264 	if (flag)
    265 		io = inout((struct ionod *)0);
    266 	else
    267 		io = 0;
    268 	switch (wdval)
    269 	{
    270 	case CASYM:
    271 		{
    272 			struct swnod *t;
    273 
    274 			t = (struct swnod *)getstor(sizeof(struct swnod));
    275 			r = (struct trenod *)t;
    276 
    277 			chkword();
    278 			if (fndef)
    279 				t->swarg = make(wdarg->argval);
    280 			else
    281 				t->swarg = wdarg->argval;
    282 			skipnl();
    283 			chksym(INSYM | BRSYM);
    284 			t->swlst = syncase(wdval == INSYM ? ESSYM : KTSYM);
    285 			t->swtyp = TSW;
    286 			break;
    287 		}
    288 
    289 	case IFSYM:
    290 		{
    291 			int	w;
    292 			struct ifnod *t;
    293 
    294 			t = (struct ifnod *)getstor(sizeof(struct ifnod));
    295 			r = (struct trenod *)t;
    296 
    297 			t->iftyp = TIF;
    298 			t->iftre = cmd(THSYM, NLFLG);
    299 			t->thtre = cmd(ELSYM | FISYM | EFSYM, NLFLG);
    300 			t->eltre = ((w = wdval) == ELSYM ? cmd(FISYM, NLFLG) : (w == EFSYM ? (wdval = IFSYM, item(0)) : 0));
    301 			if (w == EFSYM)
    302 				return(r);
    303 			break;
    304 		}
    305 
    306 	case FORSYM:
    307 		{
    308 			struct fornod *t;
    309 
    310 			t = (struct fornod *)getstor(sizeof(struct fornod));
    311 			r = (struct trenod *)t;
    312 
    313 			t->fortyp = TFOR;
    314 			t->forlst = 0;
    315 			chkword();
    316 			if (fndef)
    317 				t->fornam = make(wdarg->argval);
    318 			else
    319 				t->fornam = wdarg->argval;
    320 			if (skipnl() == INSYM)
    321 			{
    322 				chkword();
    323 
    324 				nohash++;
    325 				t->forlst = (struct comnod *)item(0);
    326 				nohash--;
    327 
    328 				if (wdval != NL && wdval != ';')
    329 					synbad();
    330 				if (wdval == NL)
    331 					chkpr();
    332 				skipnl();
    333 			}
    334 			chksym(DOSYM | BRSYM);
    335 			t->fortre = cmd(wdval == DOSYM ? ODSYM : KTSYM, NLFLG);
    336 			break;
    337 		}
    338 
    339 	case WHSYM:
    340 	case UNSYM:
    341 		{
    342 			struct whnod *t;
    343 
    344 			t = (struct whnod *)getstor(sizeof(struct whnod));
    345 			r = (struct trenod *)t;
    346 
    347 			t->whtyp = (wdval == WHSYM ? TWH : TUN);
    348 			t->whtre = cmd(DOSYM, NLFLG);
    349 			t->dotre = cmd(ODSYM, NLFLG);
    350 			break;
    351 		}
    352 
    353 	case BRSYM:
    354 		r = cmd(KTSYM, NLFLG);
    355 		break;
    356 
    357 	case '(':
    358 		{
    359 			struct parnod *p;
    360 
    361 			p = (struct parnod *)getstor(sizeof(struct parnod));
    362 			p->partre = cmd(')', NLFLG);
    363 			p->partyp = TPAR;
    364 			r = makefork(0, p);
    365 			break;
    366 		}
    367 
    368 	default:
    369 		if (io == 0)
    370 			return(0);
    371 
    372 	case 0:
    373 		{
    374 			struct comnod *t;
    375 			struct argnod *argp;
    376 			struct argnod **argtail;
    377 			struct argnod **argset = 0;
    378 			int	keywd = 1;
    379 			unsigned char	*com;
    380 
    381 			if ((wdval != NL) && ((peekn = skipwc()) == '('))
    382 			{
    383 				struct fndnod *f;
    384 				struct ionod  *saveio;
    385 
    386 				saveio = iotemp;
    387 				peekn = 0;
    388 				if (skipwc() != ')')
    389 					synbad();
    390 
    391 				/*
    392 				 * We increase fndef before calling getstor(),
    393 				 * so that getstor() uses malloc to allocate
    394 				 * memory instead of stack. This is necessary
    395 				 * since fndnod will be hung on np->namenv,
    396 				 * which persists over command executions.
    397 				 */
    398 				fndef++;
    399 				f = (struct fndnod *)getstor(sizeof(struct fndnod));
    400 				r = (struct trenod *)f;
    401 
    402 				f->fndtyp = TFND;
    403 				f->fndnam = make(wdarg->argval);
    404 				f->fndref = 0;
    405 				reserv++;
    406 				skipnl();
    407 				f->fndval = (struct trenod *)item(0);
    408 				fndef--;
    409 
    410 				if (iotemp != saveio)
    411 				{
    412 					struct ionod 	*ioptr = iotemp;
    413 
    414 					while (ioptr->iolst != saveio)
    415 						ioptr = ioptr->iolst;
    416 
    417 					ioptr->iolst = fiotemp;
    418 					fiotemp = iotemp;
    419 					iotemp = saveio;
    420 				}
    421 				return(r);
    422 			}
    423 			else
    424 			{
    425 				t = (struct comnod *)getstor(sizeof(struct comnod));
    426 				r = (struct trenod *)t;
    427 
    428 				t->comio = io; /*initial io chain*/
    429 				argtail = &(t->comarg);
    430 
    431 				while (wdval == 0)
    432 				{
    433 					if (fndef)
    434 					{
    435 						argp = wdarg;
    436 						wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
    437 						movstr(argp->argval, wdarg->argval);
    438 					}
    439 
    440 					argp = wdarg;
    441 					if (wdset && keywd)
    442 					{
    443 						argp->argnxt = (struct argnod *)argset;
    444 						argset = (struct argnod **)argp;
    445 					}
    446 					else
    447 					{
    448 						*argtail = argp;
    449 						argtail = &(argp->argnxt);
    450 						keywd = flags & keyflg;
    451 					}
    452 					word();
    453 					if (flag)
    454 					{
    455 						if (io)
    456 						{
    457 							while(io->ionxt)
    458 								io = io->ionxt;
    459 							io->ionxt = inout((struct ionod *)0);
    460 						}
    461 						else
    462 							t->comio = io = inout((struct ionod *)0);
    463  					}
    464 				}
    465 
    466 				t->comtyp = TCOM;
    467 				t->comset = (struct argnod *)argset;
    468 				*argtail = 0;
    469 
    470 				if (nohash == 0 && (fndef == 0 || (flags & hashflg)))
    471 				{
    472 					if (t->comarg)
    473 					{
    474 						com = t->comarg->argval;
    475 						if (*com && *com != DOLLAR)
    476 							pathlook(com, 0, t->comset);
    477 					}
    478 				}
    479 
    480 				return(r);
    481 			}
    482 		}
    483 
    484 	}
    485 	reserv++;
    486 	word();
    487 	if (io = inout(io))
    488 	{
    489 		r = makefork(0,r);
    490 		r->treio = io;
    491 	}
    492 	return(r);
    493 }
    494 
    495 
    496 static int
    497 skipnl()
    498 {
    499 	while ((reserv++, word() == NL))
    500 		chkpr();
    501 	return(wdval);
    502 }
    503 
    504 static struct ionod *
    505 inout(lastio)
    506 	struct ionod *lastio;
    507 {
    508 	int	iof;
    509 	struct ionod *iop;
    510 	unsigned int	c;
    511 
    512 	iof = wdnum;
    513 	switch (wdval)
    514 	{
    515 	case DOCSYM:	/*	<<	*/
    516 		iof |= IODOC|IODOC_SUBST;
    517 		break;
    518 
    519 	case APPSYM:	/*	>>	*/
    520 	case '>':
    521 		if (wdnum == 0)
    522 			iof |= 1;
    523 		iof |= IOPUT;
    524 		if (wdval == APPSYM)
    525 		{
    526 			iof |= IOAPP;
    527 			break;
    528 		}
    529 
    530 	case '<':
    531 		if ((c = nextwc()) == '&')
    532 			iof |= IOMOV;
    533 		else if (c == '>')
    534 			iof |= IORDW;
    535 		else
    536 			peekn = c | MARK;
    537 		break;
    538 
    539 	default:
    540 		return(lastio);
    541 	}
    542 
    543 	chkword();
    544 	iop = (struct ionod *)getstor(sizeof(struct ionod));
    545 
    546 	if (fndef)
    547 		iop->ioname = (char *) make(wdarg->argval);
    548 	else
    549 		iop->ioname = (char *) (wdarg->argval);
    550 
    551 	iop->iolink = 0;
    552 	iop->iofile = iof;
    553 	if (iof & IODOC)
    554 	{
    555 		iop->iolst = iopend;
    556 		iopend = iop;
    557 	}
    558 	word();
    559 	iop->ionxt = inout(lastio);
    560 	return(iop);
    561 }
    562 
    563 static void
    564 chkword(void)
    565 {
    566 	if (word())
    567 		synbad();
    568 }
    569 
    570 static void
    571 chksym(int sym)
    572 {
    573 	int	x = sym & wdval;
    574 
    575 	if (((x & SYMFLG) ? x : sym) != wdval)
    576 		synbad();
    577 }
    578 
    579 static void
    580 prsym(int sym)
    581 {
    582 	if (sym & SYMFLG)
    583 	{
    584 		const struct sysnod *sp = reserved;
    585 
    586 		while (sp->sysval && sp->sysval != sym)
    587 			sp++;
    588 		prs(sp->sysnam);
    589 	}
    590 	else if (sym == EOFSYM)
    591 		prs(_gettext(endoffile));
    592 	else
    593 	{
    594 		if (sym & SYMREP)
    595 			prc(sym);
    596 		if (sym == NL)
    597 			prs(_gettext(nlorsemi));
    598 		else
    599 			prc(sym);
    600 	}
    601 }
    602 
    603 static void
    604 synbad(void)
    605 {
    606 	prp();
    607 	prs(_gettext(synmsg));
    608 	if ((flags & ttyflg) == 0)
    609 	{
    610 		prs(_gettext(atline));
    611 		prn(standin->flin);
    612 	}
    613 	prs(colon);
    614 	prc(LQ);
    615 	if (wdval)
    616 		prsym(wdval);
    617 	else
    618 		prs_cntl(wdarg->argval);
    619 	prc(RQ);
    620 	prs(_gettext(unexpected));
    621 	newline();
    622 	exitsh(SYNBAD);
    623 }
    624