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