1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkFunctionParser.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkFunctionParser.h"
16 #include "vtkObjectFactory.h"
17 
18 #include <cctype>
19 #include <algorithm>
20 
21 vtkStandardNewMacro(vtkFunctionParser);
22 
23 static double vtkParserVectorErrorResult[3] = { VTK_PARSER_ERROR_RESULT,
24                                                 VTK_PARSER_ERROR_RESULT,
25                                                 VTK_PARSER_ERROR_RESULT };
26 //-----------------------------------------------------------------------------
vtkFunctionParser()27 vtkFunctionParser::vtkFunctionParser()
28 {
29   this->Function = nullptr;
30   this->FunctionWithSpaces = nullptr;
31   this->ByteCode = nullptr;
32   this->ByteCodeSize = 0;
33   this->Immediates = nullptr;
34   this->ImmediatesSize = 0;
35   this->Stack = nullptr;
36   this->StackSize = 0;
37   this->StackPointer = 0;
38 
39   this->EvaluateMTime.Modified();
40   this->VariableMTime.Modified();
41   this->ParseMTime.Modified();
42   this->FunctionMTime.Modified();
43   this->CheckMTime.Modified();
44 
45   this->ReplaceInvalidValues = 0;
46   this->ReplacementValue = 0.0;
47 
48   this->ParseErrorPositon = -1;
49   this->ParseError        = nullptr;
50 }
51 
52 //-----------------------------------------------------------------------------
~vtkFunctionParser()53 vtkFunctionParser::~vtkFunctionParser()
54 {
55   delete [] this->Function;
56   this->Function = nullptr;
57 
58   delete [] this->FunctionWithSpaces;
59   this->FunctionWithSpaces = nullptr;
60 
61   delete [] this->ByteCode;
62   this->ByteCode = nullptr;
63 
64   delete [] this->Immediates;
65   this->Immediates = nullptr;
66 
67   delete [] this->Stack;
68   this->Stack = nullptr;
69 
70   if(this->ParseError)
71   {
72     this->SetParseError(nullptr);
73   }
74 }
75 
76 //-----------------------------------------------------------------------------
SetFunction(const char * function)77 void vtkFunctionParser::SetFunction(const char *function)
78 {
79   if (this->Function && function && strcmp(this->Function,function) == 0)
80   {
81     return;
82   }
83 
84   if (this->Function)
85   {
86     delete [] this->Function;
87     delete [] this->FunctionWithSpaces;
88   }
89 
90   if (function)
91   {
92     this->Function = new char[strlen(function)+1];
93     this->FunctionWithSpaces = new char[strlen(function) + 1];
94 
95     strcpy(this->Function,function);
96     strcpy(this->FunctionWithSpaces, function);
97   }
98   else
99   {
100     this->Function = nullptr;
101     this->FunctionWithSpaces = nullptr;
102   }
103 
104   this->FunctionMTime.Modified();
105   this->ScalarVariableNeeded.clear();
106   this->VectorVariableNeeded.clear();
107   this->Modified();
108 }
109 
Parse()110 int vtkFunctionParser::Parse()
111 {
112   int result;
113   int i;
114 
115   if (this->Function == nullptr)
116   {
117     vtkErrorMacro("Parse: no function has been set");
118     return 0;
119   }
120 
121   result = this->CheckSyntax();
122   if (!result)
123   {
124     return 0;
125   }
126 
127   this->BuildInternalFunctionStructure();
128 
129   // need to make sure that the ambiguous operators are correct
130   // - scalar/vector +
131   // - scalar/vector -
132   // - scalar/vector unary minus
133   // - scalar/vector unary plus
134   // - * (2 scalars) or scalar multiple (scalar, vector)
135   result = this->DisambiguateOperators();
136   if (!result)
137   {
138     vtkErrorMacro("Parse: Error deciding between ambiguous operators");
139     return 0;
140   }
141 
142   // need to recalculate stack size based on number of vector variables
143   // in byte code
144   for (i = 0; i < this->ByteCodeSize; i++)
145   {
146     if ((this->ByteCode[i] >= VTK_PARSER_BEGIN_VARIABLES +
147          this->GetNumberOfScalarVariables()) ||
148         (this->ByteCode[i] == VTK_PARSER_IHAT) ||
149         (this->ByteCode[i] == VTK_PARSER_JHAT) ||
150         (this->ByteCode[i] == VTK_PARSER_KHAT))
151     {
152       this->StackSize += 2;
153     }
154   }
155 
156   if (this->StackSize)
157   {
158     this->Stack = new double[this->StackSize];
159     if (!this->Stack)
160     {
161       vtkErrorMacro("Parse: Out of memory");
162       return 0;
163     }
164   }
165 
166   // Collect meta-data about variables that are needed for evaluation of the
167   // function.
168   this->UpdateNeededVariables();
169   this->ParseMTime.Modified();
170   return 1;
171 }
172 
173 //-----------------------------------------------------------------------------
DisambiguateOperators()174 int vtkFunctionParser::DisambiguateOperators()
175 {
176   unsigned char* tempStack = new unsigned char[this->ByteCodeSize];
177   int i;
178   int tempStackPtr = -1;
179 
180   // using 0 for scalars and 1 for vectors
181   for (i = 0; i < this->ByteCodeSize; i++)
182   {
183     switch (this->ByteCode[i])
184     {
185       case VTK_PARSER_IMMEDIATE:
186         tempStackPtr++;
187         tempStack[tempStackPtr] = 0;
188         break;
189       case VTK_PARSER_UNARY_MINUS:
190         if (tempStack[tempStackPtr] != 0)
191         {
192           this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_MINUS;
193         }
194         break;
195       case VTK_PARSER_UNARY_PLUS:
196         if (tempStack[tempStackPtr] != 0)
197         {
198           this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_PLUS;
199         }
200         break;
201       case VTK_PARSER_ADD:
202         if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0)
203         {
204           this->ByteCode[i] = VTK_PARSER_VECTOR_ADD;
205         }
206         else if ((tempStack[tempStackPtr] == 0 &&
207                   tempStack[tempStackPtr-1] != 0) ||
208                  (tempStack[tempStackPtr] != 0 &&
209                   tempStack[tempStackPtr-1] == 0))
210         {
211           delete [] tempStack;
212           vtkErrorMacro("addition expects either 2 vectors or 2 scalars");
213           return 0;
214         }
215         tempStackPtr--;
216         break;
217       case VTK_PARSER_SUBTRACT:
218         if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0)
219         {
220           this->ByteCode[i] = VTK_PARSER_VECTOR_SUBTRACT;
221         }
222         else if ((tempStack[tempStackPtr] == 0 &&
223                   tempStack[tempStackPtr-1] != 0) ||
224                  (tempStack[tempStackPtr] != 0 &&
225                   tempStack[tempStackPtr-1] == 0))
226         {
227           delete [] tempStack;
228           vtkErrorMacro("subtraction expects either 2 vectors or 2 scalars");
229           return 0;
230         }
231         tempStackPtr--;
232         break;
233       case VTK_PARSER_MULTIPLY:
234         if (tempStack[tempStackPtr-1] == 0 && tempStack[tempStackPtr] == 1)
235         {
236           this->ByteCode[i] = VTK_PARSER_SCALAR_TIMES_VECTOR;
237           tempStack[tempStackPtr-1] = 1;
238         }
239         else if (tempStack[tempStackPtr-1] == 1 &&
240                  tempStack[tempStackPtr] == 0)
241         {
242           this->ByteCode[i] = VTK_PARSER_VECTOR_TIMES_SCALAR;
243           tempStack[tempStackPtr-1] = 1;
244         }
245         else if (tempStack[tempStackPtr] == 1)
246         {
247           delete [] tempStack;
248           vtkErrorMacro("multiply expecting either 2 scalars or a scalar and"
249                         << " a vector");
250           return 0;
251         }
252         tempStackPtr--;
253         break;
254       case VTK_PARSER_DIVIDE:
255         if (tempStack[tempStackPtr-1] == 1 && tempStack[tempStackPtr] == 0)
256         {
257           // vector / scalar.
258           this->ByteCode[i] = VTK_PARSER_VECTOR_OVER_SCALAR;
259           tempStack[tempStackPtr-1] = 1;
260         }
261         else if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
262         {
263           delete [] tempStack;
264           vtkErrorMacro("can't divide vectors");
265           return 0;
266         }
267         tempStackPtr--;
268         break;
269       case VTK_PARSER_POWER:
270         if (tempStack[tempStackPtr-1] == 1)
271         {
272           delete [] tempStack;
273           vtkErrorMacro("can't raise a vector to a power");
274           return 0;
275         }
276         tempStackPtr--;
277         break;
278       case VTK_PARSER_LESS_THAN:
279       case VTK_PARSER_GREATER_THAN:
280       case VTK_PARSER_EQUAL_TO:
281       case VTK_PARSER_AND:
282       case VTK_PARSER_OR:
283         if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
284         {
285           delete [] tempStack;
286           vtkErrorMacro("Vectors cannot be used in boolean expressions.");
287           return 0;
288         }
289         tempStackPtr--;
290         break;
291       case VTK_PARSER_ABSOLUTE_VALUE:
292       case VTK_PARSER_EXPONENT:
293       case VTK_PARSER_CEILING:
294       case VTK_PARSER_FLOOR:
295       case VTK_PARSER_LOGARITHM:
296       case VTK_PARSER_LOGARITHME:
297       case VTK_PARSER_LOGARITHM10:
298       case VTK_PARSER_SQUARE_ROOT:
299       case VTK_PARSER_SINE:
300       case VTK_PARSER_COSINE:
301       case VTK_PARSER_TANGENT:
302       case VTK_PARSER_ARCSINE:
303       case VTK_PARSER_ARCCOSINE:
304       case VTK_PARSER_ARCTANGENT:
305       case VTK_PARSER_HYPERBOLIC_SINE:
306       case VTK_PARSER_HYPERBOLIC_COSINE:
307       case VTK_PARSER_HYPERBOLIC_TANGENT:
308       case VTK_PARSER_SIGN:
309         if (tempStack[tempStackPtr] == 1)
310         {
311           delete [] tempStack;
312           vtkErrorMacro("expecting a scalar, but got a vector");
313           return 0;
314         }
315         break;
316       case VTK_PARSER_MIN:
317         if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
318         {
319           delete [] tempStack;
320           vtkErrorMacro("can't apply min to vectors");
321           return 0;
322         }
323         tempStackPtr--;
324         break;
325       case VTK_PARSER_MAX:
326         if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
327         {
328           delete [] tempStack;
329           vtkErrorMacro("can't apply max to vectors");
330           return 0;
331         }
332         tempStackPtr--;
333         break;
334       case VTK_PARSER_CROSS:
335         if (tempStack[tempStackPtr] == 0 || tempStack[tempStackPtr-1] == 0)
336         {
337           delete [] tempStack;
338           vtkErrorMacro("can't apply cross to scalars");
339           return 0;
340         }
341         tempStackPtr--;
342         break;
343       case VTK_PARSER_DOT_PRODUCT:
344         if (tempStack[tempStackPtr] == 0 || tempStack[tempStackPtr-1] == 0)
345         {
346           delete [] tempStack;
347           vtkErrorMacro("dot product does not operate on scalars");
348           return 0;
349         }
350         tempStack[tempStackPtr-1] = 0;
351         tempStackPtr--;
352         break;
353       case VTK_PARSER_MAGNITUDE:
354         if (tempStack[tempStackPtr] == 0)
355         {
356           delete [] tempStack;
357           vtkErrorMacro("magnitude expects a vector, but got a scalar");
358           return 0;
359         }
360         tempStack[tempStackPtr] = 0;
361         break;
362       case VTK_PARSER_NORMALIZE:
363         if (tempStack[tempStackPtr] == 0)
364         {
365           delete [] tempStack;
366           vtkErrorMacro("normalize expects a vector, but got a scalar");
367           return 0;
368         }
369         break;
370       case VTK_PARSER_IHAT:
371       case VTK_PARSER_JHAT:
372       case VTK_PARSER_KHAT:
373         tempStackPtr++;
374         tempStack[tempStackPtr] = 1;
375         break;
376       case VTK_PARSER_IF:
377         // tempStack[tempStackPtr] = tempStack[2] refers to the bool argument
378         // of if(bool,valtrue,valfalse). tempStack[1] is valtrue, and
379         // tempStack[0] is valfalse.
380         if (tempStack[tempStackPtr] != 0)
381         {
382           delete [] tempStack;
383           vtkErrorMacro("first argument of if(bool,valtrue,valfalse) cannot be a vector");
384           return 0;
385         }
386         else if (tempStack[tempStackPtr-1] != 0 &&
387                  tempStack[tempStackPtr-2] != 0)
388         {
389           this->ByteCode[i] = VTK_PARSER_VECTOR_IF;
390         }
391         else if ((tempStack[tempStackPtr-1] == 0 &&
392                   tempStack[tempStackPtr-2] != 0) ||
393                  (tempStack[tempStackPtr-1] != 0 &&
394                   tempStack[tempStackPtr-2] == 0))
395         {
396           delete [] tempStack;
397           vtkErrorMacro("the if function expects the second and third arguments to be either 2 vectors or 2 scalars");
398           return 0;
399         }
400         tempStackPtr--;
401         tempStackPtr--;
402         break;
403       default:
404         if ((this->ByteCode[i] - VTK_PARSER_BEGIN_VARIABLES) < this->GetNumberOfScalarVariables())
405         {
406           tempStackPtr++;
407           tempStack[tempStackPtr] = 0;
408         }
409         else
410         {
411           tempStackPtr++;
412           tempStack[tempStackPtr] = 1;
413         }
414     }
415   }
416 
417   delete [] tempStack;
418   return 1;
419 }
420 
421 //-----------------------------------------------------------------------------
InvalidateFunction()422 void vtkFunctionParser::InvalidateFunction()
423 {
424   this->FunctionMTime.Modified();
425 }
426 
427 //-----------------------------------------------------------------------------
Evaluate()428 bool vtkFunctionParser::Evaluate()
429 {
430   int numBytesProcessed;
431   int numImmediatesProcessed = 0;
432   int stackPosition = -1;
433   double magnitude;
434   double temp[3];
435 
436   this->StackPointer = -1;
437 
438   if (this->FunctionMTime.GetMTime() > this->ParseMTime.GetMTime())
439   {
440     if (this->Parse() == 0)
441     {
442       return false;
443     }
444   }
445 
446   for (numBytesProcessed = 0; numBytesProcessed < this->ByteCodeSize;
447        numBytesProcessed++)
448   {
449     switch (this->ByteCode[numBytesProcessed])
450     {
451       case VTK_PARSER_IMMEDIATE:
452         this->Stack[++stackPosition] =
453           this->Immediates[numImmediatesProcessed++];
454         break;
455       case VTK_PARSER_UNARY_MINUS:
456         this->Stack[stackPosition] = -(this->Stack[stackPosition]);
457         break;
458       case VTK_PARSER_UNARY_PLUS:
459         break;
460       case VTK_PARSER_ADD:
461         this->Stack[stackPosition-1] += this->Stack[stackPosition];
462         stackPosition--;
463         break;
464       case VTK_PARSER_SUBTRACT:
465         this->Stack[stackPosition-1] -= this->Stack[stackPosition];
466         stackPosition--;
467         break;
468       case VTK_PARSER_MULTIPLY:
469         this->Stack[stackPosition-1] *= this->Stack[stackPosition];
470         stackPosition--;
471         break;
472       case VTK_PARSER_DIVIDE:
473         if (this->Stack[stackPosition]==0)
474         {
475           if (this->ReplaceInvalidValues)
476           {
477             this->Stack[stackPosition-1] = this->ReplacementValue;
478             stackPosition--;
479           }
480           else
481           {
482             vtkErrorMacro("Trying to divide by zero");
483             return false;
484           }
485         }
486         else
487         {
488           this->Stack[stackPosition-1] /= this->Stack[stackPosition];
489           stackPosition--;
490         }
491         break;
492       case VTK_PARSER_POWER:
493         this->Stack[stackPosition-1] = pow(this->Stack[stackPosition-1],
494                                            this->Stack[stackPosition]);
495         stackPosition--;
496         break;
497       case VTK_PARSER_ABSOLUTE_VALUE:
498         this->Stack[stackPosition] = fabs(this->Stack[stackPosition]);
499         break;
500       case VTK_PARSER_EXPONENT:
501         this->Stack[stackPosition] = exp(this->Stack[stackPosition]);
502         break;
503       case VTK_PARSER_CEILING:
504         this->Stack[stackPosition] = ceil(this->Stack[stackPosition]);
505         break;
506       case VTK_PARSER_FLOOR:
507         this->Stack[stackPosition] = floor(this->Stack[stackPosition]);
508         break;
509       case VTK_PARSER_LOGARITHM:
510         if (this->Stack[stackPosition]<=0)
511         {
512           if (this->ReplaceInvalidValues)
513           {
514             this->Stack[stackPosition] = this->ReplacementValue;
515           }
516           else
517           {
518             vtkErrorMacro("Trying to take a log of a non-positive value");
519             return false;
520           }
521         }
522         else
523         {
524           this->Stack[stackPosition] = log(this->Stack[stackPosition]);
525         }
526         break;
527       case VTK_PARSER_LOGARITHME:
528         if (this->Stack[stackPosition]<=0)
529         {
530           if (this->ReplaceInvalidValues)
531           {
532             this->Stack[stackPosition] = this->ReplacementValue;
533           }
534           else
535           {
536             vtkErrorMacro("Trying to take a natural logarithm of a non-positive value");
537             return false;
538           }
539         }
540         else
541         {
542           this->Stack[stackPosition] = log(this->Stack[stackPosition]);
543         }
544         break;
545       case VTK_PARSER_LOGARITHM10:
546         if (this->Stack[stackPosition]<=0)
547         {
548           if (this->ReplaceInvalidValues)
549           {
550             this->Stack[stackPosition] = this->ReplacementValue;
551           }
552           else
553           {
554             vtkErrorMacro("Trying to take a log10 of a non-positive value");
555             return false;
556           }
557         }
558         else
559         {
560           this->Stack[stackPosition] =
561             log10(this->Stack[stackPosition]);
562         }
563         break;
564       case VTK_PARSER_SQUARE_ROOT:
565         if (this->Stack[stackPosition] < 0)
566         {
567           if (this->ReplaceInvalidValues)
568           {
569             this->Stack[stackPosition] = this->ReplacementValue;
570           }
571           else
572           {
573             vtkErrorMacro("Trying to take a square root of a negative value");
574             return false;
575           }
576         }
577         else
578         {
579           this->Stack[stackPosition] = sqrt(this->Stack[stackPosition]);
580         }
581         break;
582       case VTK_PARSER_SINE:
583         this->Stack[stackPosition] = sin(this->Stack[stackPosition]);
584         break;
585       case VTK_PARSER_COSINE:
586         this->Stack[stackPosition] = cos(this->Stack[stackPosition]);
587         break;
588       case VTK_PARSER_TANGENT:
589         this->Stack[stackPosition] = tan(this->Stack[stackPosition]);
590         break;
591       case VTK_PARSER_ARCSINE:
592         if (this->Stack[stackPosition] < -1 || this->Stack[stackPosition] > 1)
593         {
594           if (this->ReplaceInvalidValues)
595           {
596             this->Stack[stackPosition] = this->ReplacementValue;
597           }
598           else
599           {
600             vtkErrorMacro("Trying to take asin of a value < -1 or > 1. Arg is q" << this->Stack[stackPosition]);
601             return false;
602           }
603         }
604         else
605         {
606           this->Stack[stackPosition] = asin(this->Stack[stackPosition]);
607         }
608         break;
609       case VTK_PARSER_ARCCOSINE:
610         if(this->Stack[stackPosition]<-1 || this->Stack[stackPosition]>1)
611         {
612           if (this->ReplaceInvalidValues)
613           {
614             this->Stack[stackPosition] = this->ReplacementValue;
615           }
616           else
617           {
618             vtkErrorMacro("Trying to take acos of a value < -1 or > 1. Arg is q" << this->Stack[stackPosition]);
619             return false;
620           }
621         }
622         else
623         {
624           this->Stack[stackPosition] = acos(this->Stack[stackPosition]);
625         }
626         break;
627       case VTK_PARSER_ARCTANGENT:
628         this->Stack[stackPosition] = atan(this->Stack[stackPosition]);
629         break;
630       case VTK_PARSER_HYPERBOLIC_SINE:
631         this->Stack[stackPosition] = sinh(this->Stack[stackPosition]);
632         break;
633       case VTK_PARSER_HYPERBOLIC_COSINE:
634         this->Stack[stackPosition] = cosh(this->Stack[stackPosition]);
635         break;
636       case VTK_PARSER_HYPERBOLIC_TANGENT:
637         this->Stack[stackPosition] = tanh(this->Stack[stackPosition]);
638         break;
639       case VTK_PARSER_MIN:
640         if (this->Stack[stackPosition] < this->Stack[stackPosition-1])
641         {
642           this->Stack[stackPosition-1] = this->Stack[stackPosition];
643         }
644         stackPosition--;
645         break;
646       case VTK_PARSER_MAX:
647         if (this->Stack[stackPosition] > this->Stack[stackPosition-1])
648         {
649           this->Stack[stackPosition-1] = this->Stack[stackPosition];
650         }
651         stackPosition--;
652         break;
653       case VTK_PARSER_CROSS:
654         // Cross Product
655         #define Ux (stackPosition-5)
656         #define Uy (stackPosition-4)
657         #define Uz (stackPosition-3)
658         #define Vx (stackPosition-2)
659         #define Vy (stackPosition-1)
660         #define Vz stackPosition
661         temp[0] = this->Stack[Uy]*this->Stack[Vz] -
662                   this->Stack[Uz]*this->Stack[Vy];
663         temp[1] = this->Stack[Uz]*this->Stack[Vx] -
664                   this->Stack[Ux]*this->Stack[Vz];
665         temp[2] = this->Stack[Ux]*this->Stack[Vy] -
666                   this->Stack[Uy]*this->Stack[Vx];
667         this->Stack[Ux] = temp[0];
668         this->Stack[Uy] = temp[1];
669         this->Stack[Uz] = temp[2];
670         #undef Ux
671         #undef Uy
672         #undef Uz
673         #undef Vx
674         #undef Vy
675         #undef Vz
676         stackPosition-=3;
677         break;
678       case VTK_PARSER_SIGN:
679         if (this->Stack[stackPosition] < 0)
680         {
681           this->Stack[stackPosition] = -1;
682         }
683         else if (this->Stack[stackPosition] ==  0)
684         {
685           this->Stack[stackPosition] = 0;
686         }
687         else
688         {
689           this->Stack[stackPosition] = 1;
690         }
691         break;
692       case VTK_PARSER_VECTOR_UNARY_MINUS:
693         this->Stack[stackPosition] = -this->Stack[stackPosition];
694         this->Stack[stackPosition-1] = -this->Stack[stackPosition-1];
695         this->Stack[stackPosition-2] = -this->Stack[stackPosition-2];
696         break;
697       case VTK_PARSER_VECTOR_UNARY_PLUS:
698         break;
699       case VTK_PARSER_DOT_PRODUCT:
700         this->Stack[stackPosition-3] *= this->Stack[stackPosition];
701         this->Stack[stackPosition-4] *= this->Stack[stackPosition-1];
702         this->Stack[stackPosition-5] *= this->Stack[stackPosition-2];
703         this->Stack[stackPosition-5] = this->Stack[stackPosition-5] +
704           this->Stack[stackPosition-4] + this->Stack[stackPosition-3];
705         stackPosition -= 5;
706         break;
707       case VTK_PARSER_VECTOR_ADD:
708         this->Stack[stackPosition-3] += this->Stack[stackPosition];
709         this->Stack[stackPosition-4] += this->Stack[stackPosition-1];
710         this->Stack[stackPosition-5] += this->Stack[stackPosition-2];
711         stackPosition -= 3;
712         break;
713       case VTK_PARSER_VECTOR_SUBTRACT:
714         this->Stack[stackPosition-3] -= this->Stack[stackPosition];
715         this->Stack[stackPosition-4] -= this->Stack[stackPosition-1];
716         this->Stack[stackPosition-5] -= this->Stack[stackPosition-2];
717         stackPosition -= 3;
718         break;
719       case VTK_PARSER_SCALAR_TIMES_VECTOR:
720         this->Stack[stackPosition] *= this->Stack[stackPosition-3];
721         this->Stack[stackPosition-1] *= this->Stack[stackPosition-3];
722         this->Stack[stackPosition-2] *= this->Stack[stackPosition-3];
723         this->Stack[stackPosition-3] = this->Stack[stackPosition-2];
724         this->Stack[stackPosition-2] = this->Stack[stackPosition-1];
725         this->Stack[stackPosition-1] = this->Stack[stackPosition];
726         stackPosition--;
727         break;
728       case VTK_PARSER_VECTOR_TIMES_SCALAR:
729         this->Stack[stackPosition-3] *= this->Stack[stackPosition];
730         this->Stack[stackPosition-2] *= this->Stack[stackPosition];
731         this->Stack[stackPosition-1] *= this->Stack[stackPosition];
732         stackPosition--;
733         break;
734       case VTK_PARSER_VECTOR_OVER_SCALAR:
735         this->Stack[stackPosition-3] /= this->Stack[stackPosition];
736         this->Stack[stackPosition-2] /= this->Stack[stackPosition];
737         this->Stack[stackPosition-1] /= this->Stack[stackPosition];
738         stackPosition--;
739         break;
740       case VTK_PARSER_MAGNITUDE:
741         this->Stack[stackPosition-2] =
742           sqrt(pow(this->Stack[stackPosition], 2) +
743                pow(this->Stack[stackPosition-1], 2) +
744                pow(this->Stack[stackPosition-2], 2));
745         stackPosition -= 2;
746         break;
747       case VTK_PARSER_NORMALIZE:
748         magnitude = sqrt(pow(this->Stack[stackPosition], 2) +
749                          pow(this->Stack[stackPosition-1], 2) +
750                          pow(this->Stack[stackPosition-2], 2));
751         if (magnitude != 0)
752         {
753           this->Stack[stackPosition] /= magnitude;
754           this->Stack[stackPosition-1] /= magnitude;
755           this->Stack[stackPosition-2] /= magnitude;
756         }
757         break;
758       case VTK_PARSER_IHAT:
759         this->Stack[++stackPosition] = 1;
760         this->Stack[++stackPosition] = 0;
761         this->Stack[++stackPosition] = 0;
762         break;
763       case VTK_PARSER_JHAT:
764         this->Stack[++stackPosition] = 0;
765         this->Stack[++stackPosition] = 1;
766         this->Stack[++stackPosition] = 0;
767         break;
768       case VTK_PARSER_KHAT:
769         this->Stack[++stackPosition] = 0;
770         this->Stack[++stackPosition] = 0;
771         this->Stack[++stackPosition] = 1;
772         break;
773       case VTK_PARSER_LESS_THAN:
774         this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] < this->Stack[stackPosition]);
775         stackPosition--;
776         break;
777       case VTK_PARSER_GREATER_THAN:
778         this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] > this->Stack[stackPosition]);
779         stackPosition--;
780         break;
781       case VTK_PARSER_EQUAL_TO:
782         this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] == this->Stack[stackPosition]);
783         stackPosition--;
784         break;
785       case VTK_PARSER_AND:
786         this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] && this->Stack[stackPosition]);
787         stackPosition--;
788         break;
789       case VTK_PARSER_OR:
790         this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] || this->Stack[stackPosition]);
791         stackPosition--;
792         break;
793       case VTK_PARSER_IF:
794       {
795         // Stack[stackPosition]=Stack[2] refers to the bool
796         // argument of if(bool,valtrue,valfalse). Stack[1] is valtrue, and
797         // Stack[0] is valfalse.
798         int result = stackPosition - 2;
799         int valFalse = stackPosition - 2;
800         int valTrue = stackPosition - 1;
801         int boolArg = stackPosition;
802 
803         if (this->Stack[boolArg] != 0.0)
804           this->Stack[result] = this->Stack[valTrue];
805         else
806           this->Stack[result] = this->Stack[valFalse];
807         stackPosition -= 2;
808         break;
809       }
810       case VTK_PARSER_VECTOR_IF:
811       {
812         int xResult = stackPosition - 6;
813         int yResult = stackPosition - 5;
814         int zResult = stackPosition - 4;
815         int xValFalse = stackPosition - 6;
816         int yValFalse = stackPosition - 5;
817         int zValFalse = stackPosition - 4;
818         int xValTrue = stackPosition - 3;
819         int yValTrue = stackPosition - 2;
820         int zValTrue = stackPosition - 1;
821         int boolArg = stackPosition;
822 
823         if (this->Stack[boolArg] != 0.0)
824         {
825           this->Stack[xResult] = this->Stack[xValTrue];
826           this->Stack[yResult] = this->Stack[yValTrue];
827           this->Stack[zResult] = this->Stack[zValTrue];
828         }
829         else
830         {
831           this->Stack[xResult] = this->Stack[xValFalse];
832           this->Stack[yResult] = this->Stack[yValFalse];
833           this->Stack[zResult] = this->Stack[zValFalse];
834         }
835         stackPosition -= 4;
836         break;
837       }
838       default:
839         if ((this->ByteCode[numBytesProcessed] -
840              VTK_PARSER_BEGIN_VARIABLES) < this->GetNumberOfScalarVariables())
841         {
842           this->Stack[++stackPosition] =
843             this->ScalarVariableValues[this->ByteCode[numBytesProcessed] -
844                                       VTK_PARSER_BEGIN_VARIABLES];
845         }
846         else
847         {
848           int vectorNum = this->ByteCode[numBytesProcessed] -
849             VTK_PARSER_BEGIN_VARIABLES - this->GetNumberOfScalarVariables();
850           this->Stack[++stackPosition] =
851             this->VectorVariableValues[vectorNum][0];
852           this->Stack[++stackPosition] =
853             this->VectorVariableValues[vectorNum][1];
854           this->Stack[++stackPosition] =
855             this->VectorVariableValues[vectorNum][2];
856         }
857     }
858   }
859   this->StackPointer = stackPosition;
860 
861   this->EvaluateMTime.Modified();
862 
863   return true;
864 }
865 
866 //-----------------------------------------------------------------------------
IsScalarResult()867 int vtkFunctionParser::IsScalarResult()
868 {
869   if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
870       this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
871   {
872       if (this->Evaluate() == false)
873         return 0;
874   }
875   return (this->StackPointer == 0);
876 }
877 
878 //-----------------------------------------------------------------------------
GetScalarResult()879 double vtkFunctionParser::GetScalarResult()
880 {
881   if (!(this->IsScalarResult()))
882   {
883     vtkErrorMacro("GetScalarResult: no valid scalar result");
884     return VTK_PARSER_ERROR_RESULT;
885   }
886   return this->Stack[0];
887 }
888 
IsVectorResult()889 int vtkFunctionParser::IsVectorResult()
890 {
891   if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
892       this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
893   {
894       if (this->Evaluate() == false)
895         return 0;
896   }
897   return (this->StackPointer == 2);
898 }
899 
900 //-----------------------------------------------------------------------------
GetVectorResult()901 double *vtkFunctionParser::GetVectorResult()
902 {
903   if (!(this->IsVectorResult()))
904   {
905     vtkErrorMacro("GetVectorResult: no valid vector result");
906     return vtkParserVectorErrorResult;
907   }
908   return this->Stack;
909 }
910 
911 //-----------------------------------------------------------------------------
GetScalarVariableName(int i)912 const char* vtkFunctionParser::GetScalarVariableName(int i)
913 {
914   if (i >= 0 && i < this->GetNumberOfScalarVariables())
915   {
916     return this->ScalarVariableNames[i].c_str();
917   }
918   return nullptr;
919 }
920 
921 //-----------------------------------------------------------------------------
GetVectorVariableName(int i)922 const char* vtkFunctionParser::GetVectorVariableName(int i)
923 {
924   if (i >= 0 && i < this->GetNumberOfVectorVariables())
925   {
926     return this->VectorVariableNames[i].c_str();
927   }
928   return nullptr;
929 }
930 
931 //-----------------------------------------------------------------------------
IsVariableName(int currentIndex)932 int vtkFunctionParser::IsVariableName(int currentIndex)
933 {
934   for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
935   {
936     if (strncmp(this->ScalarVariableNames[i].c_str(), &this->Function[currentIndex],
937                 this->ScalarVariableNames[i].size()) == 0)
938     {
939       return 1;
940     }
941   }
942   for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
943   {
944     if (strncmp(this->VectorVariableNames[i].c_str(), &this->Function[currentIndex],
945                 this->VectorVariableNames[i].size()) == 0)
946     {
947       return 1;
948     }
949   }
950 
951   return 0;
952 }
953 
954 //-----------------------------------------------------------------------------
IsElementaryOperator(int op)955 int vtkFunctionParser::IsElementaryOperator(int op)
956 {
957   return strchr("+-.*/^", op) != nullptr;
958 }
959 
960 //-----------------------------------------------------------------------------
SetScalarVariableValue(const char * inVariableName,double value)961 void vtkFunctionParser::SetScalarVariableValue(const char* inVariableName,
962                                                double value)
963 {
964   char* variableName = this->RemoveSpacesFrom(inVariableName);
965   for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
966   {
967     if (strcmp(variableName, this->ScalarVariableNames[i].c_str()) == 0)
968     {
969       if (this->ScalarVariableValues[i] != value)
970       {
971         this->ScalarVariableValues[i] = value;
972         this->VariableMTime.Modified();
973         this->Modified();
974       }
975       delete [] variableName;
976       return;
977     }
978   }
979   this->ScalarVariableValues.push_back(value);
980   this->ScalarVariableNames.push_back(variableName);
981   this->VariableMTime.Modified();
982   this->Modified();
983   delete [] variableName;
984 }
985 
986 //-----------------------------------------------------------------------------
SetScalarVariableValue(int i,double value)987 void vtkFunctionParser::SetScalarVariableValue(int i, double value)
988 {
989   if (i < 0 || i >= this->GetNumberOfScalarVariables())
990   {
991     return;
992   }
993 
994   if (this->ScalarVariableValues[i] != value)
995   {
996     this->ScalarVariableValues[i] = value;
997     this->VariableMTime.Modified();
998   }
999   this->Modified();
1000 }
1001 
1002 //-----------------------------------------------------------------------------
GetScalarVariableValue(const char * inVariableName)1003 double vtkFunctionParser::GetScalarVariableValue(const char* inVariableName)
1004 {
1005   char* variableName = this->RemoveSpacesFrom(inVariableName);
1006   for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
1007   {
1008     if (strcmp(variableName, this->ScalarVariableNames[i].c_str()) == 0)
1009     {
1010       delete [] variableName;
1011       return this->ScalarVariableValues[i];
1012     }
1013   }
1014   vtkErrorMacro("GetScalarVariableValue: scalar variable name " << variableName
1015                 << " does not exist");
1016   delete [] variableName;
1017   return VTK_PARSER_ERROR_RESULT;
1018 }
1019 
1020 //-----------------------------------------------------------------------------
GetScalarVariableValue(int i)1021 double vtkFunctionParser::GetScalarVariableValue(int i)
1022 {
1023   if (i < 0 || i >= this->GetNumberOfScalarVariables())
1024   {
1025     vtkErrorMacro("GetScalarVariableValue: scalar variable number " << i
1026                   << " does not exist");
1027     return VTK_PARSER_ERROR_RESULT;
1028   }
1029 
1030   return this->ScalarVariableValues[i];
1031 }
1032 
1033 //-----------------------------------------------------------------------------
SetVectorVariableValue(const char * inVariableName,double xValue,double yValue,double zValue)1034 void vtkFunctionParser::SetVectorVariableValue(const char* inVariableName,
1035                                                double xValue, double yValue,
1036                                                double zValue)
1037 {
1038   char* variableName = this->RemoveSpacesFrom(inVariableName);
1039   for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
1040   {
1041     if (strcmp(variableName, this->VectorVariableNames[i].c_str()) == 0)
1042     {
1043       if (this->VectorVariableValues[i][0] != xValue ||
1044           this->VectorVariableValues[i][1] != yValue ||
1045           this->VectorVariableValues[i][2] != zValue)
1046       {
1047         this->VectorVariableValues[i][0] = xValue;
1048         this->VectorVariableValues[i][1] = yValue;
1049         this->VectorVariableValues[i][2] = zValue;
1050         this->VariableMTime.Modified();
1051         this->Modified();
1052       }
1053       delete [] variableName;
1054       return;
1055     }
1056   }
1057 
1058   this->VectorVariableNames.push_back(variableName);
1059   vtkTuple<double, 3> val;
1060   val[0] = xValue;
1061   val[1] = yValue;
1062   val[2] = zValue;
1063   this->VectorVariableValues.push_back(val);
1064 
1065   this->VariableMTime.Modified();
1066   this->Modified();
1067   delete [] variableName;
1068 }
1069 
1070 //-----------------------------------------------------------------------------
SetVectorVariableValue(int i,double xValue,double yValue,double zValue)1071 void vtkFunctionParser::SetVectorVariableValue(int i, double xValue,
1072                                                double yValue, double zValue)
1073 {
1074   if (i < 0 || i >= this->GetNumberOfVectorVariables())
1075   {
1076     return;
1077   }
1078   if (this->VectorVariableValues[i][0] != xValue ||
1079       this->VectorVariableValues[i][1] != yValue ||
1080       this->VectorVariableValues[i][2] != zValue)
1081   {
1082     this->VectorVariableValues[i][0] = xValue;
1083     this->VectorVariableValues[i][1] = yValue;
1084     this->VectorVariableValues[i][2] = zValue;
1085     this->VariableMTime.Modified();
1086     this->Modified();
1087   }
1088 }
1089 
1090 //-----------------------------------------------------------------------------
GetVectorVariableValue(const char * inVariableName)1091 double* vtkFunctionParser::GetVectorVariableValue(const char* inVariableName)
1092 {
1093   char* variableName = this->RemoveSpacesFrom(inVariableName);
1094 
1095   for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
1096   {
1097     if (strcmp(variableName, this->VectorVariableNames[i].c_str()) == 0)
1098     {
1099       delete [] variableName;
1100       return this->VectorVariableValues[i].GetData();
1101     }
1102   }
1103   vtkErrorMacro("GetVectorVariableValue: vector variable name " << variableName
1104                 << " does not exist");
1105   delete [] variableName;
1106   return vtkParserVectorErrorResult;
1107 }
1108 
1109 //-----------------------------------------------------------------------------
GetVectorVariableValue(int i)1110 double* vtkFunctionParser::GetVectorVariableValue(int i)
1111 {
1112   if (i < 0 || i >= this->GetNumberOfVectorVariables())
1113   {
1114     vtkErrorMacro("GetVectorVariableValue: vector variable number " << i
1115                   << " does not exist");
1116     return vtkParserVectorErrorResult;
1117   }
1118   return this->VectorVariableValues[i].GetData();
1119 }
1120 
1121 //-----------------------------------------------------------------------------
RemoveSpacesFrom(const char * variableName)1122 char* vtkFunctionParser::RemoveSpacesFrom(const char* variableName)
1123 {
1124   int len = static_cast<int>(strlen(variableName));
1125   int i;
1126   char* resultString = new char[len+1];
1127   char* out = resultString;
1128   for(i=0; i < len; ++i)
1129   {
1130     if(variableName[i] != ' ')
1131     {
1132       *out++ = variableName[i];
1133     }
1134   }
1135   *out = '\0';
1136   return resultString;
1137 }
1138 
1139 //-----------------------------------------------------------------------------
RemoveSpaces()1140 void vtkFunctionParser::RemoveSpaces()
1141 {
1142   char *tempString;
1143   int i, length;
1144 
1145   this->FunctionLength = 0;
1146   length = static_cast<int>(strlen(this->Function));
1147 
1148   tempString = new char[length+1];
1149   for (i = 0; i < length; i++)
1150   {
1151     if (!isspace(this->Function[i]))
1152     {
1153       tempString[this->FunctionLength] = this->Function[i];
1154       this->FunctionLength++;
1155     }
1156   }
1157 
1158   delete [] this->Function;
1159   this->Function = new char[this->FunctionLength+1];
1160   strncpy(this->Function, tempString,
1161           static_cast<size_t>(this->FunctionLength));
1162   this->Function[this->FunctionLength] = '\0';
1163   delete [] tempString;
1164 }
1165 
1166 //-----------------------------------------------------------------------------
OperatorWithinVariable(int idx)1167 int vtkFunctionParser::OperatorWithinVariable(int idx)
1168 {
1169   char *tmpString = nullptr;
1170 
1171   for ( int i = 0, max = this->GetNumberOfScalarVariables();  i < max;  i ++ )
1172   {
1173     int end = 0;
1174 
1175     if (  strchr( this->ScalarVariableNames[i].c_str(), this->Function[idx] ) != nullptr  )
1176     {
1177       if (    (  tmpString = strstr( this->Function, this->ScalarVariableNames[i].c_str() )  )    )
1178       {
1179         do
1180         {
1181           if (tmpString)
1182           {
1183             int start = static_cast<int>(tmpString - this->Function);
1184             end   = start + static_cast<int>( this->ScalarVariableNames[i].size() );
1185 
1186             // the variable being investigated does contain an operator (at idx)
1187             if ( start <= idx && idx <= end )  return  1;
1188 
1189             // just in case of one or even more occurrences of the
1190             // variable name (being investigated) preceding "idx" in this->Function[]
1191             // As suggested by 7islands, a greedy search is used here
1192             if ( end <= idx )  // to save strstr()  whenever possible
1193             tmpString = strstr( this->Function + end, this->ScalarVariableNames[i].c_str() );
1194           }
1195           else  break;
1196         } while ( end <= idx );
1197       }
1198     }
1199   }
1200 
1201   for ( int i = 0, max = this->GetNumberOfVectorVariables();  i < max;  i ++ )
1202   {
1203     int end = 0;
1204 
1205     if (  strchr( this->VectorVariableNames[i].c_str(), this->Function[idx] ) != nullptr  )
1206     {
1207       if (    (  tmpString = strstr( this->Function, this->VectorVariableNames[i].c_str() )  )    )
1208       {
1209         do
1210         {
1211           if (tmpString)
1212           {
1213             int start = static_cast<int>(tmpString - this->Function);
1214             end   = start + static_cast<int>( this->VectorVariableNames[i].size() );
1215 
1216             // the variable being investigated does contain an operator (at idx)
1217             if ( start <= idx && idx <= end )  return  1;
1218 
1219             // just in case of one or even more occurrences of the
1220             // variable name (being investigated) preceding "idx" in this->Function[]
1221             // As suggested by 7islands, a greedy search is used here
1222             if ( end <= idx )  // to save strstr()  whenever possible
1223             tmpString = strstr( this->Function + end, this->VectorVariableNames[i].c_str() );
1224           }
1225           else  break;
1226         } while ( end <= idx );
1227       }
1228     }
1229   }
1230 
1231   return  0;
1232 }
1233 
1234 //-----------------------------------------------------------------------------
CheckSyntax()1235 int vtkFunctionParser::CheckSyntax()
1236 {
1237   int     pos = -1;
1238   char*   error = nullptr;
1239 
1240   this->CheckExpression(pos, &error);
1241 
1242   if(pos != -1 || error)
1243   {
1244     vtkErrorMacro(<< error << "; " << " see position " << pos);
1245     return 0;
1246   }
1247   else
1248   {
1249     return 1;
1250   }
1251 }
1252 
1253 //-----------------------------------------------------------------------------
CopyParseError(int & position,char ** error)1254 void vtkFunctionParser::CopyParseError(int &position, char **error)
1255 {
1256   if(!error)
1257   {
1258     return;
1259   }
1260 
1261   position = this->ParseErrorPositon;
1262   *error   = this->ParseError;
1263 }
1264 
1265 //-----------------------------------------------------------------------------
BuildInternalFunctionStructure()1266 int vtkFunctionParser::BuildInternalFunctionStructure()
1267 {
1268   delete [] this->ByteCode;
1269   this->ByteCode = nullptr;
1270 
1271   delete [] this->Immediates;
1272   this->Immediates = nullptr;
1273 
1274   delete [] this->Stack;
1275   this->Stack = nullptr;
1276 
1277   this->ByteCodeSize = this->ImmediatesSize = this->StackSize = 0;
1278   this->StackPointer = 0;
1279   this->BuildInternalSubstringStructure(0, this->FunctionLength - 1);
1280 
1281   return 1;
1282 }
1283 
1284 //-----------------------------------------------------------------------------
BuildInternalSubstringStructure(int beginIndex,int endIndex)1285 void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex,
1286                                                         int endIndex)
1287 {
1288   int mathFunctionNum, beginIndex2;
1289   int opNum, parenthesisCount, i;
1290   // in order of reverse precedence
1291   static const char* const elementaryMathOps = "|&=<>+-.*/^";
1292 
1293   if (this->IsSubstringCompletelyEnclosed(beginIndex, endIndex))
1294   {
1295     this->BuildInternalSubstringStructure(beginIndex+1, endIndex-1);
1296     return;
1297   }
1298 
1299   if (this->Function[beginIndex] == '-')
1300   {
1301     if (this->IsSubstringCompletelyEnclosed(beginIndex+1, endIndex))
1302     {
1303       this->BuildInternalSubstringStructure(beginIndex+2, endIndex-1);
1304       this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
1305       return;
1306     }
1307     if (this->GetMathFunctionNumber(beginIndex+1) > 0 &&
1308         this->FindEndOfMathFunction(beginIndex+1) == endIndex)
1309     {
1310       this->BuildInternalSubstringStructure(beginIndex+1, endIndex);
1311       this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
1312       return;
1313     }
1314   }
1315 
1316   if (this->Function[beginIndex] == '+')
1317   {
1318     if (this->IsSubstringCompletelyEnclosed(beginIndex+1, endIndex))
1319     {
1320       this->BuildInternalSubstringStructure(beginIndex+2, endIndex-1);
1321       this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
1322       return;
1323     }
1324     if (this->GetMathFunctionNumber(beginIndex+1) > 0 &&
1325         this->FindEndOfMathFunction(beginIndex+1) == endIndex)
1326     {
1327       this->BuildInternalSubstringStructure(beginIndex+1, endIndex);
1328       this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
1329       return;
1330     }
1331   }
1332 
1333   if (isalpha(this->Function[beginIndex]))
1334   {
1335     mathFunctionNum = this->GetMathFunctionNumber(beginIndex);
1336     if (mathFunctionNum > 0)
1337     {
1338       beginIndex2 =
1339         beginIndex+this->GetMathFunctionStringLength(mathFunctionNum);
1340       while (beginIndex2 <= endIndex && this->Function[beginIndex2] == ' ')
1341       {
1342         beginIndex2++;
1343       }
1344       if (this->IsSubstringCompletelyEnclosed(beginIndex2, endIndex))
1345       {
1346         if ((mathFunctionNum == VTK_PARSER_MIN) ||
1347             (mathFunctionNum == VTK_PARSER_MAX) ||
1348             (mathFunctionNum == VTK_PARSER_CROSS))
1349         {
1350           parenthesisCount = 0;
1351           for (i = endIndex-1; i > beginIndex2; i--)
1352           {
1353             if (this->Function[i] == ')')
1354             {
1355               parenthesisCount++;
1356             }
1357             else if (this->Function[i] == '(')
1358             {
1359               parenthesisCount--;
1360             }
1361             if (parenthesisCount == 0 && this->Function[i] == ',')
1362             {
1363               this->BuildInternalSubstringStructure(beginIndex2+1, i-1);
1364               this->BuildInternalSubstringStructure(i+1, endIndex-1);
1365               this->AddInternalByte(
1366                 static_cast<unsigned char>(mathFunctionNum));
1367               this->StackPointer--;
1368               return;
1369             }
1370           } // for (i = endIndex-1; i > beginIndex2; i--)
1371         } // VTK_PARSER_MIN, ...
1372 
1373         if (mathFunctionNum == VTK_PARSER_IF)
1374         {
1375           // if(bool, valtrue, valfalse)
1376           int numCommas = 0;
1377           int secondCommaIndex = endIndex;
1378           parenthesisCount = 0;
1379           for (i = endIndex-1; i > beginIndex2; i--)
1380           {
1381             if (this->Function[i] == ')')
1382             {
1383               parenthesisCount++;
1384             }
1385             else if (this->Function[i] == '(')
1386             {
1387               parenthesisCount--;
1388             }
1389             if (parenthesisCount == 0 && this->Function[i] == ',')
1390             {
1391               numCommas++;
1392               if (numCommas == 1)
1393               {
1394                 // third arg
1395                 secondCommaIndex = i;
1396                 this->BuildInternalSubstringStructure(i+1, endIndex-1);
1397               }
1398               else // numCommas == 2
1399               {
1400                 // second arg
1401                 this->BuildInternalSubstringStructure(i+1, secondCommaIndex-1);
1402                 // first arg
1403                 this->BuildInternalSubstringStructure(beginIndex2+1, i-1);
1404                 this->AddInternalByte(
1405                   static_cast<unsigned char>(mathFunctionNum));
1406                 this->StackPointer--;
1407                 return;
1408               }
1409             } // if (parenthesisCount == 0 ... )
1410           } // for (i = endIndex-1; i > beginIndex2; i--)
1411         } // VTK_PARSER_IF, ...
1412 
1413         this->BuildInternalSubstringStructure(beginIndex2+1, endIndex-1);
1414         this->AddInternalByte(static_cast<unsigned char>(mathFunctionNum));
1415         return;
1416       } // if (this->IsSubstringCompletelyEnclosed ... )
1417     } // if (mathFunctionNum > 0)
1418   } // if (isalpha(this->Function[beginIndex]))
1419 
1420   int numMathOps = static_cast<int>(strlen(elementaryMathOps));
1421   for (opNum = 0; opNum < numMathOps; opNum++)
1422   {
1423     parenthesisCount = 0;
1424     for (i = endIndex; i > beginIndex; i--)
1425     {
1426       if (this->Function[i] == ')')
1427       {
1428         parenthesisCount++;
1429       }
1430       else if (this->Function[i] == '(')
1431       {
1432         parenthesisCount--;
1433       }
1434       if (parenthesisCount == 0 &&
1435           // arithmetic or boolean
1436           this->Function[i] == elementaryMathOps[opNum] &&
1437           !((this->Function[i] == '-' || this->Function[i] == '+') &&
1438             (this->IsElementaryOperator(this->Function[i-1]) ||
1439              this->Function[i-1] == '(' ||
1440              ((this->Function[i-1] == 'e' || this->Function[i-1] == 'E') &&
1441               i > 1 &&
1442               isdigit(this->Function[i-2])))) &&
1443           !(this->Function[i] == '.' &&
1444             (i+1 < this->FunctionLength) &&
1445              (isdigit(this->Function[i+1]))) &&
1446           !this->OperatorWithinVariable(i))
1447       {
1448         this->BuildInternalSubstringStructure(beginIndex, i-1);
1449         this->BuildInternalSubstringStructure(i+1, endIndex);
1450         this->AddInternalByte(
1451           this->GetElementaryOperatorNumber(elementaryMathOps[opNum]));
1452         this->StackPointer--;
1453         return;
1454       }
1455     } // end of   for (i = endIndex; i > beginIndex; i--)
1456   } // end of   for (opNum = 0; opNum < numMathOps; opNum++)
1457 
1458   beginIndex2 = beginIndex;
1459   bool unaryMinus = false;
1460   if (this->Function[beginIndex] == '-' ||
1461       this->Function[beginIndex] == '+')
1462   {
1463     if (this->Function[beginIndex] == '-')
1464       unaryMinus = true;
1465     beginIndex2++;
1466   }
1467 
1468   this->AddInternalByte(this->GetOperandNumber(beginIndex2));
1469   this->StackPointer++;
1470 
1471   if (this->StackPointer > this->StackSize)
1472   {
1473     this->StackSize++;
1474   }
1475   if (beginIndex2 > beginIndex)
1476   {
1477     if (unaryMinus)
1478       this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
1479     else
1480       this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
1481   }
1482 }
1483 
1484 //-----------------------------------------------------------------------------
AddInternalByte(unsigned char newByte)1485 void vtkFunctionParser::AddInternalByte(unsigned char newByte)
1486 {
1487   int i;
1488   unsigned char *tempByteCode = new unsigned char[this->ByteCodeSize];
1489 
1490   for (i = 0; i < this->ByteCodeSize; i++)
1491   { // Copy current byte code to a temporary array
1492     tempByteCode[i] = this->ByteCode[i];
1493   }
1494   delete [] this->ByteCode;
1495 
1496   // Allocate space for new byte.
1497   this->ByteCode = new unsigned char[this->ByteCodeSize + 1];
1498 
1499   // Copy contents of temporary array back to ByteCode.
1500   for (i = 0; i < this->ByteCodeSize; i++)
1501   {
1502     this->ByteCode[i] = tempByteCode[i];
1503   }
1504 
1505   this->ByteCode[this->ByteCodeSize] = newByte;
1506   this->ByteCodeSize++;
1507   delete [] tempByteCode;
1508 }
1509 
1510 //-----------------------------------------------------------------------------
IsSubstringCompletelyEnclosed(int beginIndex,int endIndex)1511 int vtkFunctionParser::IsSubstringCompletelyEnclosed(int beginIndex,
1512                                                      int endIndex)
1513 {
1514   int i, parenthesisCount;
1515 
1516   if ( this->Function[beginIndex] == '(' && this->Function[endIndex]== ')' )
1517   {
1518     parenthesisCount = 1;
1519     for (i = beginIndex + 1; i < endIndex; i++)
1520     {
1521       if (this->Function[i] == '(' )
1522       {
1523         parenthesisCount++;
1524       }
1525       else if(this->Function[i] == ')' )
1526       {
1527         parenthesisCount--;
1528       }
1529       if (parenthesisCount == 0)
1530       {
1531         break;
1532       }
1533     }
1534     if (i == endIndex)
1535     {
1536       return 1;
1537     }
1538   }
1539   return 0;
1540 }
1541 
1542 //-----------------------------------------------------------------------------
GetMathFunctionNumber(int currentIndex)1543 int vtkFunctionParser::GetMathFunctionNumber(int currentIndex)
1544 {
1545   // For addition of any new math function, please update
1546   // function GetMathFunctionNumberByCheckingParenthesis()
1547 
1548   if (strncmp(&this->Function[currentIndex], "abs", 3) == 0)
1549   {
1550     return VTK_PARSER_ABSOLUTE_VALUE;
1551   }
1552   if (strncmp(&this->Function[currentIndex], "exp", 3) == 0)
1553   {
1554     return VTK_PARSER_EXPONENT;
1555   }
1556   if (strncmp(&this->Function[currentIndex], "ceil", 4) == 0)
1557   {
1558     return VTK_PARSER_CEILING;
1559   }
1560   if (strncmp(&this->Function[currentIndex], "floor", 5) == 0)
1561   {
1562     return VTK_PARSER_FLOOR;
1563   }
1564   if (strncmp(&this->Function[currentIndex], "ln", 2) == 0)
1565   {
1566     return VTK_PARSER_LOGARITHME;
1567   }
1568   if (strncmp(&this->Function[currentIndex], "log10", 5) == 0)
1569   {
1570     return VTK_PARSER_LOGARITHM10;
1571   }
1572   if (strncmp(&this->Function[currentIndex], "log", 3) == 0)
1573   {
1574     vtkErrorMacro("The use of log function is being deprecated. "
1575                   "Please use log10 or ln instead");
1576     return VTK_PARSER_LOGARITHM;
1577   }
1578   if (strncmp(&this->Function[currentIndex], "sqrt", 4) == 0)
1579   {
1580     return VTK_PARSER_SQUARE_ROOT;
1581   }
1582   if (strncmp(&this->Function[currentIndex], "sin", 3) == 0)
1583   {
1584     if (strncmp(&this->Function[currentIndex], "sinh", 4) == 0)
1585     {
1586       return VTK_PARSER_HYPERBOLIC_SINE;
1587     }
1588     return VTK_PARSER_SINE;
1589   }
1590   if (strncmp(&this->Function[currentIndex], "cos", 3) == 0)
1591   {
1592     if (strncmp(&this->Function[currentIndex], "cosh", 4) == 0)
1593     {
1594       return VTK_PARSER_HYPERBOLIC_COSINE;
1595     }
1596     return VTK_PARSER_COSINE;
1597   }
1598   if (strncmp(&this->Function[currentIndex], "tan", 3) == 0)
1599   {
1600     if (strncmp(&this->Function[currentIndex], "tanh", 4) == 0)
1601     {
1602       return VTK_PARSER_HYPERBOLIC_TANGENT;
1603     }
1604     return VTK_PARSER_TANGENT;
1605   }
1606   if (strncmp(&this->Function[currentIndex], "asin", 4) == 0)
1607   {
1608     return VTK_PARSER_ARCSINE;
1609   }
1610   if (strncmp(&this->Function[currentIndex], "acos", 4) == 0)
1611   {
1612     return VTK_PARSER_ARCCOSINE;
1613   }
1614   if (strncmp(&this->Function[currentIndex], "atan", 4) == 0)
1615   {
1616     return VTK_PARSER_ARCTANGENT;
1617   }
1618   if (strncmp(&this->Function[currentIndex], "min", 3) == 0)
1619   {
1620     return VTK_PARSER_MIN;
1621   }
1622   if (strncmp(&this->Function[currentIndex], "max", 3) == 0)
1623   {
1624     return VTK_PARSER_MAX;
1625   }
1626   if (strncmp(&this->Function[currentIndex], "cross", 5) == 0)
1627   {
1628     return VTK_PARSER_CROSS;
1629   }
1630   if (strncmp(&this->Function[currentIndex], "sign", 4) == 0)
1631   {
1632     return VTK_PARSER_SIGN;
1633   }
1634   if (strncmp(&this->Function[currentIndex], "mag", 3) == 0)
1635   {
1636     return VTK_PARSER_MAGNITUDE;
1637   }
1638   if (strncmp(&this->Function[currentIndex], "norm", 4) == 0)
1639   {
1640     return VTK_PARSER_NORMALIZE;
1641   }
1642   if (strncmp(&this->Function[currentIndex], "if", 2) == 0)
1643   {
1644     return VTK_PARSER_IF;
1645   }
1646 
1647   return 0;
1648 }
1649 
1650 //-----------------------------------------------------------------------------
GetMathFunctionNumberByCheckingParenthesis(int currentIndex)1651 int vtkFunctionParser::GetMathFunctionNumberByCheckingParenthesis
1652   ( int currentIndex )
1653 {
1654   // This function assumes that RemoveSpaces() has been called and
1655   // hence involves the check on the '(' that immediately follows a
1656   // valid function. Addressing '(' here instead of in CheckSyntax()
1657   // allows for early detection of grammar errors, i.e., lack of '(',
1658   // and hence simplifies the parsing process.
1659 
1660   // For addition of any new math function, please update NUMBFUNCS
1661   // and add an entry to each of the three arrays below.
1662 
1663   const  int  NUMBFUNCS                =  24;
1664 
1665   static const int  charsLens[NUMBFUNCS]     = { 4,       4,        5,       6,
1666                                                  3,       6,        4,       5,
1667                                                  4,       5,        4,       5,
1668                                                  4,       5,        5,       5,
1669                                                  5,       4,        4,       6,
1670                                                  5,       4,        5,       3
1671                                          };
1672 
1673   static const int  funcNumbs[NUMBFUNCS]     = { VTK_PARSER_ABSOLUTE_VALUE,
1674                                                  VTK_PARSER_EXPONENT,
1675                                                  VTK_PARSER_CEILING,
1676                                                  VTK_PARSER_FLOOR,
1677 
1678                                                  VTK_PARSER_LOGARITHME,
1679                                                  VTK_PARSER_LOGARITHM10,
1680                                                  VTK_PARSER_LOGARITHM,
1681                                                  VTK_PARSER_SQUARE_ROOT,
1682 
1683                                                  VTK_PARSER_SINE,
1684                                                  VTK_PARSER_HYPERBOLIC_SINE,
1685                                                  VTK_PARSER_COSINE,
1686                                                  VTK_PARSER_HYPERBOLIC_COSINE,
1687 
1688                                                  VTK_PARSER_TANGENT,
1689                                                  VTK_PARSER_HYPERBOLIC_TANGENT,
1690                                                  VTK_PARSER_ARCSINE,
1691                                                  VTK_PARSER_ARCCOSINE,
1692 
1693                                                  VTK_PARSER_ARCTANGENT,
1694                                                  VTK_PARSER_MIN,
1695                                                  VTK_PARSER_MAX,
1696                                                  VTK_PARSER_CROSS,
1697 
1698                                                  VTK_PARSER_SIGN,
1699                                                  VTK_PARSER_MAGNITUDE,
1700                                                  VTK_PARSER_NORMALIZE,
1701                                                  VTK_PARSER_IF
1702                                          };
1703 
1704   static char funcNames[NUMBFUNCS][10] = { "abs(",  "exp(",   "ceil(", "floor(",
1705                                            "ln(",   "log10(", "log(",  "sqrt(",
1706                                            "sin(",  "sinh(",  "cos(",  "cosh(",
1707                                            "tan(",  "tanh(",  "asin(", "acos(",
1708                                            "atan(", "min(",   "max(",  "cross(",
1709                                            "sign(", "mag(",   "norm(", "if("
1710                                          };
1711 
1712   int   isMatched = 0;
1713   int   retNumber = 0;
1714   for ( int i = 0; i < NUMBFUNCS && isMatched == 0; i ++ )
1715   {
1716     isMatched = (  strncmp( this->Function + currentIndex,
1717                             funcNames[i], charsLens[i]
1718                           ) == 0
1719                 )  ?  1  :  0;
1720     retNumber = isMatched * funcNumbs[i];
1721   }
1722 
1723   return retNumber;
1724 }
1725 
1726 //-----------------------------------------------------------------------------
GetMathFunctionStringLength(int mathFunctionNumber)1727 int vtkFunctionParser::GetMathFunctionStringLength(int mathFunctionNumber)
1728 {
1729   switch (mathFunctionNumber)
1730   {
1731     case VTK_PARSER_LOGARITHME:
1732     case VTK_PARSER_IF:
1733       return 2;
1734     case VTK_PARSER_ABSOLUTE_VALUE:
1735     case VTK_PARSER_EXPONENT:
1736     case VTK_PARSER_LOGARITHM:
1737     case VTK_PARSER_SINE:
1738     case VTK_PARSER_COSINE:
1739     case VTK_PARSER_TANGENT:
1740     case VTK_PARSER_MAGNITUDE:
1741     case VTK_PARSER_MIN:
1742     case VTK_PARSER_MAX:
1743       return 3;
1744     case VTK_PARSER_CEILING:
1745     case VTK_PARSER_SQUARE_ROOT:
1746     case VTK_PARSER_ARCSINE:
1747     case VTK_PARSER_ARCCOSINE:
1748     case VTK_PARSER_ARCTANGENT:
1749     case VTK_PARSER_HYPERBOLIC_SINE:
1750     case VTK_PARSER_HYPERBOLIC_COSINE:
1751     case VTK_PARSER_HYPERBOLIC_TANGENT:
1752     case VTK_PARSER_NORMALIZE:
1753     case VTK_PARSER_SIGN:
1754       return 4;
1755     case VTK_PARSER_FLOOR:
1756     case VTK_PARSER_LOGARITHM10:
1757     case VTK_PARSER_CROSS:
1758       return 5;
1759     default:
1760       vtkWarningMacro("Unknown math function");
1761       return 0;
1762   }
1763 }
1764 
1765 //-----------------------------------------------------------------------------
GetMathConstantNumber(int currentIndex)1766 int vtkFunctionParser::GetMathConstantNumber(int currentIndex)
1767 {
1768   if (strncmp(&this->Function[currentIndex], "iHat", 4) == 0)
1769   {
1770     return VTK_PARSER_IHAT;
1771   }
1772   if (strncmp(&this->Function[currentIndex], "jHat", 4) == 0)
1773   {
1774     return VTK_PARSER_JHAT;
1775   }
1776   if (strncmp(&this->Function[currentIndex], "kHat", 4) == 0)
1777   {
1778     return VTK_PARSER_KHAT;
1779   }
1780 
1781   return 0;
1782 }
1783 
1784 //-----------------------------------------------------------------------------
GetMathConstantStringLength(int mathConstantNumber)1785 int vtkFunctionParser::GetMathConstantStringLength(int mathConstantNumber)
1786 {
1787   switch (mathConstantNumber)
1788   {
1789     case VTK_PARSER_IHAT:
1790     case VTK_PARSER_JHAT:
1791     case VTK_PARSER_KHAT:
1792       return 4;
1793     default:
1794       vtkWarningMacro("Unknown math constant");
1795       return 0;
1796   }
1797 }
1798 
1799 //-----------------------------------------------------------------------------
GetVariableNameLength(int variableNumber)1800 int vtkFunctionParser::GetVariableNameLength(int variableNumber)
1801 {
1802   if (variableNumber < this->GetNumberOfScalarVariables())
1803   {
1804     return static_cast<int>(this->ScalarVariableNames[variableNumber].size());
1805   }
1806   else
1807   {
1808     return static_cast<int>(
1809       this->VectorVariableNames[variableNumber -
1810                                this->GetNumberOfScalarVariables()].size());
1811   }
1812 }
1813 
1814 //-----------------------------------------------------------------------------
FindEndOfMathFunction(int beginIndex)1815 int vtkFunctionParser::FindEndOfMathFunction(int beginIndex)
1816 {
1817   int i = beginIndex, parenthesisCount;
1818 
1819   while (this->Function[i] != '(' )
1820   {
1821     i++;
1822   }
1823   i++;
1824   for (parenthesisCount = 1; parenthesisCount > 0; ++i)
1825   {
1826     parenthesisCount += (this->Function[i] == '(' ? 1 :
1827                          (this->Function[i] == ')' ? -1 : 0));
1828   }
1829   return i - 1;
1830 }
1831 
1832 //-----------------------------------------------------------------------------
FindEndOfMathConstant(int beginIndex)1833 int vtkFunctionParser::FindEndOfMathConstant(int beginIndex)
1834 {
1835   if(int constantNumber = this->GetMathConstantNumber(beginIndex))
1836   {
1837     return beginIndex+this->GetMathConstantStringLength(constantNumber);
1838   }
1839   return beginIndex;
1840 }
1841 
1842 //-----------------------------------------------------------------------------
GetElementaryOperatorNumber(char op)1843 unsigned char vtkFunctionParser::GetElementaryOperatorNumber(char op)
1844 {
1845   static const char* const operators = "+-*/^";
1846   int i;
1847 
1848   if (op == '<')
1849   {
1850     return VTK_PARSER_LESS_THAN;
1851   }
1852   if (op == '>')
1853   {
1854     return VTK_PARSER_GREATER_THAN;
1855   }
1856   if (op == '=')
1857   {
1858     return VTK_PARSER_EQUAL_TO;
1859   }
1860   if (op == '&')
1861   {
1862     return VTK_PARSER_AND;
1863   }
1864   if (op == '|')
1865   {
1866     return VTK_PARSER_OR;
1867   }
1868 
1869   for(i = 0; i < 5; i++)
1870   {
1871     if (operators[i] == op)
1872     {
1873       return static_cast<unsigned char>(VTK_PARSER_ADD + i);
1874     }
1875   }
1876   if (op == '.')
1877   {
1878     return VTK_PARSER_DOT_PRODUCT;
1879   }
1880 
1881   return 0;
1882 }
1883 
1884 //-----------------------------------------------------------------------------
GetOperandNumber(int currentIndex)1885 unsigned int vtkFunctionParser::GetOperandNumber(int currentIndex)
1886 {
1887   int variableIndex = -1;
1888 
1889   if (isdigit(this->Function[currentIndex]) ||
1890      this->Function[currentIndex] == '.') // Number
1891   {
1892     double *tempImmediates = new double[this->ImmediatesSize];
1893     for (int i = 0; i < this->ImmediatesSize; i++)
1894     { // Copy current immediates to a temporary array
1895       tempImmediates[i] = this->Immediates[i];
1896     }
1897     delete [] this->Immediates;
1898 
1899     // Allocate space for new immediate value.
1900     this->Immediates = new double[this->ImmediatesSize + 1];
1901 
1902     // Copy contents of temporary array back to Immediates.
1903     for (int i = 0; i < this->ImmediatesSize; i++)
1904     {
1905       this->Immediates[i] = tempImmediates[i];
1906     }
1907 
1908     this->Immediates[this->ImmediatesSize] =
1909       atof(&this->Function[currentIndex]);
1910     this->ImmediatesSize++;
1911     delete [] tempImmediates;
1912     return VTK_PARSER_IMMEDIATE;
1913   }
1914 
1915   if (!strncmp(&this->Function[currentIndex], "iHat", 4))
1916   {
1917     return VTK_PARSER_IHAT;
1918   }
1919   if (!strncmp(&this->Function[currentIndex], "jHat", 4))
1920   {
1921     return VTK_PARSER_JHAT;
1922   }
1923   if (!strncmp(&this->Function[currentIndex], "kHat", 4))
1924   {
1925     return VTK_PARSER_KHAT;
1926   }
1927 
1928 
1929   bool scalarVar = false;
1930   size_t currentLen = 0;
1931   //Bug 7396. If a scalar variable name is a subset of a vector var name it will
1932   //cause the scripting to crash. So instead of ending once we find a var name that matches in scalars
1933   //we will also check vectors
1934   for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
1935   { // Variable
1936     if (strncmp(&this->Function[currentIndex], this->ScalarVariableNames[i].c_str(),
1937                 this->ScalarVariableNames[i].size()) == 0)
1938     {
1939       if (variableIndex == -1 ||
1940           this->ScalarVariableNames[i].size() > currentLen )
1941       {
1942         currentLen = this->ScalarVariableNames[i].size();
1943         variableIndex = i;
1944       }
1945     }
1946   }
1947   if (variableIndex >= 0)
1948   {
1949     scalarVar = true;
1950   }
1951 
1952   for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
1953   { // Variable
1954     if (strncmp(&this->Function[currentIndex], this->VectorVariableNames[i].c_str(),
1955                 this->VectorVariableNames[i].size()) == 0)
1956     {
1957       if (variableIndex == -1
1958         || this->VectorVariableNames[i].size() > currentLen )
1959       {
1960         scalarVar = false;
1961         currentLen = this->VectorVariableNames[i].size();
1962         variableIndex = i;
1963       }
1964     }
1965   }
1966   if (variableIndex >= 0)
1967   {
1968     //add the offset if vector
1969     variableIndex = scalarVar? variableIndex : (this->GetNumberOfScalarVariables() + variableIndex);
1970     return static_cast<unsigned int>(
1971       VTK_PARSER_BEGIN_VARIABLES + variableIndex);
1972   }
1973 
1974   return 0;
1975 }
1976 
1977 //-----------------------------------------------------------------------------
RemoveScalarVariables()1978 void vtkFunctionParser::RemoveScalarVariables()
1979 {
1980   this->ScalarVariableNames.clear();
1981   this->ScalarVariableValues.clear();
1982 }
1983 
1984 //-----------------------------------------------------------------------------
RemoveVectorVariables()1985 void vtkFunctionParser::RemoveVectorVariables()
1986 {
1987   this->VectorVariableNames.clear();
1988   this->VectorVariableValues.clear();
1989 }
1990 
1991 //-----------------------------------------------------------------------------
CheckExpression(int & pos,char ** error)1992 void vtkFunctionParser::CheckExpression(int &pos, char **error)
1993 {
1994   if(this->FunctionMTime.GetMTime() > this->CheckMTime.GetMTime())
1995   {
1996     // Need to parse again.
1997 
1998     // Reset previous error cache.
1999     this->ParseErrorPositon = -1;
2000     this->SetParseError(nullptr);
2001 
2002     this->CopyParseError(pos, error);
2003   }
2004   else
2005   {
2006     this->CopyParseError(pos, error);
2007     return;
2008   }
2009 
2010   this->CheckMTime.Modified();
2011 
2012   this->RemoveSpaces();
2013 
2014   int index = 0, parenthesisCount = 0, currentChar;
2015   char* ptr;
2016   int functionNumber, constantNumber;
2017   int *expectCommaOnParenthesisCount = new int[this->FunctionLength];
2018   int *expectTwoCommasOnParenthesisCount = new int[this->FunctionLength];
2019   int i;
2020 
2021   for (i = 0; i < this->FunctionLength; i++)
2022   {
2023     expectCommaOnParenthesisCount[i] = 0;
2024     expectTwoCommasOnParenthesisCount[i] = 0;
2025   }
2026 
2027   while (1)
2028   {
2029     currentChar = this->Function[index];
2030     bool breakToOuterLoop = false;
2031 
2032     // Check for valid operand (must appear)
2033 
2034     // Check for leading -
2035     if (currentChar == '-')
2036     {
2037       currentChar = this->Function[++index];
2038       if(index == this->FunctionLength)
2039       {
2040         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2041         this->SetParseError("Syntax error: unary minus with no operand");
2042         this->CopyParseError(pos, error);
2043         delete [] expectCommaOnParenthesisCount;
2044         delete [] expectTwoCommasOnParenthesisCount;
2045         return;
2046       }
2047     }
2048 
2049     // Check for leading +
2050     if (currentChar == '+')
2051     {
2052       currentChar = this->Function[++index];
2053       if(index == this->FunctionLength)
2054       {
2055         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2056         this->SetParseError("Syntax error: unary plus with no operand");
2057         this->CopyParseError(pos, error);
2058         delete [] expectCommaOnParenthesisCount;
2059         delete [] expectTwoCommasOnParenthesisCount;
2060         return;
2061       }
2062     }
2063 
2064     // Check for math function
2065     if ((functionNumber = this->GetMathFunctionNumberByCheckingParenthesis(index)))
2066     {
2067       if ((functionNumber == VTK_PARSER_MIN) ||
2068           (functionNumber == VTK_PARSER_MAX) ||
2069           (functionNumber == VTK_PARSER_CROSS))
2070       {
2071         expectCommaOnParenthesisCount[parenthesisCount+1] = 1;
2072       }
2073       if (functionNumber == VTK_PARSER_IF)
2074       {
2075         expectTwoCommasOnParenthesisCount[parenthesisCount+1] = 1;
2076       }
2077       index += this->GetMathFunctionStringLength(functionNumber);
2078       currentChar = this->Function[index];
2079 
2080       // == currentChar should always be '(' here == a fix to Bug #9208
2081       // since GetMathFunctionNumberByCheckingParenthesis() is employed above
2082 
2083       //if ( currentChar != '(' )
2084       //  {
2085       //  vtkErrorMacro("Syntax error: input to math function not in "
2086       //                << "parentheses; see position " << index);
2087       //  delete [] expectCommaOnParenthesisCount;
2088       //  delete [] expectTwoCommasOnParenthesisCount;
2089       //  return 0;
2090       //  }
2091     }
2092 
2093     // Check for opening parenthesis
2094     if( currentChar == '(' )
2095     {
2096       parenthesisCount++;
2097       index++;
2098       continue;
2099     }
2100 
2101     // Check for number
2102     if(isdigit(currentChar) ||
2103        (currentChar == '.' && isdigit(this->Function[index+1])))
2104     {
2105       double value=strtod(&this->Function[index], &ptr);
2106       // ignore the return value, we just try to figure out
2107       // the position of the pointer after the double value.
2108       static_cast<void>(value);
2109       index += int(ptr-&this->Function[index]);
2110       currentChar = this->Function[index];
2111     }
2112     // Check for named constant
2113     else if ((constantNumber = this->GetMathConstantNumber(index)))
2114     {
2115       index += this->GetMathConstantStringLength(constantNumber);
2116       currentChar = this->Function[index];
2117     }
2118     // End parenthesis should indicate that the next character might be a
2119     // comma. This is a hack because the while (currentChar == ') below checks
2120     // for an incorrect number of commas.
2121     else if (currentChar == ')' && this->Function[index - 1] != '(')
2122     {
2123       ++index;
2124       currentChar = this->Function[index];
2125     }
2126     else
2127     { // Check for variable
2128       if (!this->IsVariableName(index))
2129       {
2130         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2131         this->SetParseError("Syntax error: expecting a variable name");
2132         this->CopyParseError(pos, error);
2133         delete [] expectCommaOnParenthesisCount;
2134         delete [] expectTwoCommasOnParenthesisCount;
2135         return;
2136       }
2137       index += this->GetVariableNameLength(this->GetOperandNumber(index) -
2138                                            VTK_PARSER_BEGIN_VARIABLES);
2139       currentChar = this->Function[index];
2140     }
2141 
2142     // Check for possible second number from min or max function
2143     if (expectCommaOnParenthesisCount[parenthesisCount] > 0)
2144     {
2145       // Check for comma
2146       if (currentChar == ',')
2147       {
2148         expectCommaOnParenthesisCount[parenthesisCount] += 1;
2149         index++;
2150         continue;
2151       }
2152     }
2153 
2154     // Check for possible second or third number from if function
2155     if (expectTwoCommasOnParenthesisCount[parenthesisCount] > 0)
2156     {
2157       // Check for comma
2158       if (currentChar == ',')
2159       {
2160         expectTwoCommasOnParenthesisCount[parenthesisCount] += 1;
2161         index++;
2162         continue;
2163       }
2164     }
2165 
2166     // Check for closing parenthesis
2167     while ( currentChar == ')' )
2168     {
2169       if (expectCommaOnParenthesisCount[parenthesisCount] != 0 &&
2170             expectCommaOnParenthesisCount[parenthesisCount] != 2)
2171       {
2172         // We can't be closing this function if
2173         // expectCommaOnParenthesisCount[..] is not 2; either it was always
2174         // 0 or it should have been incremented to 2.
2175         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2176         this->SetParseError("Syntax Error: two parameters separated by commas expected");
2177         this->CopyParseError(pos, error);
2178         delete [] expectCommaOnParenthesisCount;
2179         delete [] expectTwoCommasOnParenthesisCount;
2180         return;
2181       }
2182       if (expectTwoCommasOnParenthesisCount[parenthesisCount] != 0 &&
2183           expectTwoCommasOnParenthesisCount[parenthesisCount] != 3)
2184       {
2185         // We can't be closing this function if
2186         // expectCommaOnParenthesisCount[..] is not 3; either it was always
2187         // 0 or it should have been incremented to 3.
2188         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2189         this->SetParseError("Syntax Error: three parameters separated by commas expected");
2190         this->CopyParseError(pos, error);
2191         delete [] expectCommaOnParenthesisCount;
2192         delete [] expectTwoCommasOnParenthesisCount;
2193         return;
2194       }
2195       parenthesisCount--;
2196       if(parenthesisCount < 0)
2197       {
2198         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2199         this->SetParseError("Syntax Error: mismatched parenthesis");
2200         this->CopyParseError(pos, error);
2201         delete [] expectCommaOnParenthesisCount;
2202         delete [] expectTwoCommasOnParenthesisCount;
2203         return;
2204       }
2205       if( this->Function[index - 1] == '(' )
2206       {
2207         this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2208         this->SetParseError("Syntax Error: empty parentheses");
2209         this->CopyParseError(pos, error);
2210         delete [] expectCommaOnParenthesisCount;
2211         delete [] expectTwoCommasOnParenthesisCount;
2212         return;
2213       }
2214 
2215       // Check for possible argument in a multiple argument function. In this
2216       // case the next character might be a comma, so break out to the outer
2217       // loop before incrementing index.
2218       if ((expectCommaOnParenthesisCount[parenthesisCount] > 0 &&
2219            expectCommaOnParenthesisCount[parenthesisCount] < 2) ||
2220           (expectTwoCommasOnParenthesisCount[parenthesisCount] > 0 &&
2221            expectTwoCommasOnParenthesisCount[parenthesisCount] < 3))
2222       {
2223         breakToOuterLoop = true;
2224         break;
2225       }
2226 
2227       currentChar = this->Function[++index];
2228     } // while ( currentChar == ')' )
2229 
2230     // If necessary, break out to the outer loop.
2231     if (breakToOuterLoop == true)
2232     {
2233       continue;
2234     }
2235 
2236     // If we get here, we have a legal operand and now a legal operator or
2237     // end of string must follow.
2238 
2239     // Check for EOS
2240     // The only way to end the checking loop without error.
2241     if (index == this->FunctionLength)
2242     {
2243       break;
2244     }
2245 
2246     // Check for operator
2247     if(!this->IsElementaryOperator(currentChar) &&
2248        currentChar != '<' &&
2249        currentChar != '>' &&
2250        currentChar != '=' &&
2251        currentChar != '&' &&
2252        currentChar != '|' &&
2253        currentChar != ',')
2254     {
2255       this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2256       this->SetParseError("Syntax error: operator expected");
2257       this->CopyParseError(pos, error);
2258       delete [] expectCommaOnParenthesisCount;
2259       delete [] expectTwoCommasOnParenthesisCount;
2260       return;
2261     }
2262 
2263     if (currentChar != ',')
2264     {
2265       // If we get here, we have an operand and an operator; the next loop will
2266       // check for another operand (must appear)
2267       index++;
2268     }
2269   } // while(1)
2270 
2271   // Check that all opened parentheses are also closed
2272   if(parenthesisCount > 0)
2273   {
2274     this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
2275     this->SetParseError("Syntax Error: missing closing parenthesis");
2276     this->CopyParseError(pos, error);
2277     delete [] expectCommaOnParenthesisCount;
2278     delete [] expectTwoCommasOnParenthesisCount;
2279     return;
2280   }
2281 
2282 
2283   // The string is ok
2284   delete [] expectCommaOnParenthesisCount;
2285   delete [] expectTwoCommasOnParenthesisCount;
2286 }
2287 
2288 //-----------------------------------------------------------------------------
RemoveAllVariables()2289 void vtkFunctionParser::RemoveAllVariables()
2290 {
2291   this->RemoveScalarVariables();
2292   this->RemoveVectorVariables();
2293 }
2294 
2295 //-----------------------------------------------------------------------------
GetMTime()2296 vtkMTimeType vtkFunctionParser::GetMTime()
2297 {
2298   vtkMTimeType mTime = this->Superclass::GetMTime();
2299 
2300   if (this->EvaluateMTime > mTime)
2301   {
2302     mTime = this->EvaluateMTime;
2303   }
2304   if (this->VariableMTime > mTime)
2305   {
2306     mTime = this->VariableMTime;
2307   }
2308   if (this->ParseMTime > mTime)
2309   {
2310     mTime = this->ParseMTime;
2311   }
2312   if (this->FunctionMTime > mTime)
2313   {
2314     mTime = this->FunctionMTime;
2315   }
2316   if (this->CheckMTime > mTime)
2317   {
2318     mTime = this->CheckMTime;
2319   }
2320 
2321   return mTime;
2322 }
2323 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)2324 void vtkFunctionParser::PrintSelf(ostream& os, vtkIndent indent)
2325 {
2326   this->Superclass::PrintSelf(os,indent);
2327 
2328 
2329   os << indent << "Function: "
2330      << (this->GetFunction() ? this->GetFunction() : "(none)") << endl;
2331 
2332   os << indent << "FunctionWithSpaces: "
2333      << (this->FunctionWithSpaces ? this->FunctionWithSpaces : "(none)") << endl;
2334 
2335   for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
2336   {
2337     os << indent << "  " << this->GetScalarVariableName(i) << ": "
2338        << this->GetScalarVariableValue(i) << endl;
2339   }
2340 
2341   for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
2342   {
2343     os << indent << "  " << this->GetVectorVariableName(i) << ": ("
2344        << this->GetVectorVariableValue(i)[0] << ", "
2345        << this->GetVectorVariableValue(i)[1] << ", "
2346        << this->GetVectorVariableValue(i)[2] << ")" << endl;
2347   }
2348 
2349   if (this->EvaluateMTime.GetMTime() > this->FunctionMTime.GetMTime() &&
2350       this->EvaluateMTime.GetMTime() > this->VariableMTime.GetMTime() &&
2351       (this->StackPointer == 0 || this->StackPointer == 2))
2352   {
2353     if (this->StackPointer == 0)
2354     {
2355       os << indent << "ScalarResult: " << this->GetScalarResult() << endl;
2356       os << indent << "VectorResult: " << "(none)" << endl;
2357     }
2358     else if (this->StackPointer == 2)
2359     {
2360       os << indent << "ScalarResult: " << "(none)" << endl;
2361       os << indent << "VectorResult: " << "("
2362        << this->GetVectorResult()[0] << ", "
2363        << this->GetVectorResult()[1] << ", "
2364        << this->GetVectorResult()[2] << ")" << endl;
2365     }
2366   }
2367   else
2368   {
2369     os << indent << "ScalarResult: " << "(none)" << endl;
2370     os << indent << "VectorResult: " << "(none)" << endl;
2371   }
2372 
2373   os << indent << "Replace Invalid Values: "
2374      << (this->GetReplaceInvalidValues() ? "On" : "Off") << endl;
2375   os << indent << "Replacement Value: " << this->GetReplacementValue() << endl;
2376 
2377   os << indent << "Parse Error Position: " << this->ParseErrorPositon << endl;
2378 
2379   os << indent << "Parse Error: " << (this->ParseError ? this->ParseError : "nullptr")
2380     << endl;
2381 }
2382 
2383 //-----------------------------------------------------------------------------
FindPositionInOriginalFunction(const int & pos)2384 int vtkFunctionParser::FindPositionInOriginalFunction(const int &pos)
2385 {
2386   // Copy the value.
2387   int origPos = pos;
2388 
2389   if(this->Function && this->FunctionWithSpaces)
2390   {
2391     size_t withSpacesLen    = strlen(this->FunctionWithSpaces);
2392     size_t withoutSpacesLen = strlen(this->Function);
2393 
2394     int counter = 0;
2395     for(size_t i=0; i < withSpacesLen; ++i)
2396     {
2397       // If we have covered all the characters excluding the spaces.
2398       if(counter == static_cast<int>(withoutSpacesLen) || counter == pos)
2399       {
2400         return origPos;
2401       }
2402 
2403       char currentChar = this->FunctionWithSpaces[i];
2404       if(currentChar == ' ')
2405       {
2406         // Every time we hit a whitespace increment the origPos
2407         // as the pos is counted without spaces.
2408         ++origPos;
2409         continue;
2410       }
2411 
2412       // This needs to be incremented for all the characters except
2413       // spaces.
2414       ++counter;
2415     }
2416   }
2417 
2418   return origPos;
2419 }
2420 
2421 //-----------------------------------------------------------------------------
UpdateNeededVariables()2422 void vtkFunctionParser::UpdateNeededVariables()
2423 {
2424   this->ScalarVariableNeeded.clear();
2425   this->ScalarVariableNeeded.resize(this->ScalarVariableNames.size(), false);
2426 
2427   this->VectorVariableNeeded.clear();
2428   this->VectorVariableNeeded.resize(this->VectorVariableNames.size(), false);
2429 
2430   unsigned char numscalars = static_cast<unsigned char>(this->GetNumberOfScalarVariables());
2431 
2432   for (int cc=0; cc < this->ByteCodeSize; ++cc)
2433   {
2434     unsigned char code = this->ByteCode[cc];
2435     if (code < VTK_PARSER_BEGIN_VARIABLES)
2436     {
2437       continue;
2438     }
2439     code -= VTK_PARSER_BEGIN_VARIABLES;
2440     if (code >= numscalars)
2441     {
2442       this->VectorVariableNeeded[code - numscalars] = true;
2443     }
2444     else
2445     {
2446       this->ScalarVariableNeeded[code] = true;
2447     }
2448   }
2449 }
2450 
2451 //-----------------------------------------------------------------------------
GetScalarVariableIndex(const char * inVariableName)2452 int vtkFunctionParser::GetScalarVariableIndex(const char* inVariableName)
2453 {
2454   char* variableName = this->RemoveSpacesFrom(inVariableName);
2455   for (int i = 0; i < static_cast<int>(this->ScalarVariableNames.size()); ++i)
2456   {
2457     if (this->ScalarVariableNames[i] == variableName)
2458     {
2459       delete [] variableName;
2460       return i;
2461     }
2462   }
2463   delete [] variableName;
2464   return -1;
2465 }
2466 
2467 //-----------------------------------------------------------------------------
GetScalarVariableNeeded(int i)2468 bool vtkFunctionParser::GetScalarVariableNeeded(int i)
2469 {
2470   if (i < 0 || i >= static_cast<int>(this->ScalarVariableNeeded.size()))
2471   {
2472     return false;
2473   }
2474   return this->ScalarVariableNeeded[i];
2475 }
2476 
2477 //-----------------------------------------------------------------------------
GetScalarVariableNeeded(const char * inVariableName)2478 bool vtkFunctionParser::GetScalarVariableNeeded(const char* inVariableName)
2479 {
2480   char* variableName = this->RemoveSpacesFrom(inVariableName);
2481   std::vector<std::string>::const_iterator iter = std::find(
2482     this->ScalarVariableNames.begin(), this->ScalarVariableNames.end(),
2483     std::string(variableName));
2484   if (iter != this->ScalarVariableNames.end())
2485   {
2486     delete [] variableName;
2487     return this->GetScalarVariableNeeded(
2488       static_cast<int>(iter - this->ScalarVariableNames.begin()));
2489   }
2490   else
2491   {
2492     vtkErrorMacro("GetScalarVariableNeeded: scalar variable name " << variableName
2493                    << " does not exist");
2494     delete [] variableName;
2495     return false;
2496   }
2497 }
2498 
2499 //-----------------------------------------------------------------------------
GetVectorVariableIndex(const char * inVariableName)2500 int vtkFunctionParser::GetVectorVariableIndex(const char* inVariableName)
2501 {
2502   char* variableName = this->RemoveSpacesFrom(inVariableName);
2503   for (int i = 0; i < static_cast<int>(this->VectorVariableNames.size()); ++i)
2504   {
2505     if (this->VectorVariableNames[i] == variableName)
2506     {
2507       delete [] variableName;
2508       return i;
2509     }
2510   }
2511   delete [] variableName;
2512   return -1;
2513 }
2514 
2515 //-----------------------------------------------------------------------------
GetVectorVariableNeeded(int i)2516 bool vtkFunctionParser::GetVectorVariableNeeded(int i)
2517 {
2518   if (i < 0 || i >= static_cast<int>(this->VectorVariableNeeded.size()))
2519   {
2520     return false;
2521   }
2522   return this->VectorVariableNeeded[i];
2523 }
2524 
2525 //-----------------------------------------------------------------------------
GetVectorVariableNeeded(const char * inVariableName)2526 bool vtkFunctionParser::GetVectorVariableNeeded(const char* inVariableName)
2527 {
2528   char* variableName = this->RemoveSpacesFrom(inVariableName);
2529   std::vector<std::string>::const_iterator iter = std::find(
2530     this->VectorVariableNames.begin(), this->VectorVariableNames.end(),
2531     std::string(variableName));
2532   delete [] variableName;
2533   if (iter != this->VectorVariableNames.end())
2534   {
2535     return this->GetVectorVariableNeeded(
2536       static_cast<int>(iter - this->VectorVariableNames.begin()));
2537   }
2538   else
2539   {
2540     vtkErrorMacro("GetVectorVariableNeeded: scalar variable name " << variableName
2541                    << " does not exist");
2542     return false;
2543   }
2544 }
2545