mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-27 01:03:45 +01:00 
			
		
		
		
	Move the documentation blocks from between the parameter list and function body to above the function. Convert all the documentation blocks to Doxygen format. Signed-off-by: Rebecca Cran <rebecca@bsdio.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1324 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1324 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Generic but simple file parsing routines.
 | |
| 
 | |
| Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <ctype.h>
 | |
| 
 | |
| #include "CommonLib.h"
 | |
| #include "EfiUtilityMsgs.h"
 | |
| #include "SimpleFileParsing.h"
 | |
| 
 | |
| #ifndef MAX_PATH
 | |
| #define MAX_PATH  255
 | |
| #endif
 | |
| //
 | |
| // just in case we get in an endless loop.
 | |
| //
 | |
| #define MAX_NEST_DEPTH  20
 | |
| //
 | |
| // number of wchars
 | |
| //
 | |
| #define MAX_STRING_IDENTIFIER_NAME  100
 | |
| 
 | |
| #define T_CHAR_SPACE                ' '
 | |
| #define T_CHAR_NULL                 0
 | |
| #define T_CHAR_CR                   '\r'
 | |
| #define T_CHAR_TAB                  '\t'
 | |
| #define T_CHAR_LF                   '\n'
 | |
| #define T_CHAR_SLASH                '/'
 | |
| #define T_CHAR_BACKSLASH            '\\'
 | |
| #define T_CHAR_DOUBLE_QUOTE         '"'
 | |
| #define T_CHAR_LC_X                 'x'
 | |
| #define T_CHAR_0                    '0'
 | |
| #define T_CHAR_STAR                 '*'
 | |
| 
 | |
| //
 | |
| // We keep a linked list of these for the source files we process
 | |
| //
 | |
| typedef struct _SOURCE_FILE {
 | |
|   FILE                *Fptr;
 | |
|   CHAR8               *FileBuffer;
 | |
|   CHAR8               *FileBufferPtr;
 | |
|   UINTN               FileSize;
 | |
|   CHAR8               FileName[MAX_PATH];
 | |
|   UINTN               LineNum;
 | |
|   BOOLEAN             EndOfFile;
 | |
|   BOOLEAN             SkipToHash;
 | |
|   struct _SOURCE_FILE *Previous;
 | |
|   struct _SOURCE_FILE *Next;
 | |
|   CHAR8               ControlCharacter;
 | |
| } SOURCE_FILE;
 | |
| 
 | |
| typedef struct {
 | |
|   CHAR8   *FileBufferPtr;
 | |
| } FILE_POSITION;
 | |
| 
 | |
| //
 | |
| // Keep all our module globals in this structure
 | |
| //
 | |
| STATIC struct {
 | |
|   SOURCE_FILE SourceFile;
 | |
|   BOOLEAN     VerboseFile;
 | |
|   BOOLEAN     VerboseToken;
 | |
| } mGlobals;
 | |
| 
 | |
| STATIC
 | |
| UINTN
 | |
