home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / ssh-1.7 / part02 / eval.c next >
Encoding:
C/C++ Source or Header  |  1993-04-15  |  13.2 KB  |  712 lines

  1. /* $Copyright:    $
  2.  * Copyright (c) 1991,1992,1993 by Steve Baker
  3.  * All rights reserved
  4.  *  
  5.  * This software is provided as is without any express or implied
  6.  * warranties, including, without limitation, the implied warranties
  7.  * of merchantability and fitness for a particular purpose.
  8.  */
  9. #include "shell.h"
  10.  
  11. #define T_EOL        0
  12. #define T_OR        1
  13. #define T_AND        2
  14.  
  15. #define T_NOT        3
  16.  
  17. #define T_EQ        5
  18. #define T_NE        6
  19. #define T_GE        7
  20. #define T_GT        8
  21. #define T_LE        9
  22. #define T_LT        10
  23. #define T_TEQ        11
  24. #define T_TNE        12
  25.  
  26. #define T_STR        15
  27. #define T_NUM        16
  28. #define T_SVAR        17
  29. #define T_NVAR        18
  30.  
  31. #define T_OP        20
  32. #define T_CP        21
  33. #define T_PLUS        25
  34. #define T_MINUS        26
  35. #define T_DIV        27
  36. #define T_MUL        28
  37. #define T_MOD        29
  38.  
  39. #define T_PP        30
  40. #define T_MM        31
  41. #define T_LAND        32
  42. #define T_LOR        33
  43. #define T_TILD        34
  44.  
  45. #define T_EXSIST    35
  46. #define T_READ        36
  47. #define T_WRITE        37
  48. #define T_EXECUTE    38
  49. #define T_OWNER        39
  50. #define T_ZERO        40
  51. #define T_PLAIN        41
  52. #define T_DIR        42
  53. #define T_SIZE        43
  54. #define T_USER        44
  55. #define T_GROUP        45
  56. #define T_PROT        46
  57. #define T_MODE        47
  58.  
  59. #define T_SHL        50
  60. #define T_SHR        51
  61. #define T_XOR        52
  62.  
  63. #define T_ERR        55
  64.  
  65. struct tlist {
  66.   union _v {
  67.     char *str;
  68.     long num;
  69.     struct _setvar *var;
  70.   } v;
  71.   short vp;
  72.   char tok;
  73. } *tlst;
  74. static char *exp;
  75. static long num, lp;
  76. static short vp;
  77. static char *str;
  78. struct _setvar *_set, *getvalidset();
  79. extern int err;
  80.  
  81. long expr(), eval(), doconditionals(), domath();
  82. long domuldiv(), dounary(), doprimary();
  83. char *getvalidenv();
  84.  
  85. long expr(wrd)
  86. char *wrd;
  87. {
  88.   int nt,tp,tok;
  89.   long res;
  90.   struct tlist *tsav;
  91.   char *sav;
  92.  
  93. /* hack to save previous value of exp and tlst to make expr() re-intrant */
  94.   sav = exp;
  95.   tsav = tlst;
  96.   exp = wrd;
  97.   err = tp = 0;
  98.   tlst = (struct tlist *)calloc(nt=5,sizeof(struct tlist));
  99.  
  100.   while(tok = get_next(exp)) {
  101.     if (tp == nt) tlst = (struct tlist *)realloc(tlst,sizeof(struct tlist) * (nt+=5));
  102.     tlst[tp].tok = tok;
  103.     switch(tok) {
  104.       case T_STR:
  105.     tlst[tp].v.str = str;
  106.     break;
  107.       case T_NUM:
  108.     tlst[tp].v.num = num;
  109.     break;
  110.       case T_SVAR:
  111.     tlst[tp].vp = vp;
  112.       case T_NVAR:
  113.     tlst[tp].v.var = _set;
  114.     break;
  115.     }
  116.     tp++;
  117.   }
  118.   if (tp == nt) tlst = (struct tlist *)realloc(tlst,sizeof(struct tlist) * ++nt);
  119.   tlst[tp].tok = T_EOL;
  120.   lp = 0;
  121.   res = eval();
  122.   if (!err && tlst[lp].tok == T_CP) error(3);
  123.   else if (!err && tlst[lp].tok != T_EOL) error(1);
  124.   for(tp=0;tlst[tp].tok;tp++)
  125.     if (tlst[tp].tok == T_STR) free(tlst[tp].v.str);
  126.   free(tlst);
  127.   exp = sav;
  128.   tlst = tsav;
  129.   return err? 0 : res;
  130. }
  131.  
  132. long eval()
  133. {
  134.   int res,res2;
  135.  
  136.   res = doconditionals();
  137.   if (err) return 0;
  138.  
  139.   switch(tlst[lp++].tok) {
  140.     case T_OR:
  141.       res2 = eval();
  142.       res = res || res2;
  143.       break;
  144.     case T_AND:
  145.       res2 = eval();
  146.       res = res && res2;
  147.       break;
  148.     case T_EOL:
  149.       lp--;
  150.       return res;
  151.     case T_CP:
  152.       lp--;
  153.       return res;
  154.     default:
  155.       error(2);
  156.       break;
  157.   }
  158.   return res;
  159. }
  160.  
  161. long doconditionals()
  162. {
  163.   int ans;
  164.  
  165.   if (tlst[lp].tok == T_STR || tlst[lp].tok == T_SVAR) return dostrcmp();
  166.   ans = domath();
  167.   if (err) return 0;
  168.  
  169.   switch(tlst[lp++].tok) {
  170.     case T_EQ:
  171.       ans = ans == doconditionals();
  172.       break;
  173.     case T_NE:
  174.       ans = ans != doconditionals();
  175.       break;
  176.     case T_GE:
  177.       ans = ans >= doconditionals();
  178.       break;
  179.     case T_LE:
  180.       ans = ans <= doconditionals();
  181.       break;
  182.     case T_GT:
  183.       ans = ans > doconditionals();
  184.       break;
  185.     case T_LT:
  186.       ans = ans < doconditionals();
  187.       break;
  188.     default:
  189.       lp--;
  190.       return ans;
  191.   }
  192.   return ans;
  193. }
  194.  
  195. long domath()
  196. {
  197.   int res;
  198.  
  199.   res = domuldiv();
  200.   if (err) return 0;
  201.  
  202.   switch(tlst[lp++].tok) {
  203.     case T_PLUS:
  204.       res += domath();
  205.       break;
  206.     case T_MINUS:
  207.       res -= domath();
  208.       break;
  209.     case T_LAND:
  210.       res &= domath();
  211.       break;
  212.     case T_LOR:
  213.       res |= domath();
  214.       break;
  215.     case T_SHL:
  216.       res <<= domath();
  217.       break;
  218.     case T_SHR:
  219.       res >>= domath();
  220.       break;
  221.     case T_XOR:
  222.       res ^= domath();
  223.       break;
  224.     default:
  225.       lp--;
  226.       return res;
  227.   }
  228.   return res;
  229. }
  230.  
  231. long domuldiv()
  232. {
  233.   int res;
  234.  
  235.   res = dounary();
  236.   if (err) return 0;
  237.  
  238.   switch(tlst[lp++].tok) {
  239.     case T_MUL:
  240.       res *= domuldiv();
  241.       break;
  242.     case T_DIV:
  243.       res /= domuldiv();
  244.       break;
  245.     case T_MOD:
  246.       res %= domuldiv();
  247.       break;
  248.     default:
  249.       lp--;
  250.       return res;
  251.   }
  252.   return res;
  253. }
  254.  
  255. long dounary()
  256. {
  257.   int res, tok;
  258.   char *fil = NULL;
  259.   struct stat buf;
  260.  
  261.   if (err) return 0;
  262.   tok = tlst[lp++].tok;
  263.   if (tok >= T_EXSIST && tok <= T_MODE) {
  264.     if (tlst[lp].tok == T_STR) {
  265.       fil = tlst[lp++].v.str;
  266.     } else if (tlst[lp].tok == T_SVAR) {
  267.       fil = tlst[lp].v.var->sv.wrd[tlst[lp].vp];
  268.       lp++;
  269.     } else {
  270.       error(7);
  271.       return 0;
  272.     }
  273.     if ((tok >= T_OWNER) && (stat(fil,&buf) < 0)) fil = NULL;
  274.   }
  275.  
  276.   switch(tok) {
  277.     case T_MINUS:
  278.       res = -dounary();
  279.       break;
  280.     case T_NOT:
  281.       res = !dounary();
  282.       break;
  283.     case T_TILD:
  284.       res = ~dounary();
  285.       break;
  286.     case T_PLUS:
  287.       res = dounary();
  288.       break;
  289.     case T_MM:
  290.     case T_PP:
  291.       if (tlst[lp].tok != T_NVAR) {
  292.         error(8);
  293.     break;
  294.       }
  295.       if (!tlst[lp-1].v.var->protect) {
  296.         if (tok == T_PP) tlst[lp].v.var->sv.val++;
  297.         else tlst[lp].v.var->sv.val--;
  298.       }
  299.       res = dounary();
  300.       break;
  301.     case T_EXSIST:
  302.       if (!fil) return res = 0;
  303.       res = access(fil,F_OK)? 0 : 1;
  304.       break;
  305.     case T_READ:
  306.       if (!fil) return res = 0;
  307.       res = access(fil,R_OK)? 0 : 1;
  308.       break;
  309.     case T_WRITE:
  310.       if (!fil) return res = 0;
  311.       res = access(fil,W_OK)? 0 : 1;
  312.       break;
  313.     case T_EXECUTE:
  314.       if (!fil) return res = 0;
  315.       res = access(fil,X_OK)? 0 : 1;
  316.       break;
  317.     case T_OWNER:
  318.       if (!fil) return res = 0;
  319.       res = (buf.st_uid == getuid()? 1 : 0);
  320.       break;
  321.     case T_ZERO:
  322.       if (!fil) return res = 0;
  323.       res = (buf.st_size == 0? 1 : 0);
  324.       break;
  325.     case T_SIZE:
  326.       if (!fil) return res = 0;
  327.       res = buf.st_size;
  328.       break;
  329.     case T_PLAIN:
  330.       if (!fil) return res = 0;
  331.       res = (buf.st_mode & S_IFMT) == S_IFREG? 1 : 0;
  332.       break;
  333.     case T_DIR:
  334.       if (!fil) return res = 0;
  335.       res = (buf.st_mode & S_IFMT) == S_IFDIR? 1 : 0;
  336.       break;
  337.     case T_USER:
  338.       if (!fil) return res = -1;
  339.       res = buf.st_uid;
  340.       break;
  341.     case T_GROUP:
  342.       if (!fil) return res = -1;
  343.       res = buf.st_gid;
  344.       break;
  345.     case T_PROT:
  346.       if (!fil) return res = 0;
  347.       res = buf.st_mode & 0777;
  348.       break;
  349.     case T_MODE:
  350.       if (!fil) return res = 0;
  351.       res = buf.st_mode;
  352.       break;
  353.     default:
  354.       lp--;
  355.       res = doprimary();
  356.   }
  357.   return res;
  358. }
  359.  
  360. long doprimary()
  361. {
  362.   long res;
  363.   int tok;
  364.  
  365.   if (tlst[lp++].tok == T_OP) {
  366.     res = eval();
  367.     if (tlst[lp].tok != T_CP) error(3);
  368.     lp++;
  369.     return res;
  370.   }
  371.   switch(tlst[--lp].tok) {
  372.     case T_NUM:
  373.       return tlst[lp++].v.num;
  374.     case T_NVAR:
  375.       res = tlst[lp++].v.var->sv.val;
  376.       tok = tlst[lp].tok;
  377.       if (tok == T_PP || tok == T_MM) {
  378.         if (!tlst[lp-1].v.var->protect) {
  379.       if (tok == T_PP) tlst[lp-1].v.var->sv.val++;
  380.       else tlst[lp-1].v.var->sv.val--;
  381.     }
  382.         lp++;
  383.       }
  384.       return res;
  385.     case T_SVAR:
  386.     case T_STR:
  387.       error(4);
  388.       break;
  389.     case T_EOL:
  390.       error(5);
  391.       break;
  392.     case T_ERR:
  393.       error(6);
  394.       break;
  395.     default:
  396.       error(7);
  397.       break;
  398.   }
  399.   return 0;
  400. }
  401.  
  402. dostrcmp()
  403. {
  404.   int ans,tok;
  405.   char *s, *s2;
  406.  
  407.   if (tlst[lp].tok == T_STR) s = tlst[lp++].v.str;
  408.   else {
  409.     s = tlst[lp].v.var->sv.wrd[tlst[lp].vp];
  410.     lp++;
  411.   }
  412.  
  413.   tok = tlst[lp++].tok;
  414.   if (tok < T_EQ || tok > T_TNE) return 1;
  415.   if (tlst[lp].tok != T_STR && tlst[lp].tok != T_SVAR) {
  416.     error(7);
  417.     return 0;
  418.   }
  419.   if (tlst[lp].tok == T_STR) s2 = tlst[lp++].v.str;
  420.   else {
  421.     s2 = tlst[lp].v.var->sv.wrd[tlst[lp].vp];
  422.     lp++;
  423.   }
  424.   switch(tok) {
  425.     case T_TEQ:
  426.       ans = patmatch(s,s2);
  427.       break;
  428.     case T_TNE:
  429.       ans = !patmatch(s,s2);
  430.       break;
  431.     case T_EQ:
  432.       ans = !strcmp(s,s2);
  433.       break;
  434.     case T_NE:
  435.       ans = strcmp(s,s2);
  436.       break;
  437.     case T_GE:
  438.       ans = strcmp(s,s2) >= 0;
  439.       break;
  440.     case T_LE:
  441.       ans = strcmp(s,s2) <= 0;
  442.       break;
  443.     case T_GT:
  444.       ans = strcmp(s,s2) > 0;
  445.       break;
  446.     case T_LT:
  447.       ans = strcmp(s,s2) < 0;
  448.       break;
  449.   }
  450.   return ans;
  451. }
  452.  
  453.  
  454. error(n)
  455. int n;
  456. {
  457.   switch(n) {
  458.     case 1:
  459.     case 2:
  460.       fprintf(stderr,"End of expression expected.\n");
  461.       break;
  462.     case 3:
  463.       fprintf(stderr,"Mismatched parentheses.\n");
  464.       break;
  465.     case 4:
  466.       fprintf(stderr,"String found when numeric expected.\n");
  467.       break;
  468.     case 5:
  469.       fprintf(stderr,"Unexpected end of expression.\n");
  470.       break;
  471.     case 6:
  472.       fprintf(stderr,"Illegal character.\n");
  473.       break;
  474.     case 7:
  475.       fprintf(stderr,"String literal expected.\n");
  476.       break;
  477.     case 8:
  478.       fprintf(stderr,"Variable expected for ++ or --.\n");
  479.       break;
  480.   }
  481.   err = 1;
  482. }
  483.  
  484.  
  485. get_next()
  486. {
  487.   int i,pos;
  488.   char *s, *t, c;
  489.   static char numbuf[33];
  490.  
  491.   while(isspace(*exp)) exp++;
  492.   switch(*exp++) {
  493.     case '+':
  494.       if (*exp == '+') {
  495.         exp++;
  496.     return T_PP;
  497.       }
  498.       return T_PLUS;
  499.     case '-':
  500.       switch(*exp++) {
  501.     case 'e':
  502.       return T_EXSIST;
  503.     case 'r':
  504.       return T_READ;
  505.     case 'w':
  506.       return T_WRITE;
  507.     case 'x':
  508.       return T_EXECUTE;
  509.     case 'o':
  510.       return T_OWNER;
  511.     case 'z':
  512.       return T_ZERO;
  513.     case 'f':
  514.       return T_PLAIN;
  515.     case 'd':
  516.       return T_DIR;
  517.     case 's':
  518.       return T_SIZE;
  519.     case 'u':
  520.       return T_USER;
  521.     case 'g':
  522.       return T_GROUP;
  523.     case 'p':
  524.       return T_PROT;
  525.     case 'm':
  526.       return T_MODE;
  527.     case '-':
  528.       return T_MM;
  529.       }
  530.       exp--;
  531.       return T_MINUS;
  532.     case '/':
  533.       return T_DIV;
  534.     case '*':
  535.       return T_MUL;
  536.     case '%':
  537.       return T_MOD;
  538.     case '|':
  539.       if (*exp != '|') return T_LOR;
  540.       exp++;
  541.       return T_OR;
  542.     case '&':
  543.       if (*exp != '&') return T_LAND;
  544.       exp++;
  545.       return T_AND;
  546.     case '^':
  547.       return T_XOR;
  548.     case '~':
  549.       return T_TILD;
  550.     case '<':
  551.       if (*exp == '<') {
  552.     exp++;
  553.     return T_SHL;
  554.       }
  555.       if (*exp == '=') {
  556.     exp++;
  557.     return T_LE;
  558.       }
  559.       return T_LT;
  560.     case '>':
  561.       if (*exp == '>') {
  562.     exp++;
  563.     return T_SHR;
  564.       }
  565.       if (*exp == '=') {
  566.     exp++;
  567.     return T_GE;
  568.       }
  569.       return T_GT;
  570.     case '=':
  571.       if (*exp == '~') {
  572.         exp++;
  573.     return T_TEQ;
  574.       }
  575.       if (*exp++ != '=') return T_ERR;
  576.       return T_EQ;
  577.     case '!':
  578.       if (*exp == '=') {
  579.         exp++;
  580.     return T_NE;
  581.       }
  582.       if (*exp == '~') {
  583.     exp++;
  584.     return T_TNE;
  585.       }
  586.       return T_NOT;
  587.     case 0:
  588.       return T_EOL;
  589.     case '(':
  590.       return T_OP;
  591.     case ')':
  592.       return T_CP;
  593.     case '$':
  594.       if (*exp == '$') {
  595.     exp++;
  596.     if (*exp == '?') {
  597.       exp++;
  598.       s = getvalidenv(&exp,&pos);
  599.       if (s) {
  600.         num = 1;
  601.         free(s);
  602.       } else num = 0;
  603.       return T_NUM;
  604.     }
  605.     if (*exp == '#') {
  606.       exp++;
  607.       s = getvalidenv(&exp,&pos);
  608.       if (s) {
  609.         if (pos < 0) {
  610.           for(num=1,i=0;s[i];i++) if (s[i] == ':') num++;
  611.         } else num = strlen(s);
  612.         free(s);
  613.       } else num = 0;
  614.       return T_NUM;
  615.     }
  616.     s = getvalidenv(&exp,&pos);
  617.     str = s;
  618.     return T_STR;
  619.       }
  620.       if (*exp == '?') {
  621.         exp++;
  622.     if (getvalidset(&exp,&pos)) num = 1;
  623.     else num = 0;
  624.     return T_NUM;
  625.       }
  626.       if (*exp == '#') {
  627.     exp++;
  628.     if (_set = getvalidset(&exp,&pos)) {
  629.       if (pos < 0) num = _set->nwrds;
  630.       else num = strlen(_set->sv.wrd[pos]);
  631.     } else num = 0;
  632.     return T_NUM;
  633.       }
  634.       if (!(_set = getvalidset(&exp,&pos))) return T_ERR;
  635.       if (_set->type != T_STRING) return T_NVAR;
  636.       vp = pos < 0? 0 : pos;
  637.       return T_SVAR;
  638.       break;
  639.     case '\'':
  640.     case '"':
  641.       c = *(exp-1);
  642.       s = exp;
  643.       while(*exp && *exp != c) {
  644.         if (*exp == '\\') exp++;
  645.     exp++;
  646.       }
  647.       t = (char *)malloc((exp-s)+1);
  648.       for(i=0;s < exp;i++) t[i] = *s++;
  649.       t[i] = 0;
  650.       str = t;
  651.       if (*exp == c) exp++;
  652.       return T_STR;
  653.     default:
  654.       exp--;
  655.       i = num = 0;
  656.       if (isdigit(*exp)) {
  657.     if (*exp == '0') {
  658.       exp++;
  659.       switch(*exp++) {
  660.         case 'x':
  661.         case 'X':
  662.           while((isdigit(*exp) || (*exp >= 'a' && *exp <= 'f') || (*exp >= 'A' && *exp <= 'F')) && i < 8)
  663.         numbuf[i++] = *exp++;
  664.           if (!i || i > 8) return T_ERR;
  665.           numbuf[i] = 0;
  666.           for(i=0;numbuf[i];i++) {
  667.         num <<= 4;
  668.         num |= (isdigit(numbuf[i]) ? numbuf[i]-'0' : (islower(numbuf[i]) ? (numbuf[i] - 'a') + 10 : (numbuf[i] - 'A') + 10));
  669.           }
  670.           return T_NUM;
  671.           break;
  672.         case 'b':
  673.         case 'B':
  674.           while((*exp == '1' || *exp == '0') && i < 32) numbuf[i++] = *exp++;
  675.           if (!i || i > 32) return T_ERR;
  676.           numbuf[i] = 0;
  677.           for(i=0;numbuf[i];i++) {
  678.         num <<= 1;
  679.         if (numbuf[i] == '1') num |= 1;
  680.           }
  681.           return T_NUM;
  682.           break;
  683.         default:
  684.           exp--;
  685.           while(*exp >= '0' && *exp < '8' && i < 10) numbuf[i++] = *exp++;
  686.           if (!i) return T_NUM;
  687.           if (i > 10) return T_ERR;
  688.           numbuf[i] = 0;
  689.           for (i=0;numbuf[i];i++) {
  690.         num <<= 3;
  691.         num |= numbuf[i] - '0';
  692.           }
  693.           return T_NUM;
  694.           break;
  695.       }
  696.     }
  697.         while(isdigit(*exp) && i < 11) numbuf[i++] = *exp++;
  698.     if (i > 11) return T_ERR;
  699.     numbuf[i] = 0;
  700.     num = atoi(numbuf);
  701.     return T_NUM;
  702.       }
  703.       s = exp;
  704.       while(*exp && !isspace(*exp)) exp++;
  705.       str = t = (char *)malloc((exp-s)+1);
  706.       for(i=0;s<exp;i++) t[i] = *s++;
  707.       t[i] = 0;
  708.       return T_STR;
  709.   }
  710.   /*NOTREACHED*/
  711. }
  712.