2 Provides interface to shell MAN file parser.
4 Copyright (c) 2009 - 2013, 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 if (ManFileName
== NULL
) {
41 if (StrnCmp(ManFileName
+StrLen(ManFileName
)-4, L
".man", 4)==0) {
42 Buffer
= AllocateZeroPool(StrSize(ManFileName
));
44 StrCpy(Buffer
, ManFileName
);
47 Buffer
= AllocateZeroPool(StrSize(ManFileName
) + 4*sizeof(CHAR16
));
49 StrCpy(Buffer
, ManFileName
);
50 StrCat(Buffer
, L
".man");
57 Search the path environment variable for possible locations and test for
58 which one contains a man file with the name specified. If a valid file is found
59 stop searching and return the (opened) SHELL_FILE_HANDLE for that file.
61 @param[in] FileName Name of the file to find and open.
62 @param[out] Handle Pointer to the handle of the found file. The
63 value of this is undefined for return values
66 @retval EFI_SUCCESS The file was found. Handle is a valid SHELL_FILE_HANDLE
67 @retval EFI_INVALID_PARAMETER A parameter had an invalid value.
68 @retval EFI_NOT_FOUND The file was not found.
73 IN CONST CHAR16
*FileName
,
74 OUT SHELL_FILE_HANDLE
*Handle
82 || StrLen(FileName
) == 0
84 return (EFI_INVALID_PARAMETER
);
87 FullFileName
= ShellFindFilePath(FileName
);
88 if (FullFileName
== NULL
) {
89 return (EFI_NOT_FOUND
);
95 Status
= EfiShellOpenFileByName(FullFileName
, Handle
, EFI_FILE_MODE_READ
);
96 FreePool(FullFileName
);
102 parses through Buffer (which is MAN file formatted) and returns the
103 detailed help for any sub section specified in the comma seperated list of
104 sections provided. If the end of the file or a .TH section is found then
107 Upon a sucessful return the caller is responsible to free the memory in *HelpText
109 @param[in] Buffer Buffer to read from
110 @param[in] Sections name of command's sub sections to find
111 @param[in] HelpText pointer to pointer to string where text goes.
112 @param[in] HelpSize pointer to size of allocated HelpText (may be updated)
114 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
115 @retval EFI_SUCCESS the section was found and its description sotred in
120 ManBufferFindSections(
121 IN CONST CHAR16
*Buffer
,
122 IN CONST CHAR16
*Sections
,
123 IN CHAR16
**HelpText
,
128 CONST CHAR16
*CurrentLocation
;
129 BOOLEAN CurrentlyReading
;
140 return (EFI_INVALID_PARAMETER
);
143 Status
= EFI_SUCCESS
;
144 CurrentlyReading
= FALSE
;
147 for (CurrentLocation
= Buffer
,TempString
= NULL
148 ; CurrentLocation
!= NULL
&& *CurrentLocation
!= CHAR_NULL
149 ; CurrentLocation
=StrStr(CurrentLocation
, L
"\r\n"),TempString
= NULL
151 while(CurrentLocation
[0] == L
'\r' || CurrentLocation
[0] == L
'\n') {
154 if (CurrentLocation
[0] == L
'#') {
156 // Skip comment lines
160 if (StrnCmp(CurrentLocation
, L
".TH", 3) == 0) {
162 // we hit the end of this commands section so stop.
166 if (StrnCmp(CurrentLocation
, L
".SH ", 4) == 0) {
167 if (Sections
== NULL
) {
168 CurrentlyReading
= TRUE
;
170 } else if (CurrentlyReading
) {
171 CurrentlyReading
= FALSE
;
173 CurrentLocation
+= 4;
175 // is this a section we want to read in?
177 if (StrLen(CurrentLocation
)!=0) {
178 TempString2
= StrStr(CurrentLocation
, L
" ");
179 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\r"));
180 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\n"));
181 ASSERT(TempString
== NULL
);
182 TempString
= StrnCatGrow(&TempString
, NULL
, CurrentLocation
, TempString2
==NULL
?0:TempString2
- CurrentLocation
);
183 if (TempString
== NULL
) {
184 Status
= EFI_OUT_OF_RESOURCES
;
187 SectionName
= TempString
;
188 SectionLen
= StrLen(SectionName
);
189 SectionName
= StrStr(Sections
, SectionName
);
190 if (SectionName
== NULL
) {
193 if (*(SectionName
+ SectionLen
) == CHAR_NULL
|| *(SectionName
+ SectionLen
) == L
',') {
194 CurrentlyReading
= TRUE
;
197 } else if (CurrentlyReading
) {
199 if (StrLen(CurrentLocation
)!=0) {
200 TempString2
= StrStr(CurrentLocation
, L
"\r");
201 TempString2
= MIN(TempString2
, StrStr(CurrentLocation
, L
"\n"));
202 ASSERT(TempString
== NULL
);
203 TempString
= StrnCatGrow(&TempString
, NULL
, CurrentLocation
, TempString2
==NULL
?0:TempString2
- CurrentLocation
);
204 if (TempString
== NULL
) {
205 Status
= EFI_OUT_OF_RESOURCES
;
209 // copy and save the current line.
211 ASSERT((*HelpText
== NULL
&& *HelpSize
== 0) || (*HelpText
!= NULL
));
212 StrnCatGrow (HelpText
, HelpSize
, TempString
, 0);
213 if (HelpText
== NULL
) {
214 Status
= EFI_OUT_OF_RESOURCES
;
217 StrnCatGrow (HelpText
, HelpSize
, L
"\r\n", 0);
218 if (HelpText
== NULL
) {
219 Status
= EFI_OUT_OF_RESOURCES
;
224 SHELL_FREE_NON_NULL(TempString
);
226 if (!Found
&& !EFI_ERROR(Status
)) {
227 return (EFI_NOT_FOUND
);
233 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
234 detailed help for any sub section specified in the comma seperated list of
235 sections provided. If the end of the file or a .TH section is found then
238 Upon a sucessful return the caller is responsible to free the memory in *HelpText
240 @param[in] Handle FileHandle to read from
241 @param[in] Sections name of command's sub sections to find
242 @param[out] HelpText pointer to pointer to string where text goes.
243 @param[out] HelpSize pointer to size of allocated HelpText (may be updated)
244 @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise.
246 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
247 @retval EFI_SUCCESS the section was found and its description sotred in
253 IN SHELL_FILE_HANDLE Handle
,
254 IN CONST CHAR16
*Sections
,
255 OUT CHAR16
**HelpText
,
263 BOOLEAN CurrentlyReading
;
272 return (EFI_INVALID_PARAMETER
);
275 Status
= EFI_SUCCESS
;
276 CurrentlyReading
= FALSE
;
280 ReadLine
= AllocateZeroPool(Size
);
281 if (ReadLine
== NULL
) {
282 return (EFI_OUT_OF_RESOURCES
);
285 for (;!ShellFileHandleEof(Handle
);Size
= 1024) {
286 Status
= ShellFileHandleReadLine(Handle
, ReadLine
, &Size
, TRUE
, &Ascii
);
287 if (ReadLine
[0] == L
'#') {
289 // Skip comment lines
294 // ignore too small of buffer...
296 if (Status
== EFI_BUFFER_TOO_SMALL
) {
297 Status
= EFI_SUCCESS
;
299 if (EFI_ERROR(Status
)) {
301 } else if (StrnCmp(ReadLine
, L
".TH", 3) == 0) {
303 // we hit the end of this commands section so stop.
306 } else if (StrnCmp(ReadLine
, L
".SH", 3) == 0) {
307 if (Sections
== NULL
) {
308 CurrentlyReading
= TRUE
;
312 // we found a section
314 if (CurrentlyReading
) {
315 CurrentlyReading
= FALSE
;
318 // is this a section we want to read in?
320 for ( SectionName
= ReadLine
+ 3
321 ; *SectionName
== L
' '
323 SectionLen
= StrLen(SectionName
);
324 SectionName
= StrStr(Sections
, SectionName
);
325 if (SectionName
== NULL
) {
328 if (*(SectionName
+ SectionLen
) == CHAR_NULL
|| *(SectionName
+ SectionLen
) == L
',') {
329 CurrentlyReading
= TRUE
;
331 } else if (CurrentlyReading
) {
334 // copy and save the current line.
336 ASSERT((*HelpText
== NULL
&& *HelpSize
== 0) || (*HelpText
!= NULL
));
337 StrnCatGrow (HelpText
, HelpSize
, ReadLine
, 0);
338 StrnCatGrow (HelpText
, HelpSize
, L
"\r\n", 0);
342 if (!Found
&& !EFI_ERROR(Status
)) {
343 return (EFI_NOT_FOUND
);
349 parses through the MAN file formatted Buffer and returns the
350 "Brief Description" for the .TH section as specified by Command. If the
351 command section is not found return EFI_NOT_FOUND.
353 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
355 @param[in] Handle Buffer to read from
356 @param[in] Command name of command's section to find
357 @param[in] BriefDesc pointer to pointer to string where description goes.
358 @param[in] BriefSize pointer to size of allocated BriefDesc
360 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
361 @retval EFI_SUCCESS the section was found and its description sotred in
366 ManBufferFindTitleSection(
368 IN CONST CHAR16
*Command
,
369 IN CHAR16
**BriefDesc
,
376 CHAR16
*CurrentLocation
;
380 || (BriefDesc
!= NULL
&& BriefSize
== NULL
)
382 return (EFI_INVALID_PARAMETER
);
385 Status
= EFI_SUCCESS
;
387 TitleString
= AllocateZeroPool((7*sizeof(CHAR16
)) + StrSize(Command
));
388 if (TitleString
== NULL
) {
389 return (EFI_OUT_OF_RESOURCES
);
391 StrCpy(TitleString
, L
".TH ");
392 StrCat(TitleString
, Command
);
393 StrCat(TitleString
, L
" 0 ");
395 CurrentLocation
= StrStr(*Buffer
, TitleString
);
396 if (CurrentLocation
== NULL
){
397 Status
= EFI_NOT_FOUND
;
400 // we found it so copy out the rest of the line into BriefDesc
401 // After skipping any spaces or zeroes
403 for (CurrentLocation
+= StrLen(TitleString
)
404 ; *CurrentLocation
== L
' ' || *CurrentLocation
== L
'0' || *CurrentLocation
== L
'1' || *CurrentLocation
== L
'\"'
405 ; CurrentLocation
++);
407 TitleEnd
= StrStr(CurrentLocation
, L
"\"");
408 if (TitleEnd
== NULL
) {
409 Status
= EFI_DEVICE_ERROR
;
411 if (BriefDesc
!= NULL
) {
412 *BriefSize
= StrSize(TitleEnd
);
413 *BriefDesc
= AllocateZeroPool(*BriefSize
);
414 if (*BriefDesc
== NULL
) {
415 Status
= EFI_OUT_OF_RESOURCES
;
417 StrnCpy(*BriefDesc
, CurrentLocation
, TitleEnd
-CurrentLocation
);
421 for (CurrentLocation
= TitleEnd
422 ; *CurrentLocation
!= L
'\n'
423 ; CurrentLocation
++);
425 ; *CurrentLocation
== L
' ' || *CurrentLocation
== L
'\n' || *CurrentLocation
== L
'\r'
426 ; CurrentLocation
++);
427 *Buffer
= CurrentLocation
;
431 FreePool(TitleString
);
436 parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
437 "Brief Description" for the .TH section as specified by Command. if the
438 command section is not found return EFI_NOT_FOUND.
440 Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
442 @param[in] Handle FileHandle to read from
443 @param[in] Command name of command's section to find
444 @param[out] BriefDesc pointer to pointer to string where description goes.
445 @param[out] BriefSize pointer to size of allocated BriefDesc
446 @param[in, out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be
447 set if the file handle is at the 0 position.
449 @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
450 @retval EFI_SUCCESS the section was found and its description sotred in
455 ManFileFindTitleSection(
456 IN SHELL_FILE_HANDLE Handle
,
457 IN CONST CHAR16
*Command
,
458 OUT CHAR16
**BriefDesc OPTIONAL
,
459 OUT UINTN
*BriefSize OPTIONAL
,
460 IN OUT BOOLEAN
*Ascii
473 || (BriefDesc
!= NULL
&& BriefSize
== NULL
)
475 return (EFI_INVALID_PARAMETER
);
478 Status
= EFI_SUCCESS
;
482 ReadLine
= AllocateZeroPool(Size
);
483 if (ReadLine
== NULL
) {
484 return (EFI_OUT_OF_RESOURCES
);
487 TitleString
= AllocateZeroPool((4*sizeof(CHAR16
)) + StrSize(Command
));
488 if (TitleString
== NULL
) {
490 return (EFI_OUT_OF_RESOURCES
);
492 StrCpy(TitleString
, L
".TH ");
493 StrCat(TitleString
, Command
);
495 TitleLen
= StrLen(TitleString
);
496 for (;!ShellFileHandleEof(Handle
);Size
= 1024) {
497 Status
= ShellFileHandleReadLine(Handle
, ReadLine
, &Size
, TRUE
, Ascii
);
498 if (ReadLine
[0] == L
'#') {
500 // Skip comment lines
505 // ignore too small of buffer...
507 if (Status
== EFI_BUFFER_TOO_SMALL
) {
508 Status
= EFI_SUCCESS
;
510 if (EFI_ERROR(Status
)) {
513 if (StrnCmp(ReadLine
, TitleString
, TitleLen
) == 0) {
516 // we found it so copy out the rest of the line into BriefDesc
517 // After skipping any spaces or zeroes
519 for ( TitleEnd
= ReadLine
+TitleLen
520 ; *TitleEnd
== L
' ' || *TitleEnd
== L
'0' || *TitleEnd
== L
'1'
522 if (BriefDesc
!= NULL
) {
523 *BriefSize
= StrSize(TitleEnd
);
524 *BriefDesc
= AllocateZeroPool(*BriefSize
);
525 if (*BriefDesc
== NULL
) {
526 Status
= EFI_OUT_OF_RESOURCES
;
529 StrCpy(*BriefDesc
, TitleEnd
);
535 FreePool(TitleString
);
536 if (!Found
&& !EFI_ERROR(Status
)) {
537 return (EFI_NOT_FOUND
);
543 This function returns the help information for the specified command. The help text
544 will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)
546 If Sections is specified, then each section name listed will be compared in a casesensitive
547 manner, to the section names described in Appendix B. If the section exists,
548 it will be appended to the returned help text. If the section does not exist, no
549 information will be returned. If Sections is NULL, then all help text information
550 available will be returned.
552 if BriefDesc is NULL, then the breif description will not be savedd seperatly,
553 but placed first in the main HelpText.
555 @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.
556 @param[in] Command Points to the NULL-terminated UEFI Shell command name.
557 @param[in] Sections Points to the NULL-terminated comma-delimited
558 section names to return. If NULL, then all
559 sections will be returned.
560 @param[out] BriefDesc On return, points to a callee-allocated buffer
561 containing brief description text.
562 @param[out] HelpText On return, points to a callee-allocated buffer
563 containing all specified help text.
565 @retval EFI_SUCCESS The help text was returned.
566 @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
568 @retval EFI_INVALID_PARAMETER HelpText is NULL.
569 @retval EFI_INVALID_PARAMETER ManFileName is invalid.
570 @retval EFI_NOT_FOUND There is no help text available for Command.
575 IN CONST CHAR16
*ManFileName
,
576 IN CONST CHAR16
*Command
,
577 IN CONST CHAR16
*Sections OPTIONAL
,
578 OUT CHAR16
**BriefDesc OPTIONAL
,
579 OUT CHAR16
**HelpText
583 SHELL_FILE_HANDLE FileHandle
;
589 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
590 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
592 if ( ManFileName
== NULL
596 return (EFI_INVALID_PARAMETER
);
603 // See if it's in HII first
605 TempString
= ShellCommandGetCommandHelp(Command
);
606 if (TempString
!= NULL
) {
607 TempString2
= TempString
;
608 Status
= ManBufferFindTitleSection(&TempString2
, Command
, BriefDesc
, &BriefSize
);
609 if (!EFI_ERROR(Status
) && HelpText
!= NULL
){
610 Status
= ManBufferFindSections(TempString2
, Sections
, HelpText
, &HelpSize
);
614 TempString
= GetManFileName(ManFileName
);
615 if (TempString
== NULL
) {
616 return (EFI_INVALID_PARAMETER
);
619 Status
= SearchPathForFile(TempString
, &FileHandle
);
620 if (EFI_ERROR(Status
)) {
621 FileDevPath
= FileDevicePath(NULL
, TempString
);
622 DevPath
= AppendDevicePath (ShellInfoObject
.ImageDevPath
, FileDevPath
);
623 Status
= InternalOpenFileDevicePath(DevPath
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
624 FreePool(FileDevPath
);
628 if (!EFI_ERROR(Status
)) {
631 Status
= ManFileFindTitleSection(FileHandle
, Command
, BriefDesc
, &BriefSize
, &Ascii
);
632 if (!EFI_ERROR(Status
) && HelpText
!= NULL
){
633 Status
= ManFileFindSections(FileHandle
, Sections
, HelpText
, &HelpSize
, Ascii
);
635 ShellInfoObject
.NewEfiShellProtocol
->CloseFile(FileHandle
);
640 if (TempString
!= NULL
) {
641 FreePool(TempString
);