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