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 10.6.p3)


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