2 Generic but simple file parsing routines.
4 Copyright (c) 2004 - 2016, 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.
20 #include "CommonLib.h"
21 #include "EfiUtilityMsgs.h"
22 #include "SimpleFileParsing.h"
28 // just in case we get in an endless loop.
30 #define MAX_NEST_DEPTH 20
34 #define MAX_STRING_IDENTIFIER_NAME 100
36 #define T_CHAR_SPACE ' '
38 #define T_CHAR_CR '\r'
39 #define T_CHAR_TAB '\t'
40 #define T_CHAR_LF '\n'
41 #define T_CHAR_SLASH '/'
42 #define T_CHAR_BACKSLASH '\\'
43 #define T_CHAR_DOUBLE_QUOTE '"'
44 #define T_CHAR_LC_X 'x'
46 #define T_CHAR_STAR '*'
49 // We keep a linked list of these for the source files we process
51 typedef struct _SOURCE_FILE
{
56 CHAR8 FileName
[MAX_PATH
];
60 struct _SOURCE_FILE
*Previous
;
61 struct _SOURCE_FILE
*Next
;
62 CHAR8 ControlCharacter
;
70 // Keep all our module globals in this structure
73 SOURCE_FILE SourceFile
;
102 SOURCE_FILE
*SourceFile
108 SOURCE_FILE
*SourceFile
114 SOURCE_FILE
*SourceFile
120 SOURCE_FILE
*SourceFile
126 SOURCE_FILE
*SourceFile
139 SOURCE_FILE
*SourceFile
,
140 SOURCE_FILE
*ParentSourceFile
146 SOURCE_FILE
*SourceFile
173 STATUS_SUCCESS always
177 memset ((VOID
*) &mGlobals
, 0, sizeof (mGlobals
));
178 return STATUS_SUCCESS
;
188 Return the line number of the file we're parsing. Used
189 for error reporting purposes.
195 The line number, or 0 if no file is being processed
199 return mGlobals
.SourceFile
.LineNum
;
209 Return the name of the file we're parsing. Used
210 for error reporting purposes.
216 A pointer to the file name. Null if no file is being
221 if (mGlobals
.SourceFile
.FileName
[0]) {
222 return mGlobals
.SourceFile
.FileName
;
235 Open a file for parsing.
238 FileName - name of the file to parse
246 t_strcpy (mGlobals
.SourceFile
.FileName
, FileName
);
247 Status
= ProcessIncludeFile (&mGlobals
.SourceFile
, NULL
);
258 Check to see if the specified token is found at
259 the current position in the input file.
262 Str - the token to look for
265 TRUE - the token is next
266 FALSE - the token is not next
269 We do a simple string comparison on this function. It is
270 the responsibility of the caller to ensure that the token
271 is not a subset of some other token.
273 The file pointer is advanced past the token in the input file.
278 SkipWhiteSpace (&mGlobals
.SourceFile
);
279 if (EndOfFile (&mGlobals
.SourceFile
)) {
283 if ((Len
= t_strcmp (mGlobals
.SourceFile
.FileBufferPtr
, Str
)) > 0) {
284 mGlobals
.SourceFile
.FileBufferPtr
+= Len
;
285 if (mGlobals
.VerboseToken
) {
286 printf ("Token: '%s'\n", Str
);
302 Check to see if the specified keyword is found at
303 the current position in the input file.
306 Str - keyword to look for
309 TRUE - the keyword is next
310 FALSE - the keyword is not next
313 A keyword is defined as a "special" string that has a non-alphanumeric
314 character following it.
319 SkipWhiteSpace (&mGlobals
.SourceFile
);
320 if (EndOfFile (&mGlobals
.SourceFile
)) {
324 if ((Len
= t_strcmp (mGlobals
.SourceFile
.FileBufferPtr
, Str
)) > 0) {
325 if (isalnum ((int)mGlobals
.SourceFile
.FileBufferPtr
[Len
])) {
329 mGlobals
.SourceFile
.FileBufferPtr
+= Len
;
330 if (mGlobals
.VerboseToken
) {
331 printf ("Token: '%s'\n", Str
);
348 Get the next token from the input stream.
351 Str - pointer to a copy of the next token
352 Len - size of buffer pointed to by Str
355 TRUE - next token successfully returned
359 Preceeding white space is ignored.
360 The parser's buffer pointer is advanced past the end of the
368 SkipWhiteSpace (&mGlobals
.SourceFile
);
369 if (EndOfFile (&mGlobals
.SourceFile
)) {
373 // Have to have enough string for at least one char and a null-terminator
379 // Look at the first character. If it's an identifier, then treat it
382 TempChar
= mGlobals
.SourceFile
.FileBufferPtr
[0];
383 if (((TempChar
>= 'a') && (TempChar
<= 'z')) || ((TempChar
>= 'A') && (TempChar
<= 'Z')) || (TempChar
== '_')) {
385 mGlobals
.SourceFile
.FileBufferPtr
++;
387 while (!EndOfFile (&mGlobals
.SourceFile
) && (Index
< Len
)) {
388 TempChar
= mGlobals
.SourceFile
.FileBufferPtr
[0];
389 if (((TempChar
>= 'a') && (TempChar
<= 'z')) ||
390 ((TempChar
>= 'A') && (TempChar
<= 'Z')) ||
391 ((TempChar
>= '0') && (TempChar
<= '9')) ||
394 Str
[Index
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
395 mGlobals
.SourceFile
.FileBufferPtr
++;
399 // Invalid character for symbol name, so break out
405 // Null terminate and return success
409 } else if ((TempChar
== ')') || (TempChar
== '(') || (TempChar
== '*')) {
410 Str
[0] = mGlobals
.SourceFile
.FileBufferPtr
[0];
411 mGlobals
.SourceFile
.FileBufferPtr
++;
416 // Everything else is white-space (or EOF) separated
419 while (!EndOfFile (&mGlobals
.SourceFile
) && (Index
< Len
)) {
420 if (IsWhiteSpace (&mGlobals
.SourceFile
)) {
428 Str
[Index
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
429 mGlobals
.SourceFile
.FileBufferPtr
++;
434 // See if we just ran out of file contents, but did find a token
436 if ((Index
> 0) && EndOfFile (&mGlobals
.SourceFile
)) {
453 Parse a GUID from the input stream. Stop when you discover white space.
456 Str - pointer to a copy of the next token
457 Len - size of buffer pointed to by Str
460 TRUE - GUID string returned successfully
466 SkipWhiteSpace (&mGlobals
.SourceFile
);
467 if (EndOfFile (&mGlobals
.SourceFile
)) {
472 while (!EndOfFile (&mGlobals
.SourceFile
) && (Index
< Len
)) {
473 if (IsWhiteSpace (&mGlobals
.SourceFile
)) {
481 Str
[Index
] = mGlobals
.SourceFile
.FileBufferPtr
[0];
482 mGlobals
.SourceFile
.FileBufferPtr
++;
497 Len
= t_strlen (Str
);
498 SavePos
= mGlobals
.SourceFile
.FileBufferPtr
;
499 SkipWhiteSpace (&mGlobals
.SourceFile
);
500 while (!EndOfFile (&mGlobals
.SourceFile
)) {
501 if (t_strncmp (Str
, mGlobals
.SourceFile
.FileBufferPtr
, Len
) == 0) {
502 mGlobals
.SourceFile
.FileBufferPtr
+= Len
;
506 mGlobals
.SourceFile
.FileBufferPtr
++;
507 SkipWhiteSpace (&mGlobals
.SourceFile
);
510 mGlobals
.SourceFile
.FileBufferPtr
= SavePos
;
521 Check the token at the current file position for a numeric value.
522 May be either decimal or hex.
525 Value - pointer where to store the value
528 FALSE - current token is not a number
529 TRUE - current token is a number
535 SkipWhiteSpace (&mGlobals
.SourceFile
);
536 if (EndOfFile (&mGlobals
.SourceFile
)) {
540 if (isdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
542 // Check for hex value
544 if ((mGlobals
.SourceFile
.FileBufferPtr
[0] == T_CHAR_0
) && (mGlobals
.SourceFile
.FileBufferPtr
[1] == T_CHAR_LC_X
)) {
545 if (!isxdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[2])) {
549 mGlobals
.SourceFile
.FileBufferPtr
+= 2;
550 sscanf (mGlobals
.SourceFile
.FileBufferPtr
, "%x", &Val
);
551 *Value
= (UINT32
) Val
;
552 while (isxdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
553 mGlobals
.SourceFile
.FileBufferPtr
++;
558 *Value
= atoi (mGlobals
.SourceFile
.FileBufferPtr
);
559 while (isdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
560 mGlobals
.SourceFile
.FileBufferPtr
++;
577 Close the file being parsed.
583 STATUS_SUCCESS - the file was closed
584 STATUS_ERROR - no file is currently open
588 if (mGlobals
.SourceFile
.FileBuffer
!= NULL
) {
589 free (mGlobals
.SourceFile
.FileBuffer
);
590 memset (&mGlobals
.SourceFile
, 0, sizeof (mGlobals
.SourceFile
));
591 return STATUS_SUCCESS
;
600 SOURCE_FILE
*SourceFile
,
601 SOURCE_FILE
*ParentSourceFile
607 Given a source file, open the file and parse it
611 SourceFile - name of file to parse
612 ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
620 STATIC UINTN NestDepth
= 0;
621 CHAR8 FoundFileName
[MAX_PATH
];
624 Status
= STATUS_SUCCESS
;
627 // Print the file being processed. Indent so you can tell the include nesting
630 if (mGlobals
.VerboseFile
) {
631 fprintf (stdout
, "%*cProcessing file '%s'\n", (int)NestDepth
* 2, ' ', SourceFile
->FileName
);
632 fprintf (stdout
, "Parent source file = '%s'\n", ParentSourceFile
->FileName
);
636 // Make sure we didn't exceed our maximum nesting depth
638 if (NestDepth
> MAX_NEST_DEPTH
) {
639 Error (NULL
, 0, 3001, "Not Supported", "%s exceeeds max nesting depth (%u)", SourceFile
->FileName
, (unsigned) NestDepth
);
640 Status
= STATUS_ERROR
;
644 // Try to open the file locally, and if that fails try along our include paths.
646 strcpy (FoundFileName
, SourceFile
->FileName
);
647 if ((SourceFile
->Fptr
= fopen (LongFilePath (FoundFileName
), "rb")) == NULL
) {
651 // Process the file found
653 ProcessFile (SourceFile
);
656 // Close open files and return status
658 if (SourceFile
->Fptr
!= NULL
) {
659 fclose (SourceFile
->Fptr
);
660 SourceFile
->Fptr
= NULL
;
669 SOURCE_FILE
*SourceFile
675 Given a source file that's been opened, read the contents into an internal
676 buffer and pre-process it to remove comments.
680 SourceFile - structure containing info on the file to process
689 // Get the file size, and then read the entire thing into memory.
690 // Allocate extra space for a terminator character.
692 fseek (SourceFile
->Fptr
, 0, SEEK_END
);
693 SourceFile
->FileSize
= ftell (SourceFile
->Fptr
);
694 if (mGlobals
.VerboseFile
) {
695 printf ("FileSize = %u (0x%X)\n", (unsigned) SourceFile
->FileSize
, (unsigned) SourceFile
->FileSize
);
698 fseek (SourceFile
->Fptr
, 0, SEEK_SET
);
699 SourceFile
->FileBuffer
= (CHAR8
*) malloc (SourceFile
->FileSize
+ sizeof (CHAR8
));
700 if (SourceFile
->FileBuffer
== NULL
) {
701 Error (NULL
, 0, 4001, "Resource: memory cannot be allocated", NULL
);
705 fread ((VOID
*) SourceFile
->FileBuffer
, SourceFile
->FileSize
, 1, SourceFile
->Fptr
);
706 SourceFile
->FileBuffer
[(SourceFile
->FileSize
/ sizeof (CHAR8
))] = T_CHAR_NULL
;
708 // Pre-process the file to replace comments with spaces
710 PreprocessFile (SourceFile
);
711 SourceFile
->LineNum
= 1;
712 return STATUS_SUCCESS
;
718 SOURCE_FILE
*SourceFile
723 Preprocess a file to replace all carriage returns with NULLs so
724 we can print lines (as part of error messages) from the file to the screen.
727 SourceFile - structure that we use to keep track of an input file.
735 BOOLEAN SlashSlashComment
;
738 RewindFile (SourceFile
);
740 SlashSlashComment
= FALSE
;
741 while (!EndOfFile (SourceFile
)) {
743 // If a line-feed, then no longer in a comment if we're in a // comment
745 if (SourceFile
->FileBufferPtr
[0] == T_CHAR_LF
) {
746 SourceFile
->FileBufferPtr
++;
747 SourceFile
->LineNum
++;
748 if (InComment
&& SlashSlashComment
) {
750 SlashSlashComment
= FALSE
;
752 } else if (SourceFile
->FileBufferPtr
[0] == T_CHAR_CR
) {
754 // Replace all carriage returns with a NULL so we can print stuff
756 SourceFile
->FileBufferPtr
[0] = 0;
757 SourceFile
->FileBufferPtr
++;
759 // Check for */ comment end
761 } else if (InComment
&&
762 !SlashSlashComment
&&
763 (SourceFile
->FileBufferPtr
[0] == T_CHAR_STAR
) &&
764 (SourceFile
->FileBufferPtr
[1] == T_CHAR_SLASH
)
766 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
767 SourceFile
->FileBufferPtr
++;
768 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
769 SourceFile
->FileBufferPtr
++;
771 } else if (InComment
) {
772 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
773 SourceFile
->FileBufferPtr
++;
775 // Check for // comments
777 } else if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_SLASH
) && (SourceFile
->FileBufferPtr
[1] == T_CHAR_SLASH
)) {
779 SlashSlashComment
= TRUE
;
781 // Check for /* comment start
783 } else if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_SLASH
) && (SourceFile
->FileBufferPtr
[1] == T_CHAR_STAR
)) {
784 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
785 SourceFile
->FileBufferPtr
++;
786 SourceFile
->FileBufferPtr
[0] = T_CHAR_SPACE
;
787 SourceFile
->FileBufferPtr
++;
788 SlashSlashComment
= FALSE
;
791 SourceFile
->FileBufferPtr
++;
795 // Could check for end-of-file and still in a comment, but
796 // should not be necessary. So just restore the file pointers.
798 RewindFile (SourceFile
);
800 // Dump the reformatted file if verbose mode
802 if (mGlobals
.VerboseFile
) {
804 printf ("%04d: ", LineNum
);
805 while (!EndOfFile (SourceFile
)) {
806 if (SourceFile
->FileBufferPtr
[0] == T_CHAR_LF
) {
807 printf ("'\n%04d: '", ++LineNum
);
809 printf ("%c", SourceFile
->FileBufferPtr
[0]);
812 SourceFile
->FileBufferPtr
++;
816 printf ("FileSize = %u (0x%X)\n", (unsigned)SourceFile
->FileSize
, (unsigned)SourceFile
->FileSize
);
817 RewindFile (SourceFile
);
829 Retrieve a quoted-string from the input file.
832 Str - pointer to a copy of the quoted string parsed
833 Length - size of buffer pointed to by Str
836 TRUE - next token in input stream was a quoted string, and
837 the string value was returned in Str
842 SkipWhiteSpace (&mGlobals
.SourceFile
);
843 if (EndOfFile (&mGlobals
.SourceFile
)) {
847 if (mGlobals
.SourceFile
.FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) {
848 mGlobals
.SourceFile
.FileBufferPtr
++;
850 if (EndOfFile (&mGlobals
.SourceFile
)) {
854 // Check for closing quote
856 if (mGlobals
.SourceFile
.FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) {
857 mGlobals
.SourceFile
.FileBufferPtr
++;
862 *Str
= mGlobals
.SourceFile
.FileBufferPtr
[0];
865 mGlobals
.SourceFile
.FileBufferPtr
++;
869 // First character was not a quote, or the input string length was
870 // insufficient to contain the quoted string, so return failure code.
882 Return TRUE of FALSE to indicate whether or not we've reached the end of the
894 SkipWhiteSpace (&mGlobals
.SourceFile
);
895 return EndOfFile (&mGlobals
.SourceFile
);
902 SOURCE_FILE
*SourceFile
,
910 BOOLEAN PreviousBackslash
;
912 if (SourceFile
->FileBufferPtr
[0] != T_CHAR_DOUBLE_QUOTE
) {
913 if (Optional
== FALSE
) {
914 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "expected quoted string", "%S", SourceFile
->FileBufferPtr
);
921 SourceFile
->FileBufferPtr
++;
922 Start
= Ptr
= SourceFile
->FileBufferPtr
;
923 PreviousBackslash
= FALSE
;
924 while (!EndOfFile (SourceFile
)) {
925 if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) && (PreviousBackslash
== FALSE
)) {
927 } else if (SourceFile
->FileBufferPtr
[0] == T_CHAR_CR
) {
928 Warning (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "carriage return found in quoted string", "%S", Start
);
929 PreviousBackslash
= FALSE
;
930 } else if (SourceFile
->FileBufferPtr
[0] == T_CHAR_BACKSLASH
) {
931 PreviousBackslash
= TRUE
;
933 PreviousBackslash
= FALSE
;
936 SourceFile
->FileBufferPtr
++;
940 if (SourceFile
->FileBufferPtr
[0] != T_CHAR_DOUBLE_QUOTE
) {
941 Warning (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "missing closing quote on string", "%S", Start
);
943 SourceFile
->FileBufferPtr
++;
946 // Now allocate memory for the string and save it off
948 String
= (CHAR8
*) malloc ((Len
+ 1) * sizeof (CHAR8
));
949 if (String
== NULL
) {
950 Error (NULL
, 0, 4001, "Resource: memory cannot be allocated", NULL
);
954 // Copy the string from the file buffer to the local copy.
955 // We do no reformatting of it whatsoever at this point.
972 SOURCE_FILE
*SourceFile
976 // The file buffer pointer will typically get updated before the End-of-file flag in the
977 // source file structure, so check it first.
979 if (SourceFile
->FileBufferPtr
>= SourceFile
->FileBuffer
+ SourceFile
->FileSize
/ sizeof (CHAR8
)) {
980 SourceFile
->EndOfFile
= TRUE
;
984 if (SourceFile
->EndOfFile
) {
994 ProcessTokenInclude (
995 SOURCE_FILE
*SourceFile
998 CHAR8 IncludeFileName
[MAX_PATH
];
1001 BOOLEAN ReportedError
;
1002 SOURCE_FILE IncludedSourceFile
;
1004 ReportedError
= FALSE
;
1005 if (SkipWhiteSpace (SourceFile
) == 0) {
1006 Warning (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "expected whitespace following #include keyword", NULL
);
1009 // Should be quoted file name
1011 if (SourceFile
->FileBufferPtr
[0] != T_CHAR_DOUBLE_QUOTE
) {
1012 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "expected quoted include file name", NULL
);
1016 SourceFile
->FileBufferPtr
++;
1018 // Copy the filename as ascii to our local string
1020 To
= IncludeFileName
;
1022 while (!EndOfFile (SourceFile
)) {
1023 if ((SourceFile
->FileBufferPtr
[0] == T_CHAR_CR
) || (SourceFile
->FileBufferPtr
[0] == T_CHAR_LF
)) {
1024 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "end-of-line found in quoted include file name", NULL
);
1028 if (SourceFile
->FileBufferPtr
[0] == T_CHAR_DOUBLE_QUOTE
) {
1029 SourceFile
->FileBufferPtr
++;
1033 // If too long, then report the error once and process until the closing quote
1036 if (!ReportedError
&& (Len
>= sizeof (IncludeFileName
))) {
1037 Error (SourceFile
->FileName
, SourceFile
->LineNum
, 0, "length of include file name exceeds limit", NULL
);
1038 ReportedError
= TRUE
;
1041 if (!ReportedError
) {
1042 *To
= (CHAR8
) SourceFile
->FileBufferPtr
[0];
1046 SourceFile
->FileBufferPtr
++;
1049 if (!ReportedError
) {
1051 memset ((CHAR8
*) &IncludedSourceFile
, 0, sizeof (SOURCE_FILE
));
1052 strcpy (IncludedSourceFile
.FileName
, IncludeFileName
);
1053 ProcessIncludeFile (&IncludedSourceFile
, SourceFile
);
1059 // Error recovery -- skip to next #
1061 SourceFile
->SkipToHash
= TRUE
;
1067 SOURCE_FILE
*SourceFile
1070 switch (*SourceFile
->FileBufferPtr
) {
1085 SOURCE_FILE
*SourceFile
1091 while (!EndOfFile (SourceFile
)) {
1093 switch (*SourceFile
->FileBufferPtr
) {
1098 SourceFile
->FileBufferPtr
++;
1102 SourceFile
->FileBufferPtr
++;
1103 SourceFile
->LineNum
++;
1111 // Some tokens require trailing whitespace. If we're at the end of the
1112 // file, then we count that as well.
1114 if ((Count
== 0) && (EndOfFile (SourceFile
))) {
1129 Routine Description:
1130 Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,
1131 so only compare up to the length of Str.
1134 Buffer - pointer to first (possibly not null-terminated) string
1135 Str - pointer to null-terminated string to compare to Buffer
1138 Number of bytes matched if exact match
1139 0 if Buffer does not start with Str
1146 while (*Str
&& (*Str
== *Buffer
)) {
1184 if (*Str1
!= *Str2
) {
1218 SOURCE_FILE
*SourceFile
1221 SourceFile
->LineNum
= 1;
1222 SourceFile
->FileBufferPtr
= SourceFile
->FileBuffer
;
1223 SourceFile
->EndOfFile
= 0;
1235 while (!EndOfFile (&mGlobals
.SourceFile
) && (BufferLen
> 0)) {
1236 if (isxdigit ((int)mGlobals
.SourceFile
.FileBufferPtr
[0])) {
1237 *Buffer
= mGlobals
.SourceFile
.FileBufferPtr
[0];
1241 mGlobals
.SourceFile
.FileBufferPtr
++;
1247 // Null terminate if we can
1249 if ((Len
> 0) && (BufferLen
> 0)) {
1263 Routine Description:
1264 Parse a GUID from the input stream. Stop when you discover white space.
1267 GuidStyle - Style of the following GUID token
1268 Value - pointer to EFI_GUID struct for output
1271 TRUE - GUID string parsed successfully
1275 Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
1282 CHAR8 TempString
[20];
1283 CHAR8 TempString2
[3];
1291 // Skip white space, then start parsing
1293 SkipWhiteSpace (&mGlobals
.SourceFile
);
1294 GetFilePosition (&FPos
);
1295 if (EndOfFile (&mGlobals
.SourceFile
)) {
1299 if (GuidStyle
== PARSE_GUID_STYLE_5_FIELDS
) {
1301 // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
1303 Len
= GetHexChars (TempString
, sizeof (TempString
));
1304 if ((Len
== 0) || (Len
> 8)) {
1308 sscanf (TempString
, "%x", &Value32
);
1309 Value
->Data1
= Value32
;
1311 // Next two UINT16 fields
1313 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1317 mGlobals
.SourceFile
.FileBufferPtr
++;
1318 Len
= GetHexChars (TempString
, sizeof (TempString
));
1319 if ((Len
== 0) || (Len
> 4)) {
1323 sscanf (TempString
, "%x", &Value32
);
1324 Value
->Data2
= (UINT16
) Value32
;
1326 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1330 mGlobals
.SourceFile
.FileBufferPtr
++;
1331 Len
= GetHexChars (TempString
, sizeof (TempString
));
1332 if ((Len
== 0) || (Len
> 4)) {
1336 sscanf (TempString
, "%x", &Value32
);
1337 Value
->Data3
= (UINT16
) Value32
;
1339 // Parse the "AAAA" as two bytes
1341 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1345 mGlobals
.SourceFile
.FileBufferPtr
++;
1346 Len
= GetHexChars (TempString
, sizeof (TempString
));
1347 if ((Len
== 0) || (Len
> 4)) {
1351 sscanf (TempString
, "%x", &Value32
);
1352 Value
->Data4
[0] = (UINT8
) (Value32
>> 8);
1353 Value
->Data4
[1] = (UINT8
) Value32
;
1354 if (mGlobals
.SourceFile
.FileBufferPtr
[0] != '-') {
1358 mGlobals
.SourceFile
.FileBufferPtr
++;
1360 // Read the last 6 bytes of the GUID
1363 Len
= GetHexChars (TempString
, sizeof (TempString
));
1364 if ((Len
== 0) || (Len
> 12)) {
1368 // Insert leading 0's to make life easier
1371 From
= TempString
+ Len
- 1;
1372 To
= TempString
+ 11;
1374 while (From
>= TempString
) {
1380 while (To
>= TempString
) {
1386 // Now parse each byte
1389 for (Index
= 0; Index
< 6; Index
++) {
1391 // Copy the two characters from the input string to something
1394 TempString2
[0] = TempString
[Index
* 2];
1395 TempString2
[1] = TempString
[Index
* 2 + 1];
1396 sscanf (TempString2
, "%x", &Value32
);
1397 Value
->Data4
[Index
+ 2] = (UINT8
) Value32
;
1403 // Unsupported GUID style
1409 if (Status
== FALSE
) {
1410 SetFilePosition (&FPos
);
1422 Fpos
->FileBufferPtr
= mGlobals
.SourceFile
.FileBufferPtr
;
1423 return STATUS_SUCCESS
;
1433 // Should check range of pointer
1435 mGlobals
.SourceFile
.FileBufferPtr
= Fpos
->FileBufferPtr
;
1436 return STATUS_SUCCESS
;