3057 Remove sgml util from cmd/man
[unleashed.git] / usr / src / cmd / sh / cmd.c
blob552adcdb8ccf818264fb2871898e8281d259f526
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * UNIX shell
34 #include "defs.h"
35 #include "sym.h"
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);
50 /* ======== storage allocation for functions ======== */
52 unsigned char *
53 getstor(asize)
54 int asize;
56 if (fndef)
57 return((unsigned char *)alloc(asize));
58 else
59 return(getstak(asize));
63 /* ======== command line decoding ========*/
68 struct trenod *
69 makefork(flgs, i)
70 int flgs;
71 struct trenod *i;
73 struct forknod *t;
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);
82 static struct trenod *
83 makelist(type, i, r)
84 int type;
85 struct trenod *i, *r;
87 struct lstnod *t;
89 if (i == 0 || r == 0)
90 synbad();
91 else
93 t = (struct lstnod *)getstor(sizeof(struct lstnod));
94 t->lsttyp = type;
95 t->lstlef = i;
96 t->lstrit = r;
98 return((struct trenod *)t);
102 * cmd
103 * empty
104 * list
105 * list & [ cmd ]
106 * list [ ; cmd ]
108 struct trenod *
109 cmd(sym, flg)
110 int sym;
111 int flg;
113 struct trenod *i, *e;
114 i = list(flg);
115 if (wdval == NL)
117 if (flg & NLFLG)
119 wdval = ';';
120 chkpr();
123 else if (i == 0 && (flg & MTFLG) == 0)
124 synbad();
126 switch (wdval)
128 case '&':
129 if (i)
130 i = makefork(FAMP, i);
131 else
132 synbad();
134 case ';':
135 if (e = cmd(sym, flg | MTFLG))
136 i = makelist(TLST, i, e);
137 else if (i == 0)
138 synbad();
139 break;
141 case EOFSYM:
142 if (sym == NL)
143 break;
145 default:
146 if (sym)
147 chksym(sym);
149 return(i);
153 * list
154 * term
155 * list && term
156 * list || term
158 static struct trenod *
159 list(flg)
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);
170 * term
171 * item
172 * item |^ term
174 static struct trenod *
175 term(flg)
177 struct trenod *t;
179 reserv++;
180 if (flg & NLFLG)
181 skipnl();
182 else
183 word();
184 if ((t = item(TRUE)) && (wdval == '^' || wdval == '|'))
186 struct trenod *left;
187 struct trenod *right;
189 left = makefork(FPOU, t);
190 right = makefork(FPIN, term(NLFLG));
191 return(makefork(0, makelist(TFIL, left, right)));
193 else
194 return(t);
198 static struct regnod *
199 syncase(esym)
200 int esym;
202 skipnl();
203 if (wdval == esym)
204 return(0);
205 else
207 struct regnod *r =
208 (struct regnod *)getstor(sizeof (struct regnod));
209 struct argnod *argp;
211 r->regptr = 0;
212 for (;;)
214 if (fndef)
216 argp= wdarg;
217 wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
218 movstr(argp->argval, wdarg->argval);
221 wdarg->argnxt = r->regptr;
222 r->regptr = wdarg;
224 /* 'in' is not a reserved word in this case */
225 if (wdval == INSYM){
226 wdval = 0;
228 if (wdval || (word() != ')' && wdval != '|'))
229 synbad();
230 if (wdval == '|')
231 word();
232 else
233 break;
235 r->regcom = cmd(0, NLFLG | MTFLG);
236 if (wdval == ECSYM)
237 r->regnxt = syncase(esym);
238 else
240 chksym(esym);
241 r->regnxt = 0;
243 return(r);
248 * item
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
257 static struct trenod *
258 item(flag)
259 BOOL flag;
261 struct trenod *r;
262 struct ionod *io;
264 if (flag)
265 io = inout((struct ionod *)0);
266 else
267 io = 0;
268 switch (wdval)
270 case CASYM:
272 struct swnod *t;
274 t = (struct swnod *)getstor(sizeof(struct swnod));
275 r = (struct trenod *)t;
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;
289 case IFSYM:
291 int w;
292 struct ifnod *t;
294 t = (struct ifnod *)getstor(sizeof(struct ifnod));
295 r = (struct trenod *)t;
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;
306 case FORSYM:
308 struct fornod *t;
310 t = (struct fornod *)getstor(sizeof(struct fornod));
311 r = (struct trenod *)t;
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)
322 chkword();
324 nohash++;
325 t->forlst = (struct comnod *)item(0);
326 nohash--;
328 if (wdval != NL && wdval != ';')
329 synbad();
330 if (wdval == NL)
331 chkpr();
332 skipnl();
334 chksym(DOSYM | BRSYM);
335 t->fortre = cmd(wdval == DOSYM ? ODSYM : KTSYM, NLFLG);
336 break;
339 case WHSYM:
340 case UNSYM:
342 struct whnod *t;
344 t = (struct whnod *)getstor(sizeof(struct whnod));
345 r = (struct trenod *)t;
347 t->whtyp = (wdval == WHSYM ? TWH : TUN);
348 t->whtre = cmd(DOSYM, NLFLG);
349 t->dotre = cmd(ODSYM, NLFLG);
350 break;
353 case BRSYM:
354 r = cmd(KTSYM, NLFLG);
355 break;
357 case '(':
359 struct parnod *p;
361 p = (struct parnod *)getstor(sizeof(struct parnod));
362 p->partre = cmd(')', NLFLG);
363 p->partyp = TPAR;
364 r = makefork(0, p);
365 break;
368 default:
369 if (io == 0)
370 return(0);
372 case 0:
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;
381 if ((wdval != NL) && ((peekn = skipwc()) == '('))
383 struct fndnod *f;
384 struct ionod *saveio;
386 saveio = iotemp;
387 peekn = 0;
388 if (skipwc() != ')')
389 synbad();
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.
398 fndef++;
399 f = (struct fndnod *)getstor(sizeof(struct fndnod));
400 r = (struct trenod *)f;
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--;
410 if (iotemp != saveio)
412 struct ionod *ioptr = iotemp;
414 while (ioptr->iolst != saveio)
415 ioptr = ioptr->iolst;
417 ioptr->iolst = fiotemp;
418 fiotemp = iotemp;
419 iotemp = saveio;
421 return(r);
423 else
425 t = (struct comnod *)getstor(sizeof(struct comnod));
426 r = (struct trenod *)t;
428 t->comio = io; /*initial io chain*/
429 argtail = &(t->comarg);
431 while (wdval == 0)
433 if (fndef)
435 argp = wdarg;
436 wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD);
437 movstr(argp->argval, wdarg->argval);
440 argp = wdarg;
441 if (wdset && keywd)
443 argp->argnxt = (struct argnod *)argset;
444 argset = (struct argnod **)argp;
446 else
448 *argtail = argp;
449 argtail = &(argp->argnxt);
450 keywd = flags & keyflg;
452 word();
453 if (flag)
455 if (io)
457 while(io->ionxt)
458 io = io->ionxt;
459 io->ionxt = inout((struct ionod *)0);
461 else
462 t->comio = io = inout((struct ionod *)0);
466 t->comtyp = TCOM;
467 t->comset = (struct argnod *)argset;
468 *argtail = 0;
470 if (nohash == 0 && (fndef == 0 || (flags & hashflg)))
472 if (t->comarg)
474 com = t->comarg->argval;
475 if (*com && *com != DOLLAR)
476 pathlook(com, 0, t->comset);
480 return(r);
485 reserv++;
486 word();
487 if (io = inout(io))
489 r = makefork(0,r);
490 r->treio = io;
492 return(r);
496 static int
497 skipnl()
499 while ((reserv++, word() == NL))
500 chkpr();
501 return(wdval);
504 static struct ionod *
505 inout(lastio)
506 struct ionod *lastio;
508 int iof;
509 struct ionod *iop;
510 unsigned int c;
512 iof = wdnum;
513 switch (wdval)
515 case DOCSYM: /* << */
516 iof |= IODOC|IODOC_SUBST;
517 break;
519 case APPSYM: /* >> */
520 case '>':
521 if (wdnum == 0)
522 iof |= 1;
523 iof |= IOPUT;
524 if (wdval == APPSYM)
526 iof |= IOAPP;
527 break;
530 case '<':
531 if ((c = nextwc()) == '&')
532 iof |= IOMOV;
533 else if (c == '>')
534 iof |= IORDW;
535 else
536 peekn = c | MARK;
537 break;
539 default:
540 return(lastio);
543 chkword();
544 iop = (struct ionod *)getstor(sizeof(struct ionod));
546 if (fndef)
547 iop->ioname = (char *) make(wdarg->argval);
548 else
549 iop->ioname = (char *) (wdarg->argval);
551 iop->iolink = 0;
552 iop->iofile = iof;
553 if (iof & IODOC)
555 iop->iolst = iopend;
556 iopend = iop;
558 word();
559 iop->ionxt = inout(lastio);
560 return(iop);
563 static void
564 chkword(void)
566 if (word())
567 synbad();
570 static void
571 chksym(int sym)
573 int x = sym & wdval;
575 if (((x & SYMFLG) ? x : sym) != wdval)
576 synbad();
579 static void
580 prsym(int sym)
582 if (sym & SYMFLG)
584 const struct sysnod *sp = reserved;
586 while (sp->sysval && sp->sysval != sym)
587 sp++;
588 prs(sp->sysnam);
590 else if (sym == EOFSYM)
591 prs(_gettext(endoffile));
592 else
594 if (sym & SYMREP)
595 prc(sym);
596 if (sym == NL)
597 prs(_gettext(nlorsemi));
598 else
599 prc(sym);
603 static void
604 synbad(void)
606 prp();
607 prs(_gettext(synmsg));
608 if ((flags & ttyflg) == 0)
610 prs(_gettext(atline));
611 prn(standin->flin);
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);