Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chen A Chen <chen.a.chen@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Ruiyu Ni <Ruiyu.ni@intel.com>
		
			
				
	
	
		
			1112 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1112 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Main file for If and else shell level 1 function.
 | |
| 
 | |
|   (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
 | |
|   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "UefiShellLevel1CommandsLib.h"
 | |
| #include <Library/PrintLib.h>
 | |
| 
 | |
| typedef enum {
 | |
|   EndTagOr,
 | |
|   EndTagAnd,
 | |
|   EndTagThen,
 | |
|   EndTagMax
 | |
| } END_TAG_TYPE;
 | |
| 
 | |
| typedef enum {
 | |
|   OperatorGreaterThan,
 | |
|   OperatorLessThan,
 | |
|   OperatorEqual,
 | |
|   OperatorNotEqual,
 | |
|   OperatorGreatorOrEqual,
 | |
|   OperatorLessOrEqual,
 | |
|   OperatorUnisgnedGreaterThan,
 | |
|   OperatorUnsignedLessThan,
 | |
|   OperatorUnsignedGreaterOrEqual,
 | |
|   OperatorUnsignedLessOrEqual,
 | |
|   OperatorMax
 | |
| } BIN_OPERATOR_TYPE;
 | |
| 
 | |
| /**
 | |
|   Extract the next fragment, if there is one.
 | |
| 
 | |
|   @param[in, out] Statement    The current remaining statement.
 | |
|   @param[in] Fragment          The current fragment.
 | |
|   @param[out] Match            TRUE when there is another Fragment in Statement,
 | |
|                                FALSE otherwise.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The match operation is performed successfully.
 | |
|   @retval EFI_OUT_OF_RESOURCES Out of resources.
 | |
| **/
 | |
| EFI_STATUS
 | |
| IsNextFragment (
 | |
|   IN OUT CONST CHAR16     **Statement,
 | |
|   IN CONST CHAR16         *Fragment,
 | |
|   OUT BOOLEAN             *Match
 | |
|   )
 | |
| {
 | |
|   CHAR16                  *Tester;
 | |
| 
 | |
|   Tester = NULL;
 | |
| 
 | |
|   Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment));
 | |
|   if (Tester == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   Tester[StrLen(Fragment)] = CHAR_NULL;
 | |
|   if (gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         (CHAR16*)Fragment,
 | |
|         Tester) == 0) {
 | |
|     //
 | |
|     // increment the string pointer to the end of what we found and then chop off spaces...
 | |
|     //
 | |
|     *Statement+=StrLen(Fragment);
 | |
|     while (*Statement[0] == L' ') {
 | |
|       (*Statement)++;
 | |
|     }
 | |
|     *Match = TRUE;
 | |
|   } else {
 | |
|     *Match = FALSE;
 | |
|   }
 | |
|   FreePool(Tester);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Determine if String represents a valid profile.
 | |
| 
 | |
|   @param[in] String     The pointer to the string to test.
 | |
| 
 | |
|   @retval TRUE    String is a valid profile.
 | |
|   @retval FALSE   String is not a valid profile.
 | |
| **/
 | |
| BOOLEAN
 | |
| IsValidProfile (
 | |
|   IN CONST CHAR16 *String
 | |
|   )
 | |
| {
 | |
|   CONST CHAR16  *ProfilesString;
 | |
|   CONST CHAR16  *TempLocation;
 | |
| 
 | |
|   ProfilesString = ShellGetEnvironmentVariable(L"profiles");
 | |
|   ASSERT(ProfilesString != NULL);
 | |
|   TempLocation = StrStr(ProfilesString, String);
 | |
|   if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) {
 | |
|     return (TRUE);
 | |
|   }
 | |
