home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Archived / Updates / Flash / writeflash / !MakeFlash / c / evaluate < prev    next >
Text File  |  2000-04-23  |  13KB  |  574 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <math.h>
  6. #include <ctype.h>
  7.  
  8. #include "proto.h"
  9. #include "evaluate.h"
  10.  
  11. //#define ALLOW_ARRAYS
  12.  
  13. #define MAXVARS     64
  14.  
  15. typedef struct variable {
  16.   char name[MAXVARNAMELENGTH+1];
  17.   S32 value;
  18. #ifdef ALLOW_ARRAYS
  19.   S32 *array;
  20.   int dimension;
  21. #endif
  22. } variable;
  23.  
  24. static variable vars[MAXVARS];
  25.  
  26. static double e, PI;
  27. static int error;
  28.  
  29. static double eval(char *string);
  30. static int find_variable(char *name);
  31.  
  32.  
  33. void init_evaluator() {
  34.  
  35.   int i;
  36.  
  37.   e = exp(1.0);
  38.   PI = 2.0*acos(0.0);
  39.  
  40.   for (i = 0; i < MAXVARS; i++)    vars[i].name[0] = '\0';
  41. }
  42.  
  43.  
  44. int evaluate(char *src, S32 *value) {
  45. // do a bit of preprocessing and then evaluate the expression
  46.  
  47.   int read, write, i, parentheses;
  48.   double res;
  49.   char expr[512];
  50.  
  51.   strcpy(expr, src);
  52.   error = 0;
  53.  
  54.   // check for unmatched parentheses
  55.   parentheses = 0;
  56.   i = 0;
  57.   while (expr[i] >= 32) {
  58.     if (expr[i] == '(') parentheses++;
  59.     if (expr[i] == ')') parentheses--;
  60.     if (parentheses < 0)  return 1;
  61.     i++;
  62.   }
  63.   if (parentheses != 0)  return 1;
  64.  
  65.   // remove spaces
  66.   read = write = 0;
  67.   while (expr[read] >= 32) {
  68.     if (expr[read] > 32) {
  69.       expr[write] = expr[read];
  70.       write++;
  71.     }
  72.     read++;
  73.   }
  74.  
  75.   // terminate expression
  76.   expr[write] = 0;
  77.  
  78.   // evaluate
  79.   res = eval(expr);
  80.   if (error)   return 1;
  81.  
  82.   *value = (S32)res;
  83.   return 0;
  84. }
  85.  
  86.  
  87. int variable_exists(char *var) {
  88.  
  89.   if (find_variable(var) >= 0)  return 1;
  90.  
  91.   return 0;
  92. }
  93.  
  94.  
  95. int create_variable(char *var) {
  96.  
  97.   int vi;
  98.  
  99.   if ((strlen(var) > MAXVARNAMELENGTH) || (!*var)) {
  100.     fprintf(stderr, "Illegal varname\n");
  101.     return 1;
  102.   }
  103.  
  104.   if (variable_exists(var)) {
  105.     fprintf(stderr, "Variable '%s' already exists\n", var);
  106.     return 1;
  107.   }
  108.  
  109.   for (vi = 0; vi < MAXVARS; vi++)
  110.     if (vars[vi].name[0] == '\0') {
  111.       strcpy(vars[vi].name, var);
  112.       vars[vi].value = 0;
  113. #ifdef ALLOW_ARRAYS
  114.       vars[vi].dimension = 0;
  115. #endif
  116.       return 0;
  117.     }
  118.  
  119.   fprintf(stderr, "Failed to create variable '%s'\n", var);
  120.   return 1;
  121. }
  122.  
  123.  
  124. int destroy_variable(char *var) {
  125.  
  126.   int vi;
  127.  
  128.   vi = find_variable(var);
  129.   if (vi < 0) {
  130.     fprintf(stderr, "Variable '%s' not found\n", var);
  131.     return 1;
  132.   }
  133. #ifdef ALLOW_ARRAYS
  134.   if (vars[vi].dimension)    free(vars[vi].array);
  135. #endif
  136.   vars[vi].name[0] = '\0';
  137.  
  138.   return 0;
  139. }
  140.  
  141.  
  142. int set_variable_value(char *var, S32 value) {
  143.  
  144.   int vi;
  145.  
  146.   vi = find_variable(var);
  147.   if (vi < 0) {
  148.     fprintf(stderr, "Variable '%s' not found\n", var);
  149.     return 1;
  150.   }
  151.   vars[vi].value = value;
  152.  
  153.   return 0;
  154. }
  155.  
  156.  
  157. int read_variable_value(char *var, S32 *value) {
  158.  
  159.   int vi;
  160.  
  161.   vi = find_variable(var);
  162.   if (vi < 0) {
  163.     fprintf(stderr, "Variable '%s' not found\n", var);
  164.     return 1;
  165.   }
  166.   *value = vars[vi].value;
  167.  
  168.   return 0;
  169. }
  170.  
  171.  
  172. #ifdef ALLOW_ARRAYS
  173. int create_array(char *var, int dim) {
  174.  
  175.   int vi;
  176.  
  177.   if ((strlen(var) > MAXVARNAMELENGTH) || (!*var) || (dim < 1) || (dim > 32000)) {
  178.     fprintf(stderr, "Illegal variablename or dimension\n");
  179.     return 1;
  180.   }
  181.  
  182.   if (variable_exists(var)) {
  183.     fprintf(stderr, "Variable '%s' already exists\n", var);
  184.     return 1;
  185.   }
  186.  
  187.   for (vi = 0; vi < MAXVARS; vi++)
  188.     if (vars[vi].name[0] == '\0') {
  189.       vars[vi].array = malloc(sizeof(int)*dim);
  190.       if (!vars[vi].array) {
  191.         fprintf(stderr, "No room\n");
  192.         return 1;
  193.       }
  194.       memset(vars[vi].array, 0, sizeof(int)*dim);
  195.       strcpy(vars[vi].name, var);
  196.       vars[vi].dimension = dim;
  197.       return 0;
  198.     }
  199.  
  200.   fprintf(stderr, "Failed to create variable '%s'\n", var);
  201.   return 1;
  202. }
  203.  
  204.  
  205. int set_array_value(char *var, S32 value, int index) {
  206.  
  207.   int vi;
  208.  
  209.   vi = find_variable(var);
  210.   if (vi < 0) {
  211.     fprintf(stderr, "Variable '%s' not found\n", var);
  212.     return 1;
  213.   }
  214.   if ((index < 0) || (index > vars[vi].dimension-1)) {
  215.     fprintf(stderr, "Outside range: %s[%d]\n", vars[vi].name, vars[vi].dimension);
  216.     return 1;
  217.   }
  218.   vars[vi].array[index] = value;
  219.  
  220.   return 0;
  221. }
  222.  
  223.  
  224. int read_array_value(char *var, int index, S32 *value) {
  225.  
  226.   int vi;
  227.  
  228.   vi = find_variable(var);
  229.   if (vi < 0) {
  230.     fprintf(stderr, "Variable '%s' not found\n", var);
  231.     return 1;
  232.   }
  233.   if ((index < 0) || (index > vars[vi].dimension-1)) {
  234.     fprintf(stderr, "Outside range: %s[%d]\n", vars[vi].name, vars[vi].dimension);
  235.     return 1;
  236.   }
  237.   *value = vars[vi].array[index];
  238.  
  239.   return 0;
  240. }
  241. #endif
  242. // ----------------------------------------------------
  243.  
  244. int find_variable(char *name) {
  245.  
  246.   int vi;
  247.  
  248.   for (vi = 0; vi < MAXVARS; vi++)
  249.     if (strcmp(vars[vi].name, name) == 0)   return vi;
  250.  
  251.   return -1;
  252. }
  253.  
  254. /*
  255.  *   + - * /
  256.  *   < > == !> <= >=       1+2<3*4  =  (1+2)<(3*4)    cmps return 1 (true) or 0 (false)
  257.  *   && || & |
  258.  * numbers (integers or floats)
  259.  * PI and e
  260.  * functions
  261.  *   trig
  262.  *      SIN(expr)
  263.  *      COS(expr)
  264.  *      TAN(expr)
  265.  *   math
  266.  *      LOG(expr)
  267.  *      EXP(expr)
  268.  *      SQR(expr)
  269.  *      ABS(expr)
  270.  *      RND(expr)
  271.  *
  272.  */
  273.  
  274. static int FUNC_SIN = ('s'<<16) | ('i'<<8) | ('n');
  275. static int FUNC_COS = ('c'<<16) | ('o'<<8) | ('s');
  276. static int FUNC_TAN = ('t'<<16) | ('a'<<8) | ('n');
  277. static int FUNC_EXP = ('e'<<16) | ('x'<<8) | ('p');
  278. static int FUNC_LOG = ('l'<<16) | ('o'<<8) | ('g');
  279. static int FUNC_ABS = ('a'<<16) | ('b'<<8) | ('s');
  280. static int FUNC_SQR = ('s'<<16) | ('q'<<8) | ('r');
  281. static int FUNC_RND = ('r'<<16) | ('n'<<8) | ('d');
  282.  
  283.  
  284.  
  285. double eval(char *s) {
  286.  
  287.   int more, parentheses, i, unnecessary, length, func, varno;
  288.   double value1, value2;
  289.   float value4;
  290.  
  291.   // find the length of the string
  292.   length = strlen(s);
  293.  
  294.   if (length == 0)    return 0;
  295.  
  296.   // remove unncessary parentheses
  297.   do {
  298.     more = 0;
  299.     if ((s[0] == '(') && (s[length-1] == ')')) {
  300.       parentheses = 0;
  301.       unnecessary = 1;
  302.       i = 0;
  303.       while (i < length-1) {
  304.         if (s[i] == '(') parentheses++;
  305.         if (s[i] == ')') parentheses--;
  306.         if (parentheses == 0) unnecessary = 0;
  307.         i++;
  308.       }
  309.       if (unnecessary) {
  310.         for (i = 0; i < length-2; i++)  s[i] = s[i+1];
  311.         length -= 2;
  312.         s[length] = 0;
  313.         more = 1;
  314.       }
  315.     }
  316.   } while (more);
  317.  
  318.   // scan for comparison outside parentheses
  319.   parentheses = 0;
  320.   for (i = 0; i < length-1; i++) {
  321.     if (s[i] == '(') parentheses++;
  322.     if (s[i] == ')') parentheses--;
  323.     if ( (parentheses == 0) &&
  324.          ((s[i] == '=') || (s[i] == '<') || (s[i] == '>') || (s[i] == '!') ||
  325.           (s[i] == '&') || (s[i] == '|'))) {
  326.       char *p;
  327.       int cmp;
  328.  
  329. #define CMP_EQ      0
  330. #define CMP_NE      1
  331. #define CMP_GE      2
  332. #define CMP_GT      3
  333. #define CMP_LE      4
  334. #define CMP_LT      5
  335. #define CMP_OR      6
  336. #define CMP_AND     7
  337.  
  338.       p = s+i+1;
  339.       if ((s[i] == '=') && (s[i+1] == '=')) {
  340.         p++;
  341.         cmp = CMP_EQ;
  342.       } else if ((s[i] == '!') && (s[i+1] == '=')) {
  343.         p++;
  344.         cmp = CMP_NE;
  345.       } else if ((s[i] == '>') && (s[i+1] == '=')) {
  346.         p++;
  347.         cmp = CMP_GE;
  348.       } else if ((s[i] == '<') && (s[i+1] == '=')) {
  349.         p++;
  350.         cmp = CMP_LE;
  351.       } else if ((s[i] == '&') && (s[i+1] == '&')) {
  352.         p++;
  353.         cmp = CMP_AND;
  354.       } else if ((s[i] == '|') && (s[i+1] == '|')) {
  355.         p++;
  356.         cmp = CMP_OR;
  357.       } else if (s[i] == '>')
  358.         cmp = CMP_GT;
  359.       else if (s[i] == '<')
  360.         cmp = CMP_LT;
  361.       else {
  362.         fprintf(stderr, "Unsupported comparision\n");
  363.         error = 6;
  364.         return 0;
  365.       }
  366.  
  367.       s[i] = 0;
  368.       value1 = eval(s);                                 // eval left side
  369.       if (error)  return 0;
  370.       value2 = eval(p);                                 // eval right side
  371.       if (error)  return 0;
  372.       switch (cmp) {
  373.       case CMP_EQ:
  374.         if (value1 == value2)  return 1;
  375.         return 0;
  376.         break;
  377.       case CMP_NE:
  378.         if (value1 != value2)  return 1;
  379.         return 0;
  380.         break;
  381.       case CMP_GE:
  382.         if (value1 >= value2)  return 1;
  383.         return 0;
  384.         break;
  385.       case CMP_LE:
  386.         if (value1 <= value2)  return 1;
  387.         return 0;
  388.         break;
  389.       case CMP_GT:
  390.         if (value1 > value2)  return 1;
  391.         return 0;
  392.         break;
  393.       case CMP_LT:
  394.         if (value1 < value2)  return 1;
  395.         return 0;
  396.         break;
  397.       case CMP_OR:
  398.         return ((int)value1) || ((int)value2);
  399.         break;
  400.       case CMP_AND:
  401.         return ((int)value1) && ((int)value2);
  402.         break;
  403.       }
  404.       return 0;                                      // return result
  405.     }
  406.   }
  407.  
  408.   // scan for + outside parentheses and convert to (eval) + (eval)
  409.   parentheses = 0;
  410.   for (i = 0; i < length-1; i++) {
  411.     if (s[i] == '(') parentheses++;
  412.     if (s[i] == ')') parentheses--;
  413.     if ((parentheses == 0) && (s[i] == '+')) {
  414.       s[i] = 0;
  415.       value1 = eval(s);                                 // eval left side
  416.       if (error)  return 0;
  417.       value2 = eval(s+i+1);                             // eval right side
  418.       if (error)  return 0;
  419.       return value1 + value2;                           // return result
  420.     }
  421.   }
  422.  
  423.   // scan for - outside parentheses and convert to (eval) - (eval)
  424.   parentheses = 0;
  425.   for (i = 0; i < length-1; i++) {
  426.     if (s[i] == '(') parentheses++;
  427.     if (s[i] == ')') parentheses--;
  428.     if ((parentheses == 0) && (s[i] == '-')) {
  429.       s[i] = 0;
  430.       value1 = eval(s);                                 // eval left side
  431.       if (error)  return 0;
  432.       value2 = eval(s+i+1);                             // eval right side
  433.       if (error)  return 0;
  434.       return value1 - value2;                           // return result
  435.     }
  436.   }
  437.  
  438.   // scan for * outside parentheses and convert to (eval) * (eval)
  439.   parentheses = 0;
  440.   for (i = 0; i < length-1; i++) {
  441.     if (s[i] == '(') parentheses++;
  442.     if (s[i] == ')') parentheses--;
  443.     if ((parentheses == 0) && (s[i] == '*')) {
  444.       s[i] = 0;                                         // split in left and right side
  445.       value1 = eval(s);                                 // eval left side
  446.       if (error)  return 0;                             // if error, return immediately
  447.       value2 = eval(s+i+1);                             // eval right size
  448.       if (error)  return 0;                             // if error, return immediately
  449.       return value1 * value2;                           // return result
  450.     }
  451.   }
  452.  
  453.   // scan for / outside parentheses and convert to (eval) / (eval)
  454.   parentheses = 0;
  455.   for (i = length-1; i >= 0; i--) {                     // reversed search direction
  456.     if (s[i] == '(') parentheses++;
  457.     if (s[i] == ')') parentheses--;
  458.     if ((parentheses == 0) && (s[i] == '/')) {
  459.       s[i] = 0;
  460.       value1 = eval(s);                                 // eval left side
  461.       if (error)  return 0;                             // if error, return immediately
  462.       value2 = eval(s+i+1);                             // eval right side
  463.       if ((error == 0) && (value2 == 0.0)) {
  464.         fprintf(stderr, "Division by zero : %s/%s\n", s, s+i+1);
  465.         error = 2;
  466.       }
  467.       if (error)  return 0;
  468.       return value1 / value2;                           // return result
  469.     }
  470.   }
  471.  
  472.  
  473.   varno = find_variable(s);
  474.   if (varno >= 0)   return (double)vars[varno].value;
  475.  
  476.   // check if value is 'PI'
  477.   if ((length == 2) && (s[0] == 'P') && (s[1] == 'I'))  return PI;
  478.  
  479.   // check if value is 'e'
  480.   if ((length == 1) && (s[0] == 'e'))  return e;
  481.  
  482.   // check for functions XXX()
  483.   // SIN, COS, TAN, EXP, LOG, ABS, SQR
  484.   if (length >= 5) {
  485.     if ((s[3] == '(')  && (s[length-1] == ')') ) {
  486.       func = (s[0]<<16) | (s[1]<<8) | (s[2]);
  487.  
  488.       if (func == FUNC_SIN) {
  489.         s[length-1] = 0;
  490.         value1 = eval(s+4);
  491.         if (error)  return 0;
  492.         return sin(value1);
  493.       }
  494.  
  495.       if (func == FUNC_COS) {
  496.         s[length-1] = 0;
  497.         value1 = eval(s+4);
  498.         if (error)  return 0;
  499.         return cos(value1);
  500.       }
  501.  
  502.       if (func == FUNC_TAN) {
  503.         s[length-1] = 0;
  504.         value1 = eval(s+4);
  505.         if (error)  return 0;
  506.         return tan(value1);
  507.       }
  508.  
  509.       if (func == FUNC_LOG) {
  510.         s[length-1] = 0;
  511.         value1 = eval(s+4);
  512.         if (error)  return 0;
  513.         if (value1 <= 0) {
  514.           fprintf(stderr, "log(%s) not allowed\n", s+4);
  515.           error = 3;
  516.           return 0;
  517.         }
  518.         else
  519.           return log(value1);
  520.       }
  521.  
  522.       if (func == FUNC_EXP) {
  523.         s[length-1] = 0;
  524.         value1 = eval(s+4);
  525.         if (error)  return 0;
  526.         return exp(value1);
  527.       }
  528.  
  529.       if (func == FUNC_ABS) {
  530.         s[length-1] = 0;
  531.         value1 = eval(s+4);
  532.         if (error)  return 0;
  533.         return fabs(value1);
  534.       }
  535.  
  536.       if (func == FUNC_RND) {
  537.         s[length-1] = 0;
  538.         value1 = eval(s+4);
  539.         if (error)  return 0;
  540.         if (value1 <= 0) {
  541.           fprintf(stderr, "rnd(%s) not allowed\n", s+4);
  542.           error = 7;
  543.           return 0;
  544.         }
  545.         return (double)(rand() % (int)value1);
  546.       }
  547.  
  548.       if (func == FUNC_SQR) {
  549.         s[length-1] = 0;
  550.         value1 = eval(s+4);
  551.         if (error)  return 0;
  552.         if (value1 < 0) {
  553.           fprintf(stderr, "sqr(%s) not allowed\n", s+4);
  554.           error = 5;
  555.           return 0;
  556.         }
  557.         else
  558.           return sqrt(value1);
  559.       }
  560.  
  561.     }
  562.   }
  563.  
  564.  
  565.   // couldn't find neither + - * / so the rest must be a value
  566.   if (sscanf(s, "%e", &value4) != 1) {
  567.     error = 4;
  568.     fprintf(stderr, "Failed to evaluate '%s'\n", s);
  569.     return 0;
  570.   }
  571.  
  572.   return value4;
  573. }
  574.