Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/Evaluator.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /externals/clhep/src/Evaluator.cc (Version 11.3.0) and /externals/clhep/src/Evaluator.cc (Version 11.2.2)


  1 // -*- C++ -*-                                      1 // -*- C++ -*-
  2 // -------------------------------------------      2 // ---------------------------------------------------------------------------
  3                                                     3 
  4 #include "CLHEP/Evaluator/Evaluator.h"              4 #include "CLHEP/Evaluator/Evaluator.h"
  5                                                     5 
  6 #include <iostream>                                 6 #include <iostream>
  7 #include <sstream>                                  7 #include <sstream>
  8 #include <string>                                   8 #include <string>
  9 #include <cmath>  // for std::pow()                 9 #include <cmath>  // for std::pow()
 10 #include <stack>                                   10 #include <stack>
 11 #include <unordered_map>                           11 #include <unordered_map>
 12 #include <string.h>                                12 #include <string.h>
 13 #include <ctype.h>                                 13 #include <ctype.h>
 14 #include <errno.h>                                 14 #include <errno.h>
 15 #include <stdlib.h> // for strtod()                15 #include <stdlib.h> // for strtod()
 16                                                    16 
 17 using std::string;                                 17 using std::string;
 18 using std::stack;                                  18 using std::stack;
 19                                                    19 
 20 //--------------------------------------------     20 //---------------------------------------------------------------------------
 21 // Fix non ISO C++ compliant cast from pointer     21 // Fix non ISO C++ compliant cast from pointer to function
 22 // to void*, which is a pointer to an object       22 // to void*, which is a pointer to an object
 23 typedef void (*voidfuncptr)();                     23 typedef void (*voidfuncptr)();
 24 struct Item {                                      24 struct Item {
 25   enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTI     25   enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTION } what;
 26   double variable;                                 26   double variable;
 27   string expression;                               27   string expression;
 28   // Fix non ISO C++ compliant cast from point     28   // Fix non ISO C++ compliant cast from pointer to function
 29   // to void*, which is a pointer to an object     29   // to void*, which is a pointer to an object
 30   //void   *function;                              30   //void   *function;
 31   voidfuncptr function;                            31   voidfuncptr function;
 32                                                    32 
 33   Item()         : what(UNKNOWN),   variable(0     33   Item()         : what(UNKNOWN),   variable(0),expression(), function(0) {}
 34   Item(double x) : what(VARIABLE),  variable(x     34   Item(double x) : what(VARIABLE),  variable(x),expression(), function(0) {}
 35   Item(string x) : what(EXPRESSION),variable(0     35   Item(string x) : what(EXPRESSION),variable(0),expression(x),function(0) {}
 36   Item(voidfuncptr x) : what(FUNCTION),  varia     36   Item(voidfuncptr x) : what(FUNCTION),  variable(0),expression(), function(x) {}
 37 };                                                 37 };
 38                                                    38 
 39 using pchar = char *;                              39 using pchar = char *;
 40 using dic_type = std::unordered_map<string, It     40 using dic_type = std::unordered_map<string, Item>;
 41                                                    41 
 42 struct Struct {                                    42 struct Struct {
 43   dic_type theDictionary;                          43   dic_type theDictionary;
 44   pchar    theExpression;                          44   pchar    theExpression;
 45   pchar    thePosition;                            45   pchar    thePosition;
 46   int      theStatus;                              46   int      theStatus;
 47   double   theResult;                              47   double   theResult;
 48 };                                                 48 };
 49                                                    49 
 50 //--------------------------------------------     50 //---------------------------------------------------------------------------
 51 #define EVAL HepTool::Evaluator                    51 #define EVAL HepTool::Evaluator
 52                                                    52 
 53 #define REMOVE_BLANKS \                            53 #define REMOVE_BLANKS \
 54 for(pointer=name;;pointer++) if (!isspace(*poi     54 for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
 55 for(n=(int)strlen(pointer);n>0;n--) if (!isspa     55 for(n=(int)strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
 56                                                    56 
 57 #define SKIP_BLANKS                      \         57 #define SKIP_BLANKS                      \
 58 for(;;pointer++) {                       \         58 for(;;pointer++) {                       \
 59   c = (pointer > end) ? '\0' : *pointer; \         59   c = (pointer > end) ? '\0' : *pointer; \
 60   if (!isspace(c)) break;                \         60   if (!isspace(c)) break;                \
 61 }                                                  61 }
 62                                                    62 
 63 #define EVAL_EXIT(STATUS,POSITION) endp = POSI     63 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
 64 #define MAX_N_PAR 5                                64 #define MAX_N_PAR 5
 65                                                    65 
 66 static const char sss[MAX_N_PAR+2] = "012345";     66 static const char sss[MAX_N_PAR+2] = "012345";
 67                                                    67 
 68 enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE     68 enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
 69        PLUS, MINUS, UNARY_PLUS, UNARY_MINUS, M     69        PLUS, MINUS, UNARY_PLUS, UNARY_MINUS, MULT, DIV, POW, RBRA, VALUE };
 70                                                    70 
 71 static int engine(pchar, pchar, double &, pcha     71 static int engine(pchar, pchar, double &, pchar &, const dic_type &);
 72                                                    72 
 73 static int variable(const string & name, doubl     73 static int variable(const string & name, double & result,
 74         const dic_type & dictionary)               74         const dic_type & dictionary)
 75 /*********************************************     75 /***********************************************************************
 76  *                                                 76  *                                                                     *
 77  * Name: variable                                  77  * Name: variable                                    Date:    03.10.00 *
 78  * Author: Evgeni Chernyaev                        78  * Author: Evgeni Chernyaev                          Revised:          *
 79  *                                                 79  *                                                                     *
 80  * Function: Finds value of the variable.          80  * Function: Finds value of the variable.                              * 
 81  *           This function is used by operand(     81  *           This function is used by operand().                       *
 82  *                                                 82  *                                                                     *
 83  * Parameters:                                     83  * Parameters:                                                         *
 84  *   name   - name of the variable.                84  *   name   - name of the variable.                                    *
 85  *   result - value of the variable.               85  *   result - value of the variable.                                   *
 86  *   dictionary - dictionary of available vari     86  *   dictionary - dictionary of available variables and functions.     *
 87  *                                                 87  *                                                                     *
 88  *********************************************     88  ***********************************************************************/
 89 {                                                  89 {
 90   dic_type::const_iterator iter = dictionary.f     90   dic_type::const_iterator iter = dictionary.find(name);
 91   if (iter == dictionary.end())                    91   if (iter == dictionary.end())
 92     return EVAL::ERROR_UNKNOWN_VARIABLE;           92     return EVAL::ERROR_UNKNOWN_VARIABLE;
 93   Item item = iter->second;                        93   Item item = iter->second;
 94   switch (item.what) {                             94   switch (item.what) {
 95   case Item::VARIABLE:                             95   case Item::VARIABLE:
 96     result = item.variable;                        96     result = item.variable;
 97     return EVAL::OK;                               97     return EVAL::OK;
 98   case Item::EXPRESSION: {                         98   case Item::EXPRESSION: {
 99     pchar exp_begin = (char *)(item.expression     99     pchar exp_begin = (char *)(item.expression.c_str());
100     pchar exp_end   = exp_begin + strlen(exp_b    100     pchar exp_end   = exp_begin + strlen(exp_begin) - 1;
101     if (engine(exp_begin, exp_end, result, exp    101     if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
102       return EVAL::OK;                            102       return EVAL::OK;
103     else                                          103     else
104       return EVAL::ERROR_CALCULATION_ERROR;       104       return EVAL::ERROR_CALCULATION_ERROR;
105   }                                               105   }
106   default:                                        106   default:
107     return EVAL::ERROR_CALCULATION_ERROR;         107     return EVAL::ERROR_CALCULATION_ERROR;
108   }                                               108   }
109 }                                                 109 }
110                                                   110 
111 static int function(const string & name, stack    111 static int function(const string & name, stack<double> & par,
112         double & result, const dic_type & dict    112         double & result, const dic_type & dictionary) 
113 /*********************************************    113 /***********************************************************************
114  *                                                114  *                                                                     *
115  * Name: function                                 115  * Name: function                                    Date:    03.10.00 *
116  * Author: Evgeni Chernyaev                       116  * Author: Evgeni Chernyaev                          Revised:          *
117  *                                                117  *                                                                     *
118  * Function: Finds value of the function.         118  * Function: Finds value of the function.                              * 
119  *           This function is used by operand(    119  *           This function is used by operand().                       *
120  *                                                120  *                                                                     *
121  * Parameters:                                    121  * Parameters:                                                         *
122  *   name   - name of the function.               122  *   name   - name of the function.                                    *
123  *   par    - stack of parameters.                123  *   par    - stack of parameters.                                     *
124  *   result - value of the function.              124  *   result - value of the function.                                   *
125  *   dictionary - dictionary of available vari    125  *   dictionary - dictionary of available variables and functions.     *
126  *                                                126  *                                                                     *
127  *********************************************    127  ***********************************************************************/
128 {                                                 128 {
129   unsigned long npar = par.size();                129   unsigned long npar = par.size();
130   if (npar > MAX_N_PAR) return EVAL::ERROR_UNK    130   if (npar > MAX_N_PAR) return EVAL::ERROR_UNKNOWN_FUNCTION;
131                                                   131 
132   dic_type::const_iterator iter = dictionary.f    132   dic_type::const_iterator iter = dictionary.find(sss[npar]+name);
133   if (iter == dictionary.end()) return EVAL::E    133   if (iter == dictionary.end()) return EVAL::ERROR_UNKNOWN_FUNCTION;
134   Item item = iter->second;                       134   Item item = iter->second;
135                                                   135 
136   double pp[MAX_N_PAR] = {0.0};                   136   double pp[MAX_N_PAR] = {0.0};
137   for(unsigned long i=0; i<npar; ++i) { pp[i]     137   for(unsigned long i=0; i<npar; ++i) { pp[i] = par.top(); par.pop(); }
138   errno = 0;                                      138   errno = 0;
139   if (item.function == 0)       return EVAL::E    139   if (item.function == 0)       return EVAL::ERROR_CALCULATION_ERROR;
140   switch (npar) {                                 140   switch (npar) {
141   case 0:                                         141   case 0:
142     result = ((double (*)())item.function)();     142     result = ((double (*)())item.function)();
143     break;                                        143     break;  
144   case 1:                                         144   case 1:
145     result = ((double (*)(double))item.functio    145     result = ((double (*)(double))item.function)(pp[0]);
146     break;                                        146     break;  
147   case 2:                                         147   case 2:
148     result = ((double (*)(double,double))item.    148     result = ((double (*)(double,double))item.function)(pp[1], pp[0]);
149     break;                                        149     break;  
150   case 3:                                         150   case 3:
151     result = ((double (*)(double,double,double    151     result = ((double (*)(double,double,double))item.function)
152       (pp[2],pp[1],pp[0]);                        152       (pp[2],pp[1],pp[0]);
153     break;                                        153     break;  
154   case 4:                                         154   case 4:
155     result = ((double (*)(double,double,double    155     result = ((double (*)(double,double,double,double))item.function)
156       (pp[3],pp[2],pp[1],pp[0]);                  156       (pp[3],pp[2],pp[1],pp[0]);
157     break;                                        157     break;  
158   case 5:                                         158   case 5:
159     result = ((double (*)(double,double,double    159     result = ((double (*)(double,double,double,double,double))item.function)
160       (pp[4],pp[3],pp[2],pp[1],pp[0]);            160       (pp[4],pp[3],pp[2],pp[1],pp[0]);
161     break;                                        161     break;  
162   }                                               162   }
163   return (errno == 0) ? EVAL::OK : EVAL::ERROR    163   return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
164 }                                                 164 }
165                                                   165 
166 static int operand(pchar begin, pchar end, dou    166 static int operand(pchar begin, pchar end, double & result,
167        pchar & endp, const dic_type & dictiona    167        pchar & endp, const dic_type & dictionary) 
168 /*********************************************    168 /***********************************************************************
169  *                                                169  *                                                                     *
170  * Name: operand                                  170  * Name: operand                                     Date:    03.10.00 *
171  * Author: Evgeni Chernyaev                       171  * Author: Evgeni Chernyaev                          Revised:          *
172  *                                                172  *                                                                     *
173  * Function: Finds value of the operand. The o    173  * Function: Finds value of the operand. The operand can be either     * 
174  *           a number or a variable or a funct    174  *           a number or a variable or a function.                     *  
175  *           This function is used by engine()    175  *           This function is used by engine().                        * 
176  *                                                176  *                                                                     *
177  * Parameters:                                    177  * Parameters:                                                         *
178  *   begin  - pointer to the first character o    178  *   begin  - pointer to the first character of the operand.           *
179  *   end    - pointer to the last character of    179  *   end    - pointer to the last character of the character string.   *
180  *   result - value of the operand.               180  *   result - value of the operand.                                    *
181  *   endp   - pointer to the character where t    181  *   endp   - pointer to the character where the evaluation stoped.    *
182  *   dictionary - dictionary of available vari    182  *   dictionary - dictionary of available variables and functions.     *
183  *                                                183  *                                                                     *
184  *********************************************    184  ***********************************************************************/
185 {                                                 185 {
186   pchar pointer = begin;                          186   pchar pointer = begin;
187   int   EVAL_STATUS;                              187   int   EVAL_STATUS;
188   char  c;                                        188   char  c;
189                                                   189 
190   //   G E T   N U M B E R                        190   //   G E T   N U M B E R
191                                                   191 
192   if (!isalpha(*pointer)) {                       192   if (!isalpha(*pointer)) {
193     errno = 0;                                    193     errno = 0;
194     result = strtod(pointer, (char **)(&pointe    194     result = strtod(pointer, (char **)(&pointer));
195     if (errno == 0) {                             195     if (errno == 0) {
196       EVAL_EXIT( EVAL::OK, --pointer );           196       EVAL_EXIT( EVAL::OK, --pointer );
197     }else{                                        197     }else{
198       EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR    198       EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
199     }                                             199     }
200   }                                               200   }
201                                                   201 
202   //   G E T   N A M E                            202   //   G E T   N A M E
203                                                   203 
204   while(pointer <= end) {                         204   while(pointer <= end) {
205     c = *pointer;                                 205     c = *pointer;
206     if (c != '_' && !isalnum(c)) break;           206     if (c != '_' && !isalnum(c)) break;
207     pointer++;                                    207     pointer++;
208   }                                               208   }
209   c = *pointer;                                   209   c = *pointer;
210   *pointer = '\0';                                210   *pointer = '\0';
211   string name(begin);                             211   string name(begin);
212   *pointer = c;                                   212   *pointer = c;
213                                                   213 
214   //   G E T   V A R I A B L E                    214   //   G E T   V A R I A B L E
215                                                   215 
216   result = 0.0;                                   216   result = 0.0;
217   SKIP_BLANKS;                                    217   SKIP_BLANKS;
218   if (c != '(') {                                 218   if (c != '(') {
219     EVAL_STATUS = variable(name, result, dicti    219     EVAL_STATUS = variable(name, result, dictionary);
220     EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EV    220     EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
221   }                                               221   }
222                                                   222 
223   //   G E T   F U N C T I O N                    223   //   G E T   F U N C T I O N
224                                                   224 
225   stack<pchar>  pos;                // positio    225   stack<pchar>  pos;                // position stack 
226   stack<double> par;                // paramet    226   stack<double> par;                // parameter stack
227   double        value;                            227   double        value;
228   pchar         par_begin = pointer+1, par_end    228   pchar         par_begin = pointer+1, par_end;
229                                                   229 
230   for(;;pointer++) {                              230   for(;;pointer++) {
231     c = (pointer > end) ? '\0' : *pointer;        231     c = (pointer > end) ? '\0' : *pointer;
232     switch (c) {                                  232     switch (c) {
233     case '\0':                                    233     case '\0':  
234       EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHE    234       EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() ); 
235     case '(':                                     235     case '(':
236       pos.push(pointer); break;                   236       pos.push(pointer); break;
237     case ',':                                     237     case ',':
238       if (pos.size() == 1) {                      238       if (pos.size() == 1) {
239   par_end = pointer-1;                            239   par_end = pointer-1;
240   EVAL_STATUS = engine(par_begin, par_end, val    240   EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
241   if (EVAL_STATUS == EVAL::WARNING_BLANK_STRIN    241   if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
242     { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER,     242     { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
243   if (EVAL_STATUS != EVAL::OK)                    243   if (EVAL_STATUS != EVAL::OK)
244     { EVAL_EXIT( EVAL_STATUS, par_end ); }        244     { EVAL_EXIT( EVAL_STATUS, par_end ); }
245   par.push(value);                                245   par.push(value);
246   par_begin = pointer + 1;                        246   par_begin = pointer + 1;
247       }                                           247       }
248       break;                                      248       break;
249     case ')':                                     249     case ')':
250       if (pos.size() > 1) {                       250       if (pos.size() > 1) {
251   pos.pop();                                      251   pos.pop();
252   break;                                          252   break;
253       }else{                                      253       }else{
254   par_end = pointer-1;                            254   par_end = pointer-1;
255   EVAL_STATUS = engine(par_begin, par_end, val    255   EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
256   switch (EVAL_STATUS) {                          256   switch (EVAL_STATUS) {
257   case EVAL::OK:                                  257   case EVAL::OK:
258     par.push(value);                              258     par.push(value);
259     break;                                        259     break;
260   case EVAL::WARNING_BLANK_STRING:                260   case EVAL::WARNING_BLANK_STRING:
261     if (par.size() != 0)                          261     if (par.size() != 0)
262       { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER    262       { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
263     break;                                        263     break;
264   default:                                        264   default:
265     EVAL_EXIT( EVAL_STATUS, par_end );            265     EVAL_EXIT( EVAL_STATUS, par_end );
266   }                                               266   }
267   EVAL_STATUS = function(name, par, result, di    267   EVAL_STATUS = function(name, par, result, dictionary);
268   EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL    268   EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
269       }                                           269       }
270     }                                             270     }
271   }                                               271   }
272 }                                                 272 }
273                                                   273 
274 /*********************************************    274 /***********************************************************************
275  *                                                275  *                                                                     *
276  * Name: maker                                    276  * Name: maker                                       Date:    28.09.00 *
277  * Author: Evgeni Chernyaev                       277  * Author: Evgeni Chernyaev                          Revised:          *
278  *                                                278  *                                                                     *
279  * Function: Executes basic arithmetic operati    279  * Function: Executes basic arithmetic operations on values in the top *
280  *           of the stack. Result is placed ba    280  *           of the stack. Result is placed back into the stack.       *
281  *           This function is used by engine()    281  *           This function is used by engine().                        * 
282  *                                                282  *                                                                     *
283  * Parameters:                                    283  * Parameters:                                                         *
284  *   op  - code of the operation.                 284  *   op  - code of the operation.                                      *
285  *   val - stack of values.                       285  *   val - stack of values.                                            *
286  *                                                286  *                                                                     *
287  *********************************************    287  ***********************************************************************/
288 static int maker(int op, stack<double> & val)     288 static int maker(int op, stack<double> & val)
289 {                                                 289 {
290   if (val.size() < 2) return EVAL::ERROR_SYNTA    290   if (val.size() < 2) return EVAL::ERROR_SYNTAX_ERROR;
291   double val2 = val.top(); val.pop();             291   double val2 = val.top(); val.pop();
292   double val1 = val.top();                        292   double val1 = val.top();
293   switch (op) {                                   293   switch (op) {
294   case OR:                                // o    294   case OR:                                // operator ||
295     val.top() = (val1 || val2) ? 1. : 0.;         295     val.top() = (val1 || val2) ? 1. : 0.;
296     return EVAL::OK;                              296     return EVAL::OK;
297   case AND:                               // o    297   case AND:                               // operator &&
298     val.top() = (val1 && val2) ? 1. : 0.;         298     val.top() = (val1 && val2) ? 1. : 0.;
299     return EVAL::OK;                              299     return EVAL::OK;
300   case EQ:                                // o    300   case EQ:                                // operator ==
301     val.top() = (val1 == val2) ? 1. : 0.;         301     val.top() = (val1 == val2) ? 1. : 0.;
302     return EVAL::OK;                              302     return EVAL::OK;
303   case NE:                                // o    303   case NE:                                // operator !=
304     val.top() = (val1 != val2) ? 1. : 0.;         304     val.top() = (val1 != val2) ? 1. : 0.;
305     return EVAL::OK;                              305     return EVAL::OK;
306   case GE:                                // o    306   case GE:                                // operator >=
307     val.top() = (val1 >= val2) ? 1. : 0.;         307     val.top() = (val1 >= val2) ? 1. : 0.;
308     return EVAL::OK;                              308     return EVAL::OK;
309   case GT:                                // o    309   case GT:                                // operator >
310     val.top() = (val1 >  val2) ? 1. : 0.;         310     val.top() = (val1 >  val2) ? 1. : 0.;
311     return EVAL::OK;                              311     return EVAL::OK;
312   case LE:                                // o    312   case LE:                                // operator <=
313     val.top() = (val1 <= val2) ? 1. : 0.;         313     val.top() = (val1 <= val2) ? 1. : 0.;
314     return EVAL::OK;                              314     return EVAL::OK;
315   case LT:                                // o    315   case LT:                                // operator <
316     val.top() = (val1 <  val2) ? 1. : 0.;         316     val.top() = (val1 <  val2) ? 1. : 0.;
317     return EVAL::OK;                              317     return EVAL::OK;
318   case PLUS:                              // o    318   case PLUS:                              // operator '+'
319     val.top() = val1 + val2;                      319     val.top() = val1 + val2;
320     return EVAL::OK;                              320     return EVAL::OK;
321   case MINUS:                             // o    321   case MINUS:                             // operator '-'
322     val.top() = val1 - val2;                      322     val.top() = val1 - val2;
323     return EVAL::OK;                              323     return EVAL::OK;
324   case MULT:                              // o    324   case MULT:                              // operator '*'
325     val.top() = val1 * val2;                      325     val.top() = val1 * val2;
326     return EVAL::OK;                              326     return EVAL::OK;
327   case DIV:                               // o    327   case DIV:                               // operator '/'
328     if (val2 == 0.0) return EVAL::ERROR_CALCUL    328     if (val2 == 0.0) return EVAL::ERROR_CALCULATION_ERROR;
329     val.top() = val1 / val2;                      329     val.top() = val1 / val2;
330     return EVAL::OK;                              330     return EVAL::OK;
331   case POW:                               // o    331   case POW:                               // operator '^' (or '**')
332     errno = 0;                                    332     errno = 0;
333     val.top() = std::pow(val1,val2);              333     val.top() = std::pow(val1,val2);
334     if (errno == 0) return EVAL::OK;              334     if (errno == 0) return EVAL::OK;
335     else return EVAL::ERROR_CALCULATION_ERROR;    335     else return EVAL::ERROR_CALCULATION_ERROR;
336   case UNARY_PLUS:                                336   case UNARY_PLUS:                              // unary operator '+'
337     val.top() = val1 + val2;      // val1 is z    337     val.top() = val1 + val2;      // val1 is zero
338     return EVAL::OK;                              338     return EVAL::OK;
339   case UNARY_MINUS:                               339   case UNARY_MINUS:                             // unary operator '-'
340     val.top() = val1 - val2;      // val1 is z    340     val.top() = val1 - val2;      // val1 is zero
341     return EVAL::OK;                              341     return EVAL::OK;
342   default:                                        342   default:
343     return EVAL::ERROR_CALCULATION_ERROR;         343     return EVAL::ERROR_CALCULATION_ERROR;
344   }                                               344   }
345 }                                                 345 }
346                                                   346 
347 /*********************************************    347 /***********************************************************************
348  *                                                348  *                                                                     *
349  * Name: engine                                   349  * Name: engine                                      Date:    28.09.00 *
350  * Author: Evgeni Chernyaev                       350  * Author: Evgeni Chernyaev                          Revised:          *
351  *                                                351  *                                                                     *
352  * Function: Evaluates arithmetic expression.     352  * Function: Evaluates arithmetic expression.                          *
353  *                                                353  *                                                                     *
354  * Parameters:                                    354  * Parameters:                                                         *
355  *   begin  - pointer to the character string     355  *   begin  - pointer to the character string with expression.         *
356  *   end    - pointer to the end of the charac    356  *   end    - pointer to the end of the character string (it is needed *
357  *            for recursive call of engine(),     357  *            for recursive call of engine(), when there is no '\0').  *
358  *   result - result of the evaluation.           358  *   result - result of the evaluation.                                *
359  *   endp   - pointer to the character where t    359  *   endp   - pointer to the character where the evaluation stoped.    *
360  *   dictionary - dictionary of available vari    360  *   dictionary - dictionary of available variables and functions.     *
361  *                                                361  *                                                                     *
362  *********************************************    362  ***********************************************************************/
363 static int engine(pchar begin, pchar end, doub    363 static int engine(pchar begin, pchar end, double & result,
364       pchar & endp, const dic_type & dictionar    364       pchar & endp, const dic_type & dictionary)
365 {                                                 365 {
366   enum SyntaxTableEntry {                         366   enum SyntaxTableEntry {
367     SyntaxError = 0,                              367     SyntaxError = 0,
368     NumberVariableOrFunction = 1,                 368     NumberVariableOrFunction = 1,
369     UnaryPlusOrMinus = 2,                         369     UnaryPlusOrMinus = 2,
370     AnyOperator = 3                               370     AnyOperator = 3
371   };                                              371   };
372   static const int SyntaxTable[19][19] = {        372   static const int SyntaxTable[19][19] = {
373     //E  (  || && == != >= >  <= <  +  -  u+ u    373     //E  (  || && == != >= >  <= <  +  -  u+ u- *  /  ^  )  V - current token
374     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    374     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // E - previous
375     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    375     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // (   token
376     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    376     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // ||
377     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    377     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // &&
378     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    378     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // ==
379     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    379     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // !=
380     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    380     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // >=
381     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    381     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // >
382     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    382     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // <=
383     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    383     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // <
384     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    384     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // +
385     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    385     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // -
386     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    386     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // unary +
387     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    387     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // unary -
388     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    388     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // *
389     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    389     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // /
390     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2    390     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   // ^
391     { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3    391     { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },   // )
392     { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3    392     { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }    // V = {.,N,C}
393   };                                              393   };
394   enum ActionTableEntry {                         394   enum ActionTableEntry {
395     UnbalancedParentheses = -1,                   395     UnbalancedParentheses = -1,
396     ExpressionCompleted = 0,                      396     ExpressionCompleted = 0,
397     HigherPrecedenceOperator = 1,                 397     HigherPrecedenceOperator = 1,
398     SamePrecedenceOperator = 2,                   398     SamePrecedenceOperator = 2,
399     CloseProcessedParenthesesOrExpression = 3,    399     CloseProcessedParenthesesOrExpression = 3,
400     LowerPrecedenceOperator = 4                   400     LowerPrecedenceOperator = 4
401   };                                              401   };
402   static const int ActionTable[17][18] = {        402   static const int ActionTable[17][18] = {
403     //E  (  || && == != >= >  <= <  +  -  u+ u    403     //E  (  || && == != >= >  <= <  +  -  u+ u- *  /  ^  ) - current operator
404     { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1    404     { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, // E - top operator
405     {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1    405     {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, // (   in stack
406     { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1    406     { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // ||
407     { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1    407     { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // &&
408     { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1    408     { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // ==
409     { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1    409     { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // !=
410     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1    410     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >=
411     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1    411     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >
412     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1    412     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <=
413     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1    413     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <
414     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1    414     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // +
415     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1    415     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // -
416     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1    416     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary +
417     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1    417     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary -
418     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1    418     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // *
419     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1    419     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // /
420     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1    420     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }  // ^
421   };                                              421   };
422                                                   422 
423   stack<int>    op;                      // op    423   stack<int>    op;                      // operator stack
424   stack<pchar>  pos;                     // po    424   stack<pchar>  pos;                     // position stack
425   stack<double> val;                     // va    425   stack<double> val;                     // value stack
426   double        value;                            426   double        value;
427   pchar         pointer = begin;                  427   pchar         pointer = begin;
428   int           iWhat, iCur, iPrev = 0, iTop,     428   int           iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
429   char          c;                                429   char          c;
430                                                   430 
431   op.push(0); pos.push(pointer);         // pu    431   op.push(0); pos.push(pointer);         // push EOL to the stack
432   SKIP_BLANKS;                                    432   SKIP_BLANKS;
433   if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BL    433   if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
434   for(;;pointer++) {                              434   for(;;pointer++) {
435                                                   435 
436     //   N E X T   T O K E N                      436     //   N E X T   T O K E N
437                                                   437 
438     c = (pointer > end) ? '\0' : *pointer;        438     c = (pointer > end) ? '\0' : *pointer;
439     if (isspace(c)) continue;            // sk    439     if (isspace(c)) continue;            // skip space, tab etc.
440     switch (c) {                                  440     switch (c) {
441     case '\0': iCur = ENDL; break;                441     case '\0': iCur = ENDL; break;
442     case '(':  iCur = LBRA; break;                442     case '(':  iCur = LBRA; break;
443     case '|':                                     443     case '|':
444       if (*(pointer+1) == '|') {                  444       if (*(pointer+1) == '|') {
445   pointer++; iCur = OR; break;                    445   pointer++; iCur = OR; break;
446       }else{                                      446       }else{
447         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMB    447         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
448       }                                           448       }
449     case '&':                                     449     case '&':
450       if (*(pointer+1) == '&') {                  450       if (*(pointer+1) == '&') {
451   pointer++; iCur = AND; break;                   451   pointer++; iCur = AND; break;
452       }else{                                      452       }else{
453         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMB    453         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
454       }                                           454       }
455     case '=':                                     455     case '=':
456       if (*(pointer+1) == '=') {                  456       if (*(pointer+1) == '=') {
457   pointer++; iCur = EQ; break;                    457   pointer++; iCur = EQ; break;
458       }else{                                      458       }else{
459         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMB    459         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
460       }                                           460       }
461     case '!':                                     461     case '!':
462       if (*(pointer+1) == '=') {                  462       if (*(pointer+1) == '=') {
463   pointer++; iCur = NE; break;                    463   pointer++; iCur = NE; break;
464       }else{                                      464       }else{
465         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMB    465         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
466       }                                           466       }
467     case '>':                                     467     case '>':
468       if (*(pointer+1) == '=') { pointer++; iC    468       if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; }
469       break;                                      469       break;
470     case '<':                                     470     case '<':
471       if (*(pointer+1) == '=') { pointer++; iC    471       if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; }
472       break;                                      472       break;
473     case '+':  iCur = PLUS;  break;               473     case '+':  iCur = PLUS;  break;
474     case '-':  iCur = MINUS; break;               474     case '-':  iCur = MINUS; break;
475     case '*':                                     475     case '*':
476       if (*(pointer+1) == '*') { pointer++; iC    476       if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; }
477       break;                                      477       break;
478     case '/':  iCur = DIV;  break;                478     case '/':  iCur = DIV;  break;
479     case '^':  iCur = POW;  break;                479     case '^':  iCur = POW;  break;
480     case ')':  iCur = RBRA; break;                480     case ')':  iCur = RBRA; break;
481     default:                                      481     default:
482       if (c == '.' || isalnum(c)) {               482       if (c == '.' || isalnum(c)) {
483         iCur = VALUE; break;                      483         iCur = VALUE; break;
484       }else{                                      484       }else{
485         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMB    485         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
486       }                                           486       }
487     }                                             487     }
488                                                   488 
489     //   S Y N T A X   A N A L I S Y S            489     //   S Y N T A X   A N A L I S Y S
490                                                   490 
491     iWhat = SyntaxTable[iPrev][iCur];             491     iWhat = SyntaxTable[iPrev][iCur];
492     iPrev = iCur;                                 492     iPrev = iCur;
493     switch (iWhat) {                              493     switch (iWhat) {
494     case 0:                             // syn    494     case 0:                             // syntax error
495       EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, poi    495       EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
496     case 1:                             // ope    496     case 1:                             // operand: number, variable, function
497       EVAL_STATUS = operand(pointer, end, valu    497       EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
498       if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT    498       if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); }
499       val.push(value);                            499       val.push(value);
500       continue;                                   500       continue;
501     case 2:                             // una    501     case 2:                             // unary + or unary -
502       val.push(0.0);                              502       val.push(0.0);
503       if (iCur == PLUS)  iCur = UNARY_PLUS;       503       if (iCur == PLUS)  iCur = UNARY_PLUS;
504       if (iCur == MINUS) iCur = UNARY_MINUS;      504       if (iCur == MINUS) iCur = UNARY_MINUS;
505       // Note that for syntax purposes, ordina    505       // Note that for syntax purposes, ordinary + or - are fine.
506       // Thus iPrev need not change when we en    506       // Thus iPrev need not change when we encounter a unary minus or plus.
507     case 3: default:                    // nex    507     case 3: default:                    // next operator
508       break;                                      508       break;
509     }                                             509     }
510                                                   510 
511     //   N E X T   O P E R A T O R                511     //   N E X T   O P E R A T O R
512                                                   512 
513     for(;;) {                                     513     for(;;) {
514       if (op.size() == 0) { EVAL_EXIT( EVAL::E    514       if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
515       iTop = op.top();                            515       iTop = op.top();
516       switch (ActionTable[iTop][iCur]) {          516       switch (ActionTable[iTop][iCur]) {
517       case -1:                           // sy    517       case -1:                           // syntax error 
518   if (op.size() > 1) pointer = pos.top();         518   if (op.size() > 1) pointer = pos.top();
519   EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS,    519   EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
520       case 0:                            // la    520       case 0:                            // last operation (assignment)
521         if (val.size() == 1) {                    521         if (val.size() == 1) {
522     result = val.top();                           522     result = val.top();
523     EVAL_EXIT( EVAL::OK, pointer );               523     EVAL_EXIT( EVAL::OK, pointer );
524   }else{                                          524   }else{
525     EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, point    525     EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
526   }                                               526   }
527       case 1:                           // pus    527       case 1:                           // push current operator in stack
528   op.push(iCur); pos.push(pointer);               528   op.push(iCur); pos.push(pointer);
529   break;                                          529   break;
530       case 2:                           // exe    530       case 2:                           // execute top operator
531         EVAL_STATUS = maker(iTop, val); // put    531         EVAL_STATUS = maker(iTop, val); // put current operator in stack
532         if (EVAL_STATUS != EVAL::OK) {            532         if (EVAL_STATUS != EVAL::OK) {
533     EVAL_EXIT( EVAL_STATUS, pos.top() );          533     EVAL_EXIT( EVAL_STATUS, pos.top() );
534   }                                               534   }
535   op.top() = iCur; pos.top() = pointer;           535   op.top() = iCur; pos.top() = pointer;
536   break;                                          536   break;
537       case 3:                           // del    537       case 3:                           // delete '(' from stack
538         op.pop(); pos.pop();                      538         op.pop(); pos.pop();
539   break;                                          539   break;
540       case 4: default:                  // exe    540       case 4: default:                  // execute top operator and 
541         EVAL_STATUS = maker(iTop, val); // del    541         EVAL_STATUS = maker(iTop, val); // delete it from stack
542         if (EVAL_STATUS != EVAL::OK) {  // rep    542         if (EVAL_STATUS != EVAL::OK) {  // repete with the same iCur 
543     EVAL_EXIT( EVAL_STATUS, pos.top() );          543     EVAL_EXIT( EVAL_STATUS, pos.top() );
544   }                                               544   }
545   op.pop(); pos.pop();                            545   op.pop(); pos.pop();
546         continue;                                 546         continue;
547       }                                           547       }
548       break;                                      548       break;
549     }                                             549     }
550   }                                               550   }
551 }                                                 551 }
552                                                   552 
553 //--------------------------------------------    553 //---------------------------------------------------------------------------
554 static void setItem(const char * prefix, const    554 static void setItem(const char * prefix, const char * name,
555         const Item & item, Struct * s) {          555         const Item & item, Struct * s) {
556                                                   556 
557   if (name == 0 || *name == '\0') {               557   if (name == 0 || *name == '\0') {
558     s->theStatus = EVAL::ERROR_NOT_A_NAME;        558     s->theStatus = EVAL::ERROR_NOT_A_NAME;
559     return;                                       559     return;
560   }                                               560   }
561                                                   561 
562   //   R E M O V E   L E A D I N G   A N D   T    562   //   R E M O V E   L E A D I N G   A N D   T R A I L I N G   S P A C E S
563                                                   563 
564   const char * pointer; int n; REMOVE_BLANKS;     564   const char * pointer; int n; REMOVE_BLANKS;
565                                                   565 
566   //   C H E C K   N A M E                        566   //   C H E C K   N A M E 
567                                                   567  
568   if (n == 0) {                                   568   if (n == 0) {
569     s->theStatus = EVAL::ERROR_NOT_A_NAME;        569     s->theStatus = EVAL::ERROR_NOT_A_NAME;
570     return;                                       570     return;
571   }                                               571   }
572   for(int i=0; i<n; i++) {                        572   for(int i=0; i<n; i++) {
573     char c = *(pointer+i);                        573     char c = *(pointer+i);
574     if (c != '_' && !isalnum(c)) {                574     if (c != '_' && !isalnum(c)) {
575       s->theStatus = EVAL::ERROR_NOT_A_NAME;      575       s->theStatus = EVAL::ERROR_NOT_A_NAME;
576       return;                                     576       return;
577     }                                             577     }
578   }                                               578   }
579                                                   579 
580   //   A D D   I T E M   T O   T H E   D I C T    580   //   A D D   I T E M   T O   T H E   D I C T I O N A R Y
581                                                   581 
582   string item_name = prefix + string(pointer,n    582   string item_name = prefix + string(pointer,n);
583   dic_type::iterator iter = (s->theDictionary)    583   dic_type::iterator iter = (s->theDictionary).find(item_name);
584   if (iter != (s->theDictionary).end()) {         584   if (iter != (s->theDictionary).end()) {
585     iter->second = item;                          585     iter->second = item;
586     if (item_name == name) {                      586     if (item_name == name) {
587       s->theStatus = EVAL::WARNING_EXISTING_VA    587       s->theStatus = EVAL::WARNING_EXISTING_VARIABLE;
588     }else{                                        588     }else{
589       s->theStatus = EVAL::WARNING_EXISTING_FU    589       s->theStatus = EVAL::WARNING_EXISTING_FUNCTION;
590     }                                             590     }
591   }else{                                          591   }else{
592     (s->theDictionary)[item_name] = item;         592     (s->theDictionary)[item_name] = item;
593     s->theStatus = EVAL::OK;                      593     s->theStatus = EVAL::OK;
594   }                                               594   }
595 }                                                 595 } 
596                                                   596         
597 //--------------------------------------------    597 //---------------------------------------------------------------------------
598 namespace HepTool {                               598 namespace HepTool {
599                                                   599 
600 //--------------------------------------------    600 //---------------------------------------------------------------------------
601 Evaluator::Evaluator() {                          601 Evaluator::Evaluator() {
602   Struct * s = new Struct();                      602   Struct * s = new Struct();
603   p = (void *) s;                                 603   p = (void *) s;
604   s->theExpression = 0;                           604   s->theExpression = 0;
605   s->thePosition   = 0;                           605   s->thePosition   = 0;
606   s->theStatus     = OK;                          606   s->theStatus     = OK;
607   s->theResult     = 0.0;                         607   s->theResult     = 0.0;
608 }                                                 608 }
609                                                   609 
610 //--------------------------------------------    610 //---------------------------------------------------------------------------
611 Evaluator::~Evaluator() {                         611 Evaluator::~Evaluator() {
612   delete (Struct *)(p);                           612   delete (Struct *)(p);
613 }                                                 613 }
614                                                   614 
615 //--------------------------------------------    615 //---------------------------------------------------------------------------
616 double Evaluator::evaluate(const char * expres    616 double Evaluator::evaluate(const char * expression) {
617   Struct * s = (Struct *)(p);                     617   Struct * s = (Struct *)(p);
618   if (s->theExpression != 0) { delete[] s->the    618   if (s->theExpression != 0) { delete[] s->theExpression; }
619   s->theExpression = 0;                           619   s->theExpression = 0;
620   s->thePosition   = 0;                           620   s->thePosition   = 0;
621   s->theStatus     = WARNING_BLANK_STRING;        621   s->theStatus     = WARNING_BLANK_STRING;
622   s->theResult     = 0.0;                         622   s->theResult     = 0.0;
623   if (expression != 0) {                          623   if (expression != 0) {
624     s->theExpression = new char[strlen(express    624     s->theExpression = new char[strlen(expression)+1];
625     strcpy(s->theExpression, expression);         625     strcpy(s->theExpression, expression);
626     s->theStatus = engine(s->theExpression,       626     s->theStatus = engine(s->theExpression,
627         s->theExpression+strlen(expression)-1,    627         s->theExpression+strlen(expression)-1,
628         s->theResult,                             628         s->theResult,
629         s->thePosition,                           629         s->thePosition,
630         s->theDictionary);                        630         s->theDictionary);
631   }                                               631   }
632   return s->theResult;                            632   return s->theResult;
633 }                                                 633 }
634                                                   634 
635 //--------------------------------------------    635 //---------------------------------------------------------------------------
636 int Evaluator::status() const {                   636 int Evaluator::status() const {
637   return ((Struct *)(p))->theStatus;              637   return ((Struct *)(p))->theStatus;
638 }                                                 638 }
639                                                   639 
640 //--------------------------------------------    640 //---------------------------------------------------------------------------
641 int Evaluator::error_position() const {           641 int Evaluator::error_position() const {
642   return int(((Struct *)(p))->thePosition - ((    642   return int(((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression);
643 }                                                 643 }
644                                                   644 
645 //--------------------------------------------    645 //---------------------------------------------------------------------------
646 void Evaluator::print_error() const {             646 void Evaluator::print_error() const {
647   Struct * s = (Struct *) p;                      647   Struct * s = (Struct *) p;
648   if(s->theStatus != OK) {                        648   if(s->theStatus != OK) {
649       std::cerr << error_name() << std::endl;     649       std::cerr << error_name() << std::endl;
650   }                                               650   }
651   return;                                         651   return;
652 }                                                 652 }
653                                                   653 
654 //--------------------------------------------    654 //---------------------------------------------------------------------------
655 std::string Evaluator::error_name() const         655 std::string Evaluator::error_name() const
656 {                                                 656 {
657   char prefix[] = "Evaluator : ";                 657   char prefix[] = "Evaluator : ";
658   std::ostringstream errn;                        658   std::ostringstream errn;
659   Struct * s = (Struct *) p;                      659   Struct * s = (Struct *) p;
660   switch (s->theStatus) {                         660   switch (s->theStatus) {
661   case ERROR_NOT_A_NAME:                          661   case ERROR_NOT_A_NAME:
662     errn << prefix << "invalid name";             662     errn << prefix << "invalid name";
663     break;                                        663     break;
664   case ERROR_SYNTAX_ERROR:                        664   case ERROR_SYNTAX_ERROR:
665     errn << prefix << "syntax error";             665     errn << prefix << "syntax error";
666     break;                                        666     break;
667   case ERROR_UNPAIRED_PARENTHESIS:                667   case ERROR_UNPAIRED_PARENTHESIS:
668     errn << prefix << "unpaired parenthesis";     668     errn << prefix << "unpaired parenthesis";
669     break;                                        669     break;
670   case ERROR_UNEXPECTED_SYMBOL:                   670   case ERROR_UNEXPECTED_SYMBOL:
671     errn << prefix << "unexpected symbol";        671     errn << prefix << "unexpected symbol";
672     break;                                        672     break;
673   case ERROR_UNKNOWN_VARIABLE:                    673   case ERROR_UNKNOWN_VARIABLE:
674     errn << prefix << "unknown variable";         674     errn << prefix << "unknown variable";
675     break;                                        675     break;
676   case ERROR_UNKNOWN_FUNCTION:                    676   case ERROR_UNKNOWN_FUNCTION:
677     errn << prefix << "unknown function";         677     errn << prefix << "unknown function";
678     break;                                        678     break;
679   case ERROR_EMPTY_PARAMETER:                     679   case ERROR_EMPTY_PARAMETER: 
680     errn << prefix << "empty parameter in func    680     errn << prefix << "empty parameter in function call";
681     break;                                        681     break;
682   case ERROR_CALCULATION_ERROR:                   682   case ERROR_CALCULATION_ERROR:
683     errn << prefix << "calculation error";        683     errn << prefix << "calculation error";
684     break;                                        684     break;
685   default:                                        685   default:
686     errn << " ";                                  686     errn << " ";
687   }                                               687   }
688   return errn.str();                              688   return errn.str();
689 }                                                 689 }
690                                                   690 
691 //--------------------------------------------    691 //---------------------------------------------------------------------------
692 void Evaluator::setVariable(const char * name,    692 void Evaluator::setVariable(const char * name, double value)
693 { setItem("", name, Item(value), (Struct *)p);    693 { setItem("", name, Item(value), (Struct *)p); }
694                                                   694 
695 void Evaluator::setVariable(const char * name,    695 void Evaluator::setVariable(const char * name, const char * expression)
696 { setItem("", name, Item(expression), (Struct     696 { setItem("", name, Item(expression), (Struct *)p); }
697                                                   697 
698 //--------------------------------------------    698 //---------------------------------------------------------------------------
699 // Fix non ISO C++ compliant cast from pointer    699 // Fix non ISO C++ compliant cast from pointer to function
700 // to void*, which is a pointer to an object      700 // to void*, which is a pointer to an object
701 void Evaluator::setFunction(const char * name,    701 void Evaluator::setFunction(const char * name,
702           double (*fun)())                        702           double (*fun)())
703 { setItem("0", name, Item(reinterpret_cast<voi    703 { setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
704                                                   704 
705 void Evaluator::setFunction(const char * name,    705 void Evaluator::setFunction(const char * name,
706           double (*fun)(double))                  706           double (*fun)(double))
707 { setItem("1", name, Item(reinterpret_cast<voi    707 { setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
708                                                   708 
709 void Evaluator::setFunction(const char * name,    709 void Evaluator::setFunction(const char * name,
710           double (*fun)(double,double))           710           double (*fun)(double,double))
711 { setItem("2", name, Item(reinterpret_cast<voi    711 { setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
712                                                   712 
713 void Evaluator::setFunction(const char * name,    713 void Evaluator::setFunction(const char * name,
714           double (*fun)(double,double,double))    714           double (*fun)(double,double,double))
715 { setItem("3", name, Item(reinterpret_cast<voi    715 { setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
716                                                   716 
717 void Evaluator::setFunction(const char * name,    717 void Evaluator::setFunction(const char * name,
718           double (*fun)(double,double,double,d    718           double (*fun)(double,double,double,double))
719 { setItem("4", name, Item(reinterpret_cast<voi    719 { setItem("4", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
720                                                   720 
721 void Evaluator::setFunction(const char * name,    721 void Evaluator::setFunction(const char * name,
722           double (*fun)(double,double,double,d    722           double (*fun)(double,double,double,double,double))
723 { setItem("5", name, Item(reinterpret_cast<voi    723 { setItem("5", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
724                                                   724 
725 //--------------------------------------------    725 //---------------------------------------------------------------------------
726 bool Evaluator::findVariable(const char * name    726 bool Evaluator::findVariable(const char * name) const {
727   if (name == 0 || *name == '\0') return false    727   if (name == 0 || *name == '\0') return false;
728   const char * pointer; int n; REMOVE_BLANKS;     728   const char * pointer; int n; REMOVE_BLANKS;
729   if (n == 0) return false;                       729   if (n == 0) return false;
730   Struct * s = (Struct *)(p);                     730   Struct * s = (Struct *)(p);
731   return                                          731   return
732     ((s->theDictionary).find(string(pointer,n)    732     ((s->theDictionary).find(string(pointer,n)) == (s->theDictionary).end()) ?
733     false : true;                                 733     false : true;
734 }                                                 734 }
735                                                   735 
736 //--------------------------------------------    736 //---------------------------------------------------------------------------
737 bool Evaluator::findFunction(const char * name    737 bool Evaluator::findFunction(const char * name, int npar) const {
738   if (name == 0 || *name == '\0')    return fa    738   if (name == 0 || *name == '\0')    return false;
739   if (npar < 0  || npar > MAX_N_PAR) return fa    739   if (npar < 0  || npar > MAX_N_PAR) return false;
740   const char * pointer; int n; REMOVE_BLANKS;     740   const char * pointer; int n; REMOVE_BLANKS;
741   if (n == 0) return false;                       741   if (n == 0) return false;
742   Struct * s = (Struct *)(p);                     742   Struct * s = (Struct *)(p);
743   return ((s->theDictionary).find(sss[npar]+st    743   return ((s->theDictionary).find(sss[npar]+string(pointer,n)) ==
744     (s->theDictionary).end()) ? false : true;     744     (s->theDictionary).end()) ? false : true;
745 }                                                 745 }
746                                                   746 
747 //--------------------------------------------    747 //---------------------------------------------------------------------------
748 void Evaluator::removeVariable(const char * na    748 void Evaluator::removeVariable(const char * name) {
749   if (name == 0 || *name == '\0') return;         749   if (name == 0 || *name == '\0') return;
750   const char * pointer; int n; REMOVE_BLANKS;     750   const char * pointer; int n; REMOVE_BLANKS;
751   if (n == 0) return;                             751   if (n == 0) return;
752   Struct * s = (Struct *)(p);                     752   Struct * s = (Struct *)(p);
753   (s->theDictionary).erase(string(pointer,n));    753   (s->theDictionary).erase(string(pointer,n));
754 }                                                 754 }
755                                                   755 
756 //--------------------------------------------    756 //---------------------------------------------------------------------------
757 void Evaluator::removeFunction(const char * na    757 void Evaluator::removeFunction(const char * name, int npar) {
758   if (name == 0 || *name == '\0')    return;      758   if (name == 0 || *name == '\0')    return;
759   if (npar < 0  || npar > MAX_N_PAR) return;      759   if (npar < 0  || npar > MAX_N_PAR) return;
760   const char * pointer; int n; REMOVE_BLANKS;     760   const char * pointer; int n; REMOVE_BLANKS;
761   if (n == 0) return;                             761   if (n == 0) return;
762   Struct * s = (Struct *)(p);                     762   Struct * s = (Struct *)(p);
763   (s->theDictionary).erase(sss[npar]+string(po    763   (s->theDictionary).erase(sss[npar]+string(pointer,n));
764 }                                                 764 }
765                                                   765 
766 //--------------------------------------------    766 //---------------------------------------------------------------------------
767 void Evaluator::clear() {                         767 void Evaluator::clear() {
768   Struct * s = (Struct *) p;                      768   Struct * s = (Struct *) p;
769   s->theDictionary.clear();                       769   s->theDictionary.clear();
770   s->theExpression = 0;                           770   s->theExpression = 0;
771   s->thePosition   = 0;                           771   s->thePosition   = 0;
772   s->theStatus     = OK;                          772   s->theStatus     = OK;
773   s->theResult     = 0.0;                         773   s->theResult     = 0.0;
774 }                                                 774 }
775                                                   775 
776 //--------------------------------------------    776 //---------------------------------------------------------------------------
777 } // namespace HepTool                            777 } // namespace HepTool
778                                                   778