|   return (FALSE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Do a comparison between 2 things.
 | |
| 
 | |
|   @param[in] Compare1           The first item to compare.
 | |
|   @param[in] Compare2           The second item to compare.
 | |
|   @param[in] BinOp              The type of comparison to perform.
 | |
|   @param[in] CaseInsensitive    TRUE to do non-case comparison, FALSE otherwise.
 | |
|   @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise.
 | |
| 
 | |
|   @return     The result of the comparison.
 | |
| **/
 | |
| BOOLEAN
 | |
| TestOperation (
 | |
|   IN CONST CHAR16             *Compare1,
 | |
|   IN CONST CHAR16             *Compare2,
 | |
|   IN CONST BIN_OPERATOR_TYPE  BinOp,
 | |
|   IN CONST BOOLEAN            CaseInsensitive,
 | |
|   IN CONST BOOLEAN            ForceStringCompare
 | |
|   )
 | |
| {
 | |
|   INTN Cmp1;
 | |
|   INTN Cmp2;
 | |
| 
 | |
|   //
 | |
|   // "Compare1 BinOp Compare2"
 | |
|   //
 | |
|   switch (BinOp) {
 | |
|   case OperatorUnisgnedGreaterThan:
 | |
|   case OperatorGreaterThan:
 | |
|     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
 | |
|       //
 | |
|       // string compare
 | |
|       //
 | |
|       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // numeric compare
 | |
|       //
 | |
|       if (Compare1[0] == L'-') {
 | |
|         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
 | |
|       } else {
 | |
|         Cmp1 = (INTN)ShellStrToUintn(Compare1);
 | |
|       }
 | |
|       if (Compare2[0] == L'-') {
 | |
|         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
 | |
|       } else {
 | |
|         Cmp2 = (INTN)ShellStrToUintn(Compare2);
 | |
|       }
 | |
|       if (BinOp == OperatorGreaterThan) {
 | |
|         if (Cmp1 > Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       } else {
 | |
|         if ((UINTN)Cmp1 > (UINTN)Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return (FALSE);
 | |
|   case OperatorUnsignedLessThan:
 | |
|   case OperatorLessThan:
 | |
|     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
 | |
|       //
 | |
|       // string compare
 | |
|       //
 | |
|       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // numeric compare
 | |
|       //
 | |
|       if (Compare1[0] == L'-') {
 | |
|         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
 | |
|       } else {
 | |
|         Cmp1 = (INTN)ShellStrToUintn(Compare1);
 | |
|       }
 | |
|       if (Compare2[0] == L'-') {
 | |
|         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
 | |
|       } else {
 | |
|         Cmp2 = (INTN)ShellStrToUintn(Compare2);
 | |
|       }
 | |
|       if (BinOp == OperatorLessThan) {
 | |
|         if (Cmp1 < Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       } else {
 | |
|         if ((UINTN)Cmp1 < (UINTN)Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|     }
 | |
|     return (FALSE);
 | |
|   case OperatorEqual:
 | |
|     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
 | |
|       //
 | |
|       // string compare
 | |
|       //
 | |
|       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // numeric compare
 | |
|       //
 | |
|       if (Compare1[0] == L'-') {
 | |
|         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
 | |
|       } else {
 | |
|         Cmp1 = (INTN)ShellStrToUintn(Compare1);
 | |
|       }
 | |
|       if (Compare2[0] == L'-') {
 | |
|         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
 | |
|       } else {
 | |
|         Cmp2 = (INTN)ShellStrToUintn(Compare2);
 | |
|       }
 | |
|       if (Cmp1 == Cmp2) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     }
 | |
|     return (FALSE);
 | |
|   case OperatorNotEqual:
 | |
|     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
 | |
|       //
 | |
|       // string compare
 | |
|       //
 | |
|       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // numeric compare
 | |
|       //
 | |
|       if (Compare1[0] == L'-') {
 | |
|         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
 | |
|       } else {
 | |
|         Cmp1 = (INTN)ShellStrToUintn(Compare1);
 | |
|       }
 | |
|       if (Compare2[0] == L'-') {
 | |
|         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
 | |
|       } else {
 | |
|         Cmp2 = (INTN)ShellStrToUintn(Compare2);
 | |
|       }
 | |
|       if (Cmp1 != Cmp2) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     }
 | |
|     return (FALSE);
 | |
|   case OperatorUnsignedGreaterOrEqual:
 | |
|   case OperatorGreatorOrEqual:
 | |
|     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
 | |
|       //
 | |
|       // string compare
 | |
|       //
 | |
|       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // numeric compare
 | |
|       //
 | |
|       if (Compare1[0] == L'-') {
 | |
|         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
 | |
|       } else {
 | |
|         Cmp1 = (INTN)ShellStrToUintn(Compare1);
 | |
|       }
 | |
|       if (Compare2[0] == L'-') {
 | |
|         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
 | |
|       } else {
 | |
|         Cmp2 = (INTN)ShellStrToUintn(Compare2);
 | |
|       }
 | |
|       if (BinOp == OperatorGreatorOrEqual) {
 | |
|         if (Cmp1 >= Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       } else {
 | |
|         if ((UINTN)Cmp1 >= (UINTN)Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return (FALSE);
 | |
|   case OperatorLessOrEqual:
 | |
|   case OperatorUnsignedLessOrEqual:
 | |
|     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
 | |
|       //
 | |
|       // string compare
 | |
|       //
 | |
|       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) {
 | |
|         return (TRUE);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // numeric compare
 | |
|       //
 | |
|       if (Compare1[0] == L'-') {
 | |
|         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
 | |
|       } else {
 | |
|         Cmp1 = (INTN)ShellStrToUintn(Compare1);
 | |
|       }
 | |
|       if (Compare2[0] == L'-') {
 | |
|         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
 | |
|       } else {
 | |
|         Cmp2 = (INTN)ShellStrToUintn(Compare2);
 | |
|       }
 | |
|       if (BinOp == OperatorLessOrEqual) {
 | |
|         if (Cmp1 <= Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       } else {
 | |
|         if ((UINTN)Cmp1 <= (UINTN)Cmp2) {
 | |
|           return (TRUE);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return (FALSE);
 | |
|   default:
 | |
|     ASSERT(FALSE);
 | |
|     return (FALSE);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Process an if statement and determine if its is valid or not.
 | |
| 
 | |
|   @param[in, out] PassingState     Opon entry, the current state.  Upon exit, 
 | |
|                                    the new state.
 | |
|   @param[in] StartParameterNumber  The number of the first parameter of
 | |
|                                    this statement.
 | |
|   @param[in] EndParameterNumber    The number of the final parameter of
 | |
|                                    this statement.
 | |
|   @param[in] OperatorToUse         The type of termination operator.
 | |
|   @param[in] CaseInsensitive       TRUE for case insensitive, FALSE otherwise.
 | |
|   @param[in] ForceStringCompare    TRUE for all string based, FALSE otherwise.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER   A parameter was invalid.
 | |
|   @retval EFI_SUCCESS             The operation was successful.                                  
 | |
| **/
 | |
| EFI_STATUS
 | |
| ProcessStatement (
 | |
|   IN OUT BOOLEAN          *PassingState,
 | |
|   IN UINTN                StartParameterNumber,
 | |
|   IN UINTN                EndParameterNumber,
 | |
|   IN CONST END_TAG_TYPE   OperatorToUse,
 | |
|   IN CONST BOOLEAN        CaseInsensitive,
 | |
|   IN CONST BOOLEAN        ForceStringCompare
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   BOOLEAN                 OperationResult;
 | |
|   BOOLEAN                 NotPresent;
 | |
|   CHAR16                  *StatementWalker;
 | |
|   BIN_OPERATOR_TYPE       BinOp;
 | |
|   CHAR16                  *Compare1;
 | |
|   CHAR16                  *Compare2;
 | |
|   CHAR16                  HexString[20];
 | |
|   CHAR16                  *TempSpot;
 | |
|   BOOLEAN                 Match;
 | |
| 
 | |
|   ASSERT((END_TAG_TYPE)OperatorToUse != EndTagThen);
 | |
| 
 | |
|   Status          = EFI_SUCCESS;
 | |
|   BinOp           = OperatorMax;
 | |
|   OperationResult = FALSE;
 | |
|   Match           = FALSE;
 | |
|   StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
 | |
|   if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not", &Match)) && Match) {
 | |
|     NotPresent      = TRUE;
 | |
|     StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];
 | |
|   } else {
 | |
|     NotPresent = FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // now check for 'boolfunc' operators
 | |
|   //
 | |
|   if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint", &Match)) && Match) {
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match
 | |
|         && StatementWalker[StrLen(StatementWalker)-1] == L')') {
 | |
|       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
 | |
|       OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE);
 | |
|     } else {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");
 | |
|     }
 | |
|   } else if ((!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists", &Match)) && Match) ||
 | |
|              (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist", &Match)) && Match)) {
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match &&
 | |
|         StatementWalker[StrLen(StatementWalker)-1] == L')') {
 | |
|       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
 | |
|       //
 | |
|       // is what remains a file in CWD???
 | |
|       //
 | |
|       OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS);
 | |
|     } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) {
 | |
|       OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS);
 | |
|     } else {
 | |
|       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available", &Match)) && Match) {
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match &&
 | |
|         StatementWalker[StrLen(StatementWalker)-1] == L')') {
 | |
|       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
 | |
|       //
 | |
|       // is what remains a file in the CWD or path???
 | |
|       //
 | |
|       OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS);
 | |
|     } else {
 | |
|       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile", &Match)) && Match) {
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match &&
 | |
|         StatementWalker[StrLen(StatementWalker)-1] == L')') {
 | |
|       //
 | |
|       // Chop off that ')'
 | |
|       //
 | |
|       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
 | |
|       OperationResult = IsValidProfile(StatementWalker);
 | |
|     } else {
 | |
|       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   } else if (StartParameterNumber+1 >= EndParameterNumber) {
 | |
|       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|   } else {
 | |
|     //
 | |
|     // must be 'item binop item' style
 | |
|     //
 | |
|     Compare1 = NULL;
 | |
|     Compare2 = NULL;
 | |
|     BinOp    = OperatorMax;
 | |
| 
 | |
|     //
 | |
|     // get the first item
 | |
|     //
 | |
|     StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror", &Match)) && Match) {
 | |
|       TempSpot = StrStr(StatementWalker, L")");
 | |
|       if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
 | |
|         *TempSpot = CHAR_NULL;
 | |
|         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
 | |
|           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
 | |
|           ASSERT(Compare1 == NULL);
 | |
|           Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
 | |
|           StatementWalker += StrLen(StatementWalker) + 1;
 | |
|         } else {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror", &Match)) && Match) {
 | |
|       TempSpot = StrStr(StatementWalker, L")");
 | |
|       if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
 | |
|         *TempSpot = CHAR_NULL;
 | |
|         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
 | |
|           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
 | |
|           ASSERT(Compare1 == NULL);
 | |
|           Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
 | |
|           StatementWalker += StrLen(StatementWalker) + 1;
 | |
|         } else {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16**)(&StatementWalker), L"oemerror", &Match)) && Match) {
 | |
|       TempSpot = StrStr(StatementWalker, L")");
 | |
|       if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
 | |
|         TempSpot = CHAR_NULL;
 | |
|         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
 | |
|           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
 | |
|           ASSERT(Compare1 == NULL);
 | |
|           Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
 | |
|           StatementWalker += StrLen(StatementWalker) + 1;
 | |
|         } else {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else {
 | |
|       ASSERT(Compare1 == NULL);
 | |
|       if (EndParameterNumber - StartParameterNumber > 2) {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         //
 | |
|         // must be a raw string
 | |
|         //
 | |
|         Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // get the operator
 | |
|     //
 | |
|     ASSERT(StartParameterNumber+1<EndParameterNumber);
 | |
|     StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt", &Match)) && Match) {
 | |
|       BinOp = OperatorGreaterThan;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt", &Match)) && Match) {
 | |
|       BinOp = OperatorLessThan;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq", &Match)) && Match) {
 | |
|       BinOp = OperatorEqual;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne", &Match)) && Match) {
 | |
|       BinOp = OperatorNotEqual;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge", &Match)) && Match) {
 | |
|       BinOp = OperatorGreatorOrEqual;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le", &Match)) && Match) {
 | |
|       BinOp = OperatorLessOrEqual;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==", &Match)) && Match) {
 | |
|       BinOp = OperatorEqual;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt", &Match)) && Match) {
 | |
|       BinOp = OperatorUnisgnedGreaterThan;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult", &Match)) && Match) {
 | |
|       BinOp = OperatorUnsignedLessThan;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge", &Match)) && Match) {
 | |
|       BinOp = OperatorUnsignedGreaterOrEqual;
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule", &Match)) && Match) {
 | |
|       BinOp = OperatorUnsignedLessOrEqual;
 | |
|     } else {
 | |
|       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // get the second item
 | |
|     //
 | |
|     ASSERT(StartParameterNumber+2<=EndParameterNumber);
 | |
|     StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];
 | |
|     if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror", &Match)) && Match) {
 | |
|       TempSpot = StrStr(StatementWalker, L")");
 | |
|       if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
 | |
|         TempSpot = CHAR_NULL;
 | |
|         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
 | |
|           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
 | |
|           ASSERT(Compare2 == NULL);
 | |
|           Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
 | |
|           StatementWalker += StrLen(StatementWalker) + 1;
 | |
|         } else {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     //
 | |
|     // can this be collapsed into the above?
 | |
|     //
 | |
|     } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror", &Match)) && Match) {
 | |
|       TempSpot = StrStr(StatementWalker, L")");
 | |
|       if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
 | |
|         TempSpot = CHAR_NULL;
 | |
|         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
 | |
|           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
 | |
|           ASSERT(Compare2 == NULL);
 | |
|           Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
 | |
|           StatementWalker += StrLen(StatementWalker) + 1;
 | |
|         } else {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16**)(&StatementWalker), L"oemerror", &Match)) && Match) {
 | |
|       TempSpot = StrStr(StatementWalker, L")");
 | |
|       if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
 | |
|         TempSpot = CHAR_NULL;
 | |
|         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
 | |
|           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
 | |
|           ASSERT(Compare2 == NULL);
 | |
|           Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
 | |
|           StatementWalker += StrLen(StatementWalker) + 1;
 | |
|         } else {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // must be a raw string
 | |
|       //
 | |
|       ASSERT(Compare2 == NULL);
 | |
|       Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0);
 | |
|     }
 | |
