]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Boolean.c
Fix the wrong usage of UnicodeValueToString function
[mirror_edk2.git] / EdkModulePkg / Universal / UserInterface / SetupBrowser / Dxe / Boolean.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Boolean.c\r
15\r
16Abstract:\r
17\r
18 This routine will evaluate the IFR inconsistency data to determine if\r
19 something is a valid entry for a particular expression\r
20\r
21--*/\r
22\r
23#include "Setup.h"\r
24#include "Ui.h"\r
25\r
26//\r
27// Global stack used to evaluate boolean expresions\r
28//\r
29BOOLEAN *mBooleanEvaluationStack = (BOOLEAN) 0;\r
30BOOLEAN *mBooleanEvaluationStackEnd = (BOOLEAN) 0;\r
31\r
32STATIC\r
33VOID\r
34GrowBooleanStack (\r
35 IN OUT BOOLEAN **Stack,\r
36 IN UINTN StackSizeInBoolean\r
37 )\r
38/*++\r
39\r
40Routine Description:\r
41\r
42 Grow size of the boolean stack\r
43\r
44Arguments:\r
45\r
46 Stack - Old stack on the way in and new stack on the way out\r
47\r
48 StackSizeInBoolean - New size of the stack\r
49\r
50Returns:\r
51\r
52 NONE \r
53\r
54--*/\r
55{\r
56 BOOLEAN *NewStack;\r
57\r
58 NewStack = AllocatePool (StackSizeInBoolean * sizeof (BOOLEAN));\r
59 ASSERT (NewStack != NULL);\r
60\r
61 if (*Stack != NULL) {\r
62 //\r
63 // Copy to Old Stack to the New Stack\r
64 //\r
65 CopyMem (\r
66 NewStack,\r
67 mBooleanEvaluationStack,\r
68 (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN)\r
69 );\r
70\r
71 //\r
72 // Make the Stack pointer point to the old data in the new stack\r
73 //\r
74 *Stack = NewStack + (*Stack - mBooleanEvaluationStack);\r
75\r
76 //\r
77 // Free The Old Stack\r
78 //\r
79 gBS->FreePool (mBooleanEvaluationStack);\r
80 }\r
81\r
82 mBooleanEvaluationStack = NewStack;\r
83 mBooleanEvaluationStackEnd = NewStack + StackSizeInBoolean;\r
84}\r
85\r
86VOID\r
87InitializeBooleanEvaluator (\r
88 VOID\r
89 )\r
90/*++\r
91\r
92Routine Description:\r
93\r
94 Allocate a global stack for boolean processing.\r
95\r
96Arguments:\r
97\r
98 NONE \r
99\r
100Returns:\r
101\r
102 NONE \r
103\r
104--*/\r
105{\r
106 BOOLEAN *NullStack;\r
107\r
108 NullStack = NULL;\r
109 GrowBooleanStack (&NullStack, 0x1000);\r
110}\r
111\r
112STATIC\r
113VOID\r
114PushBool (\r
115 IN OUT BOOLEAN **Stack,\r
116 IN BOOLEAN BoolResult\r
117 )\r
118/*++\r
119\r
120Routine Description:\r
121\r
122 Push an element onto the Boolean Stack\r
123\r
124Arguments:\r
125\r
126 Stack - Current stack location.\r
127 BoolResult - BOOLEAN to push.\r
128\r
129Returns:\r
130\r
131 None.\r
132\r
133--*/\r
134{\r
135 CopyMem (*Stack, &BoolResult, sizeof (BOOLEAN));\r
136 *Stack += 1;\r
137\r
138 if (*Stack >= mBooleanEvaluationStackEnd) {\r
139 //\r
140 // If we run out of stack space make a new one that is 2X as big. Copy\r
141 // the old data into the new stack and update Stack to point to the old\r
142 // data in the new stack.\r
143 //\r
144 GrowBooleanStack (\r
145 Stack,\r
146 (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN) * 2\r
147 );\r
148 }\r
149}\r
150\r
151STATIC\r
152BOOLEAN\r
153PopBool (\r
154 IN OUT BOOLEAN **Stack\r
155 )\r
156/*++\r
157\r
158Routine Description:\r
159\r
160 Pop an element from the Boolean stack.\r
161\r
162Arguments:\r
163\r
164 Stack - Current stack location\r
165\r
166Returns:\r
167\r
168 Top of the BOOLEAN stack.\r
169\r
170--*/\r
171{\r
172 BOOLEAN ReturnValue;\r
173\r
174 *Stack -= 1;\r
175 CopyMem (&ReturnValue, *Stack, sizeof (BOOLEAN));\r
176 return ReturnValue;\r
177}\r
178\r
179EFI_STATUS\r
180GrowBooleanExpression (\r
181 IN EFI_INCONSISTENCY_DATA *InconsistentTags,\r
182 OUT VOID **BooleanExpression,\r
183 IN OUT UINTN *BooleanExpressionLength\r
184 )\r
185{\r
186 UINT8 *NewExpression;\r
187\r
188 NewExpression = AllocatePool (*BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA));\r
189 ASSERT (NewExpression != NULL);\r
190\r
191 if (*BooleanExpression != NULL) {\r
192 //\r
193 // Copy Old buffer to the New buffer\r
194 //\r
195 CopyMem (NewExpression, *BooleanExpression, *BooleanExpressionLength);\r
196\r
197 CopyMem (&NewExpression[*BooleanExpressionLength], InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));\r
198\r
199 //\r
200 // Free The Old buffer\r
201 //\r
202 gBS->FreePool (*BooleanExpression);\r
203 } else {\r
204 //\r
205 // Copy data into new buffer\r
206 //\r
207 CopyMem (NewExpression, InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));\r
208 }\r
209\r
210 *BooleanExpressionLength = *BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA);\r
211 *BooleanExpression = (VOID *) NewExpression;\r
212 return EFI_SUCCESS;\r
213}\r
214\r
215VOID\r
216CreateBooleanExpression (\r
217 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
218 IN UINT16 Value,\r
219 IN UINT16 Id,\r
220 IN BOOLEAN Complex,\r
221 OUT VOID **BooleanExpression,\r
222 OUT UINTN *BooleanExpressionLength\r
223 )\r
224/*++\r
225\r
226Routine Description:\r
227\r
228Arguments:\r
229\r
230Returns:\r
231\r
232--*/\r
233{\r
234 UINTN Count;\r
235 EFI_INCONSISTENCY_DATA *InconsistentTags;\r
236 EFI_INCONSISTENCY_DATA FakeInconsistentTags;\r
237\r
238 InconsistentTags = FileFormTags->InconsistentTags;\r
239\r
240 //\r
241 // Did we run into a question that contains the Id we are looking for?\r
242 //\r
243 for (Count = 0; InconsistentTags->Operand != 0xFF; Count++) {\r
244\r
245 //\r
246 // Reserve INVALID_OFFSET_VALUE - 1 for TURE and FALSE, because we need to treat them as well\r
247 // as ideqid etc. but they have no coresponding id, so we reserve this value.\r
248 //\r
249 if (InconsistentTags->QuestionId1 == Id ||\r
250 InconsistentTags->QuestionId1 == INVALID_OFFSET_VALUE - 1) {\r
251 //\r
252 // If !Complex - means evaluate a single if/endif expression\r
253 //\r
254 if (!Complex) {\r
255 //\r
256 // If the ConsistencyId does not match the expression we are looking for\r
257 // skip to the next consistency database entry\r
258 //\r
259 if (InconsistentTags->ConsistencyId != Value) {\r
260 goto NextEntry;\r
261 }\r
262 }\r
263 //\r
264 // We need to rewind to the beginning of the Inconsistent expression\r
265 //\r
266 for (;\r
267 (InconsistentTags->Operand != EFI_IFR_INCONSISTENT_IF_OP) &&\r
268 (InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP) &&\r
269 (InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP);\r
270 ) {\r
271 InconsistentTags = InconsistentTags->Previous;\r
272 }\r
273 //\r
274 // Store the consistency check expression, ensure the next for loop starts at the op-code afterwards\r
275 //\r
276 GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);\r
277 InconsistentTags = InconsistentTags->Next;\r
278\r
279 //\r
280 // Keep growing until we hit the End expression op-code or we hit the beginning of another\r
281 // consistency check like grayout/suppress\r
282 //\r
283 for (;\r
284 InconsistentTags->Operand != EFI_IFR_END_IF_OP &&\r
285 InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP &&\r
286 InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP;\r
287 ) {\r
288 GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);\r
289 InconsistentTags = InconsistentTags->Next;\r
290 }\r
291 //\r
292 // Store the EndExpression Op-code\r
293 //\r
294 GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);\r
295 }\r
296\r
297NextEntry:\r
298 if (InconsistentTags->Next != NULL) {\r
299 //\r
300 // Skip to next entry\r
301 //\r
302 InconsistentTags = InconsistentTags->Next;\r
303 }\r
304 }\r
305\r
306 FakeInconsistentTags.Operand = 0;\r
307\r
308 //\r
309 // Add one last expression which will signify we have definitely hit the end\r
310 //\r
311 GrowBooleanExpression (&FakeInconsistentTags, BooleanExpression, BooleanExpressionLength);\r
312}\r
313\r
314EFI_STATUS\r
315BooleanVariableWorker (\r
316 IN CHAR16 *VariableName,\r
317 IN EFI_VARIABLE_DEFINITION *VariableDefinition,\r
318 IN BOOLEAN *StackPtr,\r
319 IN OUT UINTN *SizeOfVariable,\r
320 IN OUT VOID **VariableData\r
321 )\r
322/*++\r
323\r
324Routine Description:\r
325\r
326\r
327Arguments:\r
328\r
329Returns:\r
330\r
331--*/\r
332{\r
333 EFI_STATUS Status;\r
334\r
335 Status = gRT->GetVariable (\r
336 VariableName,\r
337 &VariableDefinition->Guid,\r
338 NULL,\r
339 SizeOfVariable,\r
340 *VariableData\r
341 );\r
342\r
343 if (EFI_ERROR (Status)) {\r
344\r
345 if (Status == EFI_BUFFER_TOO_SMALL) {\r
346 *VariableData = AllocatePool (*SizeOfVariable);\r
347 ASSERT (*VariableData != NULL);\r
348\r
349 Status = gRT->GetVariable (\r
350 VariableName,\r
351 &VariableDefinition->Guid,\r
352 NULL,\r
353 SizeOfVariable,\r
354 *VariableData\r
355 );\r
356 }\r
357\r
358 if (Status == EFI_NOT_FOUND) {\r
359 //\r
360 // This is a serious flaw, we must have some standard result if a variable\r
361 // is not found. Our default behavior must either be return a TRUE or FALSE\r
362 // since there is nothing else we can really do. Therefore, my crystal ball\r
363 // says I will return a FALSE\r
364 //\r
365 PushBool (&StackPtr, FALSE);\r
366 }\r
367 }\r
368\r
369 return Status;\r
370}\r
371\r
372UINT8\r
373PredicateIfrType (\r
374 IN EFI_INCONSISTENCY_DATA *Iterator\r
375 )\r
376/*++\r
377\r
378Routine Description:\r
379 This routine is for the purpose of predicate whether the Ifr is generated by a VfrCompiler greater than or equal to 1.88 or\r
380 less than 1.88 which is legacy.\r
381\r
382Arguments:\r
383 Iterator - The pointer to inconsistency tags\r
384\r
385Returns:\r
386\r
387 0x2 - If IFR is not legacy\r
388\r
389 0x1 - If IFR is legacy\r
390\r
391--*/\r
392{\r
393 //\r
394 // legacy Ifr cover the states:\r
395 // Not ...\r
396 // Operand Opcode Operand\r
397 //\r
398 // while Operand means ideqval, TRUE, or other what can be evaluated to True or False,\r
399 // and Opcode means AND or OR.\r
400 //\r
401 if (Iterator->Operand == EFI_IFR_NOT_OP ||\r
402 Iterator->Operand == 0) {\r
403 return 0x1;\r
404 } else if (Iterator->Operand == EFI_IFR_EQ_VAR_VAL_OP ||\r
405 Iterator->Operand == EFI_IFR_EQ_ID_VAL_OP ||\r
406 Iterator->Operand == EFI_IFR_EQ_ID_ID_OP ||\r
407 Iterator->Operand == EFI_IFR_EQ_ID_LIST_OP) {\r
408 Iterator++;\r
409 if (Iterator->Operand == EFI_IFR_AND_OP ||\r
410 Iterator->Operand == EFI_IFR_OR_OP) {\r
411 Iterator--;\r
412 return 0x1;\r
413 }\r
414 Iterator--;\r
415 }\r
416 return 0x2;\r
417}\r
418\r
419VOID\r
420PostOrderEvaluate (\r
421 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
422 IN UINT16 Width,\r
423 IN OUT EFI_INCONSISTENCY_DATA **PIterator,\r
424 IN OUT BOOLEAN **StackPtr\r
425 )\r
426/*++\r
427\r
428Routine Description:\r
429 PostOrderEvaluate is used for Ifr generated by VfrCompiler greater than or equal to 1.88,\r
430 which generate Operand Operand Opcode type Ifr.\r
431 PostOrderEvaluete only evaluate boolean expression part, not suppressif/grayoutif. TRUE,\r
432 FALSE, >=, >, (, ) are supported.\r
433\r
434Arguments:\r
435\r
436 FileFormTags - The pointer to the tags of the form\r
437\r
438 Width - Width of Operand, recognized every iteration\r
439\r
440 PIterator - The pointer to inconsistency tags\r
441\r
442 StackPtr - The pointer to the evaluation stack\r
443\r
444Returns:\r
445\r
446 TRUE - If value is valid\r
447\r
448 FALSE - If value is not valid\r
449\r
450--*/\r
451{\r
452 BOOLEAN Operator;\r
453 BOOLEAN Operator2;\r
454 UINT16 *MapBuffer;\r
455 UINT16 *MapBuffer2;\r
456 UINT16 MapValue;\r
457 UINT16 MapValue2;\r
458 UINTN SizeOfVariable;\r
273bbd31 459 CHAR16 VariableName[MAXIMUM_VALUE_CHARACTERS];\r
878ddf1f 460 VOID *VariableData;\r
461 EFI_VARIABLE_DEFINITION *VariableDefinition;\r
462 EFI_STATUS Status;\r
463 UINTN Index;\r
464 BOOLEAN PushValue;\r
465\r
466 Operator = FALSE;\r
467 Operator2 = FALSE;\r
468 MapBuffer = NULL;\r
469 MapBuffer2 = NULL;\r
470 MapValue = 0;\r
471 MapValue2 = 0;\r
472 VariableData = NULL;\r
473\r
474 while (TRUE) {\r
475 if ((*PIterator)->Operand == 0) {\r
476 return;\r
477 }\r
478\r
479 Width = (*PIterator)->Width;\r
480\r
481 // \r
482 // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.\r
483 //\r
484 if ((*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE &&\r
485 (*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE - 1) {\r
486 ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber, Width, (*PIterator)->QuestionId1, (VOID **) &MapBuffer);\r
487 ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber2, Width, (*PIterator)->QuestionId2, (VOID **) &MapBuffer2);\r
488 if (MapBuffer != NULL) {\r
489 if (Width == 2) {\r
490 MapValue = *MapBuffer;\r
491 } else {\r
492 MapValue = (UINT8) *MapBuffer;\r
493 }\r
494\r
495 gBS->FreePool (MapBuffer);\r
496 }\r
497\r
498 if (MapBuffer2 != NULL) {\r
499 if (Width == 2) {\r
500 MapValue2 = *MapBuffer2;\r
501 } else {\r
502 MapValue2 = (UINT8) *MapBuffer2;\r
503 }\r
504\r
505 gBS->FreePool (MapBuffer2);\r
506 }\r
507 }\r
508\r
509 switch ((*PIterator)->Operand) {\r
510 case EFI_IFR_EQ_VAR_VAL_OP:\r
511 UnicodeValueToString (\r
512 VariableName, \r
513 FALSE, \r
514 (UINTN) (*PIterator)->QuestionId1, \r
273bbd31 515 (sizeof (VariableName) / sizeof (VariableName[0])) - 1\r
878ddf1f 516 );\r
517\r
518 SizeOfVariable = 0;\r
519\r
520 ExtractRequestedNvMap (FileFormTags, (*PIterator)->VariableNumber, &VariableDefinition);\r
521\r
522 Status = BooleanVariableWorker (\r
523 VariableName,\r
524 VariableDefinition,\r
525 *StackPtr,\r
526 &SizeOfVariable,\r
527 &VariableData\r
528 );\r
529\r
530 if (!EFI_ERROR (Status)) {\r
531 if (SizeOfVariable == 1) {\r
532 CopyMem (&MapValue, VariableData, 1);\r
533 } else {\r
534 CopyMem (&MapValue, VariableData, 2);\r
535 }\r
536\r
537 //\r
538 // Do operation after knowing the compare operator.\r
539 //\r
540 MapValue2 = (*PIterator)->Value;\r
541 (*PIterator)++;\r
542 if ((*PIterator)->Operand == EFI_IFR_GT_OP) {\r
543 PushValue = (BOOLEAN) (MapValue > MapValue2);\r
544 } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {\r
545 PushValue = (BOOLEAN) (MapValue >= MapValue2);\r
546 } else {\r
547 (*PIterator)--;\r
548 PushValue = (BOOLEAN) (MapValue == MapValue2);\r
549 }\r
550 PushBool (StackPtr, PushValue);\r
551 }\r
552\r
553 break;\r
554\r
555 case EFI_IFR_EQ_ID_VAL_OP:\r
556 //\r
557 // Do operation after knowing the compare operator.\r
558 //\r
559 MapValue2 = (*PIterator)->Value;\r
560 (*PIterator)++;\r
561 if ((*PIterator)->Operand == EFI_IFR_GT_OP) {\r
562 PushValue = (BOOLEAN) (MapValue > MapValue2);\r
563 } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {\r
564 PushValue = (BOOLEAN) (MapValue >= MapValue2);\r
565 } else {\r
566 (*PIterator)--;\r
567 PushValue = (BOOLEAN) (MapValue == MapValue2);\r
568 }\r
569 PushBool (StackPtr, PushValue);\r
570 break;\r
571\r
572 case EFI_IFR_EQ_ID_ID_OP:\r
573 //\r
574 // Do operation after knowing the compare operator.\r
575 //\r
576 (*PIterator)++;\r
577 if ((*PIterator)->Operand == EFI_IFR_GT_OP) {\r
578 PushValue = (BOOLEAN) (MapValue > MapValue2);\r
579 } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {\r
580 PushValue = (BOOLEAN) (MapValue >= MapValue2);\r
581 } else {\r
582 (*PIterator)--;\r
583 PushValue = (BOOLEAN) (MapValue == MapValue2);\r
584 }\r
585 PushBool (StackPtr, PushValue);\r
586 break;\r
587\r
588 case EFI_IFR_EQ_ID_LIST_OP:\r
589 for (Index = 0; Index < (*PIterator)->ListLength; Index++) {\r
590 Operator = (BOOLEAN) (MapValue == (*PIterator)->ValueList[Index]);\r
591 if (Operator) {\r
592 break;\r
593 }\r
594 }\r
595\r
596 PushBool (StackPtr, Operator);\r
597 break;\r
598\r
599 case EFI_IFR_TRUE_OP:\r
600 PushBool (StackPtr, TRUE);\r
601 break;\r
602\r
603 case EFI_IFR_FALSE_OP:\r
604 PushBool (StackPtr, FALSE);\r
605 break;\r
606\r
607 case EFI_IFR_AND_OP:\r
608 Operator = PopBool (StackPtr);\r
609 Operator2 = PopBool (StackPtr);\r
610 PushBool (StackPtr, (BOOLEAN) (Operator && Operator2));\r
611 break;\r
612 case EFI_IFR_OR_OP:\r
613 Operator = PopBool (StackPtr);\r
614 Operator2 = PopBool (StackPtr);\r
615 PushBool (StackPtr, (BOOLEAN) (Operator || Operator2));\r
616 break;\r
617 case EFI_IFR_NOT_OP:\r
618 Operator = PopBool (StackPtr);\r
619 PushBool (StackPtr, !Operator);\r
620 break;\r
621\r
622 case EFI_IFR_SUPPRESS_IF_OP:\r
623 case EFI_IFR_GRAYOUT_IF_OP:\r
624 case EFI_IFR_INCONSISTENT_IF_OP:\r
625 default:\r
626 //\r
627 // Return to the previous tag if runs out of boolean expression.\r
628 //\r
629 (*PIterator)--;\r
630 return;\r
631 }\r
632 (*PIterator)++;\r
633 }\r
634}\r
635\r
636BOOLEAN\r
637ValueIsNotValid (\r
638 IN BOOLEAN Complex,\r
639 IN UINT16 Value,\r
640 IN EFI_TAG *Tag,\r
641 IN EFI_FILE_FORM_TAGS *FileFormTags,\r
642 IN STRING_REF *PopUp\r
643 )\r
644/*++\r
645\r
646Routine Description:\r
647\r
648\r
649Arguments:\r
650\r
651Returns:\r
652\r
653 TRUE - If value is valid\r
654\r
655 FALSE - If value is not valid\r
656\r
657--*/\r
658{\r
659 BOOLEAN *StackPtr;\r
660 EFI_INCONSISTENCY_DATA *Iterator;\r
661 BOOLEAN Operator;\r
662 BOOLEAN Operator2;\r
663 UINTN Index;\r
664 VOID *BooleanExpression;\r
665 UINTN BooleanExpressionLength;\r
666 BOOLEAN NotOperator;\r
667 BOOLEAN OrOperator;\r
668 BOOLEAN AndOperator;\r
669 BOOLEAN ArtificialEnd;\r
670 UINT16 *MapBuffer;\r
671 UINT16 *MapBuffer2;\r
672 UINT16 MapValue;\r
673 UINT16 MapValue2;\r
674 UINTN SizeOfVariable;\r
273bbd31 675 CHAR16 VariableName[MAXIMUM_VALUE_CHARACTERS];\r
878ddf1f 676 VOID *VariableData;\r
677 EFI_STATUS Status;\r
678 UINT16 Id;\r
679 UINT16 Width;\r
680 EFI_VARIABLE_DEFINITION *VariableDefinition;\r
681 BOOLEAN CosmeticConsistency;\r
682 UINT8 IsLegacy;\r
683\r
684 VariableData = NULL;\r
685 BooleanExpressionLength = 0;\r
686 BooleanExpression = NULL;\r
687 Operator = FALSE;\r
688 ArtificialEnd = FALSE;\r
689 CosmeticConsistency = TRUE;\r
690 IsLegacy = 0;\r
691\r
692 Id = Tag->Id;\r
693 if (Tag->StorageWidth == 1) {\r
694 Width = 1;\r
695 } else {\r
696 Width = 2;\r
697 }\r
698 CreateBooleanExpression (FileFormTags, Value, Id, Complex, &BooleanExpression, &BooleanExpressionLength);\r
699\r
700 if (mBooleanEvaluationStack == 0) {\r
701 InitializeBooleanEvaluator ();\r
702 }\r
703\r
704 if (BooleanExpression == NULL) {\r
705 return FALSE;\r
706 }\r
707\r
708 StackPtr = mBooleanEvaluationStack;\r
709 Iterator = BooleanExpression;\r
710 MapBuffer = NULL;\r
711 MapBuffer2 = NULL;\r
712 MapValue = 0;\r
713 MapValue2 = 0;\r
714\r
715 while (TRUE) {\r
716 NotOperator = FALSE;\r
717 OrOperator = FALSE;\r
718 AndOperator = FALSE;\r
719\r
720 if (Iterator->Operand == 0) {\r
721 return Operator;\r
722 }\r
723\r
724 // \r
725 // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.\r
726 //\r
727 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE &&\r
728 Iterator->QuestionId1 != INVALID_OFFSET_VALUE-1) {\r
729 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);\r
730 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);\r
731 if (MapBuffer != NULL) {\r
732 if (Width == 2) {\r
733 MapValue = *MapBuffer;\r
734 } else {\r
735 MapValue = (UINT8) *MapBuffer;\r
736 }\r
737\r
738 gBS->FreePool (MapBuffer);\r
739 }\r
740\r
741 if (MapBuffer2 != NULL) {\r
742 if (Width == 2) {\r
743 MapValue2 = *MapBuffer2;\r
744 } else {\r
745 MapValue2 = (UINT8) *MapBuffer2;\r
746 }\r
747\r
748 gBS->FreePool (MapBuffer2);\r
749 }\r
750 }\r
751\r
752 switch (Iterator->Operand) {\r
753 case EFI_IFR_SUPPRESS_IF_OP:\r
754 //\r
755 // Must have hit a suppress followed by a grayout or vice-versa\r
756 //\r
757 if (ArtificialEnd) {\r
758 ArtificialEnd = FALSE;\r
759 Operator = PopBool (&StackPtr);\r
760 if (Operator) {\r
761 Tag->Suppress = TRUE;\r
762 }\r
763\r
764 return Operator;\r
765 }\r
766\r
767 ArtificialEnd = TRUE;\r
768 *PopUp = Iterator->Popup;\r
769 break;\r
770\r
771 case EFI_IFR_GRAYOUT_IF_OP:\r
772 //\r
773 // Must have hit a suppress followed by a grayout or vice-versa\r
774 //\r
775 if (ArtificialEnd) {\r
776 ArtificialEnd = FALSE;\r
777 Operator = PopBool (&StackPtr);\r
778 if (Operator) {\r
779 Tag->GrayOut = TRUE;\r
780 }\r
781\r
782 return Operator;\r
783 }\r
784\r
785 ArtificialEnd = TRUE;\r
786 *PopUp = Iterator->Popup;\r
787 break;\r
788\r
789 case EFI_IFR_INCONSISTENT_IF_OP:\r
790 CosmeticConsistency = FALSE;\r
791 *PopUp = Iterator->Popup;\r
792 break;\r
793\r
794 //\r
795 // In the case of external variable values, we must read the variable which is\r
796 // named by the human readable version of the OpCode->VariableId and the guid of the formset\r
797 //\r
798 case EFI_IFR_EQ_VAR_VAL_OP:\r
799 //\r
800 // To check whether Ifr is legacy. Once every boolean expression.\r
801 //\r
802 if (IsLegacy == 0) {\r
803 IsLegacy = PredicateIfrType (Iterator);\r
804 }\r
805 if (IsLegacy == 0x2) {\r
806 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
807 break;\r
808 }\r
809\r
810 UnicodeValueToString (\r
811 VariableName, \r
812 FALSE, \r
813 (UINTN) Iterator->QuestionId1, \r
273bbd31 814 (sizeof (VariableName) / sizeof (VariableName[0])) - 1\r
878ddf1f 815 );\r
816\r
817 SizeOfVariable = 0;\r
818\r
819 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);\r
820\r
821 Status = BooleanVariableWorker (\r
822 VariableName,\r
823 VariableDefinition,\r
824 StackPtr,\r
825 &SizeOfVariable,\r
826 &VariableData\r
827 );\r
828\r
829 if (!EFI_ERROR (Status)) {\r
830 if (SizeOfVariable == 1) {\r
831 CopyMem (&MapValue, VariableData, 1);\r
832 } else {\r
833 CopyMem (&MapValue, VariableData, 2);\r
834 }\r
835\r
836 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));\r
837 }\r
838\r
839 break;\r
840\r
841 case EFI_IFR_EQ_ID_VAL_OP:\r
842 //\r
843 // To check whether Ifr is legacy. Once every boolean expression.\r
844 //\r
845 if (IsLegacy == 0) {\r
846 IsLegacy = PredicateIfrType (Iterator);\r
847 }\r
848 if (IsLegacy == 0x2) {\r
849 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
850 break;\r
851 }\r
852\r
853 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));\r
854 break;\r
855\r
856 case EFI_IFR_EQ_ID_ID_OP:\r
857 //\r
858 // To check whether Ifr is legacy. Once every boolean expression.\r
859 //\r
860 if (IsLegacy == 0) {\r
861 IsLegacy = PredicateIfrType (Iterator);\r
862 }\r
863 if (IsLegacy == 0x2) {\r
864 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
865 break;\r
866 }\r
867\r
868 PushBool (&StackPtr, (BOOLEAN) (MapValue == MapValue2));\r
869 break;\r
870\r
871 case EFI_IFR_EQ_ID_LIST_OP:\r
872 //\r
873 // To check whether Ifr is legacy. Once every boolean expression.\r
874 //\r
875 if (IsLegacy == 0) {\r
876 IsLegacy = PredicateIfrType (Iterator);\r
877 }\r
878 if (IsLegacy == 0x2) {\r
879 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
880 break;\r
881 }\r
882\r
883 for (Index = 0; Index < Iterator->ListLength; Index++) {\r
884 Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);\r
885 if (Operator) {\r
886 break;\r
887 }\r
888 }\r
889\r
890 PushBool (&StackPtr, Operator);\r
891 break;\r
892\r
893 case EFI_IFR_AND_OP:\r
894 Iterator++;\r
895 if (Iterator->Operand == EFI_IFR_NOT_OP) {\r
896 NotOperator = TRUE;\r
897 Iterator++;\r
898 }\r
899\r
900 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {\r
901 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);\r
902 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);\r
903 if (MapBuffer != NULL) {\r
904 if (Width == 2) {\r
905 MapValue = *MapBuffer;\r
906 } else {\r
907 MapValue = (UINT8) *MapBuffer;\r
908 }\r
909\r
910 gBS->FreePool (MapBuffer);\r
911 }\r
912\r
913 if (MapBuffer2 != NULL) {\r
914 if (Width == 2) {\r
915 MapValue2 = *MapBuffer2;\r
916 } else {\r
917 MapValue2 = (UINT8) *MapBuffer2;\r
918 }\r
919\r
920 gBS->FreePool (MapBuffer2);\r
921 }\r
922 }\r
923\r
924 switch (Iterator->Operand) {\r
925 case EFI_IFR_EQ_ID_VAL_OP:\r
926 //\r
927 // If Not - flip the results\r
928 //\r
929 if (NotOperator) {\r
930 Operator = (BOOLEAN)!(MapValue == Iterator->Value);\r
931 } else {\r
932 Operator = (BOOLEAN) (MapValue == Iterator->Value);\r
933 }\r
934\r
935 PushBool (&StackPtr, Operator);\r
936 break;\r
937\r
938 //\r
939 // In the case of external variable values, we must read the variable which is\r
940 // named by the human readable version of the OpCode->VariableId and the guid of the formset\r
941 //\r
942 case EFI_IFR_EQ_VAR_VAL_OP:\r
943 UnicodeValueToString (\r
944 VariableName, \r
945 FALSE, \r
946 (UINTN) Iterator->QuestionId1, \r
273bbd31 947 (sizeof (VariableName) / sizeof (VariableName[0])) - 1\r
878ddf1f 948 );\r
949\r
950 SizeOfVariable = 0;\r
951\r
952 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);\r
953\r
954 Status = BooleanVariableWorker (\r
955 VariableName,\r
956 VariableDefinition,\r
957 StackPtr,\r
958 &SizeOfVariable,\r
959 &VariableData\r
960 );\r
961\r
962 if (!EFI_ERROR (Status)) {\r
963 if (SizeOfVariable == 1) {\r
964 CopyMem (&MapValue, VariableData, 1);\r
965 } else {\r
966 CopyMem (&MapValue, VariableData, 2);\r
967 }\r
968 //\r
969 // If Not - flip the results\r
970 //\r
971 if (NotOperator) {\r
972 PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));\r
973 } else {\r
974 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));\r
975 }\r
976 }\r
977 break;\r
978\r
979 case EFI_IFR_EQ_ID_ID_OP:\r
980 //\r
981 // If Not - flip the results\r
982 //\r
983 if (NotOperator) {\r
984 Operator = (BOOLEAN)!(MapValue == MapValue2);\r
985 } else {\r
986 Operator = (BOOLEAN) (MapValue == MapValue2);\r
987 }\r
988\r
989 PushBool (&StackPtr, Operator);\r
990 break;\r
991\r
992 case EFI_IFR_EQ_ID_LIST_OP:\r
993 for (Index = 0; Index < Iterator->ListLength; Index++) {\r
994 //\r
995 // If Not - flip the results\r
996 //\r
997 if (NotOperator) {\r
998 Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);\r
999 } else {\r
1000 Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);\r
1001 }\r
1002 //\r
1003 // If We are trying to make sure that MapValue != Item[x], keep looking through\r
1004 // the list to make sure we don't equal any other items\r
1005 //\r
1006 if (Operator && NotOperator) {\r
1007 continue;\r
1008 }\r
1009 //\r
1010 // If MapValue == Item, then we have succeeded (first found is good enough)\r
1011 //\r
1012 if (Operator) {\r
1013 break;\r
1014 }\r
1015 }\r
1016\r
1017 PushBool (&StackPtr, Operator);\r
1018 break;\r
1019\r
1020 default:\r
1021 return FALSE;\r
1022 }\r
1023\r
1024 Operator = PopBool (&StackPtr);\r
1025 Operator2 = PopBool (&StackPtr);\r
1026 PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));\r
1027 break;\r
1028\r
1029 case EFI_IFR_OR_OP:\r
1030 Iterator++;\r
1031 if (Iterator->Operand == EFI_IFR_NOT_OP) {\r
1032 NotOperator = TRUE;\r
1033 Iterator++;\r
1034 }\r
1035\r
1036 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {\r
1037 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);\r
1038 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);\r
1039 if (MapBuffer != NULL) {\r
1040 if (Width == 2) {\r
1041 MapValue = *MapBuffer;\r
1042 } else {\r
1043 MapValue = (UINT8) *MapBuffer;\r
1044 }\r
1045\r
1046 gBS->FreePool (MapBuffer);\r
1047 }\r
1048\r
1049 if (MapBuffer2 != NULL) {\r
1050 if (Width == 2) {\r
1051 MapValue2 = *MapBuffer2;\r
1052 } else {\r
1053 MapValue2 = (UINT8) *MapBuffer2;\r
1054 }\r
1055\r
1056 gBS->FreePool (MapBuffer2);\r
1057 }\r
1058 }\r
1059\r
1060 switch (Iterator->Operand) {\r
1061 case EFI_IFR_EQ_ID_VAL_OP:\r
1062 //\r
1063 // If Not - flip the results\r
1064 //\r
1065 if (NotOperator) {\r
1066 Operator = (BOOLEAN)!(MapValue == Iterator->Value);\r
1067 } else {\r
1068 Operator = (BOOLEAN) (MapValue == Iterator->Value);\r
1069 }\r
1070\r
1071 PushBool (&StackPtr, Operator);\r
1072 break;\r
1073\r
1074 //\r
1075 // In the case of external variable values, we must read the variable which is\r
1076 // named by the human readable version of the OpCode->VariableId and the guid of the formset\r
1077 //\r
1078 case EFI_IFR_EQ_VAR_VAL_OP:\r
1079 UnicodeValueToString (\r
1080 VariableName, \r
1081 FALSE, \r
1082 (UINTN) Iterator->QuestionId1, \r
273bbd31 1083 (sizeof (VariableName) / sizeof (VariableName[0])) - 1\r
878ddf1f 1084 );\r
1085\r
1086 SizeOfVariable = 0;\r
1087\r
1088 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);\r
1089\r
1090 Status = BooleanVariableWorker (\r
1091 VariableName,\r
1092 VariableDefinition,\r
1093 StackPtr,\r
1094 &SizeOfVariable,\r
1095 &VariableData\r
1096 );\r
1097\r
1098 if (!EFI_ERROR (Status)) {\r
1099 if (SizeOfVariable == 1) {\r
1100 CopyMem (&MapValue, VariableData, 1);\r
1101 } else {\r
1102 CopyMem (&MapValue, VariableData, 2);\r
1103 }\r
1104 //\r
1105 // If Not - flip the results\r
1106 //\r
1107 if (NotOperator) {\r
1108 PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));\r
1109 } else {\r
1110 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));\r
1111 }\r
1112 }\r
1113 break;\r
1114\r
1115 case EFI_IFR_EQ_ID_ID_OP:\r
1116 //\r
1117 // If Not - flip the results\r
1118 //\r
1119 if (NotOperator) {\r
1120 Operator = (BOOLEAN)!(MapValue == MapValue2);\r
1121 } else {\r
1122 Operator = (BOOLEAN) (MapValue == MapValue2);\r
1123 }\r
1124\r
1125 PushBool (&StackPtr, Operator);\r
1126 break;\r
1127\r
1128 case EFI_IFR_EQ_ID_LIST_OP:\r
1129 for (Index = 0; Index < Iterator->ListLength; Index++) {\r
1130 //\r
1131 // If Not - flip the results\r
1132 //\r
1133 if (NotOperator) {\r
1134 Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);\r
1135 } else {\r
1136 Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);\r
1137 }\r
1138 //\r
1139 // If We are trying to make sure that MapValue != Item[x], keep looking through\r
1140 // the list to make sure we don't equal any other items\r
1141 //\r
1142 if (Operator && NotOperator) {\r
1143 continue;\r
1144 }\r
1145 //\r
1146 // If MapValue == Item, then we have succeeded (first found is good enough)\r
1147 //\r
1148 if (Operator) {\r
1149 break;\r
1150 }\r
1151 }\r
1152\r
1153 PushBool (&StackPtr, Operator);\r
1154 break;\r
1155\r
1156 default:\r
1157 return FALSE;\r
1158 }\r
1159\r
1160 Operator = PopBool (&StackPtr);\r
1161 Operator2 = PopBool (&StackPtr);\r
1162 PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));\r
1163 break;\r
1164\r
1165 case EFI_IFR_NOT_OP:\r
1166 //\r
1167 // To check whether Ifr is legacy. Once every boolean expression.\r
1168 //\r
1169 if (IsLegacy == 0) {\r
1170 IsLegacy = PredicateIfrType (Iterator);\r
1171 }\r
1172 if (IsLegacy == 0x2) {\r
1173 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
1174 break;\r
1175 }\r
1176\r
1177 //\r
1178 // I don't need to set the NotOperator (I know that I have to NOT this in this case\r
1179 //\r
1180 Iterator++;\r
1181\r
1182 if (Iterator->Operand == EFI_IFR_OR_OP) {\r
1183 OrOperator = TRUE;\r
1184 Iterator++;\r
1185 }\r
1186\r
1187 if (Iterator->Operand == EFI_IFR_AND_OP) {\r
1188 AndOperator = TRUE;\r
1189 Iterator++;\r
1190 }\r
1191\r
1192 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {\r
1193 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);\r
1194 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);\r
1195 if (MapBuffer != NULL) {\r
1196 if (Width == 2) {\r
1197 MapValue = *MapBuffer;\r
1198 } else {\r
1199 MapValue = (UINT8) *MapBuffer;\r
1200 }\r
1201\r
1202 gBS->FreePool (MapBuffer);\r
1203 }\r
1204\r
1205 if (MapBuffer2 != NULL) {\r
1206 if (Width == 2) {\r
1207 MapValue2 = *MapBuffer2;\r
1208 } else {\r
1209 MapValue2 = (UINT8) *MapBuffer2;\r
1210 }\r
1211\r
1212 gBS->FreePool (MapBuffer2);\r
1213 }\r
1214 }\r
1215\r
1216 switch (Iterator->Operand) {\r
1217 case EFI_IFR_EQ_ID_VAL_OP:\r
1218 Operator = (BOOLEAN)!(MapValue == Iterator->Value);\r
1219 PushBool (&StackPtr, Operator);\r
1220 break;\r
1221\r
1222 //\r
1223 // In the case of external variable values, we must read the variable which is\r
1224 // named by the human readable version of the OpCode->VariableId and the guid of the formset\r
1225 //\r
1226 case EFI_IFR_EQ_VAR_VAL_OP:\r
1227 UnicodeValueToString (\r
1228 VariableName, \r
1229 FALSE, \r
1230 (UINTN) Iterator->QuestionId1, \r
273bbd31 1231 (sizeof (VariableName) / sizeof (VariableName[0])) - 1\r
878ddf1f 1232 );\r
1233\r
1234 SizeOfVariable = 0;\r
1235\r
1236 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);\r
1237\r
1238 Status = BooleanVariableWorker (\r
1239 VariableName,\r
1240 VariableDefinition,\r
1241 StackPtr,\r
1242 &SizeOfVariable,\r
1243 &VariableData\r
1244 );\r
1245\r
1246 if (!EFI_ERROR (Status)) {\r
1247 if (SizeOfVariable == 1) {\r
1248 CopyMem (&MapValue, VariableData, 1);\r
1249 } else {\r
1250 CopyMem (&MapValue, VariableData, 2);\r
1251 }\r
1252\r
1253 PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));\r
1254 }\r
1255 break;\r
1256\r
1257 case EFI_IFR_EQ_ID_ID_OP:\r
1258 Operator = (BOOLEAN)!(MapValue == MapValue2);\r
1259 PushBool (&StackPtr, Operator);\r
1260 break;\r
1261\r
1262 case EFI_IFR_EQ_ID_LIST_OP:\r
1263 for (Index = 0; Index < Iterator->ListLength; Index++) {\r
1264 Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);\r
1265 if (Operator) {\r
1266 continue;\r
1267 }\r
1268 }\r
1269\r
1270 PushBool (&StackPtr, Operator);\r
1271 break;\r
1272\r
1273 default:\r
1274 return FALSE;\r
1275 }\r
1276\r
1277 Operator = PopBool (&StackPtr);\r
1278 Operator2 = PopBool (&StackPtr);\r
1279\r
1280 if (OrOperator) {\r
1281 PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));\r
1282 }\r
1283\r
1284 if (AndOperator) {\r
1285 PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));\r
1286 }\r
1287\r
1288 if (!OrOperator && !AndOperator) {\r
1289 PushBool (&StackPtr, Operator);\r
1290 }\r
1291 break;\r
1292 \r
1293 case EFI_IFR_TRUE_OP:\r
1294 //\r
1295 // To check whether Ifr is legacy. Once every boolean expression.\r
1296 //\r
1297 if (IsLegacy == 0) {\r
1298 IsLegacy = PredicateIfrType (Iterator);\r
1299 }\r
1300 if (IsLegacy == 0x2) {\r
1301 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
1302 break;\r
1303 }\r
1304 break;\r
1305\r
1306 case EFI_IFR_FALSE_OP:\r
1307 //\r
1308 // To check whether Ifr is legacy. Once every boolean expression.\r
1309 //\r
1310 if (IsLegacy == 0) {\r
1311 IsLegacy = PredicateIfrType (Iterator);\r
1312 }\r
1313 if (IsLegacy == 0x2) {\r
1314 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);\r
1315 break;\r
1316 }\r
1317 break;\r
1318\r
1319 case EFI_IFR_END_IF_OP:\r
1320 Operator = PopBool (&StackPtr);\r
1321 //\r
1322 // If there is an error, return, otherwise keep looking - there might\r
1323 // be another test that causes an error\r
1324 //\r
1325 if (Operator) {\r
1326 if (Complex && CosmeticConsistency) {\r
1327 return EFI_SUCCESS;\r
1328 } else {\r
1329 return Operator;\r
1330 }\r
1331 } else {\r
1332 //\r
1333 // If not doing a global consistency check, the endif is the REAL terminator of this operation\r
1334 // This is used for grayout/suppress operations. InconsistentIf is a global operation so the EndIf is\r
1335 // not the end-all be-all of terminators.\r
1336 //\r
1337 if (!Complex) {\r
1338 return Operator;\r
1339 }\r
1340 break;\r
1341 }\r
1342\r
1343 default:\r
1344 //\r
1345 // Must have hit a non-consistency related op-code after a suppress/grayout\r
1346 //\r
1347 if (ArtificialEnd) {\r
1348 ArtificialEnd = FALSE;\r
1349 Operator = PopBool (&StackPtr);\r
1350 return Operator;\r
1351 }\r
1352\r
1353 return FALSE;\r
1354 }\r
1355\r
1356 Iterator++;\r
1357 }\r
1358\r
1359 return FALSE;\r
1360}\r