]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
ShellPkg: Fix typos.
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index 627fab0ad03550e5e990c037994a783f42d0f679..ba071e58ed6f0b7e3354b0885d0d967888ac1827 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This is THE shell (application)\r
 \r
-  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
   (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -101,30 +101,50 @@ TrimSpaces(
 }\r
 \r
 /**\r
-  Find a command line contains a split operation\r
+  Check whether the string between a pair of % is a valid envifronment variable name.\r
 \r
-  @param[in] CmdLine      The command line to parse.\r
+  @param[in] BeginPercent       pointer to the first percent.\r
+  @param[in] EndPercent          pointer to the last percent.\r
 \r
-  @retval                 A pointer to the | character in CmdLine or NULL if not present.\r
+  @retval TRUE                          is a valid environment variable name.\r
+  @retval FALSE                         is NOT a valid environment variable name.\r
 **/\r
-CONST CHAR16*\r
-EFIAPI\r
-FindSplit(\r
-  IN CONST CHAR16 *CmdLine\r
+BOOLEAN\r
+IsValidEnvironmentVariableName(\r
+  IN CONST CHAR16     *BeginPercent,\r
+  IN CONST CHAR16     *EndPercent\r
   )\r
 {\r
-  CONST CHAR16 *TempSpot;\r
-  TempSpot = NULL;\r
-  if (StrStr(CmdLine, L"|") != NULL) {\r
-    for (TempSpot = CmdLine ; TempSpot != NULL && *TempSpot != CHAR_NULL ; TempSpot++) {\r
-      if (*TempSpot == L'^' && *(TempSpot+1) == L'|') {\r
-        TempSpot++;\r
-      } else if (*TempSpot == L'|') {\r
-        break;\r
+  CONST CHAR16    *Walker;\r
+  \r
+  Walker = NULL;\r
+\r
+  ASSERT (BeginPercent != NULL);\r
+  ASSERT (EndPercent != NULL);\r
+  ASSERT (BeginPercent < EndPercent);\r
+  \r
+  if ((BeginPercent + 1) == EndPercent) {\r
+    return FALSE;\r
+  }\r
+\r
+  for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) {\r
+    if (\r
+        (*Walker >= L'0' && *Walker <= L'9') ||\r
+        (*Walker >= L'A' && *Walker <= L'Z') ||\r
+        (*Walker >= L'a' && *Walker <= L'z') ||\r
+        (*Walker == L'_')\r
+      ) {\r
+      if (Walker == BeginPercent + 1 && (*Walker >= L'0' && *Walker <= L'9')) {\r
+        return FALSE;\r
+      } else {\r
+        continue;\r
       }\r
+    } else {\r
+      return FALSE;\r
     }\r
   }\r
-  return (TempSpot);\r
+\r
+  return TRUE;\r
 }\r
 \r
 /**\r
@@ -142,7 +162,39 @@ ContainsSplit(
   )\r
 {\r
   CONST CHAR16 *TempSpot;\r
-  TempSpot = FindSplit(CmdLine);\r
+  CONST CHAR16 *FirstQuote;\r
+  CONST CHAR16 *SecondQuote;\r
+\r
+  FirstQuote    = FindFirstCharacter (CmdLine, L"\"", L'^');\r
+  SecondQuote   = NULL;\r
+  TempSpot      = FindFirstCharacter(CmdLine, L"|", L'^');\r
+\r
+  if (FirstQuote == NULL    || \r
+      TempSpot == NULL      || \r
+      TempSpot == CHAR_NULL || \r
+      FirstQuote > TempSpot\r
+      ) {\r
+    return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
+  }\r
+\r
+  while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {\r
+    if (FirstQuote == NULL || FirstQuote > TempSpot) {\r
+      break;\r
+    }    \r
+    SecondQuote = FindFirstCharacter (FirstQuote + 1, L"\"", L'^');\r
+    if (SecondQuote == NULL) {\r
+      break;\r
+    }\r
+    if (SecondQuote < TempSpot) {\r
+      FirstQuote = FindFirstCharacter (SecondQuote + 1, L"\"", L'^');\r
+      continue;\r
+    } else {\r
+      FirstQuote = FindFirstCharacter (SecondQuote + 1, L"\"", L'^');\r
+      TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');\r
+      continue;\r
+    } \r
+  }\r
+  \r
   return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
 }\r
 \r
@@ -244,9 +296,6 @@ UefiMain (
   UINTN                           Size;\r
   EFI_HANDLE                      ConInHandle;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *OldConIn;\r
-  UINTN                           ExitDataSize;\r
-  CHAR16                          *ExitData;\r
-  SHELL_STATUS                    ExitStatus;\r
 \r
   if (PcdGet8(PcdShellSupportLevel) > 3) {\r
     return (EFI_UNSUPPORTED);\r
@@ -300,12 +349,6 @@ UefiMain (
   // install our console logger.  This will keep a log of the output for back-browsing\r
   //\r
   Status = ConsoleLoggerInstall(ShellInfoObject.LogScreenCount, &ShellInfoObject.ConsoleInfo);\r
-  if(EFI_ERROR (Status)) {\r
-    ExitStatus = (SHELL_STATUS) (Status & (~MAX_BIT));\r
-  } else {\r
-    ExitStatus = SHELL_SUCCESS;\r
-  }\r
-       \r
   if (!EFI_ERROR(Status)) {\r
     //\r
     // Enable the cursor to be visible\r
@@ -419,7 +462,7 @@ UefiMain (
     // Display the mapping\r
     //\r
     if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) {\r
-      Status = RunCommand(L"map", NULL);\r
+      Status = RunCommand(L"map");\r
       ASSERT_EFI_ERROR(Status);\r
     }\r
 \r
@@ -485,11 +528,7 @@ UefiMain (
         //\r
         // process the startup script or launch the called app.\r
         //\r
-        Status = DoStartupScript(\r
-                  ShellInfoObject.ImageDevPath,\r
-                  ShellInfoObject.FileDevPath,\r
-                  &ExitStatus\r
-                  );\r
+        Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
       }\r
 \r
       if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
@@ -523,7 +562,6 @@ UefiMain (
           //\r
           Status = DoShellPrompt();\r
         } while (!ShellCommandGetExit());\r
-        ExitStatus = (SHELL_STATUS) ShellCommandGetExitCode();\r
       }\r
       if (OldConIn != NULL && ConInHandle != NULL) {\r
         CloseSimpleTextInOnFile (gST->ConIn);\r
@@ -595,33 +633,10 @@ FreeResources:
     DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
   }\r
 \r
-  if (!EFI_ERROR (Status)) {\r
-    // If the command exited with an error, we pass this error out in the ExitData\r
-    // so that it can be retrieved by the EfiShellExecute function (which may\r
-    // start the shell with gBS->StartImage)\r
-    if (ExitStatus != SHELL_SUCCESS) {\r
-      // Allocate a buffer for exit data to pass to gBS->Exit().\r
-      // This buffer will contain the empty string immediately followed by\r
-      // the shell's exit status. (The empty string is required by the UEFI spec)\r
-      ExitDataSize = (sizeof (CHAR16) + sizeof (SHELL_STATUS));\r
-      ExitData = AllocatePool (ExitDataSize);\r
-      if (ExitData == NULL) {\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-      ExitData[0] = '\0';\r
-      // Use CopyMem to avoid alignment faults\r
-      CopyMem ((ExitData + 1), &ExitStatus, sizeof (ExitStatus));\r
-\r
-      gBS->Exit (ImageHandle, EFI_ABORTED, ExitDataSize, ExitData);\r
-\r
-      ASSERT (FALSE);\r
-      return EFI_SUCCESS;\r
-    } else {\r
-      return EFI_SUCCESS;\r
-    }\r
-  } else {\r
-    return Status;\r
+  if (ShellCommandGetExit()) {\r
+    return ((EFI_STATUS)ShellCommandGetExitCode());\r
   }\r
+  return (Status);\r
 }\r
 \r
 /**\r
@@ -986,16 +1001,13 @@ ProcessCommandLine(
   @param ImagePath              the path to the image for shell.  first place to look for the startup script\r
   @param FilePath               the path to the file for shell.  second place to look for the startup script.\r
 \r
-  @param[out] ExitStatus      The exit code of the script. Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS           the variable is initialized.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 DoStartupScript(\r
-  IN  EFI_DEVICE_PATH_PROTOCOL *ImagePath,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
-  OUT SHELL_STATUS             *ExitStatus\r
+  IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -1030,7 +1042,7 @@ DoStartupScript(
       StrnCat(FileStringPath, L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
       StrnCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
     }\r
-    Status = RunCommand(FileStringPath, ExitStatus);\r
+    Status = RunCommand(FileStringPath);\r
     FreePool(FileStringPath);\r
     return (Status);\r
 \r
@@ -1107,13 +1119,7 @@ DoStartupScript(
   // If we got a file, run it\r
   //\r
   if (!EFI_ERROR(Status) && FileHandle != NULL) {\r
-    Status = RunScriptFile (\r
-              mStartupScript,\r
-              FileHandle,\r
-              L"",\r
-              ShellInfoObject.NewShellParametersProtocol,\r
-              ExitStatus\r
-              );\r
+    Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol);\r
     ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
   } else {\r
     FileStringPath = ShellFindFilePath(mStartupScript);\r
@@ -1124,13 +1130,7 @@ DoStartupScript(
       Status = EFI_SUCCESS;\r
       ASSERT(FileHandle == NULL);\r
     } else {\r
-      Status = RunScriptFile(\r
-                FileStringPath,\r
-                NULL,\r
-                L"",\r
-                ShellInfoObject.NewShellParametersProtocol,\r
-                ExitStatus\r
-                );\r
+      Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);\r
       FreePool(FileStringPath);\r
     }\r
   }\r
@@ -1195,7 +1195,7 @@ DoShellPrompt (
   //\r
   if (!EFI_ERROR (Status)) {\r
     CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;\r
-    Status = RunCommand(CmdLine, NULL);\r
+    Status = RunCommand(CmdLine);\r
     }\r
 \r
   //\r
@@ -1284,48 +1284,6 @@ ShellConvertAlias(
   return (EFI_SUCCESS);\r
 }\r
 \r
-/**\r
-  Parse for the next instance of one string within another string. Can optionally make sure that \r
-  the string was not escaped (^ character) per the shell specification.\r
-\r
-  @param[in] SourceString             The string to search within\r
-  @param[in] FindString               The string to look for\r
-  @param[in] CheckForEscapeCharacter  TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances\r
-**/\r
-CHAR16*\r
-EFIAPI\r
-FindNextInstance(\r
-  IN CONST CHAR16   *SourceString,\r
-  IN CONST CHAR16   *FindString,\r
-  IN CONST BOOLEAN  CheckForEscapeCharacter\r
-  )\r
-{\r
-  CHAR16 *Temp;\r
-  if (SourceString == NULL) {\r
-    return (NULL);\r
-  }\r
-  Temp = StrStr(SourceString, FindString);\r
-\r
-  //\r
-  // If nothing found, or we dont care about escape characters\r
-  //\r
-  if (Temp == NULL || !CheckForEscapeCharacter) {\r
-    return (Temp);\r
-  }\r
-\r
-  //\r
-  // If we found an escaped character, try again on the remainder of the string\r
-  //\r
-  if ((Temp > (SourceString)) && *(Temp-1) == L'^') {\r
-    return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter);\r
-  }\r
-\r
-  //\r
-  // we found the right character\r
-  //\r
-  return (Temp);\r
-}\r
-\r
 /**\r
   This function will eliminate unreplaced (and therefore non-found) environment variables.\r
 \r
@@ -1344,9 +1302,9 @@ StripUnreplacedEnvironmentVariables(
   CHAR16 *CurrentLocator;\r
 \r
   for (CurrentLocator = CmdLine ; CurrentLocator != NULL ; ) {\r
-    FirstQuote = FindNextInstance(CurrentLocator, L"\"", TRUE);\r
-    FirstPercent = FindNextInstance(CurrentLocator, L"%", TRUE);\r
-    SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL;\r
+    FirstQuote = FindFirstCharacter(CurrentLocator, L"\"", L'^');\r
+    FirstPercent = FindFirstCharacter(CurrentLocator, L"%", L'^');\r
+    SecondPercent = FirstPercent!=NULL?FindFirstCharacter(FirstPercent+1, L"%", L'^'):NULL;\r
     if (FirstPercent == NULL || SecondPercent == NULL) {\r
       //\r
       // If we ever dont have 2 % we are done.\r
@@ -1354,12 +1312,11 @@ StripUnreplacedEnvironmentVariables(
       break;\r
     }\r
 \r
-    if (FirstQuote < FirstPercent) {\r
-      SecondQuote = FirstQuote!= NULL?FindNextInstance(FirstQuote+1, L"\"", TRUE):NULL;\r
+    if (FirstQuote!= NULL && FirstQuote < FirstPercent) {\r
+      SecondQuote = FindFirstCharacter(FirstQuote+1, L"\"", L'^');\r
       //\r
       // Quote is first found\r
       //\r
-\r
       if (SecondQuote < FirstPercent) {\r
         //\r
         // restart after the pair of "\r
@@ -1373,19 +1330,21 @@ StripUnreplacedEnvironmentVariables(
       }\r
       continue;\r
     }\r
-    ASSERT(FirstPercent < FirstQuote);\r
-    if (SecondPercent < FirstQuote) {\r
-      FirstPercent[0] = L'\"';\r
-      SecondPercent[0] = L'\"';\r
-\r
-      //\r
-      // We need to remove from FirstPercent to SecondPercent\r
-      //\r
-      CopyMem(FirstPercent + 1, SecondPercent, StrSize(SecondPercent));\r
-      CurrentLocator = FirstPercent + 2;\r
+    \r
+    if (FirstQuote == NULL || SecondPercent < FirstQuote) {\r
+      if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {\r
+        //\r
+        // We need to remove from FirstPercent to SecondPercent\r
+        //\r
+        CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));\r
+        //\r
+        // dont need to update the locator.  both % characters are gone.\r
+        //\r
+      } else {\r
+        CurrentLocator = SecondPercent + 1;\r
+      }\r
       continue;\r
     }\r
-    ASSERT(FirstQuote < SecondPercent);\r
     CurrentLocator = FirstQuote;\r
   }\r
   return (EFI_SUCCESS);\r
@@ -1500,13 +1459,13 @@ ShellConvertVariables (
     ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);\r
     StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
     }\r
-\r
-    //\r
-    // Remove non-existant environment variables in scripts only\r
-    //\r
-    StripUnreplacedEnvironmentVariables(NewCommandLine1);\r
   }\r
 \r
+  //\r
+  // Remove non-existant environment variables\r
+  //\r
+  StripUnreplacedEnvironmentVariables(NewCommandLine1);\r
+\r
   //\r
   // Now cleanup any straggler intentionally ignored "%" characters\r
   //\r
@@ -1526,9 +1485,6 @@ ShellConvertVariables (
   @param[in] StdIn          The pointer to the Standard input.\r
   @param[in] StdOut         The pointer to the Standard output.\r
 \r
-  @param[out] ExitStatus      The exit code of the last command in the pipeline.\r
-                              Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS       The split command is executed successfully.\r
   @retval other             Some error occurs when executing the split command.\r
 **/\r
@@ -1537,8 +1493,7 @@ EFIAPI
 RunSplitCommand(\r
   IN CONST CHAR16             *CmdLine,\r
   IN       SHELL_FILE_HANDLE  *StdIn,\r
-  IN       SHELL_FILE_HANDLE  *StdOut,\r
-  OUT      SHELL_STATUS       *ExitStatus\r
+  IN       SHELL_FILE_HANDLE  *StdOut\r
   )\r
 {\r
   EFI_STATUS        Status;\r
@@ -1592,7 +1547,7 @@ RunSplitCommand(
   ASSERT(Split->SplitStdOut != NULL);\r
   InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link);\r
 \r
-  Status = RunCommand(OurCommandLine, NULL);\r
+  Status = RunCommand(OurCommandLine);\r
 \r
   //\r
   // move the output from the first to the in to the second.\r
@@ -1607,7 +1562,7 @@ RunSplitCommand(
   ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0);\r
 \r
   if (!EFI_ERROR(Status)) {\r
-    Status = RunCommand(NextCommandLine, ExitStatus);\r
+    Status = RunCommand(NextCommandLine);\r
   }\r
 \r
   //\r
@@ -1845,12 +1800,12 @@ IsValidSplit(
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
     TempWalker = (CHAR16*)Temp;\r
-    GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine));\r
-\r
-    if (GetOperationType(FirstParameter) == Unknown_Invalid) {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
-      SetLastError(SHELL_NOT_FOUND);\r
-      Status = EFI_NOT_FOUND;\r
+    if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) {\r
+      if (GetOperationType(FirstParameter) == Unknown_Invalid) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
+        SetLastError(SHELL_NOT_FOUND);\r
+        Status = EFI_NOT_FOUND;\r
+      }\r
     }\r
   }\r
 \r
@@ -1894,16 +1849,14 @@ VerifySplit(
   //\r
   // recurse to verify the next item\r
   //\r
-  TempSpot = FindSplit(CmdLine)+1;\r
+  TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;\r
   return (VerifySplit(TempSpot));\r
 }\r
 \r
 /**\r
   Process a split based operation.\r
 \r
-  @param[in] CmdLine      Pointer to the command line to process\r
-  @param[out] ExitStatus  The exit status of the command. Ignored if NULL.\r
-                          Invalid if this function returns an error.\r
+  @param[in] CmdLine    pointer to the command line to process\r
 \r
   @retval EFI_SUCCESS   The operation was successful\r
   @return               an error occured.\r
@@ -1911,8 +1864,7 @@ VerifySplit(
 EFI_STATUS\r
 EFIAPI\r
 ProcessNewSplitCommandLine(\r
-  IN CONST CHAR16       *CmdLine,\r
-  OUT      SHELL_STATUS *ExitStatus\r
+  IN CONST CHAR16 *CmdLine\r
   )\r
 {\r
   SPLIT_LIST                *Split;\r
@@ -1933,14 +1885,9 @@ ProcessNewSplitCommandLine(
   }\r
 \r
   if (Split == NULL) {\r
-    Status = RunSplitCommand(CmdLine, NULL, NULL, ExitStatus);\r
+    Status = RunSplitCommand(CmdLine, NULL, NULL);\r
   } else {\r
-    Status = RunSplitCommand(\r
-              CmdLine,\r
-              Split->SplitStdIn,\r
-              Split->SplitStdOut,\r
-              ExitStatus\r
-              );\r
+    Status = RunSplitCommand(CmdLine, Split->SplitStdIn, Split->SplitStdOut);\r
   }\r
   if (EFI_ERROR(Status)) {\r
     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine);\r
@@ -2013,24 +1960,25 @@ DoHelpUpdate(
   Walker = *CmdLine;\r
   while(Walker != NULL && *Walker != CHAR_NULL) {\r
     LastWalker = Walker;\r
-    GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine));\r
-    if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
-      LastWalker[0] = L' ';\r
-      LastWalker[1] = L' ';\r
-      NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine));\r
-      if (NewCommandLine == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
+    if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) {\r
+      if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
+        LastWalker[0] = L' ';\r
+        LastWalker[1] = L' ';\r
+        NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine));\r
+        if (NewCommandLine == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // We know the space is sufficient since we just calculated it.\r
+        //\r
+        StrnCpy(NewCommandLine, L"help ", 5);\r
+        StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));\r
+        SHELL_FREE_NON_NULL(*CmdLine);\r
+        *CmdLine = NewCommandLine;\r
         break;\r
       }\r
-\r
-      //\r
-      // We know the space is sufficient since we just calculated it.\r
-      //\r
-      StrnCpy(NewCommandLine, L"help ", 5);\r
-      StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));\r
-      SHELL_FREE_NON_NULL(*CmdLine);\r
-      *CmdLine = NewCommandLine;\r
-      break;\r
     }\r
   }\r
 \r
@@ -2120,8 +2068,6 @@ ProcessCommandLineToFinal(
   @param[in] FirstParameter   the first parameter on the command line\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
 \r
-  @param[out] ExitStatus      The exit code of the command. Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
@@ -2130,8 +2076,7 @@ EFIAPI
 RunInternalCommand(\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
-  OUT      SHELL_STATUS             *ExitStatus OPTIONAL\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2139,11 +2084,24 @@ RunInternalCommand(
   CHAR16                    **Argv;\r
   SHELL_STATUS              CommandReturnedStatus;\r
   BOOLEAN                   LastError;\r
+  CHAR16                    *Walker;\r
+  CHAR16                    *NewCmdLine;  \r
+\r
+  NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine);\r
+  if (NewCmdLine == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {\r
+    if (*Walker == L'^' && *(Walker+1) == L'#') {\r
+      CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));\r
+    }\r
+  }\r
 \r
   //\r
   // get the argc and argv updated for internal commands\r
   //\r
-  Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc);\r
+  Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc);\r
   if (!EFI_ERROR(Status)) {\r
     //\r
     // Run the internal command.\r
@@ -2158,9 +2116,6 @@ RunInternalCommand(
       if (LastError) {\r
         SetLastError(CommandReturnedStatus);\r
       }\r
-      if (ExitStatus != NULL) {\r
-        *ExitStatus = CommandReturnedStatus;\r
-      }\r
 \r
       //\r
       // Pass thru the exitcode from the app.\r
@@ -2204,6 +2159,7 @@ RunInternalCommand(
     Status = EFI_SUCCESS;\r
   }\r
 \r
+  FreePool (NewCmdLine);\r
   return (Status);\r
 }\r
 \r
@@ -2215,9 +2171,6 @@ RunInternalCommand(
   @param[in] FirstParameter   the first parameter on the command line\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
 \r
-  @param[out] ExitStatus      The exit code of the command or file.\r
-                              Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
@@ -2227,8 +2180,7 @@ RunCommandOrFile(
   IN       SHELL_OPERATION_TYPES    Type,\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
-  OUT      SHELL_STATUS             *ExitStatus\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2244,12 +2196,7 @@ RunCommandOrFile(
 \r
   switch (Type) {\r
     case   Internal_Command:\r
-      Status = RunInternalCommand(\r
-                CmdLine,\r
-                FirstParameter,\r
-                ParamProtocol,\r
-                &CalleeExitStatus\r
-                );\r
+      Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);\r
       break;\r
     case   Script_File_Name:\r
     case   Efi_Application:\r
@@ -2284,13 +2231,7 @@ RunCommandOrFile(
       }\r
       switch (Type) {\r
         case   Script_File_Name:\r
-          Status = RunScriptFile (\r
-                    CommandWithPath,\r
-                    NULL,\r
-                    CmdLine,\r
-                    ParamProtocol,\r
-                    &CalleeExitStatus\r
-                    );\r
+          Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);\r
           break;\r
         case   Efi_Application:\r
           //\r
@@ -2310,9 +2251,7 @@ RunCommandOrFile(
             DevPath,\r
             CmdLine,\r
             NULL,\r
-            &StartStatus,\r
-            NULL,\r
-            NULL\r
+            &StartStatus\r
            );\r
 \r
           SHELL_FREE_NON_NULL(DevPath);\r
@@ -2345,10 +2284,6 @@ RunCommandOrFile(
 \r
   SHELL_FREE_NON_NULL(CommandWithPath);\r
 \r
-  if (ExitStatus != NULL) {\r
-    *ExitStatus = CalleeExitStatus;\r
-  }\r
-\r
   return (Status);\r
 }\r
 \r
@@ -2360,20 +2295,16 @@ RunCommandOrFile(
   @param[in] FirstParameter   the first parameter on the command line.\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
 \r
-  @param[out] ExitStatus      The exit code of the command or file.\r
-                              Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 SetupAndRunCommandOrFile(\r
-  IN   SHELL_OPERATION_TYPES          Type,\r
-  IN   CHAR16                         *CmdLine,\r
-  IN   CHAR16                         *FirstParameter,\r
-  IN   EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
-  OUT  SHELL_STATUS                   *ExitStatus\r
+  IN SHELL_OPERATION_TYPES          Type,\r
+  IN CHAR16                         *CmdLine,\r
+  IN CHAR16                         *FirstParameter,\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2393,13 +2324,7 @@ SetupAndRunCommandOrFile(
   //\r
   if (!EFI_ERROR(Status)) {\r
     TrimSpaces(&CmdLine);\r
-    Status = RunCommandOrFile(\r
-              Type,\r
-              CmdLine,\r
-              FirstParameter,\r
-              ParamProtocol,\r
-              ExitStatus\r
-              );\r
+    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);\r
   }\r
 \r
   //\r
@@ -2424,7 +2349,6 @@ SetupAndRunCommandOrFile(
   command or dispatch an external application.\r
 \r
   @param[in] CmdLine      The command line to parse.\r
-  @param[out] ExitStatus  The exit code of the command. Ignored if NULL.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
@@ -2432,8 +2356,7 @@ SetupAndRunCommandOrFile(
 EFI_STATUS\r
 EFIAPI\r
 RunCommand(\r
-  IN CONST CHAR16         *CmdLine,\r
-  OUT      SHELL_STATUS   *ExitStatus\r
+  IN CONST CHAR16   *CmdLine\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2466,7 +2389,7 @@ RunCommand(
   for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) {\r
     if (*TempWalker == L'^') {\r
       if (*(TempWalker + 1) == L'#') {\r
-        CopyMem (TempWalker, TempWalker + 1, StrSize (TempWalker) - sizeof (TempWalker[0]));\r
+        TempWalker++;\r
       }\r
     } else if (*TempWalker == L'#') {\r
       *TempWalker = CHAR_NULL;\r
@@ -2493,7 +2416,7 @@ RunCommand(
   // We dont do normal processing with a split command line (output from one command input to another)\r
   //\r
   if (ContainsSplit(CleanOriginal)) {\r
-    Status = ProcessNewSplitCommandLine(CleanOriginal, ExitStatus);\r
+    Status = ProcessNewSplitCommandLine(CleanOriginal);\r
     SHELL_FREE_NON_NULL(CleanOriginal);\r
     return (Status);\r
   } \r
@@ -2507,33 +2430,30 @@ RunCommand(
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
   TempWalker = CleanOriginal;\r
-  GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal));\r
-\r
-  //\r
-  // Depending on the first parameter we change the behavior\r
-  //\r
-  switch (Type = GetOperationType(FirstParameter)) {\r
-    case   File_Sys_Change:\r
-      Status = ChangeMappedDrive (FirstParameter);\r
-      break;\r
-    case   Internal_Command:\r
-    case   Script_File_Name:\r
-    case   Efi_Application:\r
-      Status = SetupAndRunCommandOrFile(\r
-                Type,\r
-                CleanOriginal,\r
-                FirstParameter,\r
-                ShellInfoObject.NewShellParametersProtocol,\r
-                ExitStatus\r
-                );\r
-      break;\r
-    default:\r
-      //\r
-      // Whatever was typed, it was invalid.\r
-      //\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
-      SetLastError(SHELL_NOT_FOUND);\r
-      break;\r
+  if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) {\r
+    //\r
+    // Depending on the first parameter we change the behavior\r
+    //\r
+    switch (Type = GetOperationType(FirstParameter)) {\r
+      case   File_Sys_Change:\r
+        Status = ChangeMappedDrive (FirstParameter);\r
+        break;\r
+      case   Internal_Command:\r
+      case   Script_File_Name:\r
+      case   Efi_Application:\r
+        Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol);\r
+        break;\r
+      default:\r
+        //\r
+        // Whatever was typed, it was invalid.\r
+        //\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
+        SetLastError(SHELL_NOT_FOUND);\r
+        break;\r
+    }\r
+  } else {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
+    SetLastError(SHELL_NOT_FOUND);\r
   }\r
  \r
   SHELL_FREE_NON_NULL(CleanOriginal);\r
@@ -2580,16 +2500,13 @@ IsValidCommandName(
   @param[in] Handle             The handle to the already opened file.\r
   @param[in] Name               The name of the script file.\r
 \r
-  @param[out] ExitStatus      The exit code of the script. Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS           the script completed sucessfully\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 RunScriptFileHandle (\r
-  IN  SHELL_FILE_HANDLE  Handle,\r
-  IN  CONST CHAR16       *Name,\r
-  OUT SHELL_STATUS       *ExitStatus\r
+  IN SHELL_FILE_HANDLE  Handle,\r
+  IN CONST CHAR16       *Name\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -2605,11 +2522,8 @@ RunScriptFileHandle (
   CONST CHAR16        *CurDir;\r
   UINTN               LineCount;\r
   CHAR16              LeString[50];\r
-  SHELL_STATUS        CalleeExitStatus;\r
 \r
   ASSERT(!ShellCommandGetScriptExit());\r
-  \r
-  CalleeExitStatus = SHELL_SUCCESS;\r
 \r
   PreScriptEchoState = ShellCommandGetEchoState();\r
 \r
@@ -2710,8 +2624,10 @@ RunScriptFileHandle (
     //\r
     for (CommandLine3 = CommandLine2 ; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL ; CommandLine3++) {\r
       if (*CommandLine3 == L'^') {\r
-        if (*(CommandLine3+1) == L'#' || *(CommandLine3+1) == L':') {\r
+        if ( *(CommandLine3+1) == L':') {\r
           CopyMem(CommandLine3, CommandLine3+1, StrSize(CommandLine3) - sizeof(CommandLine3[0]));\r
+        } else if (*(CommandLine3+1) == L'#') {\r
+          CommandLine3++;\r
         }\r
       } else if (*CommandLine3 == L'#') {\r
         *CommandLine3 = CHAR_NULL;\r
@@ -2730,34 +2646,34 @@ RunScriptFileHandle (
       if (NewScriptFile->Argv != NULL) {\r
         switch (NewScriptFile->Argc) {\r
           default:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 9:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 8:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 7:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 6:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 5:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 4:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 3:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 2:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 1:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, TRUE);\r
             ASSERT_EFI_ERROR(Status);\r
             break;\r
           case 0:\r
@@ -2793,7 +2709,7 @@ RunScriptFileHandle (
             //\r
             PreCommandEchoState = ShellCommandGetEchoState();\r
             ShellCommandSetEchoState(FALSE);\r
-            Status = RunCommand(CommandLine3+1, NULL);\r
+            Status = RunCommand(CommandLine3+1);\r
 \r
             //\r
             // If command was "@echo -off" or "@echo -on" then don't restore echo state\r
@@ -2815,7 +2731,7 @@ RunScriptFileHandle (
               }\r
               ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2);\r
             }\r
-            Status = RunCommand(CommandLine3, NULL);\r
+            Status = RunCommand(CommandLine3);\r
           }\r
         }\r
 \r
@@ -2823,8 +2739,7 @@ RunScriptFileHandle (
           //\r
           // ShellCommandGetExitCode() always returns a UINT64\r
           //\r
-          CalleeExitStatus = (SHELL_STATUS) ShellCommandGetExitCode();\r
-          UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", CalleeExitStatus);\r
+          UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellCommandGetExitCode());\r
           DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););\r
           InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);\r
 \r
@@ -2836,11 +2751,9 @@ RunScriptFileHandle (
           break;\r
         }\r
         if (EFI_ERROR(Status)) {\r
-          CalleeExitStatus = (SHELL_STATUS) Status;\r
           break;\r
         }\r
         if (ShellCommandGetExit()) {\r
-          CalleeExitStatus = (SHELL_STATUS) ShellCommandGetExitCode();\r
           break;\r
         }\r
       }\r
@@ -2872,11 +2785,6 @@ RunScriptFileHandle (
   if (ShellCommandGetCurrentScriptFile()==NULL) {\r
     ShellCommandSetEchoState(PreScriptEchoState);\r
   }\r
-\r
-  if (ExitStatus != NULL) {\r
-    *ExitStatus = CalleeExitStatus;\r
-  }\r
-\r
   return (EFI_SUCCESS);\r
 }\r
 \r
@@ -2888,18 +2796,15 @@ RunScriptFileHandle (
   @param[in] CmdLine            the command line to run.\r
   @param[in] ParamProtocol      the shell parameters protocol pointer\r
 \r
-  @param[out] ExitStatus      The exit code of the script. Ignored if NULL.\r
-\r
   @retval EFI_SUCCESS           the script completed sucessfully\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 RunScriptFile (\r
-  IN  CONST CHAR16                   *ScriptPath,\r
-  IN  SHELL_FILE_HANDLE              Handle OPTIONAL,\r
-  IN  CONST CHAR16                   *CmdLine,\r
-  IN  EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
-  OUT SHELL_STATUS                   *ExitStatus\r
+  IN CONST CHAR16                   *ScriptPath,\r
+  IN SHELL_FILE_HANDLE              Handle OPTIONAL,\r
+  IN CONST CHAR16                   *CmdLine,\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -2926,7 +2831,7 @@ RunScriptFile (
         //\r
         // run it\r
         //\r
-        Status = RunScriptFileHandle(FileHandle, ScriptPath, ExitStatus);\r
+        Status = RunScriptFileHandle(FileHandle, ScriptPath);\r
 \r
         //\r
         // now close the file\r
@@ -2934,7 +2839,7 @@ RunScriptFile (
         ShellCloseFile(&FileHandle);\r
       }\r
     } else {\r
-      Status = RunScriptFileHandle(Handle, ScriptPath, ExitStatus);\r
+      Status = RunScriptFileHandle(Handle, ScriptPath);\r
     }\r
   }\r
 \r
@@ -2946,3 +2851,38 @@ RunScriptFile (
 \r
   return (Status);\r
 }\r
+\r
+/**\r
+  Return the pointer to the first occurance of any character from a list of characters.\r
+\r
+  @param[in] String           the string to parse\r
+  @param[in] CharacterList    the list of character to look for\r
+  @param[in] EscapeCharacter  An escape character to skip\r
+\r
+  @return the location of the first character in the string\r
+  @retval CHAR_NULL no instance of any character in CharacterList was found in String\r
+**/\r
+CONST CHAR16*\r
+EFIAPI\r
+FindFirstCharacter(\r
+  IN CONST CHAR16 *String,\r
+  IN CONST CHAR16 *CharacterList,\r
+  IN CONST CHAR16 EscapeCharacter\r
+  )\r
+{\r
+  UINT32 WalkChar;\r
+  UINT32 WalkStr;\r
+\r
+  for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) {\r
+    if (String[WalkStr] == EscapeCharacter) {\r
+      WalkStr++;\r
+      continue;\r
+    }\r
+    for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) {\r
+      if (String[WalkStr] == CharacterList[WalkChar]) {\r
+        return (&String[WalkStr]);\r
+      }\r
+    }\r
+  }\r
+  return (String + StrLen(String));\r
+}
\ No newline at end of file