| 
 | |
|     if (Compare1 != NULL && Compare2 != NULL && BinOp != OperatorMax) {
 | |
|       OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);
 | |
|     }
 | |
| 
 | |
|     SHELL_FREE_NON_NULL(Compare1);
 | |
|     SHELL_FREE_NON_NULL(Compare2);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // done processing do result...
 | |
|   //
 | |
| 
 | |
|   if (!EFI_ERROR(Status)) {
 | |
|     if (NotPresent) {
 | |
|       OperationResult = (BOOLEAN)(!OperationResult);
 | |
|     }
 | |
|     switch(OperatorToUse) {
 | |
|       case EndTagOr:
 | |
|         *PassingState = (BOOLEAN)(*PassingState || OperationResult);
 | |
|         break;
 | |
|       case EndTagAnd:
 | |
|         *PassingState = (BOOLEAN)(*PassingState && OperationResult);
 | |
|         break;
 | |
|       case EndTagMax:
 | |
|         *PassingState = (BOOLEAN)(OperationResult);
 | |
|         break;
 | |
|       default:
 | |
|         ASSERT(FALSE);
 | |
|     }
 | |
|   }
 | |
|   return (Status);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Break up the next part of the if statement (until the next 'and', 'or', or 'then').
 | |
| 
 | |
