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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1996, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.12.1.4 */ 32 /* 33 * UNIX shell 34 */ 35 36 #include "defs.h" 37 #include "sym.h" 38 39 static struct ionod * inout(); 40 static int chkword(); 41 static int chksym(); 42 static struct trenod * term(); 43 static struct trenod * makelist(); 44 static struct trenod * list(); 45 static struct regnod * syncase(); 46 static struct trenod * item(); 47 static int skipnl(); 48 static int prsym(); 49 static int synbad(); 50 51 52 /* ======== storage allocation for functions ======== */ 53 54 unsigned char * 55 getstor(asize) 56 int asize; 57 { 58 if (fndef) 59 return((unsigned char *)alloc(asize)); 60 else 61 return(getstak(asize)); 62 } 63 64 65 /* ======== command line decoding ========*/ 66 67 68 69 70 struct trenod * 71 makefork(flgs, i) 72 int flgs; 73 struct trenod *i; 74 { 75 register struct forknod *t; 76 77 t = (struct forknod *)getstor(sizeof(struct forknod)); 78 t->forktyp = flgs|TFORK; 79 t->forktre = i; 80 t->forkio = 0; 81 return((struct trenod *)t); 82 } 83 84 static struct trenod * 85 makelist(type, i, r) 86 int type; 87 struct trenod *i, *r; 88 { 89 register struct lstnod *t; 90 91 if (i == 0 || r == 0) 92 synbad(); 93 else 94 { 95 t = (struct lstnod *)getstor(sizeof(struct lstnod)); 96 t->lsttyp = type; 97 t->lstlef = i; 98 t->lstrit = r; 99 } 100 return((struct trenod *)t); 101 } 102 103 /* 104 * cmd 105 * empty 106 * list 107 * list & [ cmd ] 108 * list [ ; cmd ] 109 */ 110 struct trenod * 111 cmd(sym, flg) 112 register int sym; 113 int flg; 114 { 115 register struct trenod *i, *e; 116 i = list(flg); 117 if (wdval == NL) 118 { 119 if (flg & NLFLG) 120 { 121 wdval = ';'; 122 chkpr(); 123 } 124 } 125 else if (i == 0 && (flg & MTFLG) == 0) 126 synbad(); 127 128 switch (wdval) 129 { 130 case '&': 131 if (i) 132 i = makefork(FAMP, i); 133 else 134 synbad(); 135 136 case ';': 137 if (e = cmd(sym, flg | MTFLG)) 138 i = makelist(TLST, i, e); 139 else if (i == 0) 140 synbad(); 141 break; 142 143 case EOFSYM: 144 if (sym == NL) 145 break; 146 147 default: 148 if (sym) 149 chksym(sym); 150 } 151 return(i); 152 } 153 154 /* 155 * list 156 * term 157 * list && term 158 * list || term 159 */ 160 static struct trenod * 161 list(flg) 162 { 163 register struct trenod *r; 164 register int b; 165 r = term(flg); 166 while (r && ((b = (wdval == ANDFSYM)) || wdval == ORFSYM)) 167 r = makelist((b ? TAND : TORF), r, term(NLFLG)); 168 return(r); 169 } 170 171 /* 172 * term 173 * item 174 * item |^ term 175 */ 176 static struct trenod * 177 term(flg) 178 { 179 register struct trenod *t; 180 181 reserv++; 182 if (flg & NLFLG) 183 skipnl(); 184 else 185 word(); 186 if ((t = item(TRUE)) && (wdval == '^' || wdval == '|')) 187 { 188 struct trenod *left; 189 struct trenod *right; 190 191 left = makefork(FPOU, t); 192 right = makefork(FPIN, term(NLFLG)); 193 return(makefork(0, makelist(TFIL, left, right))); 194 } 195 else 196 return(t); 197 } 198 199 200 static struct regnod * 201 syncase(esym) 202 register int esym; 203 { 204 skipnl(); 205 if (wdval == esym) 206 return(0); 207 else 208 { 209 register struct regnod *r = (struct regnod *)getstor(sizeof(struct regnod)); 210 register 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 register struct trenod *r; 263 register 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 register 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 register int w; 293 register 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 register 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 register 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 register 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 register struct comnod *t; 376 register struct argnod *argp; 377 register struct argnod **argtail; 378 register 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 register int iof; 505 register struct ionod *iop; 506 register unsigned int c; 507 508 iof = wdnum; 509 switch (wdval) 510 { 511 case DOCSYM: /* << */ 512 iof |= IODOC; 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 int 560 chkword() 561 { 562 if (word()) 563 synbad(); 564 } 565 566 static int 567 chksym(sym) 568 { 569 register int x = sym & wdval; 570 571 if (((x & SYMFLG) ? x : sym) != wdval) 572 synbad(); 573 } 574 575 static int 576 prsym(sym) 577 { 578 if (sym & SYMFLG) 579 { 580 register 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(endoffile); 588 else 589 { 590 if (sym & SYMREP) 591 prc(sym); 592 if (sym == NL) 593 prs("newline or ;"); 594 else 595 prc(sym); 596 } 597 } 598 599 static int 600 synbad() 601 { 602 prp(); 603 prs(synmsg); 604 if ((flags & ttyflg) == 0) 605 { 606 prs(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(unexpected); 617 newline(); 618 exitsh(SYNBAD); 619 } 620