\r
#include <Protocol/EfiShellDynamicCommand.h>\r
\r
+/**\r
+ function to insert string items into a list in the correct alphabetical place\r
+\r
+ the resultant list is a double NULL terminated list of NULL terminated strings.\r
+\r
+ upon successful return the memory must be caller freed (unless passed back in \r
+ via a loop where it will get reallocated).\r
+\r
+ @param[in,out] DestList double pointer to the list. may be NULL.\r
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.\r
+ @param[in] Item the item to insert.\r
+\r
+ @retval EFI_SUCCESS the operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LexicalInsertIntoList(\r
+ IN OUT CHAR16 **DestList, \r
+ IN OUT UINTN *DestSize,\r
+ IN CONST CHAR16 *Item\r
+ )\r
+{\r
+ CHAR16 *NewList;\r
+ INTN LexicalMatchValue;\r
+ CHAR16 *LexicalSpot;\r
+ UINTN SizeOfAddedNameInBytes;\r
+\r
+ //\r
+ // If there are none, then just return with success\r
+ //\r
+ if (Item == NULL || *Item == CHAR_NULL || StrLen(Item)==0) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ NewList = *DestList;\r
+\r
+ SizeOfAddedNameInBytes = StrSize(Item);\r
+ NewList = ReallocatePool(*DestSize, (*DestSize) + SizeOfAddedNameInBytes, NewList);\r
+ (*DestSize) = (*DestSize) + SizeOfAddedNameInBytes;\r
+\r
+ //\r
+ // Find the correct spot in the list\r
+ //\r
+ for (LexicalSpot = NewList\r
+ ; LexicalSpot != NULL && LexicalSpot < NewList + (*DestSize)\r
+ ; LexicalSpot += StrLen(LexicalSpot) + 1\r
+ ) {\r
+ //\r
+ // Get Lexical Comparison Value between PrevCommand and Command list entry\r
+ //\r
+ LexicalMatchValue = gUnicodeCollation->StriColl (\r
+ gUnicodeCollation,\r
+ (CHAR16 *)LexicalSpot,\r
+ (CHAR16 *)Item\r
+ );\r
+ //\r
+ // The new item goes before this one.\r
+ //\r
+ if (LexicalMatchValue > 0 || StrLen(LexicalSpot) == 0) {\r
+ if (StrLen(LexicalSpot) != 0) {\r
+ //\r
+ // Move this and all other items out of the way\r
+ //\r
+ CopyMem(\r
+ LexicalSpot + (SizeOfAddedNameInBytes/sizeof(CHAR16)),\r
+ LexicalSpot,\r
+ (*DestSize) - SizeOfAddedNameInBytes - ((LexicalSpot - NewList) * sizeof(CHAR16))\r
+ );\r
+ }\r
+\r
+ //\r
+ // Stick this one in place\r
+ //\r
+ StrCpyS(LexicalSpot, SizeOfAddedNameInBytes/sizeof(CHAR16), Item);\r
+ break;\r
+ }\r
+ }\r
+\r
+ *DestList = NewList;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ function to add each command name from the linked list to the string list.\r
+\r
+ the resultant list is a double NULL terminated list of NULL terminated strings.\r
+\r
+ @param[in,out] DestList double pointer to the list. may be NULL.\r
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.\r
+ @param[in] SourceList the double linked list of commands.\r
+\r
+ @retval EFI_SUCCESS the operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CopyListOfCommandNames(\r
+ IN OUT CHAR16 **DestList, \r
+ IN OUT UINTN *DestSize,\r
+ IN CONST COMMAND_LIST *SourceList\r
+ )\r
+{\r
+ CONST COMMAND_LIST *Node;\r
+\r
+ for ( Node = (COMMAND_LIST*)GetFirstNode(&SourceList->Link)\r
+ ; SourceList != NULL && !IsListEmpty(&SourceList->Link) && !IsNull(&SourceList->Link, &Node->Link)\r
+ ; Node = (COMMAND_LIST*)GetNextNode(&SourceList->Link, &Node->Link)\r
+ ) {\r
+ LexicalInsertIntoList(DestList, DestSize, Node->CommandString);\r
+ }\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ function to add each dynamic command name to the string list.\r
+\r
+ the resultant list is a double NULL terminated list of NULL terminated strings.\r
+\r
+ @param[in,out] DestList double pointer to the list. may be NULL.\r
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.\r
+\r
+ @retval EFI_SUCCESS the operation was successful.\r
+ @return an error from HandleProtocol\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+CopyListOfCommandNamesWithDynamic(\r
+ IN OUT CHAR16** DestList, \r
+ IN OUT UINTN *DestSize\r
+ )\r
+{\r
+ EFI_HANDLE *CommandHandleList;\r
+ CONST EFI_HANDLE *NextCommand;\r
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;\r
+ EFI_STATUS Status;\r
+\r
+ CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);\r
+\r
+ //\r
+ // If there are none, then just return with success\r
+ //\r
+ if (CommandHandleList == NULL) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Append those to the list.\r
+ //\r
+ for (NextCommand = CommandHandleList ; *NextCommand != NULL && !EFI_ERROR(Status) ; NextCommand++) {\r
+ Status = gBS->HandleProtocol(\r
+ *NextCommand,\r
+ &gEfiShellDynamicCommandProtocolGuid,\r
+ (VOID **)&DynamicCommand\r
+ );\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = LexicalInsertIntoList(DestList, DestSize, DynamicCommand->CommandName);\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL(CommandHandleList);\r
+ return (Status);\r
+}\r
+\r
+\r
/**\r
Attempt to print help from a dynamically added command.\r
\r
EFI_STATUS\r
EFIAPI\r
PrintDynamicCommandHelp(\r
- IN CHAR16 *CommandToGetHelpOn,\r
- IN CHAR16 *SectionToGetHelpOn,\r
- IN BOOLEAN PrintCommandText\r
+ IN CONST CHAR16 *CommandToGetHelpOn,\r
+ IN CONST CHAR16 *SectionToGetHelpOn,\r
+ IN BOOLEAN PrintCommandText\r
)\r
{\r
EFI_STATUS Status;\r
break;\r
}\r
\r
- if ((gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, CommandToGetHelpOn)) ||\r
+ if ((gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)CommandToGetHelpOn)) ||\r
(gEfiShellProtocol->GetAlias (CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {\r
// Print as Shell Help if in ManPage format.\r
Status = ShellPrintHelp (DynamicCommand->CommandName, SectionToGetHelpOn,\r
LIST_ENTRY *Package;\r
CHAR16 *ProblemParam;\r
SHELL_STATUS ShellStatus;\r
- CONST COMMAND_LIST *CommandList;\r
- CONST COMMAND_LIST *Node;\r
+ CHAR16 *SortedCommandList;\r
+ CONST CHAR16 *CurrentCommand;\r
CHAR16 *CommandToGetHelpOn;\r
CHAR16 *SectionToGetHelpOn;\r
CHAR16 *HiiString;\r
BOOLEAN Found;\r
BOOLEAN PrintCommandText;\r
+ UINTN SortedCommandListSize;\r
\r
PrintCommandText = TRUE;\r
ProblemParam = NULL;\r
FreePool(HiiString);\r
Found = TRUE;\r
} else {\r
- CommandList = ShellCommandGetCommandList(TRUE);\r
- ASSERT(CommandList != NULL);\r
- for ( Node = (COMMAND_LIST*)GetFirstNode(&CommandList->Link)\r
- ; CommandList != NULL && !IsListEmpty(&CommandList->Link) && !IsNull(&CommandList->Link, &Node->Link)\r
- ; Node = (COMMAND_LIST*)GetNextNode(&CommandList->Link, &Node->Link)\r
- ){\r
+ SortedCommandList = NULL;\r
+ SortedCommandListSize = 0;\r
+ CopyListOfCommandNames(&SortedCommandList, &SortedCommandListSize, ShellCommandGetCommandList(TRUE));\r
+ CopyListOfCommandNamesWithDynamic(&SortedCommandList, &SortedCommandListSize);\r
+\r
+ for (CurrentCommand = SortedCommandList \r
+ ; CurrentCommand != NULL && *CurrentCommand != CHAR_NULL && CurrentCommand < SortedCommandList + SortedCommandListSize/sizeof(CHAR16)\r
+ ; CurrentCommand += StrLen(CurrentCommand) + 1\r
+ ) {\r
//\r
// Checking execution break flag when print multiple command help information.\r
//\r
if (ShellGetExecutionBreakFlag ()) {\r
break;\r
} \r
- if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, CommandToGetHelpOn)) ||\r
- (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {\r
+\r
+ if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)CurrentCommand, CommandToGetHelpOn)) ||\r
+ (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)CurrentCommand, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {\r
//\r
// We have a command to look for help on.\r
//\r
- Status = ShellPrintHelp(Node->CommandString, SectionToGetHelpOn, PrintCommandText);\r
+ Status = ShellPrintHelp(CurrentCommand, SectionToGetHelpOn, PrintCommandText);\r
+ if (EFI_ERROR(Status)) {\r
+ //\r
+ // now try to match against the dynamic command list and print help\r
+ //\r
+ Status = PrintDynamicCommandHelp (CurrentCommand, SectionToGetHelpOn, PrintCommandText);\r
+ }\r
if (Status == EFI_DEVICE_ERROR) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, Node->CommandString);\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CurrentCommand);\r
} else if (EFI_ERROR(Status)) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, Node->CommandString);\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CurrentCommand);\r
} else {\r
Found = TRUE;\r
}\r
}\r
}\r
\r
- //\r
- // now try to match against the dynamic command list and print help\r
- //\r
- Status = PrintDynamicCommandHelp (CommandToGetHelpOn, SectionToGetHelpOn,\r
- PrintCommandText);\r
- if (!EFI_ERROR(Status)) {\r
- Found = TRUE;\r
- }\r
-\r
//\r
// Search the .man file for Shell applications (Shell external commands).\r
//\r