|   @param[in] ParameterNumber      The current parameter number.
 | |
|   @param[out] EndParameter        Upon successful return, will point to the 
 | |
|                                   parameter to start the next iteration with.
 | |
|   @param[out] EndTag              Upon successful return, will point to the 
 | |
|                                   type that was found at the end of this statement.
 | |
| 
 | |
|   @retval TRUE    A valid statement was found.
 | |
|   @retval FALSE   A valid statement was not found.
 | |
| **/
 | |
| BOOLEAN
 | |
| BuildNextStatement (
 | |
|   IN UINTN          ParameterNumber,
 | |
|   OUT UINTN         *EndParameter,
 | |
|   OUT END_TAG_TYPE  *EndTag
 | |
|   )
 | |
| {
 | |
|   *EndTag = EndTagMax;
 | |
| 
 | |
|   for(
 | |
|     ; ParameterNumber < gEfiShellParametersProtocol->Argc
 | |
|     ; ParameterNumber++
 | |
|    ) {
 | |
|     if (gUnicodeCollation->StriColl(
 | |
|           gUnicodeCollation,
 | |
|           gEfiShellParametersProtocol->Argv[ParameterNumber],
 | |
|           L"or") == 0) {
 | |
|       *EndParameter = ParameterNumber - 1;
 | |
|       *EndTag = EndTagOr;
 | |
|       break;
 | |
|     } else if (gUnicodeCollation->StriColl(
 | |
|           gUnicodeCollation,
 | |
|           gEfiShellParametersProtocol->Argv[ParameterNumber],
 | |
|           L"and") == 0) {
 | |
|       *EndParameter = ParameterNumber - 1;
 | |
|       *EndTag = EndTagAnd;
 | |
|       break;
 | |
|     } else if (gUnicodeCollation->StriColl(
 | |
|           gUnicodeCollation,
 | |
|           gEfiShellParametersProtocol->Argv[ParameterNumber],
 | |
|           L"then") == 0) {
 | |
|       *EndParameter = ParameterNumber - 1;
 | |
|       *EndTag = EndTagThen;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   if (*EndTag == EndTagMax) {
 | |
|     return (FALSE);
 | |
|   }
 | |
|   return (TRUE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Move the script file pointer to a different place in the script file.
 | |
|   This one is special since it handles the if/else/endif syntax.
 | |
| 
 | |
|   @param[in] ScriptFile     The script file from GetCurrnetScriptFile().
 | |
| 
 | |
|   @retval TRUE     The move target was found and the move was successful.
 | |
|   @retval FALSE    Something went wrong.
 | |
| **/
 | |
| BOOLEAN
 | |
| MoveToTagSpecial (
 | |
|   IN SCRIPT_FILE                *ScriptFile
 | |
|   )
 | |
| {
 | |
|   SCRIPT_COMMAND_LIST *CommandNode;
 | |
|   BOOLEAN             Found;
 | |
|   UINTN               TargetCount;
 | |
|   CHAR16              *CommandName;
 | |
|   CHAR16              *CommandWalker;
 | |
|   CHAR16              *TempLocation;
 | |
| 
 | |
|   TargetCount         = 1;
 | |
|   Found               = FALSE;
 | |
| 
 | |
|   if (ScriptFile == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
 | |
|     ;  !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found
 | |
|     ;  CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link)
 | |
|    ){
 | |
| 
 | |
|     //
 | |
|     // get just the first part of the command line...
 | |
|     //
 | |
|     CommandName   = NULL;
 | |
|     CommandName   = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
 | |
|     if (CommandName == NULL) {
 | |
|       continue;
 | |
|     }
 | |
|     CommandWalker = CommandName;
 | |
| 
 | |
|     //
 | |
|     // Skip leading spaces and tabs.
 | |
|     //
 | |
|     while ((CommandWalker[0] == L' ') || (CommandWalker[0] == L'\t')) {
 | |
|       CommandWalker++;
 | |
|     }
 | |
|     TempLocation  = StrStr(CommandWalker, L" ");
 | |
| 
 | |
|     if (TempLocation != NULL) {
 | |
|       *TempLocation = CHAR_NULL;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // did we find a nested item ?
 | |
|     //
 | |
|     if (gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         (CHAR16*)CommandWalker,
 | |
|         L"If") == 0) {
 | |
|       TargetCount++;
 | |
|     } else if (TargetCount == 1 && gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         (CHAR16*)CommandWalker,
 | |
|         (CHAR16*)L"else") == 0) {
 | |
|       //
 | |
|       // else can only decrement the last part... not an nested if
 | |
|       // hence the TargetCount compare added
 | |
|       //
 | |
|       TargetCount--;
 | |
|     } else if (gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         (CHAR16*)CommandWalker,
 | |
|         (CHAR16*)L"endif") == 0) {
 | |
|       TargetCount--;
 | |
|     }
 | |
|     if (TargetCount == 0) {
 | |
|       ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link);
 | |
|       Found = TRUE;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Free the memory for this loop...
 | |
|     //
 | |
|     SHELL_FREE_NON_NULL(CommandName);
 | |
|   }
 | |
|   return (Found);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Deal with the result of the if operation.
 | |
| 
 | |
|   @param[in] Result     The result of the if.
 | |
| 
 | |
|   @retval EFI_SUCCESS       The operation was successful.
 | |
|   @retval EFI_NOT_FOUND     The ending tag could not be found.
 | |
| **/
 | |
| EFI_STATUS
 | |
| PerformResultOperation (
 | |
|   IN CONST BOOLEAN Result
 | |
|   )
 | |
| {
 | |
|   if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) {
 | |
|     return (EFI_SUCCESS);
 | |
|   }
 | |
|   return (EFI_NOT_FOUND);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function for 'if' command.
 | |
| 
 | |
|   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
 | |
|   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
 | |
| **/
 | |
| SHELL_STATUS
 | |
| EFIAPI
 | |
| ShellCommandRunIf (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS          Status;
 | |
|   SHELL_STATUS        ShellStatus;
 | |
|   BOOLEAN             CaseInsensitive;
 | |
|   BOOLEAN             ForceString;
 | |
|   UINTN               CurrentParameter;
 | |
|   UINTN               EndParameter;
 | |
|   BOOLEAN             CurrentValue;
 | |
|   END_TAG_TYPE        Ending;
 | |
|   END_TAG_TYPE        PreviousEnding;
 | |
|   SCRIPT_FILE         *CurrentScriptFile;
 | |
| 
 | |
|   Status = CommandInit();
 | |
|   ASSERT_EFI_ERROR(Status);
 | |
| 
 | |
|   if (!gEfiShellProtocol->BatchIsActive()) {
 | |
|     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"if");  
 | |
|     return (SHELL_UNSUPPORTED);
 | |
|   }
 | |
| 
 | |
|   if (gEfiShellParametersProtocol->Argc < 3) {
 | |
|     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"if");  
 | |
|     return (SHELL_INVALID_PARAMETER);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Make sure that an End exists.
 | |
|   //
 | |
|   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
 | |
|   if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {
 | |
|     ShellPrintHiiEx(
 | |
|       -1, 
 | |
|       -1, 
 | |
|       NULL, 
 | |
|       STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 
 | |
|       gShellLevel1HiiHandle, 
 | |
|       L"EndIf", 
 | |
|       L"If", 
 | |
|       CurrentScriptFile!=NULL 
 | |
|         && CurrentScriptFile->CurrentCommand!=NULL
 | |
|         ? CurrentScriptFile->CurrentCommand->Line:0);
 | |
|     return (SHELL_DEVICE_ERROR);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // initialize the shell lib (we must be in non-auto-init...)
 | |
|   //
 | |
|   Status = ShellInitialize();
 | |
|   ASSERT_EFI_ERROR(Status);
 | |
| 
 | |
|   CurrentParameter    = 1;
 | |
|   EndParameter        = 0;
 | |
| 
 | |
|   if (gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         gEfiShellParametersProtocol->Argv[1],
 | |
|         L"/i") == 0 ||
 | |
|       gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         gEfiShellParametersProtocol->Argv[2],
 | |
|         L"/i") == 0 ||
 | |
|       (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         gEfiShellParametersProtocol->Argv[3],
 | |
|         L"/i") == 0)) {
 | |
|     CaseInsensitive = TRUE;
 | |
|     CurrentParameter++;
 | |
|   } else {
 | |
|     CaseInsensitive = FALSE;
 | |
|   }
 | |
