home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / z / zsh220.zip / zsh2.2 / src / parse.c < prev    next >
C/C++ Source or Header  |  1992-05-08  |  19KB  |  961 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. #include "funcs.h"
  23.  
  24. #define YYERROR { tok = LEXERR; return NULL; }
  25. #define YYERRORV { tok = LEXERR; return; }
  26.  
  27. #define make_list() allocnode(N_LIST)
  28. #define make_sublist() allocnode(N_SUBLIST)
  29. #define make_pline() allocnode(N_PLINE)
  30. #define make_cmd() allocnode(N_CMD)
  31. #define make_forcmd() allocnode(N_FOR)
  32. #define make_casecmd() allocnode(N_CASE)
  33. #define make_ifcmd() allocnode(N_IF)
  34. #define make_whilecmd() allocnode(N_WHILE)
  35. #define make_varnode() allocnode(N_VARASG)
  36. #define make_cond() allocnode(N_COND)
  37.  
  38. /*
  39.  * event    : ENDINPUT
  40.  *            | SEPER
  41.  *            | sublist [ SEPER | AMPER ]
  42.  */
  43. List parse_event() /**/
  44. {
  45.     tok = ENDINPUT;
  46.     incmdpos = 1;
  47.     yylex();
  48.     return par_event();
  49. }
  50.  
  51. List par_event() /**/
  52. {
  53. Sublist sl;
  54. List l = NULL;
  55.  
  56.     while (tok == SEPER) {
  57.         if (isnewlin > 0) return NULL;
  58.         yylex();
  59.     }
  60.     if (tok == ENDINPUT) return NULL;
  61.     if (sl = par_sublist())
  62.         if (tok == ENDINPUT) {
  63.             l = make_list();
  64.             l->type = SYNC; l->left = sl;
  65.         } else if (tok == SEPER) {
  66.             l = make_list();
  67.             l->type = SYNC; l->left = sl;
  68.             if (isnewlin <= 0) yylex();
  69.         } else if (tok == AMPER) {
  70.             l = make_list();
  71.             l->type = ASYNC; l->left = sl;
  72.             yylex();
  73.         } else
  74.             l = NULL;
  75.     if (!l) {
  76.         if (errflag) { yyerror(); return NULL; }
  77.         yyerror();
  78.         errflag = 0;
  79.         if (isnewlin <= 0) {
  80.             int c;
  81.  
  82.             hwbegin();
  83.             while ((c = hgetc()) != '\n' && !lexstop);
  84.             if (c == '\n') hungetc('\n');
  85.             hwaddc(HISTSPACE);
  86.             hwadd();
  87.         }
  88.         errflag = 1;
  89.         return NULL;
  90.     } else {
  91.         l->right = par_event();
  92.     }
  93.     return l;
  94. }
  95.  
  96. List parse_list() /**/
  97. {
  98.     tok = ENDINPUT;
  99.     incmdpos = 1;
  100.     yylex();
  101.     return par_list();
  102. }
  103.  
  104. /*
  105.  * list    : { SEPER } [ sublist [ { SEPER | AMPER } list ] ]
  106.  */
  107. List par_list() /**/
  108. {
  109. Sublist sl;
  110. List l = NULL;
  111.  
  112.     while (tok == SEPER) yylex();
  113.     if (sl = par_sublist())
  114.         if (tok == SEPER || tok == AMPER) {
  115.             l = make_list();
  116.             l->left = sl;
  117.             l->type = (tok == SEPER) ? SYNC : ASYNC;
  118.             incmdpos = 1;
  119.             while (tok == SEPER || tok == AMPER) yylex();
  120.             l->right = par_list();
  121.         } else {
  122.             l = make_list();
  123.             l->left = sl;
  124.             l->type = SYNC;
  125.         }
  126.     return l;
  127. }
  128.  
  129. List par_list1() /**/
  130. {
  131. Sublist sl;
  132. List l = NULL;
  133.  
  134.     if (sl = par_sublist()) {
  135.         l = make_list();
  136.         l->type = SYNC;
  137.         l->left = sl;
  138.     }
  139.     return l;
  140. }
  141.  
  142. /*
  143.  * sublist    : sublist2 [ ( DBAR | DAMPER ) { SEPER } sublist ]
  144.  */
  145. Sublist par_sublist() /**/
  146. {
  147. Sublist sl;
  148.  
  149.     if (sl = par_sublist2())
  150.         if (tok == DBAR || tok == DAMPER) {
  151.             int qtok = tok;
  152.             yylex();
  153.             while (tok == SEPER) yylex();
  154.             sl->right = par_sublist();
  155.             sl->type = (qtok == DBAR) ? ORNEXT : ANDNEXT;
  156.         }
  157.     return sl;
  158. }
  159.  
  160. /*
  161.  * sublist2    : [ COPROC | BANG ] pline
  162.  */
  163. Sublist par_sublist2() /**/
  164. {
  165. Sublist sl;
  166. Pline p;
  167.  
  168.     sl = make_sublist();
  169.     if (tok == COPROC) { sl->flags |= PFLAG_COPROC; yylex(); }
  170.     else if (tok == BANG) { sl->flags |= PFLAG_NOT; yylex(); }
  171.     if (!(p = par_pline()) && !sl->flags)
  172.         return NULL;
  173.     sl->left = p;
  174.     return sl;
  175. }
  176.  
  177. /*
  178.  * pline    : cmd [ ( BAR | BARAMP ) { SEPER } pline ]
  179.  */
  180. Pline par_pline() /**/
  181. {
  182. Cmd c;
  183. Pline p,p2;
  184.  
  185.     if (!(c = par_cmd()))
  186.         return NULL;
  187.     if (tok == BAR) {
  188.         yylex();
  189.         while (tok == SEPER) yylex();
  190.         p2 = par_pline();
  191.         p = make_pline();
  192.         p->left = c; p->right = p2; p->type = PIPE;
  193.         return p;
  194.     } else if (tok == BARAMP) {
  195.         struct redir *rdr = alloc(sizeof *rdr);
  196.         rdr->type = MERGE; rdr->fd1 = 2; rdr->fd2 = 1;
  197.         addnode(c->redir,rdr);
  198.  
  199.         yylex();
  200.         p2 = par_pline();
  201.         p = make_pline();
  202.         p->left = c; p->right = p2; p->type = PIPE;
  203.         return p;
  204.     } else {
  205.         p = make_pline();
  206.         p->left = c; p->type = END;
  207.         return p;
  208.     }
  209. }
  210.  
  211. /*
  212.  * cmd    : { redir } ( for | case | if | while | repeat |
  213.  *                subsh | funcdef | time | dinbrack | simple ) { redir }
  214.  */
  215. Cmd par_cmd() /**/
  216. {
  217. Cmd c;
  218.  
  219.     c = make_cmd();
  220.     c->args = newlist();
  221.     c->redir = newlist();
  222.     c->vars = newlist();
  223.     while (IS_REDIROP(tok))
  224.         par_redir(c->redir);
  225.     switch (tok) {
  226.     case FOR: case FOREACH: case SELECT: par_for(c); break;
  227.     case CASE: par_case(c); break;
  228.     case IF: par_if(c); break;
  229.     case WHILE: case UNTIL: par_while(c); break;
  230.     case REPEAT: par_repeat(c); break;
  231.     case INPAR: case INBRACE: par_subsh(c); break;
  232.     case FUNC: par_funcdef(c); break;
  233.     case TIME: par_time(c); break;
  234.     case DINBRACK: par_dinbrack(c); break;
  235.     default: if (!par_simple(c)) return NULL; break;
  236.     }
  237.     while (IS_REDIROP(tok))
  238.         par_redir(c->redir);
  239.     incmdpos = 1;
  240.     incasepat = 0;
  241.     incond = 0;
  242.     return c;
  243. }
  244.  
  245. /*
  246.  * for    : ( FOR[EACH] | SELECT ) name ( "in" wordlist | INPAR wordlist OUTPAR )
  247.                 { SEPER } ( DO list DONE | INBRACE list OUTBRACE |
  248.                 list ZEND | list1 )
  249.  */
  250. void par_for(c) /**/
  251. Cmd c;
  252. {
  253. struct forcmd *f;
  254. int csh = (tok == FOREACH || isset(CSHJUNKIELOOPS));
  255.  
  256.     f = make_forcmd();
  257.     c->type = (tok == SELECT) ? CSELECT : CFOR;
  258.     incmdpos = 0;
  259.     yylex();
  260.     if (tok != STRING) YYERRORV;
  261.     f->name = tokstr;
  262.     incmdpos = 1;
  263.     yylex();
  264.     if (tok == STRING && !strcmp(tokstr,"in")) {
  265.         f->inflag = 1;
  266.         incmdpos = 0;
  267.         yylex();
  268.         c->args = par_wordlist();
  269.         if (tok != SEPER) YYERRORV;
  270.     } else if (tok == INPAR) {
  271.         f->inflag = 1;
  272.         incmdpos = 0;
  273.         yylex();
  274.         c->args = par_nl_wordlist();
  275.         if (tok != OUTPAR) YYERRORV;
  276.         incmdpos = 1;
  277.         yylex();
  278.     }
  279.     incmdpos = 1;
  280.     while (tok == SEPER) yylex();
  281.     if (tok == DO) {
  282.         yylex();
  283.         f->list = par_list();
  284.         if (tok != DONE) YYERRORV;
  285.         yylex();
  286.     } else if (tok == INBRACE) {
  287.         yylex();
  288.         f->list = par_list();
  289.         if (tok != OUTBRACE) YYERRORV;
  290.         yylex();
  291.     } else if (csh) {
  292.         f->list = par_list();
  293.         if (tok != ZEND) YYERRORV;
  294.         yylex();
  295.     } else if (isset(NOSHORTLOOPS)) {
  296.         YYERRORV;
  297.     } else
  298.         f->list = par_list1();
  299.     c->u.forcmd = f;
  300. }
  301.  
  302. /*
  303.  * case    : CASE STRING { SEPER } ( "in" | INBRACE )
  304.                 { { SEPER } STRING { BAR STRING } OUTPAR list [ DSEMI ] }
  305.                 { SEPER } ( "esac" | OUTBRACE )
  306.  */
  307. void par_case(c) /**/
  308. Cmd c;
  309. {
  310. struct casecmd **ccp;
  311. int brflag;
  312.  
  313.     c->type = CCASE;
  314.     incmdpos = 0;
  315.     yylex();
  316.     if (tok != STRING) YYERRORV;
  317.     addnode(c->args,tokstr);
  318.     incmdpos = 1;
  319.     yylex();
  320.     while (tok == SEPER) yylex();
  321.     if (!(tok == STRING && !strcmp(tokstr,"in")) && tok != INBRACE) YYERRORV;
  322.     brflag = (tok == INBRACE);
  323.     incasepat = 1;
  324.     incmdpos = 0;
  325.     yylex();
  326.     ccp = &c->u.casecmd;
  327.     for (;;) {
  328.         char *str;
  329.         struct casecmd *cc;
  330.  
  331.         *ccp = cc = make_casecmd();
  332.         while (tok == SEPER) yylex();
  333.         if (tok == OUTBRACE) {
  334.             yylex();
  335.             break;
  336.         }
  337.         if (tok != STRING) YYERRORV;
  338.         if (!strcmp(tokstr,"esac")) {
  339.             yylex();
  340.             break;
  341.         }
  342.         str = tokstr;
  343.         yylex();
  344.         while (tok == BAR) {
  345.             char *str2;
  346.             int sl = strlen(str);
  347.  
  348.             yylex();
  349.             if (tok != STRING) YYERRORV;
  350.             str2 = alloc(sl+strlen(tokstr)+1);
  351.             strcpy(str2,str);
  352.             str2[sl] = Bar;
  353.             strcpy(str2+sl+1,tokstr);
  354.             str = str2;
  355.             yylex();
  356.         }
  357.         if (tok != OUTPAR) YYERRORV;
  358.         incasepat = 0;
  359.         incmdpos = 1;
  360.         yylex();
  361.         cc->pat = str;
  362.         cc->list = par_list();
  363.         ccp = &cc->next;
  364.         if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag)) {
  365.             yylex();
  366.             break;
  367.         }
  368.         if (tok != DSEMI) YYERRORV;
  369.         incasepat = 1;
  370.         incmdpos = 0;
  371.         yylex();
  372.     }
  373.     *ccp = NULL;
  374. }
  375.  
  376. /*
  377.  * if    : { ( IF | ELIF ) { SEPER } ( INPAR list OUTPAR | list )
  378.             { SEPER } ( THEN list | INBRACE list OUTBRACE | list1 ) }
  379.             [ FI | ELSE list FI | ELSE { SEPER } INBRACE list OUTBRACE ]
  380.             (you get the idea...?)
  381.  */
  382. void par_if(c) /**/
  383. Cmd c;
  384. {
  385. struct ifcmd *i,**ip;
  386. int xtok;
  387.  
  388.     c->type = CIF;
  389.     ip = &c->u.ifcmd;
  390.     for (;;) {
  391.         xtok = tok;
  392.         yylex();
  393.         if (xtok == FI)
  394.             break;
  395.         while (tok == SEPER) yylex();
  396.         if (xtok == ELSE)
  397.             break;
  398.         if (!(xtok == IF || xtok == ELIF)) YYERRORV;
  399.         *ip = i = make_ifcmd();
  400.         ip = &i->next;
  401.         if (tok == INPAR) {
  402.             yylex();
  403.             i->ifl = par_list();
  404.             if (tok != OUTPAR) YYERRORV;
  405.             incmdpos = 1;
  406.             yylex();
  407.         } else {
  408.             i->ifl = par_list();
  409.             incmdpos = 1;
  410.         }
  411.         while (tok == SEPER) yylex();
  412.         xtok = FI;
  413.         if (tok == THEN) {
  414.             yylex();
  415.             i->thenl = par_list();
  416.             incmdpos = 1;
  417.         } else if (tok == INBRACE) {
  418.             yylex();
  419.             i->thenl = par_list();
  420.             if (tok != OUTBRACE) YYERRORV;
  421.             yylex();
  422.             incmdpos = 1;
  423.             if (tok == SEPER) break;
  424.         } else if (isset(NOSHORTLOOPS)) {
  425.             YYERRORV;
  426.         } else {
  427.             i->thenl = par_list1();
  428.             incmdpos = 1;
  429.             break;
  430.         }
  431.     }
  432.     if (xtok == ELSE) {
  433.         *ip = i = make_ifcmd();
  434.         if (tok == INBRACE) {
  435.             yylex();
  436.             i->thenl = par_list();
  437.             if (tok != OUTBRACE) YYERRORV;
  438.             yylex();
  439.         } else {
  440.             i->thenl = par_list();
  441.             if (tok != FI) YYERRORV;
  442.             yylex();
  443.         }
  444.     }
  445. }
  446.  
  447. /*
  448.  * while    : ( WHILE | UNTIL ) ( INPAR list OUTPAR | list ) { SEPER }
  449.                 ( DO list DONE | INBRACE list OUTBRACE | list ZEND )
  450.  */
  451. void par_while(c) /**/
  452. Cmd c;
  453. {
  454. struct whilecmd *w;
  455.  
  456.     c->type = CWHILE;
  457.     w = c->u.whilecmd = make_whilecmd();
  458.     w->cond = (tok == UNTIL);
  459.     yylex();
  460.     if (tok == INPAR) {
  461.         yylex();
  462.         w->cont = par_list();
  463.         if (tok != OUTPAR) YYERRORV;
  464.         yylex();
  465.     } else {
  466.         w->cont = par_list();
  467.     }
  468.     incmdpos = 1;
  469.     while (tok == SEPER) yylex();
  470.     if (tok == DO) {
  471.         yylex();
  472.         w->loop = par_list();
  473.         if (tok != DONE) YYERRORV;
  474.         yylex();
  475.     } else if (tok == INBRACE) {
  476.         yylex();
  477.         w->loop = par_list();
  478.         if (tok != OUTBRACE) YYERRORV;
  479.         yylex();
  480.     } else if (isset(CSHJUNKIELOOPS)) {
  481.         w->loop = par_list();
  482.         if (tok != ZEND) YYERRORV;
  483.         yylex();
  484.     } else
  485.         YYERRORV;
  486. }
  487.  
  488. /*
  489.  * repeat    : REPEAT STRING { SEPER } ( DO list DONE | list1 )
  490.  */
  491. void par_repeat(c) /**/
  492. Cmd c;
  493. {
  494.     c->type = CREPEAT;
  495.     incmdpos = 0;
  496.     yylex();
  497.     if (tok != STRING) YYERRORV;
  498.     addnode(c->args,tokstr);
  499.     incmdpos = 1;
  500.     yylex();
  501.     while (tok == SEPER) yylex();
  502.     if (tok == DO) {
  503.         yylex();
  504.         c->u.list = par_list();
  505.         if (tok != DONE) YYERRORV;
  506.         yylex();
  507.     } else {
  508.         c->u.list = par_list1();
  509.     }
  510. }
  511.  
  512. /*
  513.  * subsh    : ( INPAR | INBRACE ) list ( OUTPAR | OUTBRACE )
  514.  */
  515. void par_subsh(c) /**/
  516. Cmd c;
  517. {
  518.     c->type = (tok == INPAR) ? SUBSH : CURSH;
  519.     yylex();
  520.     c->u.list = par_list();
  521.     if (tok != ((c->type == SUBSH) ? OUTPAR : OUTBRACE)) YYERRORV;
  522.     yylex();
  523. }
  524.  
  525. /*
  526.  * funcdef    : FUNCTION wordlist [ INOUTPAR ] { SEPER }
  527.  *                    ( list1 | INBRACE list OUTBRACE )
  528.  */
  529. void par_funcdef(c) /**/
  530. Cmd c;
  531. {
  532.     nocorrect = 1;
  533.     incmdpos = 0;
  534.     yylex();
  535.     c->type = FUNCDEF;
  536.     c->args = newlist();
  537.     while (tok == STRING) {
  538.         if (*tokstr == Inbrace && !tokstr[1]) { tok = INBRACE; break; }
  539.         addnode(c->args,tokstr);
  540.         yylex();
  541.     }
  542.     nocorrect = 0;
  543.     incmdpos = 1;
  544.     if (tok == INOUTPAR) yylex();
  545.     while (tok == SEPER) yylex();
  546.     if (tok == INBRACE) {
  547.         yylex();
  548.         c->u.list = par_list();
  549.         if (tok != OUTBRACE) YYERRORV;
  550.         yylex();
  551.     } else if (isset(NOSHORTLOOPS)) {
  552.         YYERRORV;
  553.     } else
  554.         c->u.list = par_list1();
  555. }
  556.  
  557. /*
  558.  * time    : TIME sublist2
  559.  */
  560. void par_time(c) /**/
  561. Cmd c;
  562. {
  563.     yylex();
  564.     c->type = ZCTIME;
  565.     c->u.pline = par_sublist2();
  566. }
  567.  
  568. /*
  569.  * dinbrack    : DINBRACK cond DOUTBRACK
  570.  */
  571. void par_dinbrack(c) /**/
  572. Cmd c;
  573. {
  574.     c->type = COND;
  575.     incond = 1;
  576.     incmdpos = 0;
  577.     yylex();
  578.     c->u.cond = par_cond();
  579.     if (tok != DOUTBRACK) YYERRORV;
  580.     incond = 0;
  581.     incmdpos = 1;
  582.     yylex();
  583. }
  584.  
  585. /*
  586.  * simple    : { COMMAND | EXEC | NOGLOB | NOCORRECT | DASH }
  587.                     { STRING | ENVSTRING | ENVARRAY wordlist OUTPAR | redir }
  588.                     [ INOUTPAR { SEPER } ( list1 | INBRACE list OUTBRACE ) ]
  589.  */
  590. Cmd par_simple(c) /**/
  591. Cmd c;
  592. {
  593. int isnull = 1;
  594.  
  595.     c->type = SIMPLE;
  596.     for (;;) {
  597.         if (tok == COMMAND) c->flags |= CFLAG_COMMAND;
  598.         else if (tok == EXEC) c->flags |= CFLAG_EXEC;
  599.         else if (tok == NOGLOB) c->flags |= CFLAG_NOGLOB;
  600.         else if (tok == NOCORRECT) nocorrect = 1;
  601.         else if (tok == DASH) c->flags = CFLAG_DASH;
  602.         else break;
  603.         yylex();
  604.     }
  605.     if (tok == AMPER) YYERROR;
  606.     for (;;) {
  607.         if (tok == STRING) {
  608.             incmdpos = 0;
  609.             addnode(c->args,tokstr);
  610.             yylex();
  611.         } else if (tok == ENVSTRING) {
  612.             struct varasg *v = make_varnode();
  613.             v->type = PMFLAG_s;
  614.             equalsplit(v->name = tokstr,&v->str);
  615.             addnode(c->vars,v);
  616.             yylex();
  617.         } else if (tok == ENVARRAY) {
  618.             struct varasg *v = make_varnode();
  619.             int oldcmdpos = incmdpos;
  620.             v->type = PMFLAG_A;
  621.             incmdpos = 0;
  622.             v->name = tokstr;
  623.             yylex();
  624.             v->arr = par_nl_wordlist();
  625.             if (tok != OUTPAR) YYERROR;
  626.             incmdpos = oldcmdpos;
  627.             yylex();
  628.             addnode(c->vars,v);
  629.         } else if (IS_REDIROP(tok)) {
  630.             par_redir(c->redir);
  631.         } else if (tok == INOUTPAR) {
  632.             incmdpos = 1;
  633.             yylex();
  634.             while (tok == SEPER) yylex();
  635.             if (tok == INBRACE) {
  636.                 yylex();
  637.                 c->u.list = par_list();
  638.                 if (tok != OUTBRACE) YYERROR;
  639.                 yylex();
  640.             } else if (isset(NOSHORTLOOPS)) {
  641.                 YYERROR;
  642.             } else
  643.                 c->u.list = par_list1();
  644.             c->type = FUNCDEF;
  645.         } else break;
  646.         isnull = 0;
  647.     }
  648.     if (isnull && !full(c->redir)) return NULL;
  649.     if (full(c->args)) {
  650.         if (underscore)
  651.             free(underscore);
  652.         underscore = ztrdup(getdata(lastnode(c->args)));
  653.         untokenize(underscore);
  654.     }
  655.     incmdpos = 1;
  656.     return c;
  657. }
  658.  
  659. /*
  660.  * cond    : cond_1 { SEPER } [ DBAR { SEPER } cond ]
  661.  */
  662. Cond par_cond() /**/
  663. {
  664. Cond c,c2;
  665.  
  666.     c = par_cond_1();
  667.     while (tok == SEPER) yylex();
  668.     if (tok == DBAR) {
  669.         yylex();
  670.         while (tok == SEPER) yylex();
  671.         c2 = make_cond();
  672.         c2->left = c;
  673.         c2->right = par_cond();
  674.         c2->type = COND_OR;
  675.         return c2;
  676.     }
  677.     return c;
  678. }
  679.  
  680. /*
  681.  * cond_1 : cond_2 { SEPER } [ DAMPER { SEPER } cond_1 ]
  682.  */
  683. Cond par_cond_1() /**/
  684. {
  685. Cond c,c2;
  686.  
  687.     c = par_cond_2();
  688.     while (tok == SEPER) yylex();
  689.     if (tok == DAMPER) {
  690.         yylex();
  691.         while (tok == SEPER) yylex();
  692.         c2 = make_cond();
  693.         c2->left = c;
  694.         c2->right = par_cond_1();
  695.         c2->type = COND_AND;
  696.         return c2;
  697.     }
  698.     return c;
  699. }
  700.  
  701. /*
  702.  * cond_2    : BANG cond_2
  703.                 | INPAR { SEPER } cond_2 { SEPER } OUTPAR
  704.                 | STRING STRING STRING
  705.                 | STRING STRING
  706.                 | STRING ( INANG | OUTANG ) STRING
  707.  */
  708. Cond par_cond_2() /**/
  709. {
  710. Cond c,c2;
  711. char *s1,*s2,*s3;
  712. int xtok;
  713.  
  714.     if (tok == BANG) {
  715.         yylex();
  716.         c = par_cond_2();
  717.         c2 = make_cond();
  718.         c2->left = c;
  719.         c2->type = COND_NOT;
  720.         return c2;
  721.     }
  722.     if (tok == INPAR) {
  723.         yylex();
  724.         while (tok == SEPER) yylex();
  725.         c = par_cond();
  726.         while (tok == SEPER) yylex();
  727.         if (tok != OUTPAR) YYERROR;
  728.         yylex();
  729.         return c;
  730.     }
  731.     if (tok != STRING) YYERROR;
  732.     s1 = tokstr;
  733.     yylex();
  734.     xtok = tok;
  735.     if (tok == INANG || tok == OUTANG) {
  736.         yylex();
  737.         if (tok != STRING) YYERROR;
  738.         s3 = tokstr;
  739.         yylex();
  740.         c = make_cond();
  741.         c->left = s1;
  742.         c->right = s3;
  743.         c->type = (xtok == INANG) ? COND_STRLT : COND_STRGTR;
  744.         c->types[0] = c->types[1] = NT_STR;
  745.         return c;
  746.     }
  747.     if (tok != STRING) YYERROR;
  748.     s2 = tokstr;
  749.     yylex();
  750.     if (tok == STRING) {
  751.         s3 = tokstr;
  752.         yylex();
  753.         return par_cond_triple(s1,s2,s3);
  754.     } else
  755.         return par_cond_double(s1,s2);
  756. }
  757.  
  758. /*
  759.  * redir    : ( OUTANG | ... | TRINANG ) STRING
  760.  */
  761. void par_redir(l) /**/
  762. Lklist l;
  763. {
  764. char *toks;
  765. struct redir *fn = allocnode(N_REDIR);
  766. int mergerror = 0;
  767. int oldcmdpos,oldnc;
  768.  
  769.     oldcmdpos = incmdpos;
  770.     incmdpos = 0;
  771.     oldnc = nocorrect;
  772.     if (tok != INANG) nocorrect = 1;
  773.     fn->type = redirtab[tok-OUTANG];
  774.     fn->fd1 = tokfd;
  775.     yylex();
  776.     if (tok != STRING && tok != ENVSTRING) YYERRORV;
  777.     toks = tokstr;
  778.     incmdpos = oldcmdpos;
  779.     nocorrect = oldnc;
  780.     yylex();
  781.  
  782. /* assign default fd */
  783.  
  784.     if (fn->fd1 == -1)
  785.         fn->fd1 = IS_READFD(fn->type) ? 0 : 1;
  786.  
  787. /* > >(...) or < <(...) */
  788.  
  789.     if ((*toks == Inang || *toks == Outang) && toks[1] == Inpar) {
  790.         if ((fn->type & ~1) == WRITE) fn->type = OUTPIPE;
  791.         else if (fn->type == READ) fn->type = INPIPE;
  792.         else YYERRORV;
  793.         fn->name = toks;
  794.  
  795. /* <<[-] name */
  796.  
  797.     } else if (fn->type == HEREDOC || fn->type == HEREDOCDASH) {
  798.         char tbuf[256], *tlin;
  799.         int tsiz = 0, l;
  800.         /* Save the rest of the current line for later tokenization */
  801.         if (!isnewlin) {
  802.             while (hgets(tbuf, 256) != NULL) {
  803.                 l = strlen(tbuf);
  804.                 if (tsiz == 0) {
  805.                     tlin = ztrdup(tbuf); /* Test for failure? */
  806.                     tsiz = l;
  807.                 } else {
  808.                     tlin = realloc(tlin,tsiz+l+1); /* Test for failure? */
  809.                     strcpy(&tlin[tsiz], tbuf);
  810.                     tsiz += l;
  811.                 }
  812.                 if (tbuf[l-1] == '\n') break;
  813.             }
  814.         }
  815.         /* Now grab the document */
  816.         fn->name = gethere(toks,fn->type);
  817.         fn->type = HERESTR;
  818.         /* Put back the saved line to resume tokenizing */
  819.         if (tsiz > 0) {
  820.             hungets(tlin);
  821.             free(tlin);
  822.         }
  823.  
  824. /* >& name or >>& name */
  825.  
  826.     } else if (IS_ERROR_REDIR(fn->type) && getfdstr(toks) == FD_WORD) {
  827.         mergerror = 1;
  828.         fn->name = toks;
  829.         fn->type = UN_ERROR_REDIR(fn->type);
  830.  
  831. /* >>& and >>&! are only valid with a name after them */
  832.  
  833.     } else if (fn->type == ERRAPP || fn->type == ERRAPPNOW) {
  834.         YYERRORV;
  835.  
  836. /* >& # */
  837.  
  838.     } else if (fn->type == MERGE || fn->type == MERGEOUT) {
  839.         fn->fd2 = getfdstr(toks);
  840.         if (fn->fd2 == FD_CLOSE) fn->type = CLOSE;
  841.         else if (fn->fd2 == FD_WORD) fn->fd2 = (fn->type==MERGEOUT) ? 1 : 0;
  842.     } else
  843.         fn->name = toks;
  844.     addnode(l,fn);
  845.     if (mergerror)
  846.         {
  847.         struct redir *fe = allocnode(N_REDIR);
  848.  
  849.         fe->fd1 = 2;
  850.         fe->fd2 = fn->fd1;
  851.         fe->type = MERGEOUT;
  852.         addnode(l,fe);
  853.         }
  854. }
  855.  
  856. /*
  857.  * wordlist    : { STRING }
  858.  */
  859. Lklist par_wordlist() /**/
  860. {
  861. Lklist l;
  862.  
  863.     l = newlist();
  864.     while (tok == STRING) {
  865.         addnode(l,tokstr);
  866.         yylex();
  867.     }
  868.     return l;
  869. }
  870.  
  871. /*
  872.  * nl_wordlist    : { STRING | SEPER }
  873.  */
  874. Lklist par_nl_wordlist() /**/
  875. {
  876. Lklist l;
  877.  
  878.     l = newlist();
  879.     while (tok == STRING || tok == SEPER) {
  880.         if (tok != SEPER)
  881.             addnode(l,tokstr);
  882.         yylex();
  883.     }
  884.     return l;
  885. }
  886.  
  887. /* get fd associated with str */
  888.  
  889. int getfdstr(s) /**/
  890. char *s;
  891. {
  892.     if (s[1]) return FD_WORD;
  893.     if (idigit(*s)) return *s-'0';
  894.     if (*s == 'p') return FD_COPROC;
  895.     if (*s == '-') return FD_CLOSE;
  896.     return FD_WORD;
  897. }
  898.  
  899. Cond par_cond_double(a,b) /**/
  900. char *a;char *b;
  901. {
  902. Cond n = make_cond();
  903.  
  904.     if (a[0] != '-' || !a[1] || a[2])
  905.         {
  906.         zerr("parse error: condition expected: %s",a,0);
  907.         return NULL;
  908.         }
  909.     n->left = b;
  910.     n->type = a[1];
  911.     n->types[0] = n->types[1] = NT_STR;
  912.     return n;
  913. }
  914.  
  915. Cond par_cond_triple(a,b,c) /**/
  916. char *a;char *b;char *c;
  917. {
  918. Cond n = make_cond();
  919. static char *condstrs[] = {
  920.     "nt","ot","ef","eq","ne","lt","gt","le","ge",NULL
  921.     };
  922. int t0;
  923.  
  924.     if ((b[0] == Equals || b[0] == '=') && !b[1])
  925.         n->type = COND_STREQ;
  926.     else if (b[0] == '!' && b[1] == '=' && !b[2])
  927.         n->type = COND_STRNEQ;
  928.     else if (b[0] == '-')
  929.         {
  930.         for (t0 = 0; condstrs[t0]; t0++)
  931.             if (!strcmp(condstrs[t0],b+1))
  932.                 break;
  933.         if (condstrs[t0])
  934.             n->type = t0+COND_NT;
  935.         else
  936.             zerr("unrecognized condition: %s",b,0);
  937.         }
  938.     else
  939.         zerr("condition expected: %s",b,0);
  940.     n->left = a;
  941.     n->right = c;
  942.     n->types[0] = n->types[1] = NT_STR;
  943.     return n;
  944. }
  945.  
  946. void yyerror() /**/
  947. {
  948. int t0;
  949.  
  950.     for (t0 = 0; t0 != 20; t0++)
  951.         if (!yytext[t0] || yytext[t0] == '\n' || yytext[t0] == HISTSPACE)
  952.             break;
  953.     if (t0 == 20)
  954.         zerr("parse error near `%l...'",yytext,20);
  955.     else if (t0)
  956.         zerr("parse error near `%l'",yytext,t0);
  957.     else
  958.         zerr("parse error",NULL,0);
  959. }
  960.  
  961.