2 Generic but simple file parsing routines.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include "CommonLib.h"
15 #include "EfiUtilityMsgs.h"
16 #include "SimpleFileParsing.h"
22 // just in case we get in an endless loop.
24 #define MAX_NEST_DEPTH 20
28 #define MAX_STRING_IDENTIFIER_NAME 100
30 #define T_CHAR_SPACE ' '
32 #define T_CHAR_CR '\r'
33 #define T_CHAR_TAB '\t'
34 #define T_CHAR_LF '\n'
35 #define T_CHAR_SLASH '/'
36 #define T_CHAR_BACKSLASH '\\'
37 #define T_CHAR_DOUBLE_QUOTE '"'
38 #define T_CHAR_LC_X 'x'
40 #define T_CHAR_STAR '*'
43 // We keep a linked list of these for the source files we process
45 typedef struct _SOURCE_FILE
{
50 CHAR8 FileName
[MAX_PATH
];
54 struct _SOURCE_FILE
*Previous
;
55 struct _SOURCE_FILE
*Next
;
56 CHAR8 ControlCharacter
;
64 // Keep all our module globals in this structure
67 SOURCE_FILE SourceFile
;
96 SOURCE_FILE
*SourceFile
102 SOURCE_FILE
*SourceFile
108 SOURCE_FILE
*SourceFile
114 SOURCE_FILE
*SourceFile
120 SOURCE_FILE
*SourceFile
133 SOURCE_FILE
*SourceFile
,
134 SOURCE_FILE
*ParentSourceFile
140 SOURCE_FILE
*SourceFile
167 STATUS_SUCCESS always
171 memset ((VOID
*) &mGlobals
, 0, sizeof (mGlobals
));
172 return STATUS_SUCCESS
;
182 Return the line number of the file we're parsing. Used
183 for error reporting purposes.
189 The line number, or 0 if no file is being processed
193 return mGlobals
.SourceFile
.LineNum
;
203 Return the name of the file we're parsing. Used
204 for error reporting purposes.
210 A pointer to the file name. Null if no file is being
215 if (mGlobals
.SourceFile
.FileName
[0]) {
216 return mGlobals
.SourceFile
.FileName
;
229 Open a file for parsing.
232 FileName - name of the file to parse
240 t_strcpy (mGlobals
.SourceFile
.FileName
, FileName
);
241 Status
= ProcessIncludeFile (&mGlobals
.SourceFile
, NULL
);
252 Check to see if the specified token is found at
253 the current position in the input file.
256 Str - the token to look for
259 TRUE - the token is next
260 FALSE - the token is not next
263 We do a simple string comparison on this function. It is
264 the responsibility of the caller to ensure that the token
265 is not a subset of some other token.
267 The file pointer is advanced past the token in the input file.
272 SkipWhiteSpace (&mGlobals
.SourceFile
);
273 if (EndOfFile (&mGlobals
.SourceFile
)) {
277 if ((Len
= t_strcmp (mGlobals
.SourceFile
.FileBufferPtr
, Str
)) > 0) {
278 mGlobals
.SourceFile
.FileBufferPtr
+= Len
;
279 if (mGlobals
.VerboseToken
) {
280 printf ("Token: '%s'\n", Str
);
296 Check to see if the specified keyword is found at
297 the current position in the input file.
300 Str - keyword to look for
303 TRUE - the keyword is next
304 FALSE - the keyword is not next
307 A keyword is defined as a "special" string that has a non-alphanumeric
308 character following it.
313 SkipWhiteSpace (&mGlobals
.SourceFile
);
314 if (EndOfFile (&mGlobals
.SourceFile
)) {
318 if ((Len
= t_strcmp (mGlobals
.SourceFile
.FileBufferPtr
, Str
)) > 0) {
319 if (isalnum ((int)mGlobals
.SourceFile
.FileBufferPtr
[Len
])) {
323 mGlobals
.SourceFile
.FileBufferPtr
+= Len
;
324 if (mGlobals
.VerboseToken
) {
325 printf ("Token: '%s'\n", Str
);
342 Get the next token from the input stream.
345 Str - pointer to a copy of the next token
346 Len - size of buffer pointed to by Str
349 TRUE - next token successfully returned
353 Preceding white space is ignored.
354 The parser's buffer pointer is advanced past the end of the
362 SkipWhiteSpace (&mGlobals
.SourceFile
);
363 if (EndOfFile (&mGlobals
.SourceFile
)) {
367 // Have to have enough string for at least one char and a null-terminator
373 // Look at the first character. If it's an identifier, then treat it
376 TempChar
= mGlobals
.SourceFile
.FileBufferPtr
[0];
377 if (((TempChar
>= 'a') && (TempChar
<= 'z')) || ((TempChar
>= 'A') && (TempChar
<= 'Z')) || (TempChar
== '_')) {
379 mGlobals
.SourceFile
.FileBufferPtr
++;
381 while (!EndOfFile (&mGlobals
.SourceFile
) && (Index
< Len
)) {
382 TempChar
= mGlobals
.SourceFile
.FileBufferPtr
[0];
383 if (((TempChar
>= 'a') && (TempChar
<= 'z')) ||
384 ((TempChar
>= 'A') && (TempChar
<= 'Z')) ||
385 ((TempChar
>= '0') && (TempChar
<= '9')) ||
388 Str
[Index
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
389 mGlobals
.SourceFile
.FileBufferPtr
++;
393 // Invalid character for symbol name, so break out
399 // Null terminate and return success
403 } else if ((TempChar
== ')') || (TempChar
== '(') || (TempChar
== '*')) {
404 Str
[0] = mGlobals
.SourceFile
.FileBufferPtr
[0];
405 mGlobals
.SourceFile
.FileBufferPtr
++;
410 // Everything else is white-space (or EOF) separated
413 while (!EndOfFile (&mGlobals
.SourceFile
) && (Index
< Len
)) {
414 if (IsWhiteSpace (&mGlobals
.SourceFile
)) {
422 Str
[Index
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
423 mGlobals
.SourceFile
.FileBufferPtr
++;
428 // See if we just ran out of file contents, but did find a token
430 if ((Index
> 0) && EndOfFile (&mGlobals
.SourceFile
)) {
447 Parse a GUID from the input stream. Stop when you discover white space.
450 Str - pointer to a copy of the next token
451 Len - size of buffer pointed to by Str
454 TRUE - GUID string returned successfully
460 SkipWhiteSpace (&mGlobals
.SourceFile
);
461 if (EndOfFile (&mGlobals
.SourceFile
)) {
466 while (!EndOfFile (&mGlobals
.SourceFile
) && (Index
< Len
)) {
467 if (IsWhiteSpace (&mGlobals
.SourceFile
)) {
475 Str
[Index
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
476 mGlobals
.SourceFile
.FileBufferPtr
++;
491 Len
= t_strlen (Str
);
492 SavePos
= mGlobals
.SourceFile
.FileBufferPtr
;
493 SkipWhiteSpace (&mGlobals
.SourceFile
);
494 while (!EndOfFile (&mGlobals
.SourceFile
)) {
495 if (t_strncmp (Str
, mGlobals
.SourceFile
.FileBufferPtr
, Len
) == 0) {
496 mGlobals
.SourceFile
.FileBufferPtr
+= Len
;
500 mGlobals
.SourceFile
.FileBufferPtr
++;
501 SkipWhiteSpace (&mGlobals
.SourceFile
);
504 mGlobals
.SourceFile
.FileBufferPtr
= SavePos
;
515 Check the token at the current file position for a numeric value.
516 May be either decimal or hex.
519 Value - pointer where to store the value
522 FALSE - current token is not a number
523 TRUE - current token is a number
529 SkipWhiteSpace (&mGlobals
.SourceFile
);
530 if (EndOfFile (&mGlobals
.SourceFile
)) {
534 if (isdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
536 // Check for hex value
538 if ((mGlobals
.SourceFile
.FileBufferPtr
[0] == T_CHAR_0
) && (mGlobals
.SourceFile
.FileBufferPtr
[1] == T_CHAR_LC_X
)) {
539 if (!isxdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[2])) {
543 mGlobals
.SourceFile
.FileBufferPtr
+= 2;
544 sscanf (mGlobals
.SourceFile
.FileBufferPtr
, "%x", &Val
);
545 *Value
= (UINT32
) Val
;
546 while (isxdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
547 mGlobals
.SourceFile
.FileBufferPtr
++;
552 *Value
= atoi (mGlobals
.SourceFile
.FileBufferPtr
);
553 while (isdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
554 mGlobals
.SourceFile
.FileBufferPtr
++;
571 Close the file being parsed.
577 STATUS_SUCCESS - the file was closed
578 STATUS_ERROR - no file is currently open
582 if (mGlobals
.SourceFile
.FileBuffer
!= NULL
) {
583 free (mGlobals
.SourceFile
.FileBuffer
);
584 memset (&mGlobals
.SourceFile
, 0, sizeof (mGlobals
.SourceFile
));
585 return STATUS_SUCCESS
;
594 SOURCE_FILE
*SourceFile
,
595 SOURCE_FILE
*ParentSourceFile
601 Given a source file, open the file and parse it
605 SourceFile - name of file to parse
606 ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
614 STATIC UINTN NestDepth
= 0;
615 CHAR8 FoundFileName
[MAX_PATH
];
618 Status
= STATUS_SUCCESS
;
621 // Print the file being processed. Indent so you can tell the include nesting
624 if (mGlobals
.VerboseFile
) {
625 fprintf (stdout
, "%*cProcessing file '%s'\n", (int)NestDepth
* 2, ' ', SourceFile
->FileName
);
626 fprintf (stdout
, "Parent source file = '%s'\n", ParentSourceFile
->FileName
);
630 // Make sure we didn't exceed our maximum nesting depth
632 if (NestDepth
> MAX_NEST_DEPTH
) {
633 Error (NULL
, 0, 3001, "Not Supported", "%s exceeds max nesting depth (%u)", SourceFile
->FileName
, (unsigned) NestDepth
);
634 Status
= STATUS_ERROR
;
638 // Try to open the file locally, and if that fails try along our include paths.
640 strcpy (FoundFileName
, SourceFile
->FileName
);
641 if ((SourceFile
->Fptr
= fopen (LongFilePath (FoundFileName
), "rb")) == NULL
) {
645 // Process the file found
647 ProcessFile (SourceFile
);
650 // Close open files and return status
652 if (SourceFile
->Fptr
!= NULL
) {
653 fclose (SourceFile
->Fptr
);
654 SourceFile
->Fptr
= NULL
;
663 SOURCE_FILE
*SourceFile
669 Given a source file that's been opened, read the contents into an internal
670 buffer and pre-process it to remove comments.
674 SourceFile - structure containing info on the file to process
683 // Get the file size, and then read the entire thing into memory.
684 // Allocate extra space for a terminator character.
686 fseek (SourceFile
->Fptr
, 0, SEEK_END
);
687 SourceFile
->FileSize
= ftell (SourceFile
->Fptr
);
688 if (mGlobals
.VerboseFile
) {
689 printf ("FileSize = %u (0x%X)\n", (unsigned) SourceFile
->FileSize
, (unsigned) SourceFile
->FileSize
);
692 fseek (SourceFile
->Fptr
, 0, SEEK_SET
);
693 SourceFile
->FileBuffer
= (CHAR8
*) malloc (SourceFile
->FileSize
+ sizeof (CHAR8
));
694 if (SourceFile
->FileBuffer
== NULL
) {
695 Error (NULL
, 0, 4001, "Resource: memory cannot be allocated", NULL
);
699 fread ((VOID
*) SourceFile
->FileBuffer
, SourceFile
->FileSize
, 1, SourceFile
->Fptr
);
700 SourceFile
->FileBuffer
[(SourceFile
->FileSize
/ sizeof (CHAR8
))] = T_CHAR_NULL
;
702 // Pre-process the file to replace comments with spaces
704 PreprocessFile (SourceFile
);
705 SourceFile
->LineNum
= 1;
706 return STATUS_SUCCESS
;
712 SOURCE_FILE
*SourceFile
717 Preprocess a file to replace all carriage returns with NULLs so
718 we can print lines (as part of error messages) from the file to the screen.
721 SourceFile - structure that we use to keep track of an input file.
729 BOOLEAN SlashSlashComment
;
732 RewindFile (SourceFile
);
734 SlashSlashComment
= FALSE
;
735 while (!EndOfFile (SourceFile
)) {
737 // If a line-feed, then no longer in a comment if we're in a // comment
739 if (SourceFile
->FileBufferPtr
[0] == T_CHAR_LF
) {
740 SourceFile
->FileBufferPtr
++;
741 SourceFile
->LineNum
++;
742 if (InComment
&& SlashSlashComment
) {
744 SlashSlashComment
= FALSE
;
746 } else if (SourceFile
->FileBufferPtr
[0] == T_CHAR_CR
) {
748 // Replace all carriage returns with a NULL so we can print stuff
750 SourceFile
->FileBufferPtr
[0] = 0;
751 SourceFile
->FileBufferPtr
++;
753 // Check for */ comment end
755 } else if (InComment
&&
756 !SlashSlashComment
&&
757 (SourceFile
->FileBufferPtr
[0] == T_CHAR_STAR
) &&
758 (SourceFile
->FileBufferPtr
[1] == T_CHAR_SLASH
)
760 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
761 SourceFile
->FileBufferPtr
++;
762 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
763 SourceFile
->FileBufferPtr
++;
765 } else if (InComment
) {
766 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
767 SourceFile
->FileBufferPtr
++;
769 // Check for // comments
771 } else if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_SLASH
) && (SourceFile
->FileBufferPtr
[1] == T_CHAR_SLASH
)) {
773 SlashSlashComment
= TRUE
;
775 // Check for /* comment start
777 } else if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_SLASH
) && (SourceFile
->FileBufferPtr
[1] == T_CHAR_STAR
)) {
778 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
779 SourceFile
->FileBufferPtr
++;
780 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
781 SourceFile
->FileBufferPtr
++;
782 SlashSlashComment
= FALSE
;
785 SourceFile
->FileBufferPtr
++;
789 // Could check for end-of-file and still in a comment, but
790 // should not be necessary. So just restore the file pointers.
792 RewindFile (SourceFile
);
794 // Dump the reformatted file if verbose mode
796 if (mGlobals
.VerboseFile
) {
798 printf ("%04d: ", LineNum
);
799 while (!EndOfFile (SourceFile
)) {
800 if (SourceFile
->FileBufferPtr
[0] == T_CHAR_LF
) {
801 printf ("'\n%04d: '", ++LineNum
);
803 printf ("%c", SourceFile
->FileBufferPtr
[0]);
806 SourceFile
->FileBufferPtr
++;
810 printf ("FileSize = %u (0x%X)\n", (unsigned)SourceFile
->FileSize
, (unsigned)SourceFile
->FileSize
);
811 RewindFile (SourceFile
);
823 Retrieve a quoted-string from the input file.
826 Str - pointer to a copy of the quoted string parsed
827 Length - size of buffer pointed to by Str
830 TRUE - next token in input stream was a quoted string, and
831 the string value was returned in Str
836 SkipWhiteSpace (&mGlobals
.SourceFile
);
837 if (EndOfFile (&mGlobals
.SourceFile
)) {
841 if (mGlobals
.SourceFile
.FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) {
842 mGlobals
.SourceFile
.FileBufferPtr
++;
844 if (EndOfFile (&mGlobals
.SourceFile
)) {
848 // Check for closing quote
850 if (mGlobals
.SourceFile
.FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) {
851 mGlobals
.SourceFile
.FileBufferPtr
++;
856 *Str
= mGlobals
.SourceFile
.FileBufferPtr
[0];
859 mGlobals
.SourceFile
.FileBufferPtr
++;
863 // First character was not a quote, or the input string length was
864 // insufficient to contain the quoted string, so return failure code.
876 Return TRUE of FALSE to indicate whether or not we've reached the end of the
888 SkipWhiteSpace (&mGlobals
.SourceFile
);
889 return EndOfFile (&mGlobals
.SourceFile
);
896 SOURCE_FILE
*SourceFile
,
904 BOOLEAN PreviousBackslash
;
906 if (SourceFile
->FileBufferPtr
[0] != T_CHAR_DOUBLE_QUOTE
) {
907 if (Optional
== FALSE
) {
908 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "expected quoted string", "%S", SourceFile
->FileBufferPtr
);
915 SourceFile
->FileBufferPtr
++;
916 Start
= Ptr
= SourceFile
->FileBufferPtr
;
917 PreviousBackslash
= FALSE
;
918 while (!EndOfFile (SourceFile
)) {
919 if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) && (PreviousBackslash
== FALSE
)) {
921 } else if (SourceFile
->FileBufferPtr
[0] == T_CHAR_CR
) {
922 Warning (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "carriage return found in quoted string", "%S", Start
);
923 PreviousBackslash
= FALSE
;
924 } else if (SourceFile
->FileBufferPtr
[0] == T_CHAR_BACKSLASH
) {
925 PreviousBackslash
= TRUE
;
927 PreviousBackslash
= FALSE
;
930 SourceFile
->FileBufferPtr
++;
934 if (SourceFile
->FileBufferPtr
[0] != T_CHAR_DOUBLE_QUOTE
) {
935 Warning (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "missing closing quote on string", "%S", Start
);
937 SourceFile
->FileBufferPtr
++;
940 // Now allocate memory for the string and save it off
942 String
= (CHAR8
*) malloc ((Len
+ 1) * sizeof (CHAR8
));
943 if (String
== NULL
) {
944 Error (NULL
, 0, 4001, "Resource: memory cannot be allocated", NULL
);
948 // Copy the string from the file buffer to the local copy.
949 // We do no reformatting of it whatsoever at this point.
966 SOURCE_FILE
*SourceFile
970 // The file buffer pointer will typically get updated before the End-of-file flag in the
971 // source file structure, so check it first.
973 if (SourceFile
->FileBufferPtr
>= SourceFile
->FileBuffer
+ SourceFile
->FileSize
/ sizeof (CHAR8
)) {
974 SourceFile
->EndOfFile
= TRUE
;
978 if (SourceFile
->EndOfFile
) {
988 ProcessTokenInclude (
989 SOURCE_FILE
*SourceFile
992 CHAR8 IncludeFileName
[MAX_PATH
];
995 BOOLEAN ReportedError
;
996 SOURCE_FILE IncludedSourceFile
;
998 ReportedError
= FALSE
;
999 if (SkipWhiteSpace (SourceFile
) == 0) {
1000 Warning (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "expected whitespace following #include keyword", NULL
);
1003 // Should be quoted file name
1005 if (SourceFile
->FileBufferPtr
[0] != T_CHAR_DOUBLE_QUOTE
) {
1006 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "expected quoted include file name", NULL
);
1010 SourceFile
->FileBufferPtr
++;
1012 // Copy the filename as ascii to our local string
1014 To
= IncludeFileName
;
1016 while (!EndOfFile (SourceFile
)) {
1017 if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_CR
) || (SourceFile
->FileBufferPtr
[0] == T_CHAR_LF
)) {
1018 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "end-of-line found in quoted include file name", NULL
);
1022 if (SourceFile
->FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) {
1023 SourceFile
->FileBufferPtr
++;
1027 // If too long, then report the error once and process until the closing quote
1030 if (!ReportedError
&& (Len
>= sizeof (IncludeFileName
))) {
1031 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "length of include file name exceeds limit", NULL
);
1032 ReportedError
= TRUE
;
1035 if (!ReportedError
) {
1036 *To
= (CHAR8
) SourceFile
->FileBufferPtr
[0];
1040 SourceFile
->FileBufferPtr
++;
1043 if (!ReportedError
) {
1045 memset ((CHAR8
*) &IncludedSourceFile
, 0, sizeof (SOURCE_FILE
));
1046 strcpy (IncludedSourceFile
.FileName
, IncludeFileName
);
1047 ProcessIncludeFile (&IncludedSourceFile
, SourceFile
);
1053 // Error recovery -- skip to next #
1055 SourceFile
->SkipToHash
= TRUE
;
1061 SOURCE_FILE
*SourceFile
1064 switch (*SourceFile
->FileBufferPtr
) {
1079 SOURCE_FILE
*SourceFile
1085 while (!EndOfFile (SourceFile
)) {
1087 switch (*SourceFile
->FileBufferPtr
) {
1092 SourceFile
->FileBufferPtr
++;
1096 SourceFile
->FileBufferPtr
++;
1097 SourceFile
->LineNum
++;
1105 // Some tokens require trailing whitespace. If we're at the end of the
1106 // file, then we count that as well.
1108 if ((Count
== 0) && (EndOfFile (SourceFile
))) {
1123 Routine Description:
1124 Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,
1125 so only compare up to the length of Str.
1128 Buffer - pointer to first (possibly not null-terminated) string
1129 Str - pointer to null-terminated string to compare to Buffer
1132 Number of bytes matched if exact match
1133 0 if Buffer does not start with Str
1140 while (*Str
&& (*Str
== *Buffer
)) {
1178 if (*Str1
!= *Str2
) {
1212 SOURCE_FILE
*SourceFile
1215 SourceFile
->LineNum
= 1;
1216 SourceFile
->FileBufferPtr
= SourceFile
->FileBuffer
;
1217 SourceFile
->EndOfFile
= 0;
1229 while (!EndOfFile (&mGlobals
.SourceFile
) && (Len
< BufferLen
)) {
1230 if (isxdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
1231 Buffer
[Len
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
1233 mGlobals
.SourceFile
.FileBufferPtr
++;
1239 // Null terminate if we can
1241 if ((Len
> 0) && (Len
< BufferLen
)) {
1255 Routine Description:
1256 Parse a GUID from the input stream. Stop when you discover white space.
1259 GuidStyle - Style of the following GUID token
1260 Value - pointer to EFI_GUID struct for output
1263 TRUE - GUID string parsed successfully
1267 Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
1274 CHAR8 TempString
[20];
1275 CHAR8 TempString2
[3];
1283 // Skip white space, then start parsing
1285 SkipWhiteSpace (&mGlobals
.SourceFile
);
1286 GetFilePosition (&FPos
);
1287 if (EndOfFile (&mGlobals
.SourceFile
)) {
1291 if (GuidStyle
== PARSE_GUID_STYLE_5_FIELDS
) {
1293 // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
1295 Len
= GetHexChars (TempString
, sizeof (TempString
));
1296 if ((Len
== 0) || (Len
> 8)) {
1300 sscanf (TempString
, "%x", &Value32
);
1301 Value
->Data1
= Value32
;
1303 // Next two UINT16 fields
1305 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1309 mGlobals
.SourceFile
.FileBufferPtr
++;
1310 Len
= GetHexChars (TempString
, sizeof (TempString
));
1311 if ((Len
== 0) || (Len
> 4)) {
1315 sscanf (TempString
, "%x", &Value32
);
1316 Value
->Data2
= (UINT16
) Value32
;
1318 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1322 mGlobals
.SourceFile
.FileBufferPtr
++;
1323 Len
= GetHexChars (TempString
, sizeof (TempString
));
1324 if ((Len
== 0) || (Len
> 4)) {
1328 sscanf (TempString
, "%x", &Value32
);
1329 Value
->Data3
= (UINT16
) Value32
;
1331 // Parse the "AAAA" as two bytes
1333 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1337 mGlobals
.SourceFile
.FileBufferPtr
++;
1338 Len
= GetHexChars (TempString
, sizeof (TempString
));
1339 if ((Len
== 0) || (Len
> 4)) {
1343 sscanf (TempString
, "%x", &Value32
);
1344 Value
->Data4
[0] = (UINT8
) (Value32
>> 8);
1345 Value
->Data4
[1] = (UINT8
) Value32
;
1346 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1350 mGlobals
.SourceFile
.FileBufferPtr
++;
1352 // Read the last 6 bytes of the GUID
1355 Len
= GetHexChars (TempString
, sizeof (TempString
));
1356 if ((Len
== 0) || (Len
> 12)) {
1360 // Insert leading 0's to make life easier
1363 From
= TempString
+ Len
- 1;
1364 To
= TempString
+ 11;
1366 while (From
>= TempString
) {
1372 while (To
>= TempString
) {
1378 // Now parse each byte
1381 for (Index
= 0; Index
< 6; Index
++) {
1383 // Copy the two characters from the input string to something
1386 TempString2
[0] = TempString
[Index
* 2];
1387 TempString2
[1] = TempString
[Index
* 2 + 1];
1388 sscanf (TempString2
, "%x", &Value32
);
1389 Value
->Data4
[Index
+ 2] = (UINT8
) Value32
;
1395 // Unsupported GUID style
1401 if (Status
== FALSE
) {
1402 SetFilePosition (&FPos
);
1414 Fpos
->FileBufferPtr
= mGlobals
.SourceFile
.FileBufferPtr
;
1415 return STATUS_SUCCESS
;
1425 // Should check range of pointer
1427 mGlobals
.SourceFile
.FileBufferPtr
= Fpos
->FileBufferPtr
;
1428 return STATUS_SUCCESS
;