|   if (gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         gEfiShellParametersProtocol->Argv[1],
 | |
|         L"/s") == 0 ||
 | |
|       gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         gEfiShellParametersProtocol->Argv[2],
 | |
|         L"/s") == 0 ||
 | |
|       (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
 | |
|         gUnicodeCollation,
 | |
|         gEfiShellParametersProtocol->Argv[3],
 | |
|         L"/s") == 0)) {
 | |
|     ForceString     = TRUE;
 | |
|     CurrentParameter++;
 | |
|   } else {
 | |
|     ForceString     = FALSE;
 | |
|   }
 | |
| 
 | |
|   for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = EndTagMax
 | |
|       ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS
 | |
|       ; CurrentParameter++) {
 | |
|     if (gUnicodeCollation->StriColl(
 | |
|           gUnicodeCollation,
 | |
|           gEfiShellParametersProtocol->Argv[CurrentParameter],
 | |
|           L"then") == 0) {
 | |
|       //
 | |
|       // we are at the then
 | |
|       //
 | |
|       if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {
 | |
|         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle, L"if");  
 | |
|         ShellStatus = SHELL_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         Status = PerformResultOperation(CurrentValue);
 | |
|         if (EFI_ERROR(Status)) {
 | |
|           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);  
 | |
|           ShellStatus = SHELL_INVALID_PARAMETER;
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       PreviousEnding = Ending;
 | |
|       //
 | |
|       // build up the next statement for analysis
 | |
|       //
 | |
|       if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) {
 | |
|         CurrentScriptFile = ShellCommandGetCurrentScriptFile();
 | |
|         ShellPrintHiiEx(
 | |
|           -1, 
 | |
|           -1, 
 | |
|           NULL, 
 | |
|           STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 
 | |
|           gShellLevel1HiiHandle, 
 | |
|           L"Then", 
 | |
|           L"If",
 | |
|           CurrentScriptFile!=NULL 
 | |
|             && CurrentScriptFile->CurrentCommand!=NULL
 | |
|             ? CurrentScriptFile->CurrentCommand->Line:0);
 | |
|         ShellStatus = SHELL_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         //
 | |
|         // Analyze the statement
 | |
|         //
 | |
|         Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);
 | |
|         if (EFI_ERROR(Status)) {
 | |
| //          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
 | |
|           ShellStatus = SHELL_INVALID_PARAMETER;
 | |
|         } else {
 | |
|           //
 | |
|           // Optomize to get out of the loop early...
 | |
|           //
 | |
|           if ((Ending == EndTagOr && CurrentValue) || (Ending == EndTagAnd && !CurrentValue)) {
 | |
|             Status = PerformResultOperation(CurrentValue);
 | |
|             if (EFI_ERROR(Status)) {
 | |
|               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);  
 | |
|               ShellStatus = SHELL_INVALID_PARAMETER;
 | |
|             }
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       if (ShellStatus == SHELL_SUCCESS){
 | |
|         CurrentParameter = EndParameter;
 | |
|         //
 | |
|         // Skip over the or or and parameter.
 | |
|         //
 | |
|         if (Ending == EndTagOr || Ending == EndTagAnd) {
 | |
|           CurrentParameter++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return (ShellStatus);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function for 'else' command.
 | |
| 
 | |
|   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
 | |
|   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
 | |
| **/
 | |
| SHELL_STATUS
 | |
| EFIAPI
 | |
| ShellCommandRunElse (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   SCRIPT_FILE *CurrentScriptFile;
 | |
| 
 | |
|   Status = CommandInit ();
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   if (gEfiShellParametersProtocol->Argc > 1) {
 | |
|     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");  
 | |
|     return (SHELL_INVALID_PARAMETER);
 | |
|   }
 | |
| 
 | |
|   if (!gEfiShellProtocol->BatchIsActive()) {
 | |
|     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");
 | |
|     return (SHELL_UNSUPPORTED);
 | |
|   }
 | |
| 
 | |
|   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
 | |
| 
 | |
|   if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
 | |
|     ShellPrintHiiEx(
 | |
|       -1, 
 | |
|       -1, 
 | |
|       NULL, 
 | |
|       STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 
 | |
|       gShellLevel1HiiHandle, 
 | |
|       L"If", 
 | |
|       L"Else", 
 | |
|       CurrentScriptFile!=NULL 
 | |
|         && CurrentScriptFile->CurrentCommand!=NULL
 | |
|         ? CurrentScriptFile->CurrentCommand->Line:0);
 | |
|     return (SHELL_DEVICE_ERROR);
 | |
|   }
 | |
|   if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
 | |
|     ShellPrintHiiEx(
 | |
|       -1, 
 | |
|       -1, 
 | |
|       NULL, 
 | |
|       STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 
 | |
|       gShellLevel1HiiHandle, 
 | |
|       L"If", 
 | |
|       L"Else", 
 | |
|       CurrentScriptFile!=NULL 
 | |
|         && CurrentScriptFile->CurrentCommand!=NULL
 | |
|         ? CurrentScriptFile->CurrentCommand->Line:0);
 | |
|     return (SHELL_DEVICE_ERROR);
 | |
|   }
 | |
| 
 | |
|   if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, FALSE, FALSE, FALSE)) {
 | |
|     ShellPrintHiiEx(
 | |
|       -1, 
 | |
|       -1, 
 | |
|       NULL, 
 | |
|       STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 
 | |
|       gShellLevel1HiiHandle, 
 | |
|       L"EndIf", 
 | |
|       "Else", 
 | |
|       CurrentScriptFile!=NULL 
 | |
|         && CurrentScriptFile->CurrentCommand!=NULL
 | |
|         ? CurrentScriptFile->CurrentCommand->Line:0);
 | |
|     return (SHELL_DEVICE_ERROR);
 | |
|   }
 | |
| 
 | |
|   return (SHELL_SUCCESS);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function for 'endif' command.
 | |
| 
 | |
|   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
 | |
|   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
 | |
| **/
 | |
| SHELL_STATUS
 | |
| EFIAPI
 | |
| ShellCommandRunEndIf (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   SCRIPT_FILE *CurrentScriptFile;
 | |
| 
 | |
|   Status = CommandInit ();
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   if (gEfiShellParametersProtocol->Argc > 1) {
 | |
|     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");  
 | |
|     return (SHELL_INVALID_PARAMETER);
 | |
|   }
 | |
| 
 | |
|   if (!gEfiShellProtocol->BatchIsActive()) {
 | |
|     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");
 | |
|     return (SHELL_UNSUPPORTED);
 | |
|   }
 | |
| 
 | |
|   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
 | |
|   if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
 | |
|     ShellPrintHiiEx(
 | |
|       -1, 
 | |
|       -1, 
 | |
|       NULL, 
 | |
|       STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 
 | |
|       gShellLevel1HiiHandle, 
 | |
|       L"If", 
 | |
|       L"EndIf", 
 | |
|       CurrentScriptFile!=NULL 
 | |
|         && CurrentScriptFile->CurrentCommand!=NULL
 | |
|         ? CurrentScriptFile->CurrentCommand->Line:0);
 | |
|     return (SHELL_DEVICE_ERROR);
 | |
|   }
 | |
| 
 | |
|   return (SHELL_SUCCESS);
 | |
| }
 |