home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / zsh / Source / src / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-07  |  23.3 KB  |  1,253 lines

  1. /*
  2.  *
  3.  * parse.c - parser
  4.  *
  5.  * This file is part of zsh, the Z shell.
  6.  *
  7.  * This software is Copyright 1992 by Paul Falstad
  8.  *
  9.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  10.  * use this software as long as: there is no monetary profit gained
  11.  * specifically from the use or reproduction of this software, it is not
  12.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  13.  * included prominently in any copy made.
  14.  *
  15.  * The author make no claims as to the fitness or correctness of this software
  16.  * for any use whatsoever, and it is provided as is. Any use of this software
  17.  * is at the user's own risk.
  18.  *
  19.  */
  20.  
  21. #include "zsh.h"
  22.  
  23. #define YYERROR { tok = LEXERR; return NULL; }
  24. #define YYERRORV { tok = LEXERR; return; }
  25.  
  26. #define make_list() allocnode(N_LIST)
  27. #define make_sublist() allocnode(N_SUBLIST)
  28. #define make_pline() allocnode(N_PLINE)
  29. #define make_cmd() allocnode(N_CMD)
  30. #define make_forcmd() allocnode(N_FOR)
  31. #define make_casecmd() allocnode(N_CASE)
  32. #define make_ifcmd() allocnode(N_IF)
  33. #define make_whilecmd() allocnode(N_WHILE)
  34. #define make_varnode() allocnode(N_VARASG)
  35. #define make_cond() allocnode(N_COND)
  36.  
  37. /*
  38.  * event    : ENDINPUT
  39.  *            | SEPER
  40.  *            | sublist [ SEPER | AMPER ]
  41.  */
  42. List parse_event()
  43. {                /**/
  44.     tok = ENDINPUT;
  45.     incmdpos = 1;
  46.     yylex();
  47.     return par_event();
  48. }
  49.  
  50. List par_event()
  51. {                /**/
  52.     Sublist sl;
  53.     List l = NULL;
  54.  
  55.     while (tok == SEPER) {
  56.     if (isnewlin > 0)
  57.         return NULL;
  58.     yylex();
  59.     }
  60.     if (tok == ENDINPUT)
  61.     return NULL;
  62.     if ((sl = par_sublist()))
  63.     if (tok == ENDINPUT) {
  64.         l = (List) make_list();
  65.         l->type = SYNC;
  66.         l->left = sl;
  67.     } else if (tok == SEPER) {
  68.         l = (List) make_list();
  69.         l->type = SYNC;
  70.         l->left = sl;
  71.         if (isnewlin <= 0)
  72.         yylex();
  73.     } else if (tok == AMPER) {
  74.         l = (List) make_list();
  75.         l->type = ASYNC;
  76.         l->left = sl;
  77.         yylex();
  78.     } else
  79.         l = NULL;
  80.     if (!l) {
  81.     if (errflag) {
  82.         yyerror();
  83.         return NULL;
  84.     }
  85.     yyerror();
  86.     errflag = 0;
  87.     if (isnewlin <= 0) {
  88.         int c;
  89.  
  90.         hwbegin();
  91.         while ((c = hgetc()) != '\n' && !lexstop);
  92.         if (c == '\n')
  93.         hungetc('\n');
  94.         hwaddc(HISTSPACE);
  95.         hwadd();
  96.     }
  97.     errflag = 1;
  98.     return NULL;
  99.     } else {
  100.     l->right = par_event();
  101.     }
  102.     return l;
  103. }
  104.  
  105. List parse_list()
  106. {                /**/
  107.     List ret;
  108.     tok = ENDINPUT;
  109.     incmdpos = 1;
  110.     yylex();
  111.     ret = par_list();
  112.     if (tok == LEXERR) {
  113.     yyerror();
  114.     return NULL;
  115.     }
  116.     return ret;
  117. }
  118.  
  119. /*
  120.  * list    : { SEPER } [ sublist [ { SEPER | AMPER } list ] ]
  121.  */
  122. List par_list()
  123. {                /**/
  124.     Sublist sl;
  125.     List l = NULL;
  126.  
  127.     while (tok == SEPER)
  128.     yylex();
  129.     if ((sl = par_sublist()))
  130.     if (tok == SEPER || tok == AMPER) {
  131.         l = (List) make_list();
  132.         l->left = sl;
  133.         l->type = (tok == SEPER) ? SYNC : ASYNC;
  134.         incmdpos = 1;
  135.         while (tok == SEPER || tok == AMPER)
  136.         yylex();
  137.         l->right = par_list();
  138.     } else {
  139.         l = (List) make_list();
  140.         l->left = sl;
  141.         l->type = SYNC;
  142.     }
  143.     return l;
  144. }
  145.  
  146. List par_list1()
  147. {                /**/
  148.     Sublist sl;
  149.     List l = NULL;
  150.  
  151.     if ((sl = par_sublist())) {
  152.     l = (List) make_list();
  153.     l->type = SYNC;
  154.     l->left = sl;
  155.     }
  156.     return l;
  157. }
  158.  
  159. /*
  160.  * sublist    : sublist2 [ ( DBAR | DAMPER ) { SEPER } sublist ]
  161.  */
  162. Sublist par_sublist()
  163. {                /**/
  164.     Sublist sl;
  165.  
  166.     if ((sl = par_sublist2()))
  167.     if (tok == DBAR || tok == DAMPER) {
  168.         int qtok = tok;
  169.  
  170.         cmdpush(tok == DBAR ? CS_CMDOR : CS_CMDAND);
  171.         yylex();
  172.         while (tok == SEPER)
  173.         yylex();
  174.         sl->right = par_sublist();
  175.         sl->type = (qtok == DBAR) ? ORNEXT : ANDNEXT;
  176.         cmdpop();
  177.     }
  178.     return sl;
  179. }
  180.  
  181. /*
  182.  * sublist2    : [ COPROC | BANG ] pline
  183.  */
  184. Sublist par_sublist2()
  185. {                /**/
  186.     Sublist sl;
  187.     Pline p;
  188.  
  189.     sl = (Sublist) make_sublist();
  190.     if (tok == COPROC) {
  191.     sl->flags |= PFLAG_COPROC;
  192.     yylex();
  193.     } else if (tok == BANG) {
  194.     sl->flags |= PFLAG_NOT;
  195.     yylex();
  196.     }
  197.     if (!(p = par_pline()) && !sl->flags)
  198.     return NULL;
  199.     sl->left = p;
  200.     return sl;
  201. }
  202.  
  203. /*
  204.  * pline    : cmd [ ( BAR | BARAMP ) { SEPER } pline ]
  205.  */
  206. Pline par_pline()
  207. {                /**/
  208.     Cmd c;
  209.     Pline p, p2;
  210.  
  211.     if (!(c = par_cmd()))
  212.     return NULL;
  213.     if (tok == BAR) {
  214.     c->flags &= ~CFLAG_EXEC;
  215.     cmdpush(CS_PIPE);
  216.     yylex();
  217.     while (tok == SEPER)
  218.         yylex();
  219.     p2 = par_pline();
  220.     cmdpop();
  221.     p = (Pline) make_pline();
  222.     p->left = c;
  223.     p->right = p2;
  224.     p->type = PIPE;
  225.     return p;
  226.     } else if (tok == BARAMP) {
  227.     struct redir *rdr = (struct redir *)allocnode(N_REDIR);
  228.  
  229.     c->flags &= ~CFLAG_EXEC;
  230.     rdr->type = MERGEOUT;
  231.     rdr->fd1 = 2;
  232.     rdr->fd2 = 1;
  233.     addnode(c->redir, rdr);
  234.  
  235.     cmdpush(CS_ERRPIPE);
  236.     yylex();
  237.     p2 = par_pline();
  238.     cmdpop();
  239.     p = (Pline) make_pline();
  240.     p->left = c;
  241.     p->right = p2;
  242.     p->type = PIPE;
  243.     return p;
  244.     } else {
  245.     p = (Pline) make_pline();
  246.     p->left = c;
  247.     p->type = END;
  248.     return p;
  249.     }
  250. }
  251.  
  252. /*
  253.  * cmd    : { redir } ( for | case | if | while | repeat |
  254.  *                subsh | funcdef | time | dinbrack | dinpar | simple ) { redir }
  255.  */
  256. Cmd par_cmd()
  257. {                /**/
  258.     Cmd c;
  259.  
  260.     c = (Cmd) make_cmd();
  261.     c->args = newlist();
  262.     c->redir = newlist();
  263.     c->vars = newlist();
  264.     while (IS_REDIROP(tok))
  265.     par_redir(c->redir);
  266.     switch (tok) {
  267.     case FOR:
  268.     cmdpush(CS_FOR);
  269.     par_for(c);
  270.     cmdpop();
  271.     break;
  272.     case FOREACH:
  273.     cmdpush(CS_FOREACH);
  274.     par_for(c);
  275.     cmdpop();
  276.     break;
  277.     case SELECT:
  278.     cmdpush(CS_SELECT);
  279.     par_for(c);
  280.     cmdpop();
  281.     break;
  282.     case CASE:
  283.     cmdpush(CS_CASE);
  284.     par_case(c);
  285.     cmdpop();
  286.     break;
  287.     case IF:
  288.     par_if(c);
  289.     break;
  290.     case WHILE:
  291.     cmdpush(CS_WHILE);
  292.     par_while(c);
  293.     cmdpop();
  294.     break;
  295.     case UNTIL:
  296.     cmdpush(CS_UNTIL);
  297.     par_while(c);
  298.     cmdpop();
  299.     break;
  300.     case REPEAT:
  301.     cmdpush(CS_REPEAT);
  302.     par_repeat(c);
  303.     cmdpop();
  304.     break;
  305.     case INPAR:
  306.     cmdpush(CS_SUBSH);
  307.     par_subsh(c);
  308.     cmdpop();
  309.     break;
  310.     case INBRACE:
  311.     cmdpush(CS_CURSH);
  312.     par_subsh(c);
  313.     cmdpop();
  314.     break;
  315.     case FUNC:
  316.     cmdpush(CS_FUNCDEF);
  317.     par_funcdef(c);
  318.     cmdpop();
  319.     break;
  320.     case TIME:
  321.     par_time(c);
  322.     break;
  323.     case DINBRACK:
  324.     cmdpush(CS_COND);
  325.     par_dinbrack(c);
  326.     cmdpop();
  327.     break;
  328.     case DINPAR:
  329.     cmdpush(CS_MATH);
  330.     par_dinpar(c);
  331.     cmdpop();
  332.     break;
  333.     default:
  334.     if (!par_simple(c))
  335.         return NULL;
  336.     break;
  337.     }
  338.     while (IS_REDIROP(tok))
  339.     par_redir(c->redir);
  340.     incmdpos = 1;
  341.     incasepat = 0;
  342.     incond = 0;
  343.     return c;
  344. }
  345.  
  346. /*
  347.  * for    : ( FOR[EACH] | SELECT ) name ( "in" wordlist | INPAR wordlist OUTPAR )
  348.                 { SEPER } ( DO list DONE | INBRACE list OUTBRACE |
  349.                 list ZEND | list1 )
  350.  */
  351. void par_for(c)            /**/
  352. Cmd c;
  353. {
  354.     struct forcmd *f;
  355.     int csh = (tok == FOREACH || isset(CSHJUNKIELOOPS));
  356.  
  357.     f = (struct forcmd *)make_forcmd();
  358.     c->type = (tok == SELECT) ? CSELECT : CFOR;
  359.     incmdpos = 0;
  360.     yylex();
  361.     if (tok != STRING || !isident(tokstr))
  362.     YYERRORV;
  363.     f->name = tokstr;
  364.     incmdpos = 1;
  365.     yylex();
  366.     if (tok == STRING && !strcmp(tokstr, "in")) {
  367.     f->inflag = 1;
  368.     incmdpos = 0;
  369.     yylex();
  370.     c->args = par_wordlist();
  371.     if (tok != SEPER)
  372.         YYERRORV;
  373.     } else if (tok == INPAR) {
  374.     f->inflag = 1;
  375.     incmdpos = 0;
  376.     yylex();
  377.     c->args = par_nl_wordlist();
  378.     if (tok != OUTPAR)
  379.         YYERRORV;
  380.     incmdpos = 1;
  381.     yylex();
  382.     }
  383.     incmdpos = 1;
  384.     while (tok == SEPER)
  385.     yylex();
  386.     if (tok == DO) {
  387.     yylex();
  388.     f->list = par_list();
  389.     if (tok != DONE)
  390.         YYERRORV;
  391.     yylex();
  392.     } else if (tok == INBRACE) {
  393.     yylex();
  394.     f->list = par_list();
  395.     if (tok != OUTBRACE)
  396.         YYERRORV;
  397.     yylex();
  398.     } else if (csh) {
  399.     f->list = par_list();
  400.     if (tok != ZEND)
  401.         YYERRORV;
  402.     yylex();
  403.     } else if (isset(NOSHORTLOOPS)) {
  404.     YYERRORV;
  405.     } else
  406.     f->list = par_list1();
  407.     c->u.forcmd = f;
  408. }
  409.  
  410. /*
  411.  * case    : CASE STRING { SEPER } ( "in" | INBRACE )
  412.                 { { SEPER } STRING { BAR STRING } OUTPAR list [ DSEMI ] }
  413.                 { SEPER } ( "esac" | OUTBRACE )
  414.  */
  415. void par_case(c)        /**/
  416. Cmd c;
  417. {
  418.     int brflag;
  419.     Lklist pats, lists;
  420.     int n = 0;
  421.     char **pp;
  422.     List *ll;
  423.     Lknode no;
  424.     struct casecmd *cc;
  425.  
  426.     c->type = CCASE;
  427.     incmdpos = 0;
  428.     yylex();
  429.     if (tok != STRING)
  430.     YYERRORV;
  431.     addnode(c->args, tokstr);
  432.     incmdpos = 1;
  433.     yylex();
  434.     while (tok == SEPER)
  435.     yylex();
  436.     if (!(tok == STRING && !strcmp(tokstr, "in")) && tok != INBRACE)
  437.     YYERRORV;
  438.     brflag = (tok == INBRACE);
  439.     incasepat = 1;
  440.     incmdpos = 0;
  441.     yylex();
  442.     cc = c->u.casecmd = (struct casecmd *)make_casecmd();
  443.     pats = newlist();
  444.     lists = newlist();
  445.     for (;;) {
  446.     char *str;
  447.  
  448.     while (tok == SEPER)
  449.         yylex();
  450.     if (tok == OUTBRACE) {
  451.         yylex();
  452.         break;
  453.     }
  454.     if (tok != STRING)
  455.         YYERRORV;
  456.     if (!strcmp(tokstr, "esac")) {
  457.         yylex();
  458.         break;
  459.     }
  460.     str = tokstr;
  461.     yylex();
  462.     while (tok == BAR) {
  463.         char *str2;
  464.         int sl = strlen(str);
  465.  
  466.         yylex();
  467.         if (tok != STRING)
  468.         YYERRORV;
  469.         str2 = (char *)alloc(sl + strlen(tokstr) + 2);
  470.         strcpy(str2, str);
  471.         str2[sl] = Bar;
  472.         strcpy(str2 + sl + 1, tokstr);
  473.         str = str2;
  474.         yylex();
  475.     }
  476.     if (tok != OUTPAR)
  477.         YYERRORV;
  478.     incasepat = 0;
  479.     incmdpos = 1;
  480.     yylex();
  481.     addnode(pats, str);
  482.     addnode(lists, par_list());
  483.     n++;
  484.     if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag)) {
  485.         yylex();
  486.         break;
  487.     }
  488.     if (tok != DSEMI)
  489.         YYERRORV;
  490.     incasepat = 1;
  491.     incmdpos = 0;
  492.     yylex();
  493.     }
  494.     
  495.     cc->pats = (char **) alloc((n + 1) * sizeof(char *));
  496.     for (pp = cc->pats, no = firstnode(pats); no; incnode(no))
  497.     *pp++ = (char *) getdata(no);
  498.     *pp = NULL;
  499.     cc->lists = (List *) alloc((n + 1) * sizeof(List));
  500.     for (ll = cc->lists, no = firstnode(lists); no; incnode(no), ll++)
  501.     if (!(*ll = (List) getdata(no)))
  502.         *ll = &dummy_list;
  503.     *ll = NULL;
  504. }
  505.  
  506. /*
  507.  * if    : { ( IF | ELIF ) { SEPER } ( INPAR list OUTPAR | list )
  508.             { SEPER } ( THEN list | INBRACE list OUTBRACE | list1 ) }
  509.             [ FI | ELSE list FI | ELSE { SEPER } INBRACE list OUTBRACE ]
  510.             (you get the idea...?)
  511.  */
  512. void par_if(c)            /**/
  513. Cmd c;
  514. {
  515.     struct ifcmd *i;
  516.     int xtok;
  517.     unsigned char nc;
  518.     Lklist ifsl, thensl;
  519.     Lknode no;
  520.     int ni = 0, nt = 0;
  521.     List l, *ll;
  522.  
  523.     ifsl = newlist();
  524.     thensl = newlist();
  525.  
  526.     c->type = CIF;
  527.     for (;;) {
  528.     xtok = tok;
  529.     cmdpush(xtok == IF ? CS_IF : CS_ELIF);
  530.     yylex();
  531.     if (xtok == FI)
  532.         break;
  533.     if (xtok == ELSE)
  534.         break;
  535.     while (tok == SEPER)
  536.         yylex();
  537.     if (!(xtok == IF || xtok == ELIF)) {
  538.         cmdpop();
  539.         YYERRORV;
  540.     }
  541.     if (tok == INPAR) {
  542.         yylex();
  543.         l = par_list();
  544.         if (tok != OUTPAR) {
  545.         cmdpop();
  546.         YYERRORV;
  547.         }
  548.         addnode(ifsl, l);
  549.         ni++;
  550.         incmdpos = 1;
  551.         yylex();
  552.     } else {
  553.         addnode(ifsl, par_list());
  554.         ni++;
  555.         incmdpos = 1;
  556.     }
  557.     while (tok == SEPER)
  558.         yylex();
  559.     xtok = FI;
  560.     nc = cmdstack[cmdsp - 1] == CS_IF ? CS_IFTHEN : CS_ELIFTHEN;
  561.     if (tok == THEN) {
  562.         cmdpop();
  563.         cmdpush(nc);
  564.         yylex();
  565.         addnode(thensl, par_list());
  566.         nt++;
  567.         incmdpos = 1;
  568.         cmdpop();
  569.     } else if (tok == INBRACE) {
  570.         cmdpop();
  571.         cmdpush(nc);
  572.         yylex();
  573.         l = par_list();
  574.         if (tok != OUTBRACE) {
  575.         cmdpop();
  576.         YYERRORV;
  577.         }
  578.         addnode(thensl, l);
  579.         nt++;
  580.         yylex();
  581.         incmdpos = 1;
  582.         if (tok == SEPER)
  583.         break;
  584.         cmdpop();
  585.     } else if (isset(NOSHORTLOOPS)) {
  586.         cmdpop();
  587.         YYERRORV;
  588.     } else {
  589.         cmdpop();
  590.         cmdpush(nc);
  591.         addnode(thensl, par_list1());
  592.         nt++;
  593.         cmdpop();
  594.         incmdpos = 1;
  595.         break;
  596.     }
  597.     }
  598.     cmdpop();
  599.     if (xtok == ELSE) {
  600.     cmdpush(CS_ELSE);
  601.     while (tok == SEPER)
  602.         yylex();
  603.     if (tok == INBRACE) {
  604.         yylex();
  605.         l = par_list();
  606.         if (tok != OUTBRACE) {
  607.         cmdpop();
  608.         YYERRORV;
  609.         }
  610.         addnode(thensl, l);
  611.         nt++;
  612.         yylex();
  613.     } else {
  614.         l = par_list();
  615.         if (tok != FI) {
  616.         cmdpop();
  617.         YYERRORV;
  618.         }
  619.         addnode(thensl, l);
  620.         nt++;
  621.         yylex();
  622.     }
  623.     cmdpop();
  624.     }
  625.  
  626.     i = (struct ifcmd *) make_ifcmd();
  627.     i->ifls = (List *) alloc((ni + 1) * sizeof(List));
  628.     i->thenls = (List *) alloc((nt + 1) * sizeof(List));
  629.  
  630.     for (ll = i->ifls, no = firstnode(ifsl); no; incnode(no), ll++)
  631.     if (!(*ll = (List) getdata(no)))
  632.         *ll = &dummy_list;
  633.     *ll = NULL;
  634.     for (ll = i->thenls, no = firstnode(thensl); no; incnode(no), ll++)
  635.     if(!(*ll = (List) getdata(no)))
  636.         *ll = &dummy_list;
  637.     *ll = NULL;
  638.  
  639.     c->u.ifcmd = i;
  640. }
  641.  
  642. /*
  643.  * while    : ( WHILE | UNTIL ) ( INPAR list OUTPAR | list ) { SEPER }
  644.                 ( DO list DONE | INBRACE list OUTBRACE | list ZEND )
  645.  */
  646. void par_while(c)        /**/
  647. Cmd c;
  648. {
  649.     struct whilecmd *w;
  650.  
  651.     c->type = CWHILE;
  652.     w = c->u.whilecmd = (struct whilecmd *)make_whilecmd();
  653.     w->cond = (tok == UNTIL);
  654.     yylex();
  655.     if (tok == INPAR) {
  656.     yylex();
  657.     w->cont = par_list();
  658.     if (tok != OUTPAR)
  659.         YYERRORV;
  660.     yylex();
  661.     } else {
  662.     w->cont = par_list();
  663.     }
  664.     incmdpos = 1;
  665.     while (tok == SEPER)
  666.     yylex();
  667.     if (tok == DO) {
  668.     yylex();
  669.     w->loop = par_list();
  670.     if (tok != DONE)
  671.         YYERRORV;
  672.     yylex();
  673.     } else if (tok == INBRACE) {
  674.     yylex();
  675.     w->loop = par_list();
  676.     if (tok != OUTBRACE)
  677.         YYERRORV;
  678.     yylex();
  679.     } else if (isset(CSHJUNKIELOOPS)) {
  680.     w->loop = par_list();
  681.     if (tok != ZEND)
  682.         YYERRORV;
  683.     yylex();
  684.     } else
  685.     YYERRORV;
  686. }
  687.  
  688. /*
  689.  * repeat    : REPEAT STRING { SEPER } ( DO list DONE | list1 )
  690.  */
  691. void par_repeat(c)        /**/
  692. Cmd c;
  693. {
  694.     c->type = CREPEAT;
  695.     incmdpos = 0;
  696.     yylex();
  697.     if (tok != STRING)
  698.     YYERRORV;
  699.     addnode(c->args, tokstr);
  700.     incmdpos = 1;
  701.     yylex();
  702.     while (tok == SEPER)
  703.     yylex();
  704.     if (tok == DO) {
  705.     yylex();
  706.     c->u.list = par_list();
  707.     if (tok != DONE)
  708.         YYERRORV;
  709.     yylex();
  710.     } else {
  711.     c->u.list = par_list1();
  712.     }
  713. }
  714.  
  715. /*
  716.  * subsh    : ( INPAR | INBRACE ) list ( OUTPAR | OUTBRACE )
  717.  */
  718. void par_subsh(c)        /**/
  719. Cmd c;
  720. {
  721.     c->type = (tok == INPAR) ? SUBSH : CURSH;
  722.     yylex();
  723.     c->u.list = par_list();
  724.     if (tok != ((c->type == SUBSH) ? OUTPAR : OUTBRACE))
  725.     YYERRORV;
  726.     incmdpos = 0;
  727.     yylex();
  728. }
  729.  
  730. /*
  731.  * funcdef    : FUNCTION wordlist [ INOUTPAR ] { SEPER }
  732.  *                    ( list1 | INBRACE list OUTBRACE )
  733.  */
  734. void par_funcdef(c)        /**/
  735. Cmd c;
  736. {
  737.     nocorrect = 1;
  738.     incmdpos = 0;
  739.     yylex();
  740.     c->type = FUNCDEF;
  741.     c->args = newlist();
  742.     incmdpos = 1;
  743.     while (tok == STRING) {
  744.     if (*tokstr == Inbrace && !tokstr[1]) {
  745.         tok = INBRACE;
  746.         break;
  747.     }
  748.     addnode(c->args, tokstr);
  749.     yylex();
  750.     }
  751.     nocorrect = 0;
  752.     if (tok == INOUTPAR)
  753.     yylex();
  754.     while (tok == SEPER)
  755.     yylex();
  756.     if (tok == INBRACE) {
  757.     yylex();
  758.     c->u.list = par_list();
  759.     if (tok != OUTBRACE)
  760.         YYERRORV;
  761.     yylex();
  762.     } else if (isset(NOSHORTLOOPS)) {
  763.     YYERRORV;
  764.     } else
  765.     c->u.list = par_list1();
  766. }
  767.  
  768. /*
  769.  * time    : TIME sublist2
  770.  */
  771. void par_time(c)        /**/
  772. Cmd c;
  773. {
  774.     yylex();
  775.     c->type = ZCTIME;
  776.     c->u.pline = par_sublist2();
  777. }
  778.  
  779. /*
  780.  * dinbrack    : DINBRACK cond DOUTBRACK
  781.  */
  782. void par_dinbrack(c)        /**/
  783. Cmd c;
  784. {
  785.     c->type = COND;
  786.     incond = 1;
  787.     incmdpos = 0;
  788.     yylex();
  789.     c->u.cond = par_cond();
  790.     if (tok != DOUTBRACK)
  791.     YYERRORV;
  792.     incond = 0;
  793.     incmdpos = 1;
  794.     yylex();
  795. }
  796.  
  797. /*
  798.  * dinpar : DINPAR expr DOUTPAR
  799.  */
  800. void par_dinpar(c)        /**/
  801. Cmd c;
  802. {
  803.     c->type = SIMPLE;
  804.     addnode(c->args, dupstring("builtin"));
  805.     addnode(c->args, dupstring("let"));
  806.     incmdpos = 0;
  807.     yylex();
  808.     if (tok != DOUTPAR)
  809.     YYERRORV;
  810.     addnode(c->args, tokstr);
  811.     if (underscore)
  812.     free(underscore);
  813.     underscore = ztrdup(tokstr);
  814.     untokenize(underscore);
  815.     incmdpos = 1;
  816.     yylex();
  817. }
  818.  
  819. /*
  820.  * simple    : { COMMAND | EXEC | NOGLOB | NOCORRECT | DASH }
  821.                     { STRING | ENVSTRING | ENVARRAY wordlist OUTPAR | redir }
  822.                     [ INOUTPAR { SEPER } ( list1 | INBRACE list OUTBRACE ) ]
  823.  */
  824. Cmd par_simple(c)        /**/
  825. Cmd c;
  826. {
  827.     int isnull = 1;
  828.  
  829.     c->type = SIMPLE;
  830.     for (;;) {
  831.     if (tok == COMMAND)
  832.         c->flags |= CFLAG_COMMAND;
  833.     else if (tok == EXEC)
  834.         c->flags |= CFLAG_EXEC;
  835.     else if (tok == NOGLOB)
  836.         c->flags |= CFLAG_NOGLOB;
  837.     else if (tok == NOCORRECT)
  838.         nocorrect = 1;
  839.     else if (tok == DASH)
  840.         c->flags = CFLAG_DASH;
  841.     else
  842.         break;
  843.     yylex();
  844.     }
  845.     if (tok == AMPER)
  846.     YYERROR;
  847.     for (;;) {
  848.     if (tok == STRING) {
  849.         incmdpos = 0;
  850.         addnode(c->args, tokstr);
  851.         yylex();
  852.     } else if (tok == ENVSTRING) {
  853.         struct varasg *v = (struct varasg *)make_varnode();
  854.  
  855.         v->type = PMFLAG_s;
  856.         equalsplit(v->name = tokstr, &v->str);
  857.         addnode(c->vars, v);
  858.         yylex();
  859.     } else if (tok == ENVARRAY) {
  860.         struct varasg *v = (struct varasg *)make_varnode();
  861.         int oldcmdpos = incmdpos;
  862.  
  863.         v->type = PMFLAG_A;
  864.         incmdpos = 0;
  865.         v->name = tokstr;
  866.         cmdpush(CS_ARRAY);
  867.         yylex();
  868.         v->arr = par_nl_wordlist();
  869.         cmdpop();
  870.         if (tok != OUTPAR)
  871.         YYERROR;
  872.         incmdpos = oldcmdpos;
  873.         yylex();
  874.         addnode(c->vars, v);
  875.     } else if (IS_REDIROP(tok)) {
  876.         par_redir(c->redir);
  877.     } else if (tok == INOUTPAR) {
  878.         incmdpos = 1;
  879.         cmdpush(CS_FUNCDEF);
  880.         yylex();
  881.         while (tok == SEPER)
  882.         yylex();
  883.         if (tok == INBRACE) {
  884.         yylex();
  885.         c->u.list = par_list();
  886.         if (tok != OUTBRACE) {
  887.             cmdpop();
  888.             YYERROR;
  889.         }
  890.         yylex();
  891.         } else if (isset(NOSHORTLOOPS)) {
  892.         cmdpop();
  893.         YYERROR;
  894.         } else
  895.         c->u.list = par_list1();
  896.         cmdpop();
  897.         c->type = FUNCDEF;
  898.     } else
  899.         break;
  900.     isnull = 0;
  901.     }
  902.     if (isnull && empty(c->redir))
  903.     return NULL;
  904.     if (full(c->args)) {
  905.     if (underscore)
  906.         free(underscore);
  907.     underscore = ztrdup(getdata(lastnode(c->args)));
  908.     untokenize(underscore);
  909.     }
  910.     incmdpos = 1;
  911.     return c;
  912. }
  913.  
  914. /*
  915.  * cond    : cond_1 { SEPER } [ DBAR { SEPER } cond ]
  916.  */
  917. Cond par_cond()
  918. {                /**/
  919.     Cond c, c2;
  920.  
  921.     c = par_cond_1();
  922.     while (tok == SEPER)
  923.     yylex();
  924.     if (tok == DBAR) {
  925.     yylex();
  926.     while (tok == SEPER)
  927.         yylex();
  928.     c2 = (Cond) make_cond();
  929.     c2->left = (vptr) c;
  930.     c2->right = (vptr) par_cond();
  931.     c2->type = COND_OR;
  932.     return c2;
  933.     }
  934.     return c;
  935. }
  936.  
  937. /*
  938.  * cond_1 : cond_2 { SEPER } [ DAMPER { SEPER } cond_1 ]
  939.  */
  940. Cond par_cond_1()
  941. {                /**/
  942.     Cond c, c2;
  943.  
  944.     c = par_cond_2();
  945.     while (tok == SEPER)
  946.     yylex();
  947.     if (tok == DAMPER) {
  948.     yylex();
  949.     while (tok == SEPER)
  950.         yylex();
  951.     c2 = (Cond) make_cond();
  952.     c2->left = (vptr) c;
  953.     c2->right = (vptr) par_cond_1();
  954.     c2->type = COND_AND;
  955.     return c2;
  956.     }
  957.     return c;
  958. }
  959.  
  960. /*
  961.  * cond_2    : BANG cond_2
  962.                 | INPAR { SEPER } cond_2 { SEPER } OUTPAR
  963.                 | STRING STRING STRING
  964.                 | STRING STRING
  965.                 | STRING ( INANG | OUTANG ) STRING
  966.  */
  967. Cond par_cond_2()
  968. {                /**/
  969.     Cond c, c2;
  970.     char *s1, *s2, *s3;
  971.     int xtok;
  972.  
  973.     if (tok == BANG) {
  974.     yylex();
  975.     c = par_cond_2();
  976.     c2 = (Cond) make_cond();
  977.     c2->left = (vptr) c;
  978.     c2->type = COND_NOT;
  979.     return c2;
  980.     }
  981.     if (tok == INPAR) {
  982.     yylex();
  983.     while (tok == SEPER)
  984.         yylex();
  985.     c = par_cond();
  986.     while (tok == SEPER)
  987.         yylex();
  988.     if (tok != OUTPAR)
  989.         YYERROR;
  990.     yylex();
  991.     return c;
  992.     }
  993.     if (tok != STRING)
  994.     YYERROR;
  995.     s1 = tokstr;
  996.     yylex();
  997.     xtok = tok;
  998.     if (tok == INANG || tok == OUTANG) {
  999.     yylex();
  1000.     if (tok != STRING)
  1001.         YYERROR;
  1002.     s3 = tokstr;
  1003.     yylex();
  1004.     c = (Cond) make_cond();
  1005.     c->left = (vptr) s1;
  1006.     c->right = (vptr) s3;
  1007.     c->type = (xtok == INANG) ? COND_STRLT : COND_STRGTR;
  1008.     c->ntype = NT_SET(N_COND, 1, NT_STR, NT_STR, 0, 0);
  1009.     return c;
  1010.     }
  1011.     if (tok != STRING)
  1012.     YYERROR;
  1013.     s2 = tokstr;
  1014.     incond++;  /* parentheses do globbing */
  1015.     yylex();
  1016.     incond--;  /* parentheses do grouping */
  1017.     if (tok == STRING) {
  1018.     s3 = tokstr;
  1019.     yylex();
  1020.     return par_cond_triple(s1, s2, s3);
  1021.     } else
  1022.     return par_cond_double(s1, s2);
  1023. }
  1024.  
  1025. /*
  1026.  * redir    : ( OUTANG | ... | TRINANG ) STRING
  1027.  */
  1028. void par_redir(l)        /**/
  1029. Lklist l;
  1030. {
  1031.     char *toks;
  1032.     struct redir *fn = (struct redir *)allocnode(N_REDIR);
  1033.     int mergerror = 0;
  1034.     int oldcmdpos, oldnc;
  1035.     unsigned char bc = bangchar;
  1036.  
  1037.     oldcmdpos = incmdpos;
  1038.     incmdpos = 0;
  1039.     oldnc = nocorrect;
  1040.     if (tok != INANG)
  1041.     nocorrect = 1;
  1042.     fn->type = redirtab[tok - OUTANG];
  1043.     fn->fd1 = tokfd;
  1044.     if (fn->type == HEREDOC || fn->type == HEREDOCDASH)
  1045.     bangchar = '\0';
  1046.     yylex();
  1047.     bangchar = bc;
  1048.     if (tok != STRING && tok != ENVSTRING)
  1049.     YYERRORV;
  1050.     toks = tokstr;
  1051.     incmdpos = oldcmdpos;
  1052.     nocorrect = oldnc;
  1053.     yylex();
  1054.  
  1055. /* assign default fd */
  1056.  
  1057.     if (fn->fd1 == -1)
  1058.     fn->fd1 = IS_READFD(fn->type) ? 0 : 1;
  1059.  
  1060. /* > >(...) or < <(...) */
  1061.  
  1062.     if ((*toks == Inang || *toks == Outang) && toks[1] == Inpar) {
  1063.     if ((fn->type & ~1) == WRITE)
  1064.         fn->type = OUTPIPE;
  1065.     else if (fn->type == READ)
  1066.         fn->type = INPIPE;
  1067.     else
  1068.         YYERRORV;
  1069.     fn->name = toks;
  1070.  
  1071.     /* <<[-] name */
  1072.  
  1073.     } else if (fn->type == HEREDOC || fn->type == HEREDOCDASH) {
  1074.     char tbuf[256], *tlin = NULL;
  1075.     int tsiz = 0, redirl;
  1076.  
  1077.     /* Save the rest of the current line for later tokenization */
  1078.     if (!isnewlin) {
  1079.         while (hgets(tbuf, 256) != NULL) {
  1080.         redirl = strlen(tbuf);
  1081.         if (tsiz == 0) {
  1082.             tlin = ztrdup(tbuf);    /* Test for failure? */
  1083.             tsiz = redirl;
  1084.         } else {
  1085.             tlin = realloc(tlin, tsiz + redirl + 1);    /* Test for failure? */
  1086.             strcpy(&tlin[tsiz], tbuf);
  1087.             tsiz += redirl;
  1088.         }
  1089.         if (tbuf[redirl - 1] == '\n')
  1090.             break;
  1091.         }
  1092.     }
  1093.     cmdpush(fn->type == HEREDOC ? CS_HEREDOC : CS_HEREDOCD);
  1094.     /* Now grab the document */
  1095.     fn->name = gethere(toks, fn->type);
  1096.     fn->type = HERESTR;
  1097.     cmdpop();
  1098.     /* Put back the saved line to resume tokenizing */
  1099.     if (tsiz > 0) {
  1100.         hungets(tlin);
  1101.         free(tlin);
  1102.     }
  1103.     /* >& name or >>& name */
  1104.  
  1105.     } else if (IS_ERROR_REDIR(fn->type) && getfdstr(toks) == FD_WORD) {
  1106.     mergerror = 1;
  1107.     fn->name = toks;
  1108.     fn->type = UN_ERROR_REDIR(fn->type);
  1109.  
  1110.     /* >>& and >>&! are only valid with a name after them */
  1111.  
  1112.     } else if (fn->type == ERRAPP || fn->type == ERRAPPNOW) {
  1113.     YYERRORV;
  1114.  
  1115.     /* >& # */
  1116.  
  1117.     } else if (fn->type == MERGE || fn->type == MERGEOUT) {
  1118.     fn->fd2 = getfdstr(toks);
  1119.     if (fn->fd2 == FD_CLOSE)
  1120.         fn->type = CLOSE;
  1121.     else if (fn->fd2 == FD_WORD)
  1122.         fn->fd2 = (fn->type == MERGEOUT) ? 1 : 0;
  1123.     } else
  1124.     fn->name = toks;
  1125.     addnode(l, fn);
  1126.     if (mergerror) {
  1127.     struct redir *fe = (struct redir *)allocnode(N_REDIR);
  1128.  
  1129.     fe->fd1 = 2;
  1130.     fe->fd2 = fn->fd1;
  1131.     fe->type = MERGEOUT;
  1132.     addnode(l, fe);
  1133.     }
  1134. }
  1135.  
  1136. /*
  1137.  * wordlist    : { STRING }
  1138.  */
  1139. Lklist par_wordlist()
  1140. {                /**/
  1141.     Lklist l;
  1142.  
  1143.     l = newlist();
  1144.     while (tok == STRING) {
  1145.     addnode(l, tokstr);
  1146.     yylex();
  1147.     }
  1148.     return l;
  1149. }
  1150.  
  1151. /*
  1152.  * nl_wordlist    : { STRING | SEPER }
  1153.  */
  1154. Lklist par_nl_wordlist()
  1155. {                /**/
  1156.     Lklist l;
  1157.  
  1158.     l = newlist();
  1159.     while (tok == STRING || tok == SEPER) {
  1160.     if (tok != SEPER)
  1161.         addnode(l, tokstr);
  1162.     yylex();
  1163.     }
  1164.     return l;
  1165. }
  1166.  
  1167. /* get fd associated with str */
  1168.  
  1169. int getfdstr(s)            /**/
  1170. char *s;
  1171. {
  1172.     if (s[1])
  1173.     return FD_WORD;
  1174.     if (idigit(*s))
  1175.     return *s - '0';
  1176.     if (*s == 'p')
  1177.     return FD_COPROC;
  1178.     if (*s == '-')
  1179.     return FD_CLOSE;
  1180.     return FD_WORD;
  1181. }
  1182.  
  1183. Cond par_cond_double(a, b)    /**/
  1184. char *a;
  1185. char *b;
  1186. {
  1187.     Cond n = (Cond) make_cond();
  1188.  
  1189.     if (a[0] != '-' || !a[1] || a[2]) {
  1190.     zerr("parse error: condition expected: %s", a, 0);
  1191.     return NULL;
  1192.     }
  1193.     n->left = (vptr) b;
  1194.     n->type = a[1];
  1195.     n->ntype = NT_SET(N_COND, 1, NT_STR, NT_STR, 0, 0);
  1196.     return n;
  1197. }
  1198.  
  1199. int get_cond_num(tst)        /**/
  1200. char *tst;
  1201. {
  1202.     static char *condstrs[] =
  1203.     {
  1204.     "nt", "ot", "ef", "eq", "ne", "lt", "gt", "le", "ge", NULL
  1205.     };
  1206.     int t0;
  1207.  
  1208.     for (t0 = 0; condstrs[t0]; t0++)
  1209.     if (!strcmp(condstrs[t0], tst))
  1210.         return t0;
  1211.     return -1;
  1212. }
  1213.  
  1214. Cond par_cond_triple(a, b, c)    /**/
  1215. char *a;
  1216. char *b;
  1217. char *c;
  1218. {
  1219.     Cond n = (Cond) make_cond();
  1220.     int t0;
  1221.  
  1222.     if ((b[0] == Equals || b[0] == '=') && !b[1])
  1223.     n->type = COND_STREQ;
  1224.     else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2])
  1225.     n->type = COND_STRNEQ;
  1226.     else if (b[0] == '-') {
  1227.     if ((t0 = get_cond_num(b+1)) > -1)
  1228.         n->type = t0 + COND_NT;
  1229.     else
  1230.         zerr("unrecognized condition: %s", b, 0);
  1231.     } else
  1232.     zerr("condition expected: %s", b, 0);
  1233.     n->left = (vptr) a;
  1234.     n->right = (vptr) c;
  1235.     n->ntype = NT_SET(N_COND, 1, NT_STR, NT_STR, 0, 0);
  1236.     return n;
  1237. }
  1238.  
  1239. void yyerror()
  1240. {                /**/
  1241.     int t0;
  1242.  
  1243.     for (t0 = 0; t0 != 20; t0++)
  1244.     if (!yytext[t0] || yytext[t0] == '\n' || yytext[t0] == HISTSPACE)
  1245.         break;
  1246.     if (t0 == 20)
  1247.     zerr("parse error near `%l...'", yytext, 20);
  1248.     else if (t0)
  1249.     zerr("parse error near `%l'", yytext, t0);
  1250.     else
  1251.     zerr("parse error", NULL, 0);
  1252. }
  1253.