1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.parse.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
   2: /*
   3:  * sh.parse.c: Interpret a list of tokens
   4:  */
   5: /*-
   6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
   7:  * All rights reserved.
   8:  *
   9:  * Redistribution and use in source and binary forms, with or without
  10:  * modification, are permitted provided that the following conditions
  11:  * are met:
  12:  * 1. Redistributions of source code must retain the above copyright
  13:  *    notice, this list of conditions and the following disclaimer.
  14:  * 2. Redistributions in binary form must reproduce the above copyright
  15:  *    notice, this list of conditions and the following disclaimer in the
  16:  *    documentation and/or other materials provided with the distribution.
  17:  * 3. All advertising materials mentioning features or use of this software
  18:  *    must display the following acknowledgement:
  19:  *	This product includes software developed by the University of
  20:  *	California, Berkeley and its contributors.
  21:  * 4. Neither the name of the University nor the names of its contributors
  22:  *    may be used to endorse or promote products derived from this software
  23:  *    without specific prior written permission.
  24:  *
  25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35:  * SUCH DAMAGE.
  36:  */
  37: #include "config.h"
  38: #if !defined(lint) && !defined(pdp11)
  39: static char *rcsid()
  40:     { return "$Id: sh.parse.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
  41: #endif
  42: 
  43: #include "sh.h"
  44: 
  45: /*
  46:  * C shell
  47:  */
  48: static  void         asyntax __P((struct wordent *, struct wordent *));
  49: static  void         asyn0   __P((struct wordent *, struct wordent *));
  50: static  void         asyn3   __P((struct wordent *, struct wordent *));
  51: static  struct wordent  *freenod __P((struct wordent *, struct wordent *));
  52: static  struct command  *syn0    __P((struct wordent *, struct wordent *, int));
  53: static  struct command  *syn1    __P((struct wordent *, struct wordent *, int));
  54: static  struct command  *syn1a   __P((struct wordent *, struct wordent *, int));
  55: static  struct command  *syn1b   __P((struct wordent *, struct wordent *, int));
  56: static  struct command  *syn2    __P((struct wordent *, struct wordent *, int));
  57: static  struct command  *syn3    __P((struct wordent *, struct wordent *, int));
  58: 
  59: #define ALEFT   21      /* max of 20 alias expansions	 */
  60: #define HLEFT   11      /* max of 10 history expansions	 */
  61: /*
  62:  * Perform aliasing on the word list lex
  63:  * Do a (very rudimentary) parse to separate into commands.
  64:  * If word 0 of a command has an alias, do it.
  65:  * Repeat a maximum of 20 times.
  66:  */
  67: static int aleft;
  68: extern int hleft;
  69: void
  70: alias(lex)
  71:     register struct wordent *lex;
  72: {
  73:     jmp_buf osetexit;
  74: 
  75:     aleft = ALEFT;
  76:     hleft = HLEFT;
  77:     getexit(osetexit);
  78:     (void) setexit();
  79:     if (haderr) {
  80:     resexit(osetexit);
  81:     reset();
  82:     }
  83:     if (--aleft == 0)
  84:     stderror(ERR_ALIASLOOP);
  85:     asyntax(lex->next, lex);
  86:     resexit(osetexit);
  87: }
  88: 
  89: static void
  90: asyntax(p1, p2)
  91:     register struct wordent *p1, *p2;
  92: {
  93:     while (p1 != p2)
  94:     if (any(";&\n", p1->word[0]))
  95:         p1 = p1->next;
  96:     else {
  97:         asyn0(p1, p2);
  98:         return;
  99:     }
 100: }
 101: 
 102: static void
 103: asyn0(p1, p2)
 104:     struct wordent *p1;
 105:     register struct wordent *p2;
 106: {
 107:     register struct wordent *p;
 108:     register int l = 0;
 109: 
 110:     for (p = p1; p != p2; p = p->next)
 111:     switch (p->word[0]) {
 112: 
 113:     case '(':
 114:         l++;
 115:         continue;
 116: 
 117:     case ')':
 118:         l--;
 119:         if (l < 0)
 120:         stderror(ERR_TOOMANYRP);
 121:         continue;
 122: 
 123:     case '>':
 124:         if (p->next != p2 && eq(p->next->word, STRand))
 125:         p = p->next;
 126:         continue;
 127: 
 128:     case '&':
 129:     case '|':
 130:     case ';':
 131:     case '\n':
 132:         if (l != 0)
 133:         continue;
 134:         asyn3(p1, p);
 135:         asyntax(p->next, p2);
 136:         return;
 137:     }
 138:     if (l == 0)
 139:     asyn3(p1, p2);
 140: }
 141: 
 142: static void
 143: asyn3(p1, p2)
 144:     struct wordent *p1;
 145:     register struct wordent *p2;
 146: {
 147:     register struct varent *ap;
 148:     struct wordent alout;
 149:     register bool redid;
 150: 
 151:     if (p1 == p2)
 152:     return;
 153:     if (p1->word[0] == '(') {
 154:     for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
 155:         if (p2 == p1)
 156:         return;
 157:     if (p2 == p1->next)
 158:         return;
 159:     asyn0(p1->next, p2);
 160:     return;
 161:     }
 162:     ap = adrof1(p1->word, &aliases);
 163:     if (ap == 0)
 164:     return;
 165:     alhistp = p1->prev;
 166:     alhistt = p2;
 167:     alvec = ap->vec;
 168:     redid = lex(&alout);
 169:     alhistp = alhistt = 0;
 170:     alvec = 0;
 171:     if (seterr) {
 172:     freelex(&alout);
 173:     stderror(ERR_OLD);
 174:     }
 175:     if (p1->word[0] && eq(p1->word, alout.next->word)) {
 176:     Char   *cp = alout.next->word;
 177: 
 178:     alout.next->word = Strspl(STRQNULL, cp);
 179:     xfree((ptr_t) cp);
 180:     }
 181:     p1 = freenod(p1, redid ? p2 : p1->next);
 182:     if (alout.next != &alout) {
 183:     p1->next->prev = alout.prev->prev;
 184:     alout.prev->prev->next = p1->next;
 185:     alout.next->prev = p1;
 186:     p1->next = alout.next;
 187:     xfree((ptr_t) alout.prev->word);
 188:     xfree((ptr_t) (alout.prev));
 189:     }
 190:     reset();            /* throw! */
 191: }
 192: 
 193: static struct wordent *
 194: freenod(p1, p2)
 195:     register struct wordent *p1, *p2;
 196: {
 197:     register struct wordent *retp = p1->prev;
 198: 
 199:     while (p1 != p2) {
 200:     xfree((ptr_t) p1->word);
 201:     p1 = p1->next;
 202:     xfree((ptr_t) (p1->prev));
 203:     }
 204:     retp->next = p2;
 205:     p2->prev = retp;
 206:     return (retp);
 207: }
 208: 
 209: #define P_HERE  1
 210: #define P_IN    2
 211: #define P_OUT   4
 212: #define P_DIAG  8
 213: 
 214: /*
 215:  * syntax
 216:  *	empty
 217:  *	syn0
 218:  */
 219: struct command *
 220: syntax(p1, p2, flags)
 221:     register struct wordent *p1, *p2;
 222:     int     flags;
 223: {
 224: 
 225:     while (p1 != p2)
 226:     if (any(";&\n", p1->word[0]))
 227:         p1 = p1->next;
 228:     else
 229:         return (syn0(p1, p2, flags));
 230:     return (0);
 231: }
 232: 
 233: /*
 234:  * syn0
 235:  *	syn1
 236:  *	syn1 & syntax
 237:  */
 238: static struct command *
 239: syn0(p1, p2, flags)
 240:     struct wordent *p1, *p2;
 241:     int     flags;
 242: {
 243:     register struct wordent *p;
 244:     register struct command *t, *t1;
 245:     int     l;
 246: 
 247:     l = 0;
 248:     for (p = p1; p != p2; p = p->next)
 249:     switch (p->word[0]) {
 250: 
 251:     case '(':
 252:         l++;
 253:         continue;
 254: 
 255:     case ')':
 256:         l--;
 257:         if (l < 0)
 258:         seterror(ERR_TOOMANYRP);
 259:         continue;
 260: 
 261:     case '|':
 262:         if (p->word[1] == '|')
 263:         continue;
 264:         /* fall into ... */
 265: 
 266:     case '>':
 267:         if (p->next != p2 && eq(p->next->word, STRand))
 268:         p = p->next;
 269:         continue;
 270: 
 271:     case '&':
 272:         if (l != 0)
 273:         break;
 274:         if (p->word[1] == '&')
 275:         continue;
 276:         t1 = syn1(p1, p, flags);
 277:         if (t1->t_dtyp == NODE_LIST ||
 278:         t1->t_dtyp == NODE_AND ||
 279:         t1->t_dtyp == NODE_OR) {
 280:         t = (struct command *) xcalloc(1, sizeof(*t));
 281:         t->t_dtyp = NODE_PAREN;
 282:         t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
 283:         t->t_dspr = t1;
 284:         t1 = t;
 285:         }
 286:         else
 287:         t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
 288:         t = (struct command *) xcalloc(1, sizeof(*t));
 289:         t->t_dtyp = NODE_LIST;
 290:         t->t_dflg = 0;
 291:         t->t_dcar = t1;
 292:         t->t_dcdr = syntax(p, p2, flags);
 293:         return (t);
 294:     }
 295:     if (l == 0)
 296:     return (syn1(p1, p2, flags));
 297:     seterror(ERR_TOOMANYLP);
 298:     return (0);
 299: }
 300: 
 301: /*
 302:  * syn1
 303:  *	syn1a
 304:  *	syn1a ; syntax
 305:  */
 306: static struct command *
 307: syn1(p1, p2, flags)
 308:     struct wordent *p1, *p2;
 309:     int     flags;
 310: {
 311:     register struct wordent *p;
 312:     register struct command *t;
 313:     int     l;
 314: 
 315:     l = 0;
 316:     for (p = p1; p != p2; p = p->next)
 317:     switch (p->word[0]) {
 318: 
 319:     case '(':
 320:         l++;
 321:         continue;
 322: 
 323:     case ')':
 324:         l--;
 325:         continue;
 326: 
 327:     case ';':
 328:     case '\n':
 329:         if (l != 0)
 330:         break;
 331:         t = (struct command *) xcalloc(1, sizeof(*t));
 332:         t->t_dtyp = NODE_LIST;
 333:         t->t_dcar = syn1a(p1, p, flags);
 334:         t->t_dcdr = syntax(p->next, p2, flags);
 335:         if (t->t_dcdr == 0)
 336:         t->t_dcdr = t->t_dcar, t->t_dcar = 0;
 337:         return (t);
 338:     }
 339:     return (syn1a(p1, p2, flags));
 340: }
 341: 
 342: /*
 343:  * syn1a
 344:  *	syn1b
 345:  *	syn1b || syn1a
 346:  */
 347: static struct command *
 348: syn1a(p1, p2, flags)
 349:     struct wordent *p1, *p2;
 350:     int     flags;
 351: {
 352:     register struct wordent *p;
 353:     register struct command *t;
 354:     register int l = 0;
 355: 
 356:     for (p = p1; p != p2; p = p->next)
 357:     switch (p->word[0]) {
 358: 
 359:     case '(':
 360:         l++;
 361:         continue;
 362: 
 363:     case ')':
 364:         l--;
 365:         continue;
 366: 
 367:     case '|':
 368:         if (p->word[1] != '|')
 369:         continue;
 370:         if (l == 0) {
 371:         t = (struct command *) xcalloc(1, sizeof(*t));
 372:         t->t_dtyp = NODE_OR;
 373:         t->t_dcar = syn1b(p1, p, flags);
 374:         t->t_dcdr = syn1a(p->next, p2, flags);
 375:         t->t_dflg = 0;
 376:         return (t);
 377:         }
 378:         continue;
 379:     }
 380:     return (syn1b(p1, p2, flags));
 381: }
 382: 
 383: /*
 384:  * syn1b
 385:  *	syn2
 386:  *	syn2 && syn1b
 387:  */
 388: static struct command *
 389: syn1b(p1, p2, flags)
 390:     struct wordent *p1, *p2;
 391:     int     flags;
 392: {
 393:     register struct wordent *p;
 394:     register struct command *t;
 395:     register int l = 0;
 396: 
 397:     for (p = p1; p != p2; p = p->next)
 398:     switch (p->word[0]) {
 399: 
 400:     case '(':
 401:         l++;
 402:         continue;
 403: 
 404:     case ')':
 405:         l--;
 406:         continue;
 407: 
 408:     case '&':
 409:         if (p->word[1] == '&' && l == 0) {
 410:         t = (struct command *) xcalloc(1, sizeof(*t));
 411:         t->t_dtyp = NODE_AND;
 412:         t->t_dcar = syn2(p1, p, flags);
 413:         t->t_dcdr = syn1b(p->next, p2, flags);
 414:         t->t_dflg = 0;
 415:         return (t);
 416:         }
 417:         continue;
 418:     }
 419:     return (syn2(p1, p2, flags));
 420: }
 421: 
 422: /*
 423:  * syn2
 424:  *	syn3
 425:  *	syn3 | syn2
 426:  *	syn3 |& syn2
 427:  */
 428: static struct command *
 429: syn2(p1, p2, flags)
 430:     struct wordent *p1, *p2;
 431:     int     flags;
 432: {
 433:     register struct wordent *p, *pn;
 434:     register struct command *t;
 435:     register int l = 0;
 436:     int     f;
 437: 
 438:     for (p = p1; p != p2; p = p->next)
 439:     switch (p->word[0]) {
 440: 
 441:     case '(':
 442:         l++;
 443:         continue;
 444: 
 445:     case ')':
 446:         l--;
 447:         continue;
 448: 
 449:     case '|':
 450:         if (l != 0)
 451:         continue;
 452:         t = (struct command *) xcalloc(1, sizeof(*t));
 453:         f = flags | P_OUT;
 454:         pn = p->next;
 455:         if (pn != p2 && pn->word[0] == '&') {
 456:         f |= P_DIAG;
 457:         t->t_dflg |= F_STDERR;
 458:         }
 459:         t->t_dtyp = NODE_PIPE;
 460:         t->t_dcar = syn3(p1, p, f);
 461:         if (pn != p2 && pn->word[0] == '&')
 462:         p = pn;
 463:         t->t_dcdr = syn2(p->next, p2, flags | P_IN);
 464:         return (t);
 465:     }
 466:     return (syn3(p1, p2, flags));
 467: }
 468: 
 469: static char RELPAR[] = {'<', '>', '(', ')', '\0'};
 470: 
 471: /*
 472:  * syn3
 473:  *	( syn0 ) [ < in  ] [ > out ]
 474:  *	word word* [ < in ] [ > out ]
 475:  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
 476:  *
 477:  *	KEYWORD = (@ exit foreach if set switch test while)
 478:  */
 479: static struct command *
 480: syn3(p1, p2, flags)
 481:     struct wordent *p1, *p2;
 482:     int     flags;
 483: {
 484:     register struct wordent *p;
 485:     struct wordent *lp, *rp;
 486:     register struct command *t;
 487:     register int l;
 488:     Char  **av;
 489:     int     n, c;
 490:     bool    specp = 0;
 491: 
 492:     if (p1 != p2) {
 493:     p = p1;
 494: again:
 495:     switch (srchx(p->word)) {
 496: 
 497:     case T_ELSE:
 498:         p = p->next;
 499:         if (p != p2)
 500:         goto again;
 501:         break;
 502: 
 503:     case T_EXIT:
 504:     case T_FOREACH:
 505:     case T_IF:
 506:     case T_LET:
 507:     case T_SET:
 508:     case T_SWITCH:
 509:     case T_WHILE:
 510:         specp = 1;
 511:         break;
 512:     }
 513:     }
 514:     n = 0;
 515:     l = 0;
 516:     for (p = p1; p != p2; p = p->next)
 517:     switch (p->word[0]) {
 518: 
 519:     case '(':
 520:         if (specp)
 521:         n++;
 522:         l++;
 523:         continue;
 524: 
 525:     case ')':
 526:         if (specp)
 527:         n++;
 528:         l--;
 529:         continue;
 530: 
 531:     case '>':
 532:     case '<':
 533:         if (l != 0) {
 534:         if (specp)
 535:             n++;
 536:         continue;
 537:         }
 538:         if (p->next == p2)
 539:         continue;
 540:         if (any(RELPAR, p->next->word[0]))
 541:         continue;
 542:         n--;
 543:         continue;
 544: 
 545:     default:
 546:         if (!specp && l != 0)
 547:         continue;
 548:         n++;
 549:         continue;
 550:     }
 551:     if (n < 0)
 552:     n = 0;
 553:     t = (struct command *) xcalloc(1, sizeof(*t));
 554:     av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
 555:     t->t_dcom = av;
 556:     n = 0;
 557:     if (p2->word[0] == ')')
 558:     t->t_dflg = F_NOFORK;
 559:     lp = 0;
 560:     rp = 0;
 561:     l = 0;
 562:     for (p = p1; p != p2; p = p->next) {
 563:     c = p->word[0];
 564:     switch (c) {
 565: 
 566:     case '(':
 567:         if (l == 0) {
 568:         if (lp != 0 && !specp)
 569:             seterror(ERR_BADPLP);
 570:         lp = p->next;
 571:         }
 572:         l++;
 573:         goto savep;
 574: 
 575:     case ')':
 576:         l--;
 577:         if (l == 0)
 578:         rp = p;
 579:         goto savep;
 580: 
 581:     case '>':
 582:         if (l != 0)
 583:         goto savep;
 584:         if (p->word[1] == '>')
 585:         t->t_dflg |= F_APPEND;
 586:         if (p->next != p2 && eq(p->next->word, STRand)) {
 587:         t->t_dflg |= F_STDERR, p = p->next;
 588:         if (flags & (P_OUT | P_DIAG)) {
 589:             seterror(ERR_OUTRED);
 590:             continue;
 591:         }
 592:         }
 593:         if (p->next != p2 && eq(p->next->word, STRbang))
 594:         t->t_dflg |= F_OVERWRITE, p = p->next;
 595:         if (p->next == p2) {
 596:         seterror(ERR_MISRED);
 597:         continue;
 598:         }
 599:         p = p->next;
 600:         if (any(RELPAR, p->word[0])) {
 601:         seterror(ERR_MISRED);
 602:         continue;
 603:         }
 604:         if ((flags & P_OUT) && (flags & P_DIAG) == 0 || t->t_drit)
 605:         seterror(ERR_OUTRED);
 606:         else
 607:         t->t_drit = Strsave(p->word);
 608:         continue;
 609: 
 610:     case '<':
 611:         if (l != 0)
 612:         goto savep;
 613:         if (p->word[1] == '<')
 614:         t->t_dflg |= F_READ;
 615:         if (p->next == p2) {
 616:         seterror(ERR_MISRED);
 617:         continue;
 618:         }
 619:         p = p->next;
 620:         if (any(RELPAR, p->word[0])) {
 621:         seterror(ERR_MISRED);
 622:         continue;
 623:         }
 624:         if ((flags & P_HERE) && (t->t_dflg & F_READ))
 625:         seterror(ERR_REDPAR);
 626:         else if ((flags & P_IN) || t->t_dlef)
 627:         seterror(ERR_INRED);
 628:         else
 629:         t->t_dlef = Strsave(p->word);
 630:         continue;
 631: 
 632:     savep:
 633:         if (!specp)
 634:         continue;
 635:     default:
 636:         if (l != 0 && !specp)
 637:         continue;
 638:         if (seterr == 0)
 639:         av[n] = Strsave(p->word);
 640:         n++;
 641:         continue;
 642:     }
 643:     }
 644:     if (lp != 0 && !specp) {
 645:     if (n != 0)
 646:         seterror(ERR_BADPLPS);
 647:     t->t_dtyp = NODE_PAREN;
 648:     t->t_dspr = syn0(lp, rp, P_HERE);
 649:     }
 650:     else {
 651:     if (n == 0)
 652:         seterror(ERR_NULLCOM);
 653:     t->t_dtyp = NODE_COMMAND;
 654:     }
 655:     return (t);
 656: }
 657: 
 658: void
 659: freesyn(t)
 660:     register struct command *t;
 661: {
 662:     register Char **v;
 663: 
 664:     if (t == 0)
 665:     return;
 666:     switch (t->t_dtyp) {
 667: 
 668:     case NODE_COMMAND:
 669:     for (v = t->t_dcom; *v; v++)
 670:         xfree((ptr_t) * v);
 671:     xfree((ptr_t) (t->t_dcom));
 672:     xfree((ptr_t) t->t_dlef);
 673:     xfree((ptr_t) t->t_drit);
 674:     break;
 675:     case NODE_PAREN:
 676:     freesyn(t->t_dspr);
 677:     xfree((ptr_t) t->t_dlef);
 678:     xfree((ptr_t) t->t_drit);
 679:     break;
 680: 
 681:     case NODE_AND:
 682:     case NODE_OR:
 683:     case NODE_PIPE:
 684:     case NODE_LIST:
 685:     freesyn(t->t_dcar), freesyn(t->t_dcdr);
 686:     break;
 687:     }
 688:     xfree((ptr_t) t);
 689: }

Defined functions

asyn0 defined in line 102; used 2 times
asyn3 defined in line 142; used 2 times
asyntax defined in line 89; used 2 times
freenod defined in line 193; used 1 times
rcsid defined in line 39; never used
syn0 defined in line 238; used 2 times
syn1 defined in line 306; used 2 times
syn1a defined in line 347; used 3 times
syn1b defined in line 388; used 3 times
syn2 defined in line 428; used 3 times
syn3 defined in line 479; used 2 times

Defined variables

RELPAR defined in line 469; used 3 times
aleft defined in line 67; used 2 times

Defined macros

ALEFT defined in line 59; used 1 times
  • in line 75
HLEFT defined in line 60; used 1 times
  • in line 76
P_DIAG defined in line 212; used 3 times
P_HERE defined in line 209; used 2 times
P_IN defined in line 210; used 2 times
P_OUT defined in line 211; used 3 times
Last modified: 1991-08-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3517
Valid CSS Valid XHTML 1.0 Strict