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 *
getstor(asize)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 *
makefork(flgs,i)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 *
makelist(type,i,r)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 *
cmd(sym,flg)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 *
list(flg)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 *
term(flg)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 *
syncase(esym)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 *
item(flag)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
skipnl()497 skipnl()
498 {
499 while ((reserv++, word() == NL))
500 chkpr();
501 return(wdval);
502 }
503
504 static struct ionod *
inout(lastio)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
chkword(void)564 chkword(void)
565 {
566 if (word())
567 synbad();
568 }
569
570 static void
chksym(int sym)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
prsym(int sym)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
synbad(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