home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / sh / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-12  |  6.0 KB  |  407 lines

  1. #
  2. /*
  3.  * UNIX shell
  4.  *
  5.  * S. R. Bourne
  6.  * Bell Telephone Laboratories
  7.  *
  8.  */
  9.  
  10. #include    "defs.h"
  11. #include    "sym.h"
  12.  
  13. PROC IOPTR    inout();
  14. PROC VOID    chkword();
  15. PROC VOID    chksym();
  16. PROC TREPTR    term();
  17. PROC TREPTR    makelist();
  18. PROC TREPTR    list();
  19. PROC REGPTR    syncase();
  20. PROC TREPTR    item();
  21. PROC VOID    skipnl();
  22. PROC VOID    prsym();
  23. PROC VOID    synbad();
  24.  
  25.  
  26. /* ========    command line decoding    ========*/
  27.  
  28.  
  29.  
  30.  
  31. TREPTR    makefork(flgs, i)
  32.     INT        flgs;
  33.     TREPTR        i;
  34. {
  35.     REG TREPTR    t;
  36.  
  37.     t=getstak(FORKTYPE);
  38.     t->forktyp=flgs|TFORK; t->forktre=i; t->forkio=0;
  39.     return(t);
  40. }
  41.  
  42. LOCAL TREPTR    makelist(type,i,r)
  43.     INT        type;
  44.     TREPTR        i, r;
  45. {
  46.     REG TREPTR    t;
  47.  
  48.     IF i==0 ORF r==0
  49.     THEN    synbad();
  50.     ELSE    t = getstak(LSTTYPE);
  51.         t->lsttyp = type;
  52.         t->lstlef = i; t->lstrit = r;
  53.     FI
  54.     return(t);
  55. }
  56.  
  57. /*
  58.  * cmd
  59.  *    empty
  60.  *    list
  61.  *    list & [ cmd ]
  62.  *    list [ ; cmd ]
  63.  */
  64.  
  65. TREPTR    cmd(sym,flg)
  66.     REG INT        sym;
  67.     INT        flg;
  68. {
  69.     REG TREPTR    i, e;
  70.  
  71.     i = list(flg);
  72.  
  73.     IF wdval==NL
  74.     THEN    IF flg&NLFLG
  75.         THEN    wdval=';'; chkpr(NL);
  76.         FI
  77.     ELIF i==0 ANDF (flg&MTFLG)==0
  78.     THEN    synbad();
  79.     FI
  80.  
  81.     SWITCH wdval IN
  82.  
  83.         case '&':
  84.         IF i
  85.         THEN    i = makefork(FINT|FPRS|FAMP, i);
  86.         ELSE    synbad();
  87.         FI
  88.  
  89.         case ';':
  90.         IF e=cmd(sym,flg|MTFLG)
  91.         THEN    i=makelist(TLST, i, e);
  92.         FI
  93.         break;
  94.  
  95.         case EOFSYM:
  96.         IF sym==NL
  97.         THEN    break;
  98.         FI
  99.  
  100.         default:
  101.         IF sym
  102.         THEN    chksym(sym);
  103.         FI
  104.  
  105.     ENDSW
  106.     return(i);
  107. }
  108.  
  109. /*
  110.  * list
  111.  *    term
  112.  *    list && term
  113.  *    list || term
  114.  */
  115.  
  116. LOCAL TREPTR    list(flg)
  117. {
  118.     REG TREPTR    r;
  119.     REG INT        b;
  120.  
  121.     r = term(flg);
  122.     WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM)
  123.     DO    r = makelist((b ? TAND : TORF), r, term(NLFLG));
  124.     OD
  125.     return(r);
  126. }
  127.  
  128. /*
  129.  * term
  130.  *    item
  131.  *    item |^ term
  132.  */
  133.  
  134. LOCAL TREPTR    term(flg)
  135. {
  136.     REG TREPTR    t;
  137.  
  138.     reserv++;
  139.     IF flg&NLFLG
  140.     THEN    skipnl();
  141.     ELSE    word();
  142.     FI
  143.  
  144.     IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|')
  145.     THEN    return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG))));
  146.     ELSE    return(t);
  147.     FI
  148. }
  149.  
  150. LOCAL REGPTR    syncase(esym)
  151.     REG INT    esym;
  152. {
  153.     skipnl();
  154.     IF wdval==esym
  155.     THEN    return(0);
  156.     ELSE    REG REGPTR    r=getstak(REGTYPE);
  157.         r->regptr=0;
  158.         LOOP wdarg->argnxt=r->regptr;
  159.              r->regptr=wdarg;
  160.              IF wdval ORF ( word()!=')' ANDF wdval!='|' )
  161.              THEN synbad();
  162.              FI
  163.              IF wdval=='|'
  164.              THEN word();
  165.              ELSE break;
  166.              FI
  167.         POOL
  168.         r->regcom=cmd(0,NLFLG|MTFLG);
  169.         IF wdval==ECSYM
  170.         THEN    r->regnxt=syncase(esym);
  171.         ELSE    chksym(esym);
  172.             r->regnxt=0;
  173.         FI
  174.         return(r);
  175.     FI
  176. }
  177.  
  178. /*
  179.  * item
  180.  *
  181.  *    ( cmd ) [ < in  ] [ > out ]
  182.  *    word word* [ < in ] [ > out ]
  183.  *    if ... then ... else ... fi
  184.  *    for ... while ... do ... done
  185.  *    case ... in ... esac
  186.  *    begin ... end
  187.  */
  188.  
  189. LOCAL TREPTR    item(flag)
  190.     BOOL        flag;
  191. {
  192.     REG TREPTR    t;
  193.     REG IOPTR    io;
  194.  
  195.     IF flag
  196.     THEN    io=inout((IOPTR)0);
  197.     ELSE    io=0;
  198.     FI
  199.  
  200.     SWITCH wdval IN
  201.  
  202.         case CASYM:
  203.         BEGIN
  204.            t=getstak(SWTYPE);
  205.            chkword();
  206.            t->swarg=wdarg->argval;
  207.            skipnl(); chksym(INSYM|BRSYM);
  208.            t->swlst=syncase(wdval==INSYM?ESSYM:KTSYM);
  209.            t->swtyp=TSW;
  210.            break;
  211.         END
  212.  
  213.         case IFSYM:
  214.         BEGIN
  215.            REG INT    w;
  216.            t=getstak(IFTYPE);
  217.            t->iftyp=TIF;
  218.            t->iftre=cmd(THSYM,NLFLG);
  219.            t->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG);
  220.            t->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0));
  221.            IF w==EFSYM THEN return(t) FI
  222.            break;
  223.         END
  224.  
  225.         case FORSYM:
  226.         BEGIN
  227.            t=getstak(FORTYPE);
  228.            t->fortyp=TFOR;
  229.            t->forlst=0;
  230.            chkword();
  231.            t->fornam=wdarg->argval;
  232.            IF skipnl()==INSYM
  233.            THEN    chkword();
  234.             t->forlst=item(0);
  235.             IF wdval!=NL ANDF wdval!=';'
  236.             THEN    synbad();
  237.             FI
  238.             chkpr(wdval); skipnl();
  239.            FI
  240.            chksym(DOSYM|BRSYM);
  241.            t->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG);
  242.            break;
  243.         END
  244.  
  245.         case WHSYM:
  246.         case UNSYM:
  247.         BEGIN
  248.            t=getstak(WHTYPE);
  249.            t->whtyp=(wdval==WHSYM ? TWH : TUN);
  250.            t->whtre = cmd(DOSYM,NLFLG);
  251.            t->dotre = cmd(ODSYM,NLFLG);
  252.            break;
  253.         END
  254.  
  255.         case BRSYM:
  256.         t=cmd(KTSYM,NLFLG);
  257.         break;
  258.  
  259.         case '(':
  260.         BEGIN
  261.            REG PARPTR     p;
  262.            p=getstak(PARTYPE);
  263.            p->partre=cmd(')',NLFLG);
  264.            p->partyp=TPAR;
  265.            t=makefork(0,p);
  266.            break;
  267.         END
  268.  
  269.         default:
  270.         IF io==0
  271.         THEN    return(0);
  272.         FI
  273.  
  274.         case 0:
  275.         BEGIN
  276.            REG ARGPTR    argp;
  277.            REG ARGPTR    *argtail;
  278.            REG ARGPTR    *argset=0;
  279.            INT        keywd=1;
  280.            t=getstak(COMTYPE);
  281.            t->comio=io; /*initial io chain*/
  282.            argtail = &(t->comarg);
  283.            WHILE wdval==0
  284.            DO    argp = wdarg;
  285.             IF wdset ANDF keywd
  286.             THEN    argp->argnxt=argset; argset=argp;
  287.             ELSE    *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg;
  288.             FI
  289.             word();
  290.             IF flag
  291.             THEN t->comio=inout(t->comio);
  292.             FI
  293.            OD
  294.  
  295.            t->comtyp=TCOM; t->comset=argset; *argtail=0;
  296.            return(t);
  297.         END
  298.  
  299.     ENDSW
  300.     reserv++; word();
  301.     IF io=inout(io)
  302.     THEN    t=makefork(0,t); t->treio=io;
  303.     FI
  304.     return(t);
  305. }
  306.  
  307.  
  308. LOCAL VOID    skipnl()
  309. {
  310.     WHILE (reserv++, word()==NL) DO chkpr(NL) OD
  311.     return(wdval);
  312. }
  313.  
  314. LOCAL IOPTR    inout(lastio)
  315.     IOPTR        lastio;
  316. {
  317.     REG INT        iof;
  318.     REG IOPTR    iop;
  319.     REG CHAR    c;
  320.  
  321.     iof=wdnum;
  322.  
  323.     SWITCH wdval IN
  324.  
  325.         case DOCSYM:
  326.         iof |= IODOC; break;
  327.  
  328.         case APPSYM:
  329.         case '>':
  330.         IF wdnum==0 THEN iof |= 1 FI
  331.         iof |= IOPUT;
  332.         IF wdval==APPSYM
  333.         THEN    iof |= IOAPP; break;
  334.         FI
  335.  
  336.         case '<':
  337.         IF (c=nextc(0))=='&'
  338.         THEN    iof |= IOMOV;
  339.         ELIF c=='>'
  340.         THEN    iof |= IORDW;
  341.         ELSE    peekc=c|MARK;
  342.         FI
  343.         break;
  344.  
  345.         default:
  346.         return(lastio);
  347.     ENDSW
  348.  
  349.     chkword();
  350.     iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof;
  351.     IF iof&IODOC
  352.     THEN iop->iolst=iopend; iopend=iop;
  353.     FI
  354.     word(); iop->ionxt=inout(lastio);
  355.     return(iop);
  356. }
  357.  
  358. LOCAL VOID    chkword()
  359. {
  360.     IF word()
  361.     THEN    synbad();
  362.     FI
  363. }
  364.  
  365. LOCAL VOID    chksym(sym)
  366. {
  367.     REG INT        x = sym&wdval;
  368.     IF ((x&SYMFLG) ? x : sym) != wdval
  369.     THEN    synbad();
  370.     FI
  371. }
  372.  
  373. LOCAL VOID    prsym(sym)
  374. {
  375.     IF sym&SYMFLG
  376.     THEN    REG SYSPTR    sp=reserved;
  377.         WHILE sp->sysval
  378.             ANDF sp->sysval!=sym
  379.         DO sp++ OD
  380.         prs(sp->sysnam);
  381.     ELIF sym==EOFSYM
  382.     THEN    prs(endoffile);
  383.     ELSE    IF sym&SYMREP THEN prc(sym) FI
  384.         IF sym==NL
  385.         THEN    prs("newline");
  386.         ELSE    prc(sym);
  387.         FI
  388.     FI
  389. }
  390.  
  391. LOCAL VOID    synbad()
  392. {
  393.     prp(); prs(synmsg);
  394.     IF (flags&ttyflg)==0
  395.     THEN    prs(atline); prn(standin->flin);
  396.     FI
  397.     prs(colon);
  398.     prc(LQ);
  399.     IF wdval
  400.     THEN    prsym(wdval);
  401.     ELSE    prs(wdarg->argval);
  402.     FI
  403.     prc(RQ); prs(unexpected);
  404.     newline();
  405.     exitsh(SYNBAD);
  406. }
  407.