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 23 /* 24 * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /* 33 * UNIX shell 34 */ 35 36 #include "defs.h" 37 #include "sym.h" 38 39 static struct ionod * inout(); 40 static void chkword(void); 41 static void chksym(int); 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 void prsym(int); 49 static void synbad(void); 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 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 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 int sym; 113 int flg; 114 { 115 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 struct trenod *r; 164 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 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 int esym; 203 { 204 skipnl(); 205 if (wdval == esym) 206 return(0); 207 else 208 { 209 struct regnod *r = 210 (struct regnod *)getstor(sizeof (struct regnod)); 211 struct argnod *argp; 212 213 r->regptr = 0; 214 for (;;) 215 { 216 if (fndef) 217 { 218 argp= wdarg; 219 wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD); 220 movstr(argp->argval, wdarg->argval); 221 } 222 223 wdarg->argnxt = r->regptr; 224 r->regptr = wdarg; 225 226 /* 'in' is not a reserved word in this case */ 227 if (wdval == INSYM){ 228 wdval = 0; 229 } 230 if (wdval || (word() != ')' && wdval != '|')) 231 synbad(); 232 if (wdval == '|') 233 word(); 234 else 235 break; 236 } 237 r->regcom = cmd(0, NLFLG | MTFLG); 238 if (wdval == ECSYM) 239 r->regnxt = syncase(esym); 240 else 241 { 242 chksym(esym); 243 r->regnxt = 0; 244 } 245 return(r); 246 } 247 } 248 249 /* 250 * item 251 * 252 * ( cmd ) [ < in ] [ > out ] 253 * word word* [ < in ] [ > out ] 254 * if ... then ... else ... fi 255 * for ... while ... do ... done 256 * case ... in ... esac 257 * begin ... end 258 */ 259 static struct trenod * 260 item(flag) 261 BOOL flag; 262 { 263 struct trenod *r; 264 struct ionod *io; 265 266 if (flag) 267 io = inout((struct ionod *)0); 268 else 269 io = 0; 270 switch (wdval) 271 { 272 case CASYM: 273 { 274 struct swnod *t; 275 276 t = (struct swnod *)getstor(sizeof(struct swnod)); 277 r = (struct trenod *)t; 278 279 chkword(); 280 if (fndef) 281 t->swarg = make(wdarg->argval); 282 else 283 t->swarg = wdarg->argval; 284 skipnl(); 285 chksym(INSYM | BRSYM); 286 t->swlst = syncase(wdval == INSYM ? ESSYM : KTSYM); 287 t->swtyp = TSW; 288 break; 289 } 290 291 case IFSYM: 292 { 293 int w; 294 struct ifnod *t; 295 296 t = (struct ifnod *)getstor(sizeof(struct ifnod)); 297 r = (struct trenod *)t; 298 299 t->iftyp = TIF; 300 t->iftre = cmd(THSYM, NLFLG); 301 t->thtre = cmd(ELSYM | FISYM | EFSYM, NLFLG); 302 t->eltre = ((w = wdval) == ELSYM ? cmd(FISYM, NLFLG) : (w == EFSYM ? (wdval = IFSYM, item(0)) : 0)); 303 if (w == EFSYM) 304 return(r); 305 break; 306 } 307 308 case FORSYM: 309 { 310 struct fornod *t; 311 312 t = (struct fornod *)getstor(sizeof(struct fornod)); 313 r = (struct trenod *)t; 314 315 t->fortyp = TFOR; 316 t->forlst = 0; 317 chkword(); 318 if (fndef) 319 t->fornam = make(wdarg->argval); 320 else 321 t->fornam = wdarg->argval; 322 if (skipnl() == INSYM) 323 { 324 chkword(); 325 326 nohash++; 327 t->forlst = (struct comnod *)item(0); 328 nohash--; 329 330 if (wdval != NL && wdval != ';') 331 synbad(); 332 if (wdval == NL) 333 chkpr(); 334 skipnl(); 335 } 336 chksym(DOSYM | BRSYM); 337 t->fortre = cmd(wdval == DOSYM ? ODSYM : KTSYM, NLFLG); 338 break; 339 } 340 341 case WHSYM: 342 case UNSYM: 343 { 344 struct whnod *t; 345 346 t = (struct whnod *)getstor(sizeof(struct whnod)); 347 r = (struct trenod *)t; 348 349 t->whtyp = (wdval == WHSYM ? TWH : TUN); 350 t->whtre = cmd(DOSYM, NLFLG); 351 t->dotre = cmd(ODSYM, NLFLG); 352 break; 353 } 354 355 case BRSYM: 356 r = cmd(KTSYM, NLFLG); 357 break; 358 359 case '(': 360 { 361 struct parnod *p; 362 363 p = (struct parnod *)getstor(sizeof(struct parnod)); 364 p->partre = cmd(')', NLFLG); 365 p->partyp = TPAR; 366 r = makefork(0, p); 367 break; 368 } 369 370 default: 371 if (io == 0) 372 return(0); 373 374 case 0: 375 { 376 struct comnod *t; 377 struct argnod *argp; 378 struct argnod **argtail; 379 struct argnod **argset = 0; 380 int keywd = 1; 381 unsigned char *com; 382 383 if ((wdval != NL) && ((peekn = skipwc()) == '(')) 384 { 385 struct fndnod *f; 386 struct ionod *saveio; 387 388 saveio = iotemp; 389 peekn = 0; 390 if (skipwc() != ')') 391 synbad(); 392 393 f = (struct fndnod *)getstor(sizeof(struct fndnod)); 394 r = (struct trenod *)f; 395 396 f->fndtyp = TFND; 397 if (fndef) 398 f->fndnam = make(wdarg->argval); 399 else 400 f->fndnam = wdarg->argval; 401 reserv++; 402 fndef++; 403 skipnl(); 404 f->fndval = (struct trenod *)item(0); 405 fndef--; 406 407 if (iotemp != saveio) 408 { 409 struct ionod *ioptr = iotemp; 410 411 while (ioptr->iolst != saveio) 412 ioptr = ioptr->iolst; 413 414 ioptr->iolst = fiotemp; 415 fiotemp = iotemp; 416 iotemp = saveio; 417 } 418 return(r); 419 } 420 else 421 { 422 t = (struct comnod *)getstor(sizeof(struct comnod)); 423 r = (struct trenod *)t; 424 425 t->comio = io; /*initial io chain*/ 426 argtail = &(t->comarg); 427 428 while (wdval == 0) 429 { 430 if (fndef) 431 { 432 argp = wdarg; 433 wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD); 434 movstr(argp->argval, wdarg->argval); 435 } 436 437 argp = wdarg; 438 if (wdset && keywd) 439 { 440 argp->argnxt = (struct argnod *)argset; 441 argset = (struct argnod **)argp; 442 } 443 else 444 { 445 *argtail = argp; 446 argtail = &(argp->argnxt); 447 keywd = flags & keyflg; 448 } 449 word(); 450 if (flag) 451 { 452 if (io) 453 { 454 while(io->ionxt) 455 io = io->ionxt; 456 io->ionxt = inout((struct ionod *)0); 457 } 458 else 459 t->comio = io = inout((struct ionod *)0); 460 } 461 } 462 463 t->comtyp = TCOM; 464 t->comset = (struct argnod *)argset; 465 *argtail = 0; 466 467 if (nohash == 0 && (fndef == 0 || (flags & hashflg))) 468 { 469 if (t->comarg) 470 { 471 com = t->comarg->argval; 472 if (*com && *com != DOLLAR) 473 pathlook(com, 0, t->comset); 474 } 475 } 476 477 return(r); 478 } 479 } 480 481 } 482 reserv++; 483 word(); 484 if (io = inout(io)) 485 { 486 r = makefork(0,r); 487 r->treio = io; 488 } 489 return(r); 490 } 491 492 493 static int 494 skipnl() 495 { 496 while ((reserv++, word() == NL)) 497 chkpr(); 498 return(wdval); 499 } 500 501 static struct ionod * 502 inout(lastio) 503 struct ionod *lastio; 504 { 505 int iof; 506 struct ionod *iop; 507 unsigned int c; 508 509 iof = wdnum; 510 switch (wdval) 511 { 512 case DOCSYM: /* << */ 513 iof |= IODOC; 514 break; 515 516 case APPSYM: /* >> */ 517 case '>': 518 if (wdnum == 0) 519 iof |= 1; 520 iof |= IOPUT; 521 if (wdval == APPSYM) 522 { 523 iof |= IOAPP; 524 break; 525 } 526 527 case '<': 528 if ((c = nextwc()) == '&') 529 iof |= IOMOV; 530 else if (c == '>') 531 iof |= IORDW; 532 else 533 peekn = c | MARK; 534 break; 535 536 default: 537 return(lastio); 538 } 539 540 chkword(); 541 iop = (struct ionod *)getstor(sizeof(struct ionod)); 542 543 if (fndef) 544 iop->ioname = (char *) make(wdarg->argval); 545 else 546 iop->ioname = (char *) (wdarg->argval); 547 548 iop->iolink = 0; 549 iop->iofile = iof; 550 if (iof & IODOC) 551 { 552 iop->iolst = iopend; 553 iopend = iop; 554 } 555 word(); 556 iop->ionxt = inout(lastio); 557 return(iop); 558 } 559 560 static void 561 chkword(void) 562 { 563 if (word()) 564 synbad(); 565 } 566 567 static void 568 chksym(int sym) 569 { 570 int x = sym & wdval; 571 572 if (((x & SYMFLG) ? x : sym) != wdval) 573 synbad(); 574 } 575 576 static void 577 prsym(int sym) 578 { 579 if (sym & SYMFLG) 580 { 581 const struct sysnod *sp = reserved; 582 583 while (sp->sysval && sp->sysval != sym) 584 sp++; 585 prs(sp->sysnam); 586 } 587 else if (sym == EOFSYM) 588 prs(endoffile); 589 else 590 { 591 if (sym & SYMREP) 592 prc(sym); 593 if (sym == NL) 594 prs("newline or ;"); 595 else 596 prc(sym); 597 } 598 } 599 600 static void 601 synbad(void) 602 { 603 prp(); 604 prs(synmsg); 605 if ((flags & ttyflg) == 0) 606 { 607 prs(atline); 608 prn(standin->flin); 609 } 610 prs(colon); 611 prc(LQ); 612 if (wdval) 613 prsym(wdval); 614 else 615 prs_cntl(wdarg->argval); 616 prc(RQ); 617 prs(unexpected); 618 newline(); 619 exitsh(SYNBAD); 620 } 621