2 Provides interface to shell MAN file parser.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Verifies that the filename has .MAN on the end.
20 allocates a new buffer and copies the name (appending .MAN if necessary)
22 ASSERT if ManFileName is NULL
24 @param[in] ManFileName original filename
26 @return the new filename with .man as the extension.
31 IN CONST CHAR16
*ManFileName
35 ASSERT(ManFileName
!= NULL
);
39 if (StrnCmp(ManFileName
+StrLen(ManFileName
)-4, L
".man", 4)==0) {
40 Buffer
= AllocateZeroPool(StrSize(ManFileName
));
41 StrCpy(Buffer
, ManFileName
);
43 Buffer
= AllocateZeroPool(StrSize(ManFileName
) + 4*sizeof(CHAR16
));
44 StrCpy(Buffer
, ManFileName
);
45 StrCat(Buffer
, L
".man");
51 Search the path environment variable for possible locations and test for
52 which one contains a man file with the name specified. If a valid file is found
53 stop searching and return the (opened) SHELL_FILE_HANDLE for that file.
55 @param[in] FileName Name of the file to find and open.
56 @param[out] Handle Pointer to the handle of the found file. The
57 value of this is undefined for return values
60 @retval EFI_SUCCESS The file was found. Handle is a valid SHELL_FILE_HANDLE
61 @retval EFI_INVALID_PARAMETER A parameter had an invalid value.
62 @retval EFI_NOT_FOUND The file was not found.
67 IN CONST CHAR16
*FileName
,
68 OUT SHELL_FILE_HANDLE
*Handle
76 || StrLen(FileName
) == 0
78 return (EFI_INVALID_PARAMETER
);
81 FullFileName
= ShellFindFilePath(FileName
);
82 if (FullFileName
== NULL
) {
83 return (EFI_NOT_FOUND
);
89 Status
= EfiShellOpenFileByName(FullFileName
, Handle
, EFI_FILE_MODE_READ
);
90 FreePool(FullFileName
);
96 parses through Buffer (which is MAN file formatted) and returns the
97 detailed help for any sub section specified in the comma seperated list of
98 sections provided. If the end of the file or a .TH section is found then
101 Upon a sucessful return the caller is responsible to free the memory in *HelpText
103 @param[in] Buffer Buffer to read from
104 @param[in] Sections name of command's sub sections to find
105 @param[in] HelpText pointer to pointer to string where text goes.
106 @param[in] HelpSize pointer to size of allocated HelpText (may be updated)
108 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
109 @retval EFI_SUCCESS the section was found and its description sotred in
114 ManBufferFindSections(
115 IN CONST CHAR16
*Buffer
,
116 IN CONST CHAR16
*Sections
,
117 IN CHAR16
**HelpText
,
122 CONST CHAR16
*CurrentLocation
;
123 BOOLEAN CurrentlyReading
;
134 return (EFI_INVALID_PARAMETER
);
137 Status
= EFI_SUCCESS
;
138 CurrentlyReading
= FALSE
;
141 for (CurrentLocation
= Buffer
,TempString
= NULL
142 ; CurrentLocation
!= NULL
&& *CurrentLocation
!= CHAR_NULL
143 ; CurrentLocation
=StrStr(CurrentLocation
, L
"\r\n"),TempString
= NULL
145 while(CurrentLocation
[0] == L
'\r' || CurrentLocation
[0] == L
'\n') {
148 if (CurrentLocation
[0] == L
'#') {
150 // Skip comment lines
154 if (StrnCmp(CurrentLocation
, L
".TH", 3) == 0) {
156 // we hit the end of this commands section so stop.
160 if (StrnCmp(CurrentLocation
, L
".SH ", 4) == 0) {
161 if (Sections
== NULL
) {
162 CurrentlyReading
= TRUE
;
164 } else if (CurrentlyReading
) {
165 CurrentlyReading
= FALSE
;
167 CurrentLocation
+= 4;
169 // is this a section we want to read in?
171 if (StrLen(CurrentLocation
)!=0) {
172 TempString2
= StrStr(CurrentLocation
, L
" ");
173 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\r"));
174 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\n"));
175 ASSERT(TempString
== NULL
);
176 TempString
= StrnCatGrow(&TempString
, NULL
, CurrentLocation
, TempString2
==NULL
?0:TempString2
- CurrentLocation
);
177 SectionName
= TempString
;
178 SectionLen
= StrLen(SectionName
);
179 SectionName
= StrStr(Sections
, SectionName
);
180 if (SectionName
== NULL
) {
183 if (*(SectionName
+ SectionLen
) == CHAR_NULL
|| *(SectionName
+ SectionLen
) == L
',') {
184 CurrentlyReading
= TRUE
;
187 } else if (CurrentlyReading
) {
189 if (StrLen(CurrentLocation
)!=0) {
190 TempString2
= StrStr(CurrentLocation
, L
"\r");
191 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\n"));
192 ASSERT(TempString
== NULL
);
193 TempString
= StrnCatGrow(&TempString
, NULL
, CurrentLocation
, TempString2
==NULL
?0:TempString2
- CurrentLocation
);
195 // copy and save the current line.
197 ASSERT((*HelpText
== NULL
&& *HelpSize
== 0) || (*HelpText
!= NULL
));
198 StrnCatGrow (HelpText
, HelpSize
, TempString
, 0);
199 StrnCatGrow (HelpText
, HelpSize
, L
"\r\n", 0);
202 SHELL_FREE_NON_NULL(TempString
);
204 if (!Found
&& !EFI_ERROR(Status
)) {
205 return (EFI_NOT_FOUND
);
211 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
212 detailed help for any sub section specified in the comma seperated list of
213 sections provided. If the end of the file or a .TH section is found then
216 Upon a sucessful return the caller is responsible to free the memory in *HelpText
218 @param[in] Handle FileHandle to read from
219 @param[in] Sections name of command's sub sections to find
220 @param[out] HelpText pointer to pointer to string where text goes.
221 @param[out] HelpSize pointer to size of allocated HelpText (may be updated)
222 @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise.
224 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
225 @retval EFI_SUCCESS the section was found and its description sotred in
231 IN SHELL_FILE_HANDLE Handle
,
232 IN CONST CHAR16
*Sections
,
233 OUT CHAR16
**HelpText
,
241 BOOLEAN CurrentlyReading
;
250 return (EFI_INVALID_PARAMETER
);
253 Status
= EFI_SUCCESS
;
254 CurrentlyReading
= FALSE
;
258 ReadLine
= AllocateZeroPool(Size
);
259 if (ReadLine
== NULL
) {
260 return (EFI_OUT_OF_RESOURCES
);
263 for (;!ShellFileHandleEof(Handle
);Size
= 1024) {
264 Status
= ShellFileHandleReadLine(Handle
, ReadLine
, &Size
, TRUE
, &Ascii
);
265 if (ReadLine
[0] == L
'#') {
267 // Skip comment lines
272 // ignore too small of buffer...
274 if (Status
== EFI_BUFFER_TOO_SMALL
) {
275 Status
= EFI_SUCCESS
;
277 if (EFI_ERROR(Status
)) {
279 } else if (StrnCmp(ReadLine
, L
".TH", 3) == 0) {
281 // we hit the end of this commands section so stop.
284 } else if (StrnCmp(ReadLine
, L
".SH", 3) == 0) {
285 if (Sections
== NULL
) {
286 CurrentlyReading
= TRUE
;
290 // we found a section
292 if (CurrentlyReading
) {
293 CurrentlyReading
= FALSE
;
296 // is this a section we want to read in?
298 for ( SectionName
= ReadLine
+ 3
299 ; *SectionName
== L
' '
301 SectionLen
= StrLen(SectionName
);
302 SectionName
= StrStr(Sections
, SectionName
);
303 if (SectionName
== NULL
) {
306 if (*(SectionName
+ SectionLen
) == CHAR_NULL
|| *(SectionName
+ SectionLen
) == L
',') {
307 CurrentlyReading
= TRUE
;
309 } else if (CurrentlyReading
) {
312 // copy and save the current line.
314 ASSERT((*HelpText
== NULL
&& *HelpSize
== 0) || (*HelpText
!= NULL
));
315 StrnCatGrow (HelpText
, HelpSize
, ReadLine
, 0);
316 StrnCatGrow (HelpText
, HelpSize
, L
"\r\n", 0);
320 if (!Found
&& !EFI_ERROR(Status
)) {
321 return (EFI_NOT_FOUND
);
327 parses through the MAN file formatted Buffer and returns the
328 "Brief Description" for the .TH section as specified by Command. If the
329 command section is not found return EFI_NOT_FOUND.
331 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
333 @param[in] Handle Buffer to read from
334 @param[in] Command name of command's section to find
335 @param[in] BriefDesc pointer to pointer to string where description goes.
336 @param[in] BriefSize pointer to size of allocated BriefDesc
338 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
339 @retval EFI_SUCCESS the section was found and its description sotred in
344 ManBufferFindTitleSection(
346 IN CONST CHAR16
*Command
,
347 IN CHAR16
**BriefDesc
,
354 CHAR16
*CurrentLocation
;
358 || (BriefDesc
!= NULL
&& BriefSize
== NULL
)
360 return (EFI_INVALID_PARAMETER
);
363 Status
= EFI_SUCCESS
;
365 TitleString
= AllocatePool((7*sizeof(CHAR16
)) + StrSize(Command
));
366 if (TitleString
== NULL
) {
367 return (EFI_OUT_OF_RESOURCES
);
369 StrCpy(TitleString
, L
".TH ");
370 StrCat(TitleString
, Command
);
371 StrCat(TitleString
, L
" 0 ");
373 CurrentLocation
= StrStr(*Buffer
, TitleString
);
374 if (CurrentLocation
== NULL
){
375 Status
= EFI_NOT_FOUND
;
378 // we found it so copy out the rest of the line into BriefDesc
379 // After skipping any spaces or zeroes
381 for (CurrentLocation
+= StrLen(TitleString
)
382 ; *CurrentLocation
== L
' ' || *CurrentLocation
== L
'0' || *CurrentLocation
== L
'1' || *CurrentLocation
== L
'\"'
383 ; CurrentLocation
++);
385 TitleEnd
= StrStr(CurrentLocation
, L
"\"");
386 ASSERT(TitleEnd
!= NULL
);
387 if (BriefDesc
!= NULL
) {
388 *BriefSize
= StrSize(TitleEnd
);
389 *BriefDesc
= AllocateZeroPool(*BriefSize
);
390 if (*BriefDesc
== NULL
) {
391 Status
= EFI_OUT_OF_RESOURCES
;
393 StrnCpy(*BriefDesc
, CurrentLocation
, TitleEnd
-CurrentLocation
);
397 for (CurrentLocation
= TitleEnd
398 ; *CurrentLocation
!= L
'\n'
399 ; CurrentLocation
++);
401 ; *CurrentLocation
== L
' ' || *CurrentLocation
== L
'\n' || *CurrentLocation
== L
'\r'
402 ; CurrentLocation
++);
403 *Buffer
= CurrentLocation
;
406 FreePool(TitleString
);
411 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
412 "Brief Description" for the .TH section as specified by Command. if the
413 command section is not found return EFI_NOT_FOUND.
415 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
417 @param[in] Handle FileHandle to read from
418 @param[in] Command name of command's section to find
419 @param[out] BriefDesc pointer to pointer to string where description goes.
420 @param[out] BriefSize pointer to size of allocated BriefDesc
421 @param[in,out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be
422 set if the file handle is at the 0 position.
424 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
425 @retval EFI_SUCCESS the section was found and its description sotred in
430 ManFileFindTitleSection(
431 IN SHELL_FILE_HANDLE Handle
,
432 IN CONST CHAR16
*Command
,
433 OUT CHAR16
**BriefDesc OPTIONAL
,
434 OUT UINTN
*BriefSize OPTIONAL
,
435 IN OUT BOOLEAN
*Ascii
448 || (BriefDesc
!= NULL
&& BriefSize
== NULL
)
450 return (EFI_INVALID_PARAMETER
);
453 Status
= EFI_SUCCESS
;
457 ReadLine
= AllocateZeroPool(Size
);
458 if (ReadLine
== NULL
) {
459 return (EFI_OUT_OF_RESOURCES
);
462 TitleString
= AllocatePool((4*sizeof(CHAR16
)) + StrSize(Command
));
463 if (TitleString
== NULL
) {
465 return (EFI_OUT_OF_RESOURCES
);
467 StrCpy(TitleString
, L
".TH ");
468 StrCat(TitleString
, Command
);
469 TitleLen
= StrLen(TitleString
);
470 for (;!ShellFileHandleEof(Handle
);Size
= 1024) {
471 Status
= ShellFileHandleReadLine(Handle
, ReadLine
, &Size
, TRUE
, Ascii
);
472 if (ReadLine
[0] == L
'#') {
474 // Skip comment lines
479 // ignore too small of buffer...
481 if (Status
== EFI_BUFFER_TOO_SMALL
) {
482 Status
= EFI_SUCCESS
;
484 if (EFI_ERROR(Status
)) {
487 if (StrnCmp(ReadLine
, TitleString
, TitleLen
) == 0) {
490 // we found it so copy out the rest of the line into BriefDesc
491 // After skipping any spaces or zeroes
493 for ( TitleEnd
= ReadLine
+TitleLen
494 ; *TitleEnd
== L
' ' || *TitleEnd
== L
'0' || *TitleEnd
== L
'1'
496 if (BriefDesc
!= NULL
) {
497 *BriefSize
= StrSize(TitleEnd
);
498 *BriefDesc
= AllocateZeroPool(*BriefSize
);
499 if (*BriefDesc
== NULL
) {
500 Status
= EFI_OUT_OF_RESOURCES
;
503 StrCpy(*BriefDesc
, TitleEnd
);
509 FreePool(TitleString
);
510 if (!Found
&& !EFI_ERROR(Status
)) {
511 return (EFI_NOT_FOUND
);
517 This function returns the help information for the specified command. The help text
518 will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)
520 If Sections is specified, then each section name listed will be compared in a casesensitive
521 manner, to the section names described in Appendix B. If the section exists,
522 it will be appended to the returned help text. If the section does not exist, no
523 information will be returned. If Sections is NULL, then all help text information
524 available will be returned.
526 if BriefDesc is NULL, then the breif description will not be savedd seperatly,
527 but placed first in the main HelpText.
529 @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.
530 @param[in] Command Points to the NULL-terminated UEFI Shell command name.
531 @param[in] Sections Points to the NULL-terminated comma-delimited
532 section names to return. If NULL, then all
533 sections will be returned.
534 @param[out] BriefDesc On return, points to a callee-allocated buffer
535 containing brief description text.
536 @param[out] HelpText On return, points to a callee-allocated buffer
537 containing all specified help text.
539 @retval EFI_SUCCESS The help text was returned.
540 @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
542 @retval EFI_INVALID_PARAMETER HelpText is NULL
543 @retval EFI_NOT_FOUND There is no help text available for Command.
548 IN CONST CHAR16
*ManFileName
,
549 IN CONST CHAR16
*Command
,
550 IN CONST CHAR16
*Sections OPTIONAL
,
551 OUT CHAR16
**BriefDesc OPTIONAL
,
552 OUT CHAR16
**HelpText
556 SHELL_FILE_HANDLE FileHandle
;
562 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
563 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
565 if ( ManFileName
== NULL
569 return (EFI_INVALID_PARAMETER
);
576 // See if it's in HII first
578 TempString
= ShellCommandGetCommandHelp(Command
);
579 if (TempString
!= NULL
) {
580 TempString2
= TempString
;
581 Status
= ManBufferFindTitleSection(&TempString2
, Command
, BriefDesc
, &BriefSize
);
582 if (!EFI_ERROR(Status
) && HelpText
!= NULL
){
583 Status
= ManBufferFindSections(TempString2
, Sections
, HelpText
, &HelpSize
);
587 TempString
= GetManFileName(ManFileName
);
589 Status
= SearchPathForFile(TempString
, &FileHandle
);
590 if (EFI_ERROR(Status
)) {
591 FileDevPath
= FileDevicePath(NULL
, TempString
);
592 DevPath
= AppendDevicePath (ShellInfoObject
.ImageDevPath
, FileDevPath
);
593 Status
= InternalOpenFileDevicePath(DevPath
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
594 FreePool(FileDevPath
);
598 if (!EFI_ERROR(Status
)) {
601 Status
= ManFileFindTitleSection(FileHandle
, Command
, BriefDesc
, &BriefSize
, &Ascii
);
602 if (!EFI_ERROR(Status
) && HelpText
!= NULL
){
603 Status
= ManFileFindSections(FileHandle
, Sections
, HelpText
, &HelpSize
, Ascii
);
605 ShellInfoObject
.NewEfiShellProtocol
->CloseFile(FileHandle
);
610 if (TempString
!= NULL
) {
611 FreePool(TempString
);