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