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