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