| t_strcmp (
 | |
|   CHAR8  *Buffer,
 | |
|   CHAR8  *Str
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| UINTN
 | |
| t_strncmp (
 | |
|   CHAR8  *Str1,
 | |
|   CHAR8  *Str2,
 | |
|   INTN    Len
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| UINTN
 | |
| t_strlen (
 | |
|   CHAR8  *Str
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| RewindFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| BOOLEAN
 | |
| IsWhiteSpace (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| UINTN
 | |
| SkipWhiteSpace (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| BOOLEAN
 | |
| EndOfFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| PreprocessFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| CHAR8   *
 | |
| t_strcpy (
 | |
|   CHAR8  *Dest,
 | |
|   CHAR8  *Src
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| STATUS
 | |
| ProcessIncludeFile (
 | |
|   SOURCE_FILE *SourceFile,
 | |
|   SOURCE_FILE *ParentSourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| STATUS
 | |
| ProcessFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| STATUS
 | |
| GetFilePosition (
 | |
|   FILE_POSITION *Fpos
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| STATUS
 | |
| SetFilePosition (
 | |
|   FILE_POSITION *Fpos
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   @retval STATUS_SUCCESS always
 | |
| **/
 | |
| STATUS
 | |
| SFPInit (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   memset ((VOID *) &mGlobals, 0, sizeof (mGlobals));
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the line number of the file we're parsing. Used
 | |
|   for error reporting purposes.
 | |
| 
 | |
|   @return The line number, or 0 if no file is being processed
 | |
| **/
 | |
| UINTN
 | |
| SFPGetLineNumber (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return mGlobals.SourceFile.LineNum;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the name of the file we're parsing. Used
 | |
|   for error reporting purposes.
 | |
| 
 | |
|   @return A pointer to the file name. Null if no file is being
 | |
|   processed.
 | |
| **/
 | |
| CHAR8  *
 | |
| SFPGetFileName (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   if (mGlobals.SourceFile.FileName[0]) {
 | |
|     return mGlobals.SourceFile.FileName;
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Open a file for parsing.
 | |
| 
 | |
|   @param FileName  name of the file to parse
 | |
| **/
 | |
| STATUS
 | |
| SFPOpenFile (
 | |
|   CHAR8      *FileName
 | |
|   )
 | |
| {
 | |
|   STATUS  Status;
 | |
|   t_strcpy (mGlobals.SourceFile.FileName, FileName);
 | |
|   Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check to see if the specified token is found at
 | |
|   the current position in the input file.
 | |
| 
 | |
|  @note:
 | |
|    We do a simple string comparison on this function. It is
 | |
|    the responsibility of the caller to ensure that the token
 | |
|    is not a subset of some other token.
 | |
| 
 | |
|    The file pointer is advanced past the token in the input file.
 | |
| 
 | |
|   @param Str the token to look for
 | |
| 
 | |
|   @retval TRUE the token is next
 | |
|   @retval FALSE the token is not next
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPIsToken (
 | |
|   CHAR8  *Str
 | |
|   )
 | |
| {
 | |
|   UINTN  Len;
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
 | |
|     mGlobals.SourceFile.FileBufferPtr += Len;
 | |
|     if (mGlobals.VerboseToken) {
 | |
|       printf ("Token: '%s'\n", Str);
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check to see if the specified keyword is found at
 | |
|   the current position in the input file.
 | |
| 
 | |
|  @note:
 | |
|    A keyword is defined as a "special" string that has a non-alphanumeric
 | |
|    character following it.
 | |
| 
 | |
|   @param Str keyword to look for
 | |
| 
 | |
|   @retval TRUE the keyword is next
 | |
|   @retval FALSE the keyword is not next
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPIsKeyword (
 | |
|   CHAR8  *Str
 | |
|   )
 | |
| {
 | |
|   UINTN  Len;
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
 | |
|     if (isalnum ((int)mGlobals.SourceFile.FileBufferPtr[Len])) {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     mGlobals.SourceFile.FileBufferPtr += Len;
 | |
|     if (mGlobals.VerboseToken) {
 | |
|       printf ("Token: '%s'\n", Str);
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the next token from the input stream.
 | |
| 
 | |
|  @note:
 | |
|    Preceding white space is ignored.
 | |
|    The parser's buffer pointer is advanced past the end of the
 | |
|    token.
 | |
| 
 | |
|   @param Str pointer to a copy of the next token
 | |
|   @param Len size of buffer pointed to by Str
 | |
| 
 | |
|   @retval TRUE  next token successfully returned
 | |
|   @retval FALSE otherwise
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPGetNextToken (
 | |
|   CHAR8  *Str,
 | |
|   UINTN  Len
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
|   CHAR8  TempChar;
 | |
| 
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
|   //
 | |
|   // Have to have enough string for at least one char and a null-terminator
 | |
|   //
 | |
|   if (Len < 2) {
 | |
|     return FALSE;
 | |
|   }
 | |
|   //
 | |
|   // Look at the first character. If it's an identifier, then treat it
 | |
|   // as such
 | |
|   //
 | |
|   TempChar = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|   if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) {
 | |
|     Str[0] = TempChar;
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     Index = 1;
 | |
|     while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
 | |
|       TempChar = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|       if (((TempChar >= 'a') && (TempChar <= 'z')) ||
 | |
|           ((TempChar >= 'A') && (TempChar <= 'Z')) ||
 | |
|           ((TempChar >= '0') && (TempChar <= '9')) ||
 | |
|           (TempChar == '_')
 | |
|           ) {
 | |
|         Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|         mGlobals.SourceFile.FileBufferPtr++;
 | |
|         Index++;
 | |
|       } else {
 | |
|         //
 | |
|         // Invalid character for symbol name, so break out
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Null terminate and return success
 | |
|     //
 | |
|     Str[Index] = 0;
 | |
|     return TRUE;
 | |
|   } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) {
 | |
|     Str[0] = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     Str[1] = 0;
 | |
|     return TRUE;
 | |
|   } else {
 | |
|     //
 | |
|     // Everything else is white-space (or EOF) separated
 | |
|     //
 | |
|     Index = 0;
 | |
|     while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
 | |
|       if (IsWhiteSpace (&mGlobals.SourceFile)) {
 | |
|         if (Index > 0) {
 | |
|           Str[Index] = 0;
 | |
|           return TRUE;
 | |
|         }
 | |
| 
 | |
|         return FALSE;
 | |
|       } else {
 | |
|         Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|         mGlobals.SourceFile.FileBufferPtr++;
 | |
|         Index++;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // See if we just ran out of file contents, but did find a token
 | |
|     //
 | |
|     if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) {
 | |
|       Str[Index] = 0;
 | |
|       return TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse a GUID from the input stream. Stop when you discover white space.
 | |
| 
 | |
|   @param Str pointer to a copy of the next token
 | |
|   @param Len size of buffer pointed to by Str
 | |
| 
 | |
|   @retval TRUE  GUID string returned successfully
 | |
|   @retval FALSE otherwise
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPGetGuidToken (
 | |
|   CHAR8  *Str,
 | |
|   UINT32 Len
 | |
|   )
 | |
| {
 | |
|   UINT32  Index;
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   Index = 0;
 | |
|   while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
 | |
|     if (IsWhiteSpace (&mGlobals.SourceFile)) {
 | |
|       if (Index > 0) {
 | |
|         Str[Index] = 0;
 | |
|         return TRUE;
 | |
|       }
 | |
| 
 | |
|       return FALSE;
 | |
|     } else {
 | |
|       Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|       mGlobals.SourceFile.FileBufferPtr++;
 | |
|       Index++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| SFPSkipToToken (
 | |
|   CHAR8  *Str
 | |
|   )
 | |
| {
 | |
|   UINTN  Len;
 | |
|   CHAR8         *SavePos;
 | |
|   Len     = t_strlen (Str);
 | |
|   SavePos = mGlobals.SourceFile.FileBufferPtr;
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   while (!EndOfFile (&mGlobals.SourceFile)) {
 | |
|     if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {
 | |
|       mGlobals.SourceFile.FileBufferPtr += Len;
 | |
|       return TRUE;
 | |
|     }
 | |
| 
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   }
 | |
| 
 | |
|   mGlobals.SourceFile.FileBufferPtr = SavePos;
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check the token at the current file position for a numeric value.
 | |
|   May be either decimal or hex.
 | |
| 
 | |
|   @param Value  pointer where to store the value
 | |
| 
 | |
|   @retval FALSE    current token is not a number
 | |
|   @retval TRUE     current token is a number
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPGetNumber (
 | |
|   UINTN *Value
 | |
|   )
 | |
| {
 | |
|   int Val;
 | |
| 
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (isdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
 | |
|     //
 | |
|     // Check for hex value
 | |
|     //
 | |
|     if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {
 | |
|       if (!isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[2])) {
 | |
|         return FALSE;
 | |
|       }
 | |
| 
 | |
|       mGlobals.SourceFile.FileBufferPtr += 2;
 | |
|       sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", &Val);
 | |
|       *Value = (UINT32) Val;
 | |
|       while (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
 | |
|         mGlobals.SourceFile.FileBufferPtr++;
 | |
|       }
 | |
| 
 | |
|       return TRUE;
 | |
|     } else {
 | |
|       *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
 | |
|       while (isdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
 | |
|         mGlobals.SourceFile.FileBufferPtr++;
 | |
|       }
 | |
| 
 | |
|       return TRUE;
 | |
|     }
 | |
|   } else {
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Close the file being parsed.
 | |
| 
 | |
|   @retval STATUS_SUCCESS the file was closed
 | |
|   @retval STATUS_ERROR   no file is currently open
 | |
| **/
 | |
| STATUS
 | |
| SFPCloseFile (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   if (mGlobals.SourceFile.FileBuffer != NULL) {
 | |
|     free (mGlobals.SourceFile.FileBuffer);
 | |
|     memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
 | |
|     return STATUS_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return STATUS_ERROR;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Given a source file, open the file and parse it
 | |
| 
 | |
|   @param SourceFile        name of file to parse
 | |
|   @param ParentSourceFile  for error reporting purposes, the file that #included SourceFile.
 | |
| 
 | |
|   @return Standard status.
 | |
| **/
 | |
| STATIC
 | |
| STATUS
 | |
| ProcessIncludeFile (
 | |
|   SOURCE_FILE *SourceFile,
 | |
|   SOURCE_FILE *ParentSourceFile
 | |
|   )
 | |
| {
 | |
|   STATIC UINTN NestDepth = 0;
 | |
|   CHAR8               FoundFileName[MAX_PATH];
 | |
|   STATUS              Status;
 | |
| 
 | |
|   Status = STATUS_SUCCESS;
 | |
|   NestDepth++;
 | |
|   //
 | |
|   // Print the file being processed. Indent so you can tell the include nesting
 | |
|   // depth.
 | |
|   //
 | |
|   if (mGlobals.VerboseFile) {
 | |
|     fprintf (stdout, "%*cProcessing file '%s'\n", (int)NestDepth * 2, ' ', SourceFile->FileName);
 | |
|     fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile->FileName);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Make sure we didn't exceed our maximum nesting depth
 | |
|   //
 | |
|   if (NestDepth > MAX_NEST_DEPTH) {
 | |
|     Error (NULL, 0, 3001, "Not Supported", "%s exceeds max nesting depth (%u)", SourceFile->FileName, (unsigned) NestDepth);
 | |
|     Status = STATUS_ERROR;
 | |
|     goto Finish;
 | |
|   }
 | |
|   //
 | |
|   // Try to open the file locally, and if that fails try along our include paths.
 | |
|   //
 | |
|   strcpy (FoundFileName, SourceFile->FileName);
 | |
|   if ((SourceFile->Fptr = fopen (LongFilePath (FoundFileName), "rb")) == NULL) {
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Process the file found
 | |
|   //
 | |
|   ProcessFile (SourceFile);
 | |
| Finish:
 | |
|   //
 | |
|   // Close open files and return status
 | |
|   //
 | |
|   if (SourceFile->Fptr != NULL) {
 | |
|     fclose (SourceFile->Fptr);
 | |
|     SourceFile->Fptr = NULL;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Given a source file that's been opened, read the contents into an internal
 | |
|   buffer and pre-process it to remove comments.
 | |
| 
 | |
|   @param SourceFile        structure containing info on the file to process
 | |
| 
 | |
|   @return Standard status.
 | |
| **/
 | |
| STATIC
 | |
| STATUS
 | |
| ProcessFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Get the file size, and then read the entire thing into memory.
 | |
|   // Allocate extra space for a terminator character.
 | |
|   //
 | |
|   fseek (SourceFile->Fptr, 0, SEEK_END);
 | |
|   SourceFile->FileSize = ftell (SourceFile->Fptr);
 | |
|   if (mGlobals.VerboseFile) {
 | |
|     printf ("FileSize = %u (0x%X)\n", (unsigned) SourceFile->FileSize, (unsigned) SourceFile->FileSize);
 | |
|   }
 | |
| 
 | |
|   fseek (SourceFile->Fptr, 0, SEEK_SET);
 | |
|   SourceFile->FileBuffer = (CHAR8  *) malloc (SourceFile->FileSize + sizeof (CHAR8 ));
 | |
|   if (SourceFile->FileBuffer == NULL) {
 | |
|     Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
 | |
|   SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (CHAR8 ))] = T_CHAR_NULL;
 | |
|   //
 | |
|   // Pre-process the file to replace comments with spaces
 | |
|   //
 | |
|   PreprocessFile (SourceFile);
 | |
|   SourceFile->LineNum = 1;
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Preprocess a file to replace all carriage returns with NULLs so
 | |
|   we can print lines (as part of error messages) from the file to the screen.
 | |
| 
 | |
|   @param SourceFile structure that we use to keep track of an input file.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| PreprocessFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   BOOLEAN InComment;
 | |
|   BOOLEAN SlashSlashComment;
 | |
|   int     LineNum;
 | |
| 
 | |
|   RewindFile (SourceFile);
 | |
|   InComment         = FALSE;
 | |
|   SlashSlashComment = FALSE;
 | |
|   while (!EndOfFile (SourceFile)) {
 | |
|     //
 | |
|     // If a line-feed, then no longer in a comment if we're in a // comment
 | |
|     //
 | |
|     if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       SourceFile->LineNum++;
 | |
|       if (InComment && SlashSlashComment) {
 | |
|         InComment         = FALSE;
 | |
|         SlashSlashComment = FALSE;
 | |
|       }
 | |
|     } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
 | |
|       //
 | |
|       // Replace all carriage returns with a NULL so we can print stuff
 | |
|       //
 | |
|       SourceFile->FileBufferPtr[0] = 0;
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       //
 | |
|       // Check for */ comment end
 | |
|       //
 | |
|     } else if (InComment &&
 | |
|              !SlashSlashComment &&
 | |
|              (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) &&
 | |
|              (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)
 | |
|             ) {
 | |
|       SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       InComment = FALSE;
 | |
|     } else if (InComment) {
 | |
|       SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       //
 | |
|       // Check for // comments
 | |
|       //
 | |
|     } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
 | |
|       InComment         = TRUE;
 | |
|       SlashSlashComment = TRUE;
 | |
|       //
 | |
|       // Check for /* comment start
 | |
|       //
 | |
|     } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) {
 | |
|       SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       SlashSlashComment = FALSE;
 | |
|       InComment         = TRUE;
 | |
|     } else {
 | |
|       SourceFile->FileBufferPtr++;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Could check for end-of-file and still in a comment, but
 | |
|   // should not be necessary. So just restore the file pointers.
 | |
|   //
 | |
|   RewindFile (SourceFile);
 | |
|   //
 | |
|   // Dump the reformatted file if verbose mode
 | |
|   //
 | |
|   if (mGlobals.VerboseFile) {
 | |
|     LineNum = 1;
 | |
|     printf ("%04d: ", LineNum);
 | |
|     while (!EndOfFile (SourceFile)) {
 | |
|       if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
 | |
|         printf ("'\n%04d: '", ++LineNum);
 | |
|       } else {
 | |
|         printf ("%c", SourceFile->FileBufferPtr[0]);
 | |
|       }
 | |
| 
 | |
|       SourceFile->FileBufferPtr++;
 | |
|     }
 | |
| 
 | |
|     printf ("'\n");
 | |
|     printf ("FileSize = %u (0x%X)\n", (unsigned)SourceFile->FileSize, (unsigned)SourceFile->FileSize);
 | |
|     RewindFile (SourceFile);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieve a quoted-string from the input file.
 | |
| 
 | |
|   @param Str    pointer to a copy of the quoted string parsed
 | |
|   @param Length size of buffer pointed to by Str
 | |
| 
 | |
|   @retval TRUE    next token in input stream was a quoted string, and
 | |
|                   the string value was returned in Str
 | |
|   @retval FALSE   otherwise
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPGetQuotedString (
 | |
|   CHAR8       *Str,
 | |
|   INTN         Length
 | |
|   )
 | |
| {
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     while (Length > 0) {
 | |
|       if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|         return FALSE;
 | |
|       }
 | |
|       //
 | |
|       // Check for closing quote
 | |
|       //
 | |
|       if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
 | |
|         mGlobals.SourceFile.FileBufferPtr++;
 | |
|         *Str = 0;
 | |
|         return TRUE;
 | |
|       }
 | |
| 
 | |
|       *Str = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|       Str++;
 | |
|       Length--;
 | |
|       mGlobals.SourceFile.FileBufferPtr++;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // First character was not a quote, or the input string length was
 | |
|   // insufficient to contain the quoted string, so return failure code.
 | |
|   //
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return TRUE of FALSE to indicate whether or not we've reached the end of the
 | |
|   file we're parsing.
 | |
| 
 | |
|   @retval TRUE    EOF reached
 | |
|   @retval FALSE   otherwise
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPIsEOF (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   return EndOfFile (&mGlobals.SourceFile);
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| STATIC
 | |
| CHAR8  *
 | |
| GetQuotedString (
 | |
|   SOURCE_FILE *SourceFile,
 | |
|   BOOLEAN     Optional
 | |
|   )
 | |
| {
 | |
|   CHAR8         *String;
 | |
|   CHAR8         *Start;
 | |
|   CHAR8         *Ptr;
 | |
|   UINTN         Len;
 | |
|   BOOLEAN       PreviousBackslash;
 | |
| 
 | |
|   if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
 | |
|     if (Optional == FALSE) {
 | |
|       Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   Len = 0;
 | |
|   SourceFile->FileBufferPtr++;
 | |
|   Start             = Ptr = SourceFile->FileBufferPtr;
 | |
|   PreviousBackslash = FALSE;
 | |
|   while (!EndOfFile (SourceFile)) {
 | |
|     if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) {
 | |
|       break;
 | |
|     } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
 | |
|       Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
 | |
|       PreviousBackslash = FALSE;
 | |
|     } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {
 | |
|       PreviousBackslash = TRUE;
 | |
|     } else {
 | |
|       PreviousBackslash = FALSE;
 | |
|     }
 | |
| 
 | |
|     SourceFile->FileBufferPtr++;
 | |
|     Len++;
 | |
|   }
 | |
| 
 | |
|   if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
 | |
|     Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
 | |
|   } else {
 | |
|     SourceFile->FileBufferPtr++;
 | |
|   }
 | |
|   //
 | |
|   // Now allocate memory for the string and save it off
 | |
|   //
 | |
|   String = (CHAR8  *) malloc ((Len + 1) * sizeof (CHAR8 ));
 | |
|   if (String == NULL) {
 | |
|     Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL);
 | |
|     return NULL;
 | |
|   }
 | |
|   //
 | |
|   // Copy the string from the file buffer to the local copy.
 | |
|   // We do no reformatting of it whatsoever at this point.
 | |
|   //
 | |
|   Ptr = String;
 | |
|   while (Len > 0) {
 | |
|     *Ptr = *Start;
 | |
|     Start++;
 | |
|     Ptr++;
 | |
|     Len--;
 | |
|   }
 | |
| 
 | |
|   *Ptr = 0;
 | |
|   return String;
 | |
| }
 | |
| #endif
 | |
| STATIC
 | |
| BOOLEAN
 | |
| EndOfFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // The file buffer pointer will typically get updated before the End-of-file flag in the
 | |
|   // source file structure, so check it first.
 | |
|   //
 | |
|   if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (CHAR8 )) {
 | |
|     SourceFile->EndOfFile = TRUE;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if (SourceFile->EndOfFile) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| STATIC
 | |
| VOID
 | |
| ProcessTokenInclude (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   CHAR8          IncludeFileName[MAX_PATH];
 | |
|   CHAR8          *To;
 | |
|   UINTN  Len;
 | |
|   BOOLEAN       ReportedError;
 | |
|   SOURCE_FILE   IncludedSourceFile;
 | |
| 
 | |
|   ReportedError = FALSE;
 | |
|   if (SkipWhiteSpace (SourceFile) == 0) {
 | |
|     Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
 | |
|   }
 | |
|   //
 | |
|   // Should be quoted file name
 | |
|   //
 | |
|   if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
 | |
|     Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
 | |
|     goto FailDone;
 | |
|   }
 | |
| 
 | |
|   SourceFile->FileBufferPtr++;
 | |
|   //
 | |
|   // Copy the filename as ascii to our local string
 | |
|   //
 | |
|   To  = IncludeFileName;
 | |
|   Len = 0;
 | |
|   while (!EndOfFile (SourceFile)) {
 | |
|     if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {
 | |
|       Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
 | |
|       goto FailDone;
 | |
|     }
 | |
| 
 | |
|     if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // If too long, then report the error once and process until the closing quote
 | |
|     //
 | |
|     Len++;
 | |
|     if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
 | |
|       Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
 | |
|       ReportedError = TRUE;
 | |
|     }
 | |
| 
 | |
|     if (!ReportedError) {
 | |
|       *To = (CHAR8 ) SourceFile->FileBufferPtr[0];
 | |
|       To++;
 | |
|     }
 | |
| 
 | |
|     SourceFile->FileBufferPtr++;
 | |
|   }
 | |
| 
 | |
|   if (!ReportedError) {
 | |
|     *To = 0;
 | |
|     memset ((CHAR8 *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
 | |
|     strcpy (IncludedSourceFile.FileName, IncludeFileName);
 | |
|     ProcessIncludeFile (&IncludedSourceFile, SourceFile);
 | |
|   }
 | |
| 
 | |
|   return ;
 | |
| FailDone:
 | |
|   //
 | |
|   // Error recovery -- skip to next #
 | |
|   //
 | |
|   SourceFile->SkipToHash = TRUE;
 | |
| }
 | |
| #endif
 | |
| STATIC
 | |
| BOOLEAN
 | |
| IsWhiteSpace (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   switch (*SourceFile->FileBufferPtr) {
 | |
|   case T_CHAR_NULL:
 | |
|   case T_CHAR_CR:
 | |
|   case T_CHAR_SPACE:
 | |
|   case T_CHAR_TAB:
 | |
|   case T_CHAR_LF:
 | |
|     return TRUE;
 | |
| 
 | |
|   default:
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| UINTN
 | |
| SkipWhiteSpace (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   UINTN  Count;
 | |
| 
 | |
|   Count = 0;
 | |
|   while (!EndOfFile (SourceFile)) {
 | |
|     Count++;
 | |
|     switch (*SourceFile->FileBufferPtr) {
 | |
|     case T_CHAR_NULL:
 | |
|     case T_CHAR_CR:
 | |
|     case T_CHAR_SPACE:
 | |
|     case T_CHAR_TAB:
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       break;
 | |
| 
 | |
|     case T_CHAR_LF:
 | |
|       SourceFile->FileBufferPtr++;
 | |
|       SourceFile->LineNum++;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return Count - 1;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Some tokens require trailing whitespace. If we're at the end of the
 | |
|   // file, then we count that as well.
 | |
|   //
 | |
|   if ((Count == 0) && (EndOfFile (SourceFile))) {
 | |
|     Count++;
 | |
|   }
 | |
| 
 | |
|   return Count;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,
 | |
|   so only compare up to the length of Str.
 | |
| 
 | |
|   @param Buffer  pointer to first (possibly not null-terminated) string
 | |
|   @param Str     pointer to null-terminated string to compare to Buffer
 | |
| 
 | |
|   @retval Number of bytes matched if exact match
 | |
|   @retval 0 if Buffer does not start with Str
 | |
| **/
 | |
| STATIC
 | |
| UINTN
 | |
| t_strcmp (
 | |
|   CHAR8  *Buffer,
 | |
|   CHAR8  *Str
 | |
|   )
 | |
| {
 | |
|   UINTN  Len;
 | |
| 
 | |
|   Len = 0;
 | |
|   while (*Str && (*Str == *Buffer)) {
 | |
|     Buffer++;
 | |
|     Str++;
 | |
|     Len++;
 | |
|   }
 | |
| 
 | |
|   if (*Str) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return Len;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| UINTN
 | |
| t_strlen (
 | |
|   CHAR8  *Str
 | |
|   )
 | |
| {
 | |
|   UINTN  Len;
 | |
|   Len = 0;
 | |
|   while (*Str) {
 | |
|     Len++;
 | |
|     Str++;
 | |
|   }
 | |
| 
 | |
|   return Len;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| UINTN
 | |
| t_strncmp (
 | |
|   CHAR8  *Str1,
 | |
|   CHAR8  *Str2,
 | |
|   INTN    Len
 | |
|   )
 | |
| {
 | |
|   while (Len > 0) {
 | |
|     if (*Str1 != *Str2) {
 | |
|       return Len;
 | |
|     }
 | |
| 
 | |
|     Len--;
 | |
|     Str1++;
 | |
|     Str2++;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| CHAR8  *
 | |
| t_strcpy (
 | |
|   CHAR8  *Dest,
 | |
|   CHAR8  *Src
 | |
|   )
 | |
| {
 | |
|   CHAR8   *SaveDest;
 | |
|   SaveDest = Dest;
 | |
|   while (*Src) {
 | |
|     *Dest = *Src;
 | |
|     Dest++;
 | |
|     Src++;
 | |
|   }
 | |
| 
 | |
|   *Dest = 0;
 | |
|   return SaveDest;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| RewindFile (
 | |
|   SOURCE_FILE *SourceFile
 | |
|   )
 | |
| {
 | |
|   SourceFile->LineNum       = 1;
 | |
|   SourceFile->FileBufferPtr = SourceFile->FileBuffer;
 | |
|   SourceFile->EndOfFile     = 0;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| UINT32
 | |
| GetHexChars (
 | |
|   CHAR8       *Buffer,
 | |
|   UINT32      BufferLen
 | |
|   )
 | |
| {
 | |
|   UINT32  Len;
 | |
|   Len = 0;
 | |
|   while (!EndOfFile (&mGlobals.SourceFile) && (Len < BufferLen)) {
 | |
|     if (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
 | |
|       Buffer[Len] = mGlobals.SourceFile.FileBufferPtr[0];
 | |
|       Len++;
 | |
|       mGlobals.SourceFile.FileBufferPtr++;
 | |
|     } else {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Null terminate if we can
 | |
|   //
 | |
|   if ((Len > 0) && (Len < BufferLen)) {
 | |
|     Buffer[Len] = 0;
 | |
|   }
 | |
| 
 | |
|   return Len;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse a GUID from the input stream. Stop when you discover white space.
 | |
| 
 | |
|  GUID styles
 | |
|    Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
 | |
| 
 | |
|   @param GuidStyle Style of the following GUID token
 | |
|   @param Value     pointer to EFI_GUID struct for output
 | |
| 
 | |
|   @retval TRUE  GUID string parsed successfully
 | |
|   @retval FALSE otherwise
 | |
| **/
 | |
| BOOLEAN
 | |
| SFPGetGuid (
 | |
|   INTN         GuidStyle,
 | |
|   EFI_GUID    *Value
 | |
|   )
 | |
| {
 | |
|   INT32         Value32;
 | |
|   UINT32        Index;
 | |
|   FILE_POSITION FPos;
 | |
|   CHAR8         TempString[20];
 | |
|   CHAR8         TempString2[3];
 | |
|   CHAR8         *From;
 | |
|   CHAR8         *To;
 | |
|   UINT32        Len;
 | |
|   BOOLEAN       Status;
 | |
| 
 | |
|   Status = FALSE;
 | |
|   //
 | |
|   // Skip white space, then start parsing
 | |
|   //
 | |
|   SkipWhiteSpace (&mGlobals.SourceFile);
 | |
|   GetFilePosition (&FPos);
 | |
|   if (EndOfFile (&mGlobals.SourceFile)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) {
 | |
|     //
 | |
|     // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
 | |
|     //
 | |
|     Len = GetHexChars (TempString, sizeof (TempString));
 | |
|     if ((Len == 0) || (Len > 8)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     sscanf (TempString, "%x", &Value32);
 | |
|     Value->Data1 = Value32;
 | |
|     //
 | |
|     // Next two UINT16 fields
 | |
|     //
 | |
|     if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     Len = GetHexChars (TempString, sizeof (TempString));
 | |
|     if ((Len == 0) || (Len > 4)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     sscanf (TempString, "%x", &Value32);
 | |
|     Value->Data2 = (UINT16) Value32;
 | |
| 
 | |
|     if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     Len = GetHexChars (TempString, sizeof (TempString));
 | |
|     if ((Len == 0) || (Len > 4)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     sscanf (TempString, "%x", &Value32);
 | |
|     Value->Data3 = (UINT16) Value32;
 | |
|     //
 | |
|     // Parse the "AAAA" as two bytes
 | |
|     //
 | |
|     if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     Len = GetHexChars (TempString, sizeof (TempString));
 | |
|     if ((Len == 0) || (Len > 4)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     sscanf (TempString, "%x", &Value32);
 | |
|     Value->Data4[0] = (UINT8) (Value32 >> 8);
 | |
|     Value->Data4[1] = (UINT8) Value32;
 | |
|     if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     mGlobals.SourceFile.FileBufferPtr++;
 | |
|     //
 | |
|     // Read the last 6 bytes of the GUID
 | |
|     //
 | |
|     //
 | |
|     Len = GetHexChars (TempString, sizeof (TempString));
 | |
|     if ((Len == 0) || (Len > 12)) {
 | |
|       goto Done;
 | |
|     }
 | |
|     //
 | |
|     // Insert leading 0's to make life easier
 | |
|     //
 | |
|     if (Len != 12) {
 | |
|       From            = TempString + Len - 1;
 | |
|       To              = TempString + 11;
 | |
|       TempString[12]  = 0;
 | |
|       while (From >= TempString) {
 | |
|         *To = *From;
 | |
|         To--;
 | |
|         From--;
 | |
|       }
 | |
| 
 | |
|       while (To >= TempString) {
 | |
|         *To = '0';
 | |
|         To--;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Now parse each byte
 | |
|     //
 | |
|     TempString2[2] = 0;
 | |
|     for (Index = 0; Index < 6; Index++) {
 | |
|       //
 | |
|       // Copy the two characters from the input string to something
 | |
|       // we can parse.
 | |
|       //
 | |
|       TempString2[0]  = TempString[Index * 2];
 | |
|       TempString2[1]  = TempString[Index * 2 + 1];
 | |
|       sscanf (TempString2, "%x", &Value32);
 | |
|       Value->Data4[Index + 2] = (UINT8) Value32;
 | |
|     }
 | |
| 
 | |
|     Status = TRUE;
 | |
|   } else {
 | |
|     //
 | |
|     // Unsupported GUID style
 | |
|     //
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (Status == FALSE) {
 | |
|     SetFilePosition (&FPos);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| STATUS
 | |
| GetFilePosition (
 | |
|   FILE_POSITION *Fpos
 | |
|   )
 | |
| {
 | |
|   Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr;
 | |
|   return STATUS_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| STATUS
 | |
| SetFilePosition (
 | |
|   FILE_POSITION *Fpos
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Should check range of pointer
 | |
|   //
 | |
|   mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr;
 | |
|   return STATUS_SUCCESS;
 | |
| }
 |