home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Shells / zsh-3.0.5-MIHS / src / Src / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-25  |  24.3 KB  |  1,317 lines

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