home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / pdksh-src.lha / src / amiga / pdksh / sh / syn.c < prev    next >
C/C++ Source or Header  |  1993-12-01  |  10KB  |  576 lines

  1. /*
  2.  * shell parser (C version)
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: syn.c,v 1.2 1992/04/25 08:33:28 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.         t = newtp(TFOR);
  262.         musthave(LWORD, 0);
  263.         t->str = strsave(ident, ATEMP);
  264.         multiline++;
  265.         t->vars = wordlist();
  266.         t->left = dogroup(0);
  267.         multiline--;
  268.         break;
  269.  
  270.       case WHILE:
  271.       case UNTIL:
  272.         multiline++;
  273.         t = newtp((c == WHILE) ? TWHILE: TUNTIL);
  274.         t->left = c_list();
  275.         t->right = dogroup(1);
  276.         multiline--;
  277.         break;
  278.  
  279.       case CASE:
  280.         t = newtp(TCASE);
  281.         musthave(LWORD, 0);
  282.         t->str = yylval.cp;
  283.         multiline++;
  284.         musthave(IN, KEYWORD|CONTIN);
  285.         t->left = caselist();
  286.         musthave(ESAC, KEYWORD);
  287.         multiline--;
  288.         break;
  289.  
  290.       case IF:
  291.         multiline++;
  292.         t = newtp(TIF);
  293.         t->left = c_list();
  294.         t->right = thenpart();
  295.         musthave(FI, KEYWORD);
  296.         multiline--;
  297.         break;
  298.  
  299.       case TIME:
  300.         t = pipeline(CONTIN);
  301.         t = block(TTIME, t, NOBLOCK, NOWORDS);
  302.         break;
  303.  
  304.       case FUNCTION:
  305.         t = newtp(TFUNCT);
  306.         musthave(LWORD, 0);
  307.         t->str = strsave(ident, ATEMP);
  308.         musthave('{', CONTIN|KEYWORD);
  309.         t->left = nested(TBRACE, '}');
  310.         break;
  311.  
  312. #if 0
  313.       case MDPAREN:
  314.         t = newtp(TCOM);
  315.         XPput(args, "let");
  316.         musthave(LWORD, LETEXPR);
  317.         XPput(args, yylval.cp);
  318.         while (tpeek(0) == REDIR) {
  319.             if (iopn >= NUFILE)
  320.                 yyerror("too many redirections");
  321.             iops[iopn++] = synio(0);
  322.         }
  323.         break;
  324. #endif
  325.     }
  326.  
  327.     while ((iop = synio(0)) != NULL) {
  328.         if (iopn >= NUFILE)
  329.             yyerror("too many redirections");
  330.         iops[iopn++] = iop;
  331.     }
  332.  
  333.     if (iopn == 0) {
  334.         afree((void*) iops, ATEMP);
  335.         t->ioact = NULL;
  336.     } else {
  337.         iops[iopn++] = NULL;
  338.         aresize((void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
  339.         t->ioact = iops;
  340.     }
  341.  
  342.     if (t->type == TCOM) {
  343.         XPput(args, NULL);
  344.         t->args = (char **) XPclose(args);
  345.         XPput(vars, NULL);
  346.         t->vars = (char **) XPclose(vars);
  347.     } else {
  348.         XPfree(args);
  349.         XPfree(vars);
  350.     }
  351.  
  352.     return t;
  353. }
  354.  
  355. static struct op *
  356. dogroup(onlydone)
  357.     int onlydone;
  358. {
  359.     register int c;
  360.     register struct op *list;
  361.  
  362.     c = token(CONTIN|KEYWORD);
  363.     if (c == DONE && onlydone)
  364.         return NULL;
  365.     if (c != DO)
  366.         SYNTAXERR;
  367.     list = c_list();
  368.     musthave(DONE, KEYWORD);
  369.     return list;
  370. }
  371.  
  372. static struct op *
  373. thenpart()
  374. {
  375.     register int c;
  376.     register struct op *t;
  377.  
  378.     if ((c = token(0)) != THEN) {
  379.         REJECT;
  380.         return NULL;
  381.     }
  382.     t = newtp(0);
  383.     t->left = c_list();
  384.     if (t->left == NULL)
  385.         SYNTAXERR;
  386.     t->right = elsepart();
  387.     return (t);
  388. }
  389.  
  390. static struct op *
  391. elsepart()
  392. {
  393.     register int c;
  394.     register struct op *t;
  395.  
  396.     switch (c = token(0)) {
  397.       case ELSE:
  398.         if ((t = c_list()) == NULL)
  399.             SYNTAXERR;
  400.         return (t);
  401.  
  402.       case ELIF:
  403.         t = newtp(TELIF);
  404.         t->left = c_list();
  405.         t->right = thenpart();
  406.         return (t);
  407.  
  408.       default:
  409.         REJECT;
  410.         return NULL;
  411.     }
  412. }
  413.  
  414. static struct op *
  415. caselist()
  416. {
  417.     register struct op *t, *tl;
  418.  
  419.     t = tl = NULL;
  420.     while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
  421.         struct op *tc = casepart();
  422.         if (tl == NULL)
  423.             t = tl = tc, tl->right = NULL;
  424.         else
  425.             tl->right = tc, tl = tc;
  426.     }
  427.     return (t);
  428. }
  429.  
  430. static struct op *
  431. casepart()
  432. {
  433.     register struct op *t;
  434.     register int c, cf;
  435.     XPtrV ptns;
  436.  
  437.     XPinit(ptns, 16);
  438.     t = newtp(TPAT);
  439.     cf = CONTIN|KEYWORD;
  440.     c = token(cf);
  441.     if (c != '(')
  442.         REJECT;
  443.     else
  444.         cf = 0;
  445.     do {
  446.         musthave(LWORD, cf);
  447.         XPput(ptns, yylval.cp);
  448.         cf = 0;
  449.     } while ((c = token(0)) == '|');
  450.     REJECT;
  451.     XPput(ptns, NULL);
  452.     t->vars = (char **) XPclose(ptns);
  453.     musthave(')', 0);
  454.  
  455.     t->left = c_list();
  456.     if ((tpeek(CONTIN|KEYWORD)) != ESAC)
  457.         musthave(BREAK, CONTIN|KEYWORD);
  458.     return (t);
  459. }
  460.  
  461. static char **
  462. wordlist()
  463. {
  464.     register int c;
  465.     XPtrV args;
  466.  
  467.     XPinit(args, 16);
  468.     if ((c = token(CONTIN|KEYWORD)) != IN) {
  469.         REJECT;
  470.         return NULL;
  471.     }
  472.     while ((c = token(0)) == LWORD)
  473.         XPput(args, yylval.cp);
  474.     if (c != '\n' && c != ';')
  475.         SYNTAXERR;
  476.     if (XPsize(args) == 0) {
  477.         XPfree(args);
  478.         return NULL;
  479.     } else {
  480.         XPput(args, NULL);
  481.         return (char **) XPclose(args);
  482.     }
  483. }
  484.  
  485. /*
  486.  * supporting functions
  487.  */
  488.  
  489. static struct op *
  490. block(type, t1, t2, wp)
  491.     struct op *t1, *t2;
  492.     char **wp;
  493. {
  494.     register struct op *t;
  495.  
  496.     t = newtp(type);
  497.     t->left = t1;
  498.     t->right = t2;
  499.     t->vars = wp;
  500.     return (t);
  501. }
  502.  
  503. const    struct res {
  504.     char    *name;
  505.     int    val;
  506. } restab[] = {
  507.     "for",        FOR,
  508.     "case",        CASE,
  509.     "esac",        ESAC,
  510.     "while",    WHILE,
  511.     "do",        DO,
  512.     "done",        DONE,
  513.     "if",        IF,
  514.     "in",        IN,
  515.     "then",        THEN,
  516.     "else",        ELSE,
  517.     "elif",        ELIF,
  518.     "until",    UNTIL,
  519.     "fi",        FI,
  520.     "function",    FUNCTION,
  521.     "time",        TIME,
  522.     "{",        '{',
  523.     "}",        '}',
  524.     0
  525. };
  526.  
  527. keywords()
  528. {
  529.     register struct res const *rp;
  530.     register struct tbl *p;
  531.  
  532.     for (rp = restab; rp->name; rp++) {
  533.         p = tenter(&lexicals, rp->name, hash(rp->name));
  534.         p->flag |= DEFINED|ISSET;
  535.         p->type = CKEYWD;
  536.         p->val.i = rp->val;
  537.     }
  538. }
  539.  
  540. static struct op *
  541. newtp(type)
  542.     int type;
  543. {
  544.     register struct op *t;
  545.  
  546.     t = (struct op *) alloc(sizeof(*t), ATEMP);
  547.     t->type = type;
  548.     t->args = t->vars = NULL;
  549.     t->ioact = NULL;
  550.     t->left = t->right = NULL;
  551.     t->str = NULL;
  552.     return (t);
  553. }
  554.  
  555. static void
  556. zzerr()
  557. {
  558.     yyerror("syntax error");
  559. }
  560.  
  561. struct op *
  562. compile(s)
  563.     Source *s;
  564. {
  565.     yynerrs = 0;
  566.     multiline = 0;
  567.     herep = heres;
  568.     source = s;
  569.     if (yyparse())
  570.         unwind();
  571.     if (s->type == STTY || s->type == SFILE || s->type == SHIST)
  572.         s->str = null;    /* line is not preserved */
  573.     return outtree;
  574. }
  575.  
  576.