mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yingke Liu <yingke.d.liu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15971 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1438 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1438 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
Generic but simple file parsing routines.
 | 
						|
 | 
						|
Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#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
 | 
						|
  );
 | 
						|
 | 
						|
STATUS
 | 
						|
SFPInit (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
Arguments:
 | 
						|
  None.
 | 
						|
 | 
						|
Returns:
 | 
						|
  STATUS_SUCCESS always
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  memset ((VOID *) &mGlobals, 0, sizeof (mGlobals));
 | 
						|
  return STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
UINTN
 | 
						|
SFPGetLineNumber (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Return the line number of the file we're parsing. Used
 | 
						|
  for error reporting purposes.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  None.
 | 
						|
 | 
						|
Returns:
 | 
						|
  The line number, or 0 if no file is being processed
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return mGlobals.SourceFile.LineNum;
 | 
						|
}
 | 
						|
 | 
						|
CHAR8  *
 | 
						|
SFPGetFileName (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Return the name of the file we're parsing. Used
 | 
						|
  for error reporting purposes.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  None.
 | 
						|
 | 
						|
Returns:
 | 
						|
  A pointer to the file name. Null if no file is being
 | 
						|
  processed.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (mGlobals.SourceFile.FileName[0]) {
 | 
						|
    return mGlobals.SourceFile.FileName;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
STATUS
 | 
						|
SFPOpenFile (
 | 
						|
  CHAR8      *FileName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Open a file for parsing.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FileName  - name of the file to parse
 | 
						|
 | 
						|
Returns:
 | 
						|
  
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  STATUS  Status;
 | 
						|
  t_strcpy (mGlobals.SourceFile.FileName, FileName);
 | 
						|
  Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPIsToken (
 | 
						|
  CHAR8  *Str
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Check to see if the specified token is found at
 | 
						|
  the current position in the input file.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Str - the token to look for
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE - the token is next
 | 
						|
  FALSE - the token is not next
 | 
						|
 | 
						|
Notes:
 | 
						|
  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.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPIsKeyword (
 | 
						|
  CHAR8  *Str
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Check to see if the specified keyword is found at
 | 
						|
  the current position in the input file.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Str - keyword to look for
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE - the keyword is next
 | 
						|
  FALSE - the keyword is not next
 | 
						|
 | 
						|
Notes:
 | 
						|
  A keyword is defined as a "special" string that has a non-alphanumeric
 | 
						|
  character following it.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPGetNextToken (
 | 
						|
  CHAR8  *Str,
 | 
						|
  UINTN  Len
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Get the next token from the input stream. 
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Str - pointer to a copy of the next token
 | 
						|
  Len - size of buffer pointed to by Str
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE  - next token successfully returned
 | 
						|
  FALSE - otherwise
 | 
						|
 | 
						|
Notes:
 | 
						|
  Preceeding white space is ignored. 
 | 
						|
  The parser's buffer pointer is advanced past the end of the
 | 
						|
  token.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPGetGuidToken (
 | 
						|
  CHAR8  *Str,
 | 
						|
  UINT32 Len
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Parse a GUID from the input stream. Stop when you discover white space.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Str - pointer to a copy of the next token
 | 
						|
  Len - size of buffer pointed to by Str
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE  - GUID string returned successfully
 | 
						|
  FALSE - otherwise
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPGetNumber (
 | 
						|
  UINTN *Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Check the token at the current file position for a numeric value.
 | 
						|
  May be either decimal or hex.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Value  - pointer where to store the value
 | 
						|
 | 
						|
Returns:
 | 
						|
  FALSE    - current token is not a number
 | 
						|
  TRUE     - current token is a number
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  unsigned 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;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
STATUS
 | 
						|
SFPCloseFile (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Close the file being parsed.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  None.
 | 
						|
 | 
						|
Returns:
 | 
						|
  STATUS_SUCCESS - the file was closed 
 | 
						|
  STATUS_ERROR   - no file is currently open
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (mGlobals.SourceFile.FileBuffer != NULL) {
 | 
						|
    free (mGlobals.SourceFile.FileBuffer);
 | 
						|
    memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
 | 
						|
    return STATUS_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return STATUS_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
STATUS
 | 
						|
ProcessIncludeFile (
 | 
						|
  SOURCE_FILE *SourceFile,
 | 
						|
  SOURCE_FILE *ParentSourceFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Given a source file, open the file and parse it
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  SourceFile        - name of file to parse
 | 
						|
  ParentSourceFile  - for error reporting purposes, the file that #included SourceFile.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Standard status.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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 exceeeds 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;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
STATUS
 | 
						|
ProcessFile (
 | 
						|
  SOURCE_FILE *SourceFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Given a source file that's been opened, read the contents into an internal
 | 
						|
  buffer and pre-process it to remove comments.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  SourceFile        - structure containing info on the file to process
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Standard status.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
PreprocessFile (
 | 
						|
  SOURCE_FILE *SourceFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  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.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  SourceFile - structure that we use to keep track of an input file.
 | 
						|
 | 
						|
Returns:
 | 
						|
  Nothing.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPGetQuotedString (
 | 
						|
  CHAR8       *Str,
 | 
						|
  INTN         Length
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Retrieve a quoted-string from the input file. 
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  Str    - pointer to a copy of the quoted string parsed
 | 
						|
  Length - size of buffer pointed to by Str
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE    - next token in input stream was a quoted string, and
 | 
						|
            the string value was returned in Str
 | 
						|
  FALSE   - otherwise
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPIsEOF (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Return TRUE of FALSE to indicate whether or not we've reached the end of the
 | 
						|
  file we're parsing.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  NA
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE    - EOF reached
 | 
						|
  FALSE   - otherwise
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
UINTN
 | 
						|
t_strcmp (
 | 
						|
  CHAR8  *Buffer,
 | 
						|
  CHAR8  *Str
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  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.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Buffer  - pointer to first (possibly not null-terminated) string
 | 
						|
  Str     - pointer to null-terminated string to compare to Buffer
 | 
						|
 | 
						|
Returns:
 | 
						|
  Number of bytes matched if exact match
 | 
						|
  0 if Buffer does not start with 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) && (BufferLen > 0)) {
 | 
						|
    if (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
 | 
						|
      *Buffer = mGlobals.SourceFile.FileBufferPtr[0];
 | 
						|
      Buffer++;
 | 
						|
      Len++;
 | 
						|
      BufferLen--;
 | 
						|
      mGlobals.SourceFile.FileBufferPtr++;
 | 
						|
    } else {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Null terminate if we can
 | 
						|
  //
 | 
						|
  if ((Len > 0) && (BufferLen > 0)) {
 | 
						|
    *Buffer = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return Len;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
SFPGetGuid (
 | 
						|
  INTN         GuidStyle,
 | 
						|
  EFI_GUID    *Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Parse a GUID from the input stream. Stop when you discover white space.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  GuidStyle - Style of the following GUID token
 | 
						|
  Value     - pointer to EFI_GUID struct for output
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE  - GUID string parsed successfully
 | 
						|
  FALSE - otherwise
 | 
						|
 | 
						|
  GUID styles
 | 
						|
    Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  unsigned      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;
 | 
						|
}
 |