home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / k / ksh48.zip / sh / syn.c < prev    next >
C/C++ Source or Header  |  1992-09-06  |  11KB  |  578 lines

  1. /*
  2.  * shell parser (C version)
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: syn.c,v 1.3 1992/08/10 12:03:10 sjg Exp $";
  7. #endif
  8.  
  9. #include "stdh.h"
  10. #include <errno.h>
  11. #include <setjmp.h>
  12. #include "sh.h"
  13. #include "expand.h"
  14.  
  15. static struct op *pipeline  ARGS((int cf));
  16. static struct op *andor     ARGS((void));
  17. static struct op *c_list    ARGS((void));
  18. static struct ioword *synio ARGS((int cf));
  19. static void     musthave    ARGS((int c, int cf));
  20. static struct op *nested    ARGS((int type, int mark));
  21. static struct op *command   ARGS((int cf));
  22. static struct op *dogroup   ARGS((int onlydone));
  23. static struct op *thenpart  ARGS((void));
  24. static struct op *elsepart  ARGS((void));
  25. static struct op *caselist  ARGS((void));
  26. static struct op *casepart  ARGS((void));
  27. static char **  wordlist    ARGS((void));
  28. static struct op *block     ARGS((int type, struct op *t1, struct op *t2, char **wp));
  29. static struct op *newtp     ARGS((int type));
  30. static void     zzerr       ARGS((void));
  31.  
  32. static    struct    op    *outtree; /* yyparse output */
  33.  
  34. static    int    reject;        /* token(cf) gets symbol again */
  35. static    int    symbol;        /* yylex value */
  36.  
  37. #define    REJECT    (reject = 1)
  38. #define    ACCEPT    (reject = 0)
  39. #define    token(cf) \
  40.     ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
  41. #define    tpeek(cf) \
  42.     ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
  43.  
  44. int
  45. yyparse()
  46. {
  47.     ACCEPT;
  48.     yynerrs = 0;
  49.     if ((tpeek(KEYWORD|ALIAS)) == 0) { /* EOF */
  50.         outtree = newtp(TEOF);
  51.         return 0;
  52.     }
  53.     outtree = c_list();
  54.     musthave('\n', 0);
  55.     return (yynerrs != 0);
  56. }
  57.  
  58. static struct op *
  59. pipeline(cf)
  60.     int cf;
  61. {
  62.     register struct op *t, *p, *tl = NULL;
  63.     register int c;
  64.  
  65.     t = command(cf);
  66.     if (t != NULL) {
  67.         while ((c = token(0)) == '|') {
  68.             if ((p = command(CONTIN)) == NULL)
  69.                 SYNTAXERR;
  70.             if (tl == NULL)
  71.                 t = tl = block(TPIPE, t, p, NOWORDS);
  72.             else
  73.                 tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
  74.             /*t = block(TPIPE, t, p, NOWORDS);*/
  75.         }
  76.         REJECT;
  77.     }
  78.     return (t);
  79. }
  80.  
  81. static struct op *
  82. andor()
  83. {
  84.     register struct op *t, *p;
  85.     register int c;
  86.  
  87.     t = pipeline(0);
  88.     if (t != NULL) {
  89.         while ((c = token(0)) == LOGAND || c == LOGOR) {
  90.             if ((p = pipeline(CONTIN)) == NULL)
  91.                 SYNTAXERR;
  92.             t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
  93.         }
  94.         REJECT;
  95.     }
  96.     return (t);
  97. }
  98.  
  99. static struct op *
  100. c_list()
  101. {
  102.     register struct op *t, *p, *tl = NULL;
  103.     register int c;
  104.  
  105.     t = andor();
  106.     if (t != NULL) {
  107.         while ((c = token(0)) == ';' || c == '&' ||
  108.                ((multiline || source->type == SSTRING
  109.                 || (source->type == SALIAS)) && c == '\n')) {
  110.             if (c == '&') {
  111.                 if (tl)
  112.                     tl->right = block(TASYNC, tl->right, NOBLOCK, NOWORDS);
  113.                 else
  114.                     t = block(TASYNC, t, NOBLOCK, NOWORDS);
  115.             }
  116.             if ((p = andor()) == NULL)
  117.                 return (t);
  118.             if (tl == NULL)
  119.                 t = tl = block(TLIST, t, p, NOWORDS);
  120.             else
  121.                 tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
  122.         }
  123.         REJECT;
  124.     }
  125.     return (t);
  126. }
  127.  
  128. static struct ioword *
  129. synio(cf)
  130.     int cf;
  131. {
  132.     register struct ioword *iop;
  133.  
  134.     if (tpeek(cf) != REDIR)
  135.         return NULL;
  136.     ACCEPT;
  137.     iop = yylval.iop;
  138.     musthave(LWORD, 0);
  139.     iop->name = yylval.cp;
  140.     if ((iop->flag&IOTYPE) == IOHERE) {
  141.         if (*ident != 0) /* unquoted */
  142.             iop->flag |= IOEVAL;
  143.         if (herep >= &heres[HERES])
  144.             errorf("too many <<'s\n");
  145.         *herep++ = iop;
  146.     }
  147.     return iop;
  148. }
  149.  
  150. static void
  151. musthave(c, cf)
  152.     int c, cf;
  153. {
  154.     if ((token(cf)) != c)
  155.         SYNTAXERR;
  156. }
  157.  
  158. static struct op *
  159. nested(type, mark)
  160.     int type, mark;
  161. {
  162.     register struct op *t;
  163.  
  164.     multiline++;
  165.     t = c_list();
  166.     musthave(mark, KEYWORD);
  167.     multiline--;
  168.     return (block(type, t, NOBLOCK, NOWORDS));
  169. }
  170.  
  171. static struct op *
  172. command(cf)
  173.     int cf;
  174. {
  175.     register struct op *t;
  176.     register int c, iopn = 0;
  177.     struct ioword *iop, **iops;
  178.     XPtrV args, vars;
  179.  
  180.     iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), ATEMP);
  181.     XPinit(args, 16);
  182.     XPinit(vars, 16);
  183.  
  184.     if (multiline)
  185.         cf = CONTIN;
  186.     cf |= KEYWORD|ALIAS;
  187.  
  188.     while ((iop = synio(cf)) != NULL) {
  189.         if (iopn >= NUFILE)
  190.             yyerror("too many redirections");
  191.         iops[iopn++] = iop;
  192.         cf &=~ CONTIN;
  193.     }
  194.  
  195.     switch (c = token(cf)) {
  196.       case 0:
  197.         yyerror("unexpected EOF");
  198.         return NULL;
  199.  
  200.       default:
  201.         REJECT;
  202.         if (iopn == 0)
  203.             return NULL; /* empty line */
  204.         t = newtp(TCOM);
  205.         break;
  206.  
  207.       case LWORD:
  208.       case MDPAREN:
  209.         REJECT;
  210.         t = newtp(TCOM);
  211.         if (c == MDPAREN) {
  212.             ACCEPT;
  213.             XPput(args,"let");
  214.             musthave(LWORD,LETEXPR);
  215.             XPput(args,yylval.cp);
  216.         }
  217.         while (1)
  218.             switch (tpeek(0)) {
  219.               case REDIR:
  220.                 if (iopn >= NUFILE)
  221.                     yyerror("too many redirections");
  222.                 iops[iopn++] = synio(0);
  223.                 break;
  224.  
  225.               case LWORD:
  226.                 ACCEPT;
  227.                 if ((XPsize(args) == 0 || flag[FKEYWORD])
  228.                     && strchr(ident+1, '='))
  229.                     {XPput(vars, yylval.cp);}
  230.                 else
  231.                     {XPput(args, yylval.cp);}
  232.                 break;
  233.  
  234.               case MPAREN:
  235.                 ACCEPT;
  236.                 if (XPsize(args) != 1)
  237.                     SYNTAXERR;
  238.                 if (*ident == 0)
  239.                     yyerror("invalid function name\n");
  240.                 t = newtp(TFUNCT);
  241.                 t->str = strsave(ident, ATEMP);
  242.                 musthave('{', CONTIN|KEYWORD);
  243.                 t->left = nested(TBRACE, '}');
  244.                 return t;
  245.  
  246.               default:
  247.                 goto Leave;
  248.             }
  249.       Leave:
  250.         break;
  251.  
  252.       case '(':
  253.         t = nested(TPAREN, ')');
  254.         break;
  255.  
  256.       case '{':
  257.         t = nested(TBRACE, '}');
  258.         break;
  259.  
  260.       case FOR:
  261.       case SELECT:
  262.         t = newtp((c == FOR) ? TFOR: TSELECT);
  263.         musthave(LWORD, 0);
  264.         t->str = strsave(ident, ATEMP);
  265.         multiline++;
  266.         t->vars = wordlist();
  267.         t->left = dogroup(0);
  268.         multiline--;
  269.         break;
  270.  
  271.       case WHILE:
  272.       case UNTIL:
  273.         multiline++;
  274.         t = newtp((c == WHILE) ? TWHILE: TUNTIL);
  275.         t->left = c_list();
  276.         t->right = dogroup(1);
  277.         multiline--;
  278.         break;
  279.  
  280.       case CASE:
  281.         t = newtp(TCASE);
  282.         musthave(LWORD, 0);
  283.         t->str = yylval.cp;
  284.         multiline++;
  285.         musthave(IN, KEYWORD|CONTIN);
  286.         t->left = caselist();
  287.         musthave(ESAC, KEYWORD);
  288.         multiline--;
  289.         break;
  290.  
  291.       case IF:
  292.         multiline++;
  293.         t = newtp(TIF);
  294.         t->left = c_list();
  295.         t->right = thenpart();
  296.         musthave(FI, KEYWORD);
  297.         multiline--;
  298.         break;
  299.  
  300.       case TIME:
  301.         t = pipeline(CONTIN);
  302.         t = block(TTIME, t, NOBLOCK, NOWORDS);
  303.         break;
  304.  
  305.       case FUNCTION:
  306.         t = newtp(TFUNCT);
  307.         musthave(LWORD, 0);
  308.         t->str = strsave(ident, ATEMP);
  309.         musthave('{', CONTIN|KEYWORD);
  310.         t->left = nested(TBRACE, '}');
  311.         break;
  312.  
  313. #if 0
  314.       case MDPAREN:
  315.         t = newtp(TCOM);
  316.         XPput(args, "let");
  317.         musthave(LWORD, LETEXPR);
  318.         XPput(args, yylval.cp);
  319.         while (tpeek(0) == REDIR) {
  320.             if (iopn >= NUFILE)
  321.                 yyerror("too many redirections");
  322.             iops[iopn++] = synio(0);
  323.         }
  324.         break;
  325. #endif
  326.     }
  327.  
  328.     while ((iop = synio(0)) != NULL) {
  329.         if (iopn >= NUFILE)
  330.             yyerror("too many redirections");
  331.         iops[iopn++] = iop;
  332.     }
  333.  
  334.     if (iopn == 0) {
  335.         afree((void*) iops, ATEMP);
  336.         t->ioact = NULL;
  337.     } else {
  338.         iops[iopn++] = NULL;
  339.         aresize((void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
  340.         t->ioact = iops;
  341.     }
  342.  
  343.     if (t->type == TCOM) {
  344.         XPput(args, NULL);
  345.         t->args = (char **) XPclose(args);
  346.         XPput(vars, NULL);
  347.         t->vars = (char **) XPclose(vars);
  348.     } else {
  349.         XPfree(args);
  350.         XPfree(vars);
  351.     }
  352.  
  353.     return t;
  354. }
  355.  
  356. static struct op *
  357. dogroup(onlydone)
  358.     int onlydone;
  359. {
  360.     register int c;
  361.     register struct op *list;
  362.  
  363.     c = token(CONTIN|KEYWORD);
  364.     if (c == DONE && onlydone)
  365.         return NULL;
  366.     if (c != DO)
  367.         SYNTAXERR;
  368.     list = c_list();
  369.     musthave(DONE, KEYWORD);
  370.     return list;
  371. }
  372.  
  373. static struct op *
  374. thenpart()
  375. {
  376.     register int c;
  377.     register struct op *t;
  378.  
  379.     if ((c = token(0)) != THEN) {
  380.         REJECT;
  381.         return NULL;
  382.     }
  383.     t = newtp(0);
  384.     t->left = c_list();
  385.     if (t->left == NULL)
  386.         SYNTAXERR;
  387.     t->right = elsepart();
  388.     return (t);
  389. }
  390.  
  391. static struct op *
  392. elsepart()
  393. {
  394.     register int c;
  395.     register struct op *t;
  396.  
  397.     switch (c = token(0)) {
  398.       case ELSE:
  399.         if ((t = c_list()) == NULL)
  400.             SYNTAXERR;
  401.         return (t);
  402.  
  403.       case ELIF:
  404.         t = newtp(TELIF);
  405.         t->left = c_list();
  406.         t->right = thenpart();
  407.         return (t);
  408.  
  409.       default:
  410.         REJECT;
  411.         return NULL;
  412.     }
  413. }
  414.  
  415. static struct op *
  416. caselist()
  417. {
  418.     register struct op *t, *tl;
  419.  
  420.     t = tl = NULL;
  421.     while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
  422.         struct op *tc = casepart();
  423.         if (tl == NULL)
  424.             t = tl = tc, tl->right = NULL;
  425.         else
  426.             tl->right = tc, tl = tc;
  427.     }
  428.     return (t);
  429. }
  430.  
  431. static struct op *
  432. casepart()
  433. {
  434.     register struct op *t;
  435.     register int c, cf;
  436.     XPtrV ptns;
  437.  
  438.     XPinit(ptns, 16);
  439.     t = newtp(TPAT);
  440.     cf = CONTIN|KEYWORD;
  441.     c = token(cf);
  442.     if (c != '(')
  443.         REJECT;
  444.     else
  445.         cf = 0;
  446.     do {
  447.         musthave(LWORD, cf);
  448.         XPput(ptns, yylval.cp);
  449.         cf = 0;
  450.     } while ((c = token(0)) == '|');
  451.     REJECT;
  452.     XPput(ptns, NULL);
  453.     t->vars = (char **) XPclose(ptns);
  454.     musthave(')', 0);
  455.  
  456.     t->left = c_list();
  457.     if ((tpeek(CONTIN|KEYWORD)) != ESAC)
  458.         musthave(BREAK, CONTIN|KEYWORD);
  459.     return (t);
  460. }
  461.  
  462. static char **
  463. wordlist()
  464. {
  465.     register int c;
  466.     XPtrV args;
  467.  
  468.     XPinit(args, 16);
  469.     if ((c = token(CONTIN|KEYWORD)) != IN) {
  470.         REJECT;
  471.         return NULL;
  472.     }
  473.     while ((c = token(0)) == LWORD)
  474.         XPput(args, yylval.cp);
  475.     if (c != '\n' && c != ';')
  476.         SYNTAXERR;
  477.     if (XPsize(args) == 0) {
  478.         XPfree(args);
  479.         return NULL;
  480.     } else {
  481.         XPput(args, NULL);
  482.         return (char **) XPclose(args);
  483.     }
  484. }
  485.  
  486. /*
  487.  * supporting functions
  488.  */
  489.  
  490. static struct op *
  491. block(type, t1, t2, wp)
  492.     struct op *t1, *t2;
  493.     char **wp;
  494. {
  495.     register struct op *t;
  496.  
  497.     t = newtp(type);
  498.     t->left = t1;
  499.     t->right = t2;
  500.     t->vars = wp;
  501.     return (t);
  502. }
  503.  
  504. const    struct res {
  505.     char    *name;
  506.     int    val;
  507. } restab[] = {
  508.     "for",        FOR,
  509.     "select",    SELECT,
  510.     "case",        CASE,
  511.     "esac",        ESAC,
  512.     "while",    WHILE,
  513.     "do",        DO,
  514.     "done",        DONE,
  515.     "if",        IF,
  516.     "in",        IN,
  517.     "then",        THEN,
  518.     "else",        ELSE,
  519.     "elif",        ELIF,
  520.     "until",    UNTIL,
  521.     "fi",        FI,
  522.     "function",    FUNCTION,
  523.     "time",        TIME,
  524.     "{",        '{',
  525.     "}",        '}',
  526.     0
  527. };
  528.  
  529. keywords()
  530. {
  531.     register struct res const *rp;
  532.     register struct tbl *p;
  533.  
  534.     for (rp = restab; rp->name; rp++) {
  535.         p = tenter(&lexicals, rp->name, hash(rp->name));
  536.         p->flag |= DEFINED|ISSET;
  537.         p->type = CKEYWD;
  538.         p->val.i = rp->val;
  539.     }
  540. }
  541.  
  542. static struct op *
  543. newtp(type)
  544.     int type;
  545. {
  546.     register struct op *t;
  547.  
  548.     t = (struct op *) alloc(sizeof(*t), ATEMP);
  549.     t->type = type;
  550.     t->args = t->vars = NULL;
  551.     t->ioact = NULL;
  552.     t->left = t->right = NULL;
  553.     t->str = NULL;
  554.     return (t);
  555. }
  556.  
  557. static void
  558. zzerr()
  559. {
  560.     yyerror("syntax error");
  561. }
  562.  
  563. struct op *
  564. compile(s)
  565.     Source *s;
  566. {
  567.     yynerrs = 0;
  568.     multiline = 0;
  569.     herep = heres;
  570.     source = s;
  571.     if (yyparse())
  572.         unwind();
  573.     if (s->type == STTY || s->type == SFILE || s->type == SHIST)
  574.         s->str = null;    /* line is not preserved */
  575.     return outtree;
  576. }
  577.  
  578.