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