]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / Common / SimpleFileParsing.c
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c
new file mode 100644 (file)
index 0000000..2a2fbe6
--- /dev/null
@@ -0,0 +1,1456 @@
+/*++\r
+\r
+Copyright (c) 2004, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  SimpleFileParsing.c  \r
+\r
+Abstract:\r
+\r
+  Generic but simple file parsing routines.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include "SimpleFileParsing.h"\r
+\r
+#define MAX_PATH  255\r
+//\r
+// just in case we get in an endless loop.\r
+//\r
+#define MAX_NEST_DEPTH  20\r
+//\r
+// number of wchars\r
+//\r
+#define MAX_STRING_IDENTIFIER_NAME  100\r
+\r
+#define MAX_LINE_LEN                400\r
+\r
+#define T_CHAR_SPACE                ' '\r
+#define T_CHAR_NULL                 0\r
+#define T_CHAR_CR                   '\r'\r
+#define T_CHAR_TAB                  '\t'\r
+#define T_CHAR_LF                   '\n'\r
+#define T_CHAR_SLASH                '/'\r
+#define T_CHAR_BACKSLASH            '\\'\r
+#define T_CHAR_DOUBLE_QUOTE         '"'\r
+#define T_CHAR_LC_X                 'x'\r
+#define T_CHAR_0                    '0'\r
+#define T_CHAR_STAR                 '*'\r
+\r
+//\r
+// We keep a linked list of these for the source files we process\r
+//\r
+typedef struct _SOURCE_FILE {\r
+  FILE                *Fptr;\r
+  T_CHAR              *FileBuffer;\r
+  T_CHAR              *FileBufferPtr;\r
+  unsigned int        FileSize;\r
+  char                FileName[MAX_PATH];\r
+  unsigned int        LineNum;\r
+  BOOLEAN             EndOfFile;\r
+  BOOLEAN             SkipToHash;\r
+  struct _SOURCE_FILE *Previous;\r
+  struct _SOURCE_FILE *Next;\r
+  T_CHAR              ControlCharacter;\r
+} SOURCE_FILE;\r
+\r
+typedef struct {\r
+  T_CHAR  *FileBufferPtr;\r
+} FILE_POSITION;\r
+\r
+//\r
+// Keep all our module globals in this structure\r
+//\r
+static struct {\r
+  SOURCE_FILE SourceFile;\r
+  BOOLEAN     VerboseFile;\r
+  BOOLEAN     VerboseToken;\r
+} mGlobals;\r
+\r
+static\r
+unsigned int\r
+t_strcmp (\r
+  T_CHAR *Buffer,\r
+  T_CHAR *Str\r
+  );\r
+\r
+static\r
+unsigned int\r
+t_strncmp (\r
+  T_CHAR *Str1,\r
+  T_CHAR *Str2,\r
+  int    Len\r
+  );\r
+\r
+static\r
+unsigned int\r
+t_strlen (\r
+  T_CHAR *Str\r
+  );\r
+\r
+static\r
+void\r
+RewindFile (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+IsWhiteSpace (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+unsigned int\r
+SkipWhiteSpace (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+EndOfFile (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+void\r
+PreprocessFile (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+T_CHAR  *\r
+t_strcpy (\r
+  T_CHAR *Dest,\r
+  T_CHAR *Src\r
+  );\r
+\r
+static\r
+STATUS\r
+ProcessIncludeFile (\r
+  SOURCE_FILE *SourceFile,\r
+  SOURCE_FILE *ParentSourceFile\r
+  );\r
+\r
+static\r
+STATUS\r
+ParseFile (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+FILE    *\r
+FindFile (\r
+  char          *FileName,\r
+  char          *FoundFileName,\r
+  unsigned int  FoundFileNameLen\r
+  );\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+STATUS\r
+GetFilePosition (\r
+  FILE_POSITION *Fpos\r
+  );\r
+\r
+static\r
+STATUS\r
+SetFilePosition (\r
+  FILE_POSITION *Fpos\r
+  );\r
+\r
+STATUS\r
+SFPInit (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  STATUS_SUCCESS always\r
+\r
+--*/\r
+{\r
+  memset ((void *) &mGlobals, 0, sizeof (mGlobals));\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+unsigned\r
+int\r
+SFPGetLineNumber (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Return the line number of the file we're parsing. Used\r
+  for error reporting purposes.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  The line number, or 0 if no file is being processed\r
+\r
+--*/\r
+{\r
+  return mGlobals.SourceFile.LineNum;\r
+}\r
+\r
+T_CHAR *\r
+SFPGetFileName (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Return the name of the file we're parsing. Used\r
+  for error reporting purposes.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  A pointer to the file name. Null if no file is being\r
+  processed.\r
+\r
+--*/\r
+{\r
+  if (mGlobals.SourceFile.FileName[0]) {\r
+    return mGlobals.SourceFile.FileName;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+STATUS\r
+SFPOpenFile (\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Open a file for parsing.\r
+\r
+Arguments:\r
+  FileName  - name of the file to parse\r
+\r
+Returns:\r
+  \r
+\r
+--*/\r
+{\r
+  STATUS  Status;\r
+  t_strcpy (mGlobals.SourceFile.FileName, FileName);\r
+  Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+SFPIsToken (\r
+  T_CHAR *Str\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Check to see if the specified token is found at\r
+  the current position in the input file.\r
+\r
+Arguments:\r
+  Str - the token to look for\r
+\r
+Returns:\r
+  TRUE - the token is next\r
+  FALSE - the token is not next\r
+\r
+Notes:\r
+  We do a simple string comparison on this function. It is\r
+  the responsibility of the caller to ensure that the token\r
+  is not a subset of some other token.\r
+\r
+  The file pointer is advanced past the token in the input file.\r
+\r
+--*/\r
+{\r
+  unsigned int  Len;\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {\r
+    mGlobals.SourceFile.FileBufferPtr += Len;\r
+    if (mGlobals.VerboseToken) {\r
+      printf ("Token: '%s'\n", Str);\r
+    }\r
+\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+SFPIsKeyword (\r
+  T_CHAR *Str\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Check to see if the specified keyword is found at\r
+  the current position in the input file.\r
+\r
+Arguments:\r
+  Str - keyword to look for\r
+\r
+Returns:\r
+  TRUE - the keyword is next\r
+  FALSE - the keyword is not next\r
+\r
+Notes:\r
+  A keyword is defined as a "special" string that has a non-alphanumeric\r
+  character following it.\r
+\r
+--*/\r
+{\r
+  unsigned int  Len;\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {\r
+    if (isalnum (mGlobals.SourceFile.FileBufferPtr[Len])) {\r
+      return FALSE;\r
+    }\r
+\r
+    mGlobals.SourceFile.FileBufferPtr += Len;\r
+    if (mGlobals.VerboseToken) {\r
+      printf ("Token: '%s'\n", Str);\r
+    }\r
+\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+SFPGetNextToken (\r
+  T_CHAR        *Str,\r
+  unsigned int  Len\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get the next token from the input stream. \r
+\r
+Arguments:\r
+  Str - pointer to a copy of the next token\r
+  Len - size of buffer pointed to by Str\r
+\r
+Returns:\r
+  TRUE  - next token successfully returned\r
+  FALSE - otherwise\r
+\r
+Notes:\r
+  Preceeding white space is ignored. \r
+  The parser's buffer pointer is advanced past the end of the\r
+  token.\r
+\r
+--*/\r
+{\r
+  unsigned int  Index;\r
+  T_CHAR        TempChar;\r
+\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+  //\r
+  // Have to have enough string for at least one char and a null-terminator\r
+  //\r
+  if (Len < 2) {\r
+    return FALSE;\r
+  }\r
+  //\r
+  // Look at the first character. If it's an identifier, then treat it\r
+  // as such\r
+  //\r
+  TempChar = mGlobals.SourceFile.FileBufferPtr[0];\r
+  if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) {\r
+    Str[0] = TempChar;\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    Index = 1;\r
+    while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {\r
+      TempChar = mGlobals.SourceFile.FileBufferPtr[0];\r
+      if (((TempChar >= 'a') && (TempChar <= 'z')) ||\r
+          ((TempChar >= 'A') && (TempChar <= 'Z')) ||\r
+          ((TempChar >= '0') && (TempChar <= '9')) ||\r
+          (TempChar == '_')\r
+          ) {\r
+        Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];\r
+        mGlobals.SourceFile.FileBufferPtr++;\r
+        Index++;\r
+      } else {\r
+        //\r
+        // Invalid character for symbol name, so break out\r
+        //\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // Null terminate and return success\r
+    //\r
+    Str[Index] = 0;\r
+    return TRUE;\r
+  } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) {\r
+    Str[0] = mGlobals.SourceFile.FileBufferPtr[0];\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    Str[1] = 0;\r
+    return TRUE;\r
+  } else {\r
+    //\r
+    // Everything else is white-space (or EOF) separated\r
+    //\r
+    Index = 0;\r
+    while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {\r
+      if (IsWhiteSpace (&mGlobals.SourceFile)) {\r
+        if (Index > 0) {\r
+          Str[Index] = 0;\r
+          return TRUE;\r
+        }\r
+\r
+        return FALSE;\r
+      } else {\r
+        Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];\r
+        mGlobals.SourceFile.FileBufferPtr++;\r
+        Index++;\r
+      }\r
+    }\r
+    //\r
+    // See if we just ran out of file contents, but did find a token\r
+    //\r
+    if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) {\r
+      Str[Index] = 0;\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+SFPGetGuidToken (\r
+  T_CHAR *Str,\r
+  UINT32 Len\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Parse a GUID from the input stream. Stop when you discover white space.\r
+\r
+Arguments:\r
+  Str - pointer to a copy of the next token\r
+  Len - size of buffer pointed to by Str\r
+\r
+Returns:\r
+  TRUE  - GUID string returned successfully\r
+  FALSE - otherwise\r
+\r
+--*/\r
+{\r
+  UINT32  Index;\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+\r
+  Index = 0;\r
+  while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {\r
+    if (IsWhiteSpace (&mGlobals.SourceFile)) {\r
+      if (Index > 0) {\r
+        Str[Index] = 0;\r
+        return TRUE;\r
+      }\r
+\r
+      return FALSE;\r
+    } else {\r
+      Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];\r
+      mGlobals.SourceFile.FileBufferPtr++;\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+SFPSkipToToken (\r
+  T_CHAR *Str\r
+  )\r
+{\r
+  unsigned int  Len;\r
+  T_CHAR        *SavePos;\r
+  Len     = t_strlen (Str);\r
+  SavePos = mGlobals.SourceFile.FileBufferPtr;\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  while (!EndOfFile (&mGlobals.SourceFile)) {\r
+    if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {\r
+      mGlobals.SourceFile.FileBufferPtr += Len;\r
+      return TRUE;\r
+    }\r
+\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    SkipWhiteSpace (&mGlobals.SourceFile);\r
+  }\r
+\r
+  mGlobals.SourceFile.FileBufferPtr = SavePos;\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+SFPGetNumber (\r
+  unsigned int *Value\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Check the token at the current file position for a numeric value.\r
+  May be either decimal or hex.\r
+\r
+Arguments:\r
+  Value  - pointer where to store the value\r
+\r
+Returns:\r
+  FALSE    - current token is not a number\r
+  TRUE     - current token is a number\r
+\r
+--*/\r
+{\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
+    //\r
+    // Check for hex value\r
+    //\r
+    if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {\r
+      if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {\r
+        return FALSE;\r
+      }\r
+\r
+      mGlobals.SourceFile.FileBufferPtr += 2;\r
+      sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);\r
+      while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
+        mGlobals.SourceFile.FileBufferPtr++;\r
+      }\r
+\r
+      return TRUE;\r
+    } else {\r
+      *Value = atoi (mGlobals.SourceFile.FileBufferPtr);\r
+      while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
+        mGlobals.SourceFile.FileBufferPtr++;\r
+      }\r
+\r
+      return TRUE;\r
+    }\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+STATUS\r
+SFPCloseFile (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Close the file being parsed.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - the file was closed \r
+  STATUS_ERROR   - no file is currently open\r
+\r
+--*/\r
+{\r
+  if (mGlobals.SourceFile.FileBuffer != NULL) {\r
+    free (mGlobals.SourceFile.FileBuffer);\r
+    memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));\r
+    return STATUS_SUCCESS;\r
+  }\r
+\r
+  return STATUS_ERROR;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessIncludeFile (\r
+  SOURCE_FILE *SourceFile,\r
+  SOURCE_FILE *ParentSourceFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Given a source file, open the file and parse it\r
+  \r
+Arguments:\r
+\r
+  SourceFile        - name of file to parse\r
+  ParentSourceFile  - for error reporting purposes, the file that #included SourceFile.\r
+\r
+Returns:\r
+\r
+  Standard status.\r
+  \r
+--*/\r
+{\r
+  static unsigned int NestDepth = 0;\r
+  char                FoundFileName[MAX_PATH];\r
+  STATUS              Status;\r
+\r
+  Status = STATUS_SUCCESS;\r
+  NestDepth++;\r
+  //\r
+  // Print the file being processed. Indent so you can tell the include nesting\r
+  // depth.\r
+  //\r
+  if (mGlobals.VerboseFile) {\r
+    fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);\r
+    fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile);\r
+  }\r
+\r
+  //\r
+  // Make sure we didn't exceed our maximum nesting depth\r
+  //\r
+  if (NestDepth > MAX_NEST_DEPTH) {\r
+    Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);\r
+    Status = STATUS_ERROR;\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Try to open the file locally, and if that fails try along our include paths.\r
+  //\r
+  strcpy (FoundFileName, SourceFile->FileName);\r
+  if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Process the file found\r
+  //\r
+  ProcessFile (SourceFile);\r
+Finish:\r
+  //\r
+  // Close open files and return status\r
+  //\r
+  if (SourceFile->Fptr != NULL) {\r
+    fclose (SourceFile->Fptr);\r
+    SourceFile->Fptr = NULL;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Given a source file that's been opened, read the contents into an internal\r
+  buffer and pre-process it to remove comments.\r
+  \r
+Arguments:\r
+\r
+  SourceFile        - structure containing info on the file to process\r
+\r
+Returns:\r
+\r
+  Standard status.\r
+  \r
+--*/\r
+{\r
+  //\r
+  // Get the file size, and then read the entire thing into memory.\r
+  // Allocate extra space for a terminator character.\r
+  //\r
+  fseek (SourceFile->Fptr, 0, SEEK_END);\r
+  SourceFile->FileSize = ftell (SourceFile->Fptr);\r
+  if (mGlobals.VerboseFile) {\r
+    printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize);\r
+  }\r
+\r
+  fseek (SourceFile->Fptr, 0, SEEK_SET);\r
+  SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));\r
+  if (SourceFile->FileBuffer == NULL) {\r
+    Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  fread ((void *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);\r
+  SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;\r
+  //\r
+  // Pre-process the file to replace comments with spaces\r
+  //\r
+  PreprocessFile (SourceFile);\r
+  SourceFile->LineNum = 1;\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+PreprocessFile (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Preprocess a file to replace all carriage returns with NULLs so\r
+  we can print lines (as part of error messages) from the file to the screen.\r
+  \r
+Arguments:\r
+  SourceFile - structure that we use to keep track of an input file.\r
+\r
+Returns:\r
+  Nothing.\r
+  \r
+--*/\r
+{\r
+  BOOLEAN InComment;\r
+  BOOLEAN SlashSlashComment;\r
+  int     LineNum;\r
+\r
+  RewindFile (SourceFile);\r
+  InComment         = FALSE;\r
+  SlashSlashComment = FALSE;\r
+  while (!EndOfFile (SourceFile)) {\r
+    //\r
+    // If a line-feed, then no longer in a comment if we're in a // comment\r
+    //\r
+    if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {\r
+      SourceFile->FileBufferPtr++;\r
+      SourceFile->LineNum++;\r
+      if (InComment && SlashSlashComment) {\r
+        InComment         = FALSE;\r
+        SlashSlashComment = FALSE;\r
+      }\r
+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {\r
+      //\r
+      // Replace all carriage returns with a NULL so we can print stuff\r
+      //\r
+      SourceFile->FileBufferPtr[0] = 0;\r
+      SourceFile->FileBufferPtr++;\r
+      //\r
+      // Check for */ comment end\r
+      //\r
+    } else if (InComment &&\r
+             !SlashSlashComment &&\r
+             (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) &&\r
+             (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)\r
+            ) {\r
+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;\r
+      SourceFile->FileBufferPtr++;\r
+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;\r
+      SourceFile->FileBufferPtr++;\r
+      InComment = FALSE;\r
+    } else if (InComment) {\r
+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;\r
+      SourceFile->FileBufferPtr++;\r
+      //\r
+      // Check for // comments\r
+      //\r
+    } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {\r
+      InComment         = TRUE;\r
+      SlashSlashComment = TRUE;\r
+      //\r
+      // Check for /* comment start\r
+      //\r
+    } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) {\r
+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;\r
+      SourceFile->FileBufferPtr++;\r
+      SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;\r
+      SourceFile->FileBufferPtr++;\r
+      SlashSlashComment = FALSE;\r
+      InComment         = TRUE;\r
+    } else {\r
+      SourceFile->FileBufferPtr++;\r
+    }\r
+  }\r
+  //\r
+  // Could check for end-of-file and still in a comment, but\r
+  // should not be necessary. So just restore the file pointers.\r
+  //\r
+  RewindFile (SourceFile);\r
+  //\r
+  // Dump the reformatted file if verbose mode\r
+  //\r
+  if (mGlobals.VerboseFile) {\r
+    LineNum = 1;\r
+    printf ("%04d: ", LineNum);\r
+    while (!EndOfFile (SourceFile)) {\r
+      if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {\r
+        printf ("'\n%04d: '", ++LineNum);\r
+      } else {\r
+        printf ("%c", SourceFile->FileBufferPtr[0]);\r
+      }\r
+\r
+      SourceFile->FileBufferPtr++;\r
+    }\r
+\r
+    printf ("'\n");\r
+    printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize);\r
+    RewindFile (SourceFile);\r
+  }\r
+}\r
+\r
+BOOLEAN\r
+SFPGetQuotedString (\r
+  T_CHAR      *Str,\r
+  int         Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Retrieve a quoted-string from the input file. \r
+  \r
+Arguments:\r
+  Str    - pointer to a copy of the quoted string parsed\r
+  Length - size of buffer pointed to by Str\r
+\r
+Returns:\r
+  TRUE    - next token in input stream was a quoted string, and\r
+            the string value was returned in Str\r
+  FALSE   - otherwise\r
+  \r
+--*/\r
+{\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    while (Length > 0) {\r
+      if (EndOfFile (&mGlobals.SourceFile)) {\r
+        return FALSE;\r
+      }\r
+      //\r
+      // Check for closing quote\r
+      //\r
+      if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {\r
+        mGlobals.SourceFile.FileBufferPtr++;\r
+        *Str = 0;\r
+        return TRUE;\r
+      }\r
+\r
+      *Str = mGlobals.SourceFile.FileBufferPtr[0];\r
+      Str++;\r
+      Length--;\r
+      mGlobals.SourceFile.FileBufferPtr++;\r
+    }\r
+  }\r
+  //\r
+  // First character was not a quote, or the input string length was\r
+  // insufficient to contain the quoted string, so return failure code.\r
+  //\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+SFPIsEOF (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Return TRUE of FALSE to indicate whether or not we've reached the end of the\r
+  file we're parsing.\r
+  \r
+Arguments:\r
+  NA\r
+\r
+Returns:\r
+  TRUE    - EOF reached\r
+  FALSE   - otherwise\r
+  \r
+--*/\r
+{\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  return EndOfFile (&mGlobals.SourceFile);\r
+}\r
+\r
+#if 0\r
+static\r
+T_CHAR *\r
+GetQuotedString (\r
+  SOURCE_FILE *SourceFile,\r
+  BOOLEAN     Optional\r
+  )\r
+{\r
+  T_CHAR        *String;\r
+  T_CHAR        *Start;\r
+  T_CHAR        *Ptr;\r
+  unsigned int  Len;\r
+  BOOLEAN       PreviousBackslash;\r
+\r
+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {\r
+    if (Optional == FALSE) {\r
+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);\r
+    }\r
+\r
+    return NULL;\r
+  }\r
+\r
+  Len = 0;\r
+  SourceFile->FileBufferPtr++;\r
+  Start             = Ptr = SourceFile->FileBufferPtr;\r
+  PreviousBackslash = FALSE;\r
+  while (!EndOfFile (SourceFile)) {\r
+    if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) {\r
+      break;\r
+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {\r
+      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);\r
+      PreviousBackslash = FALSE;\r
+    } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {\r
+      PreviousBackslash = TRUE;\r
+    } else {\r
+      PreviousBackslash = FALSE;\r
+    }\r
+\r
+    SourceFile->FileBufferPtr++;\r
+    Len++;\r
+  }\r
+\r
+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {\r
+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);\r
+  } else {\r
+    SourceFile->FileBufferPtr++;\r
+  }\r
+  //\r
+  // Now allocate memory for the string and save it off\r
+  //\r
+  String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));\r
+  if (String == NULL) {\r
+    Error (NULL, 0, 0, "memory allocation failed", NULL);\r
+    return NULL;\r
+  }\r
+  //\r
+  // Copy the string from the file buffer to the local copy.\r
+  // We do no reformatting of it whatsoever at this point.\r
+  //\r
+  Ptr = String;\r
+  while (Len > 0) {\r
+    *Ptr = *Start;\r
+    Start++;\r
+    Ptr++;\r
+    Len--;\r
+  }\r
+\r
+  *Ptr = 0;\r
+  return String;\r
+}\r
+#endif\r
+static\r
+BOOLEAN\r
+EndOfFile (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+{\r
+  //\r
+  // The file buffer pointer will typically get updated before the End-of-file flag in the\r
+  // source file structure, so check it first.\r
+  //\r
+  if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {\r
+    SourceFile->EndOfFile = TRUE;\r
+    return TRUE;\r
+  }\r
+\r
+  if (SourceFile->EndOfFile) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+#if 0\r
+static\r
+void\r
+ProcessTokenInclude (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+{\r
+  char          IncludeFileName[MAX_PATH];\r
+  char          *To;\r
+  unsigned int  Len;\r
+  BOOLEAN       ReportedError;\r
+  SOURCE_FILE   IncludedSourceFile;\r
+\r
+  ReportedError = FALSE;\r
+  if (SkipWhiteSpace (SourceFile) == 0) {\r
+    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);\r
+  }\r
+  //\r
+  // Should be quoted file name\r
+  //\r
+  if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {\r
+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);\r
+    goto FailDone;\r
+  }\r
+\r
+  SourceFile->FileBufferPtr++;\r
+  //\r
+  // Copy the filename as ascii to our local string\r
+  //\r
+  To  = IncludeFileName;\r
+  Len = 0;\r
+  while (!EndOfFile (SourceFile)) {\r
+    if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {\r
+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);\r
+      goto FailDone;\r
+    }\r
+\r
+    if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {\r
+      SourceFile->FileBufferPtr++;\r
+      break;\r
+    }\r
+    //\r
+    // If too long, then report the error once and process until the closing quote\r
+    //\r
+    Len++;\r
+    if (!ReportedError && (Len >= sizeof (IncludeFileName))) {\r
+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);\r
+      ReportedError = TRUE;\r
+    }\r
+\r
+    if (!ReportedError) {\r
+      *To = (T_CHAR) SourceFile->FileBufferPtr[0];\r
+      To++;\r
+    }\r
+\r
+    SourceFile->FileBufferPtr++;\r
+  }\r
+\r
+  if (!ReportedError) {\r
+    *To = 0;\r
+    memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));\r
+    strcpy (IncludedSourceFile.FileName, IncludeFileName);\r
+    ProcessIncludeFile (&IncludedSourceFile, SourceFile);\r
+  }\r
+\r
+  return ;\r
+FailDone:\r
+  //\r
+  // Error recovery -- skip to next #\r
+  //\r
+  SourceFile->SkipToHash = TRUE;\r
+}\r
+#endif\r
+static\r
+BOOLEAN\r
+IsWhiteSpace (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+{\r
+  switch (*SourceFile->FileBufferPtr) {\r
+  case T_CHAR_NULL:\r
+  case T_CHAR_CR:\r
+  case T_CHAR_SPACE:\r
+  case T_CHAR_TAB:\r
+  case T_CHAR_LF:\r
+    return TRUE;\r
+\r
+  default:\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+unsigned int\r
+SkipWhiteSpace (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+{\r
+  unsigned int  Count;\r
+\r
+  Count = 0;\r
+  while (!EndOfFile (SourceFile)) {\r
+    Count++;\r
+    switch (*SourceFile->FileBufferPtr) {\r
+    case T_CHAR_NULL:\r
+    case T_CHAR_CR:\r
+    case T_CHAR_SPACE:\r
+    case T_CHAR_TAB:\r
+      SourceFile->FileBufferPtr++;\r
+      break;\r
+\r
+    case T_CHAR_LF:\r
+      SourceFile->FileBufferPtr++;\r
+      SourceFile->LineNum++;\r
+      break;\r
+\r
+    default:\r
+      return Count - 1;\r
+    }\r
+  }\r
+  //\r
+  // Some tokens require trailing whitespace. If we're at the end of the\r
+  // file, then we count that as well.\r
+  //\r
+  if ((Count == 0) && (EndOfFile (SourceFile))) {\r
+    Count++;\r
+  }\r
+\r
+  return Count;\r
+}\r
+\r
+static\r
+unsigned int\r
+t_strcmp (\r
+  T_CHAR *Buffer,\r
+  T_CHAR *Str\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,\r
+  so only compare up to the length of Str.\r
+\r
+Arguments:\r
+  Buffer  - pointer to first (possibly not null-terminated) string\r
+  Str     - pointer to null-terminated string to compare to Buffer\r
+\r
+Returns:\r
+  Number of bytes matched if exact match\r
+  0 if Buffer does not start with Str\r
+\r
+--*/\r
+{\r
+  unsigned int  Len;\r
+\r
+  Len = 0;\r
+  while (*Str && (*Str == *Buffer)) {\r
+    Buffer++;\r
+    Str++;\r
+    Len++;\r
+  }\r
+\r
+  if (*Str) {\r
+    return 0;\r
+  }\r
+\r
+  return Len;\r
+}\r
+\r
+static\r
+unsigned int\r
+t_strlen (\r
+  T_CHAR *Str\r
+  )\r
+{\r
+  unsigned int  Len;\r
+  Len = 0;\r
+  while (*Str) {\r
+    Len++;\r
+    Str++;\r
+  }\r
+\r
+  return Len;\r
+}\r
+\r
+static\r
+unsigned int\r
+t_strncmp (\r
+  T_CHAR *Str1,\r
+  T_CHAR *Str2,\r
+  int    Len\r
+  )\r
+{\r
+  while (Len > 0) {\r
+    if (*Str1 != *Str2) {\r
+      return Len;\r
+    }\r
+\r
+    Len--;\r
+    Str1++;\r
+    Str2++;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+static\r
+T_CHAR *\r
+t_strcpy (\r
+  T_CHAR *Dest,\r
+  T_CHAR *Src\r
+  )\r
+{\r
+  T_CHAR  *SaveDest;\r
+  SaveDest = Dest;\r
+  while (*Src) {\r
+    *Dest = *Src;\r
+    Dest++;\r
+    Src++;\r
+  }\r
+\r
+  *Dest = 0;\r
+  return SaveDest;\r
+}\r
+\r
+static\r
+void\r
+RewindFile (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+{\r
+  SourceFile->LineNum       = 1;\r
+  SourceFile->FileBufferPtr = SourceFile->FileBuffer;\r
+  SourceFile->EndOfFile     = 0;\r
+}\r
+\r
+static\r
+UINT32\r
+GetHexChars (\r
+  T_CHAR      *Buffer,\r
+  UINT32      BufferLen\r
+  )\r
+{\r
+  UINT32  Len;\r
+  Len = 0;\r
+  while (!EndOfFile (&mGlobals.SourceFile) && (BufferLen > 0)) {\r
+    if (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {\r
+      *Buffer = mGlobals.SourceFile.FileBufferPtr[0];\r
+      Buffer++;\r
+      Len++;\r
+      BufferLen--;\r
+      mGlobals.SourceFile.FileBufferPtr++;\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Null terminate if we can\r
+  //\r
+  if ((Len > 0) && (BufferLen > 0)) {\r
+    *Buffer = 0;\r
+  }\r
+\r
+  return Len;\r
+}\r
+\r
+BOOLEAN\r
+SFPGetGuid (\r
+  int         GuidStyle,\r
+  EFI_GUID    *Value\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Parse a GUID from the input stream. Stop when you discover white space.\r
+\r
+Arguments:\r
+  GuidStyle - Style of the following GUID token\r
+  Value     - pointer to EFI_GUID struct for output\r
+\r
+Returns:\r
+  TRUE  - GUID string parsed successfully\r
+  FALSE - otherwise\r
+\r
+  GUID styles\r
+    Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD\r
+\r
+--*/\r
+{\r
+  UINT32        Value32;\r
+  UINT32        Index;\r
+  FILE_POSITION FPos;\r
+  T_CHAR        TempString[20];\r
+  T_CHAR        TempString2[3];\r
+  T_CHAR        *From;\r
+  T_CHAR        *To;\r
+  UINT32        Len;\r
+  BOOLEAN       Status;\r
+\r
+  Status = FALSE;\r
+  //\r
+  // Skip white space, then start parsing\r
+  //\r
+  SkipWhiteSpace (&mGlobals.SourceFile);\r
+  GetFilePosition (&FPos);\r
+  if (EndOfFile (&mGlobals.SourceFile)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) {\r
+    //\r
+    // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD\r
+    //\r
+    Len = GetHexChars (TempString, sizeof (TempString));\r
+    if ((Len == 0) || (Len > 8)) {\r
+      goto Done;\r
+    }\r
+\r
+    sscanf (TempString, "%x", &Value32);\r
+    Value->Data1 = Value32;\r
+    //\r
+    // Next two UINT16 fields\r
+    //\r
+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {\r
+      goto Done;\r
+    }\r
+\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    Len = GetHexChars (TempString, sizeof (TempString));\r
+    if ((Len == 0) || (Len > 4)) {\r
+      goto Done;\r
+    }\r
+\r
+    sscanf (TempString, "%x", &Value32);\r
+    Value->Data2 = (UINT16) Value32;\r
+\r
+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {\r
+      goto Done;\r
+    }\r
+\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    Len = GetHexChars (TempString, sizeof (TempString));\r
+    if ((Len == 0) || (Len > 4)) {\r
+      goto Done;\r
+    }\r
+\r
+    sscanf (TempString, "%x", &Value32);\r
+    Value->Data3 = (UINT16) Value32;\r
+    //\r
+    // Parse the "AAAA" as two bytes\r
+    //\r
+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {\r
+      goto Done;\r
+    }\r
+\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    Len = GetHexChars (TempString, sizeof (TempString));\r
+    if ((Len == 0) || (Len > 4)) {\r
+      goto Done;\r
+    }\r
+\r
+    sscanf (TempString, "%x", &Value32);\r
+    Value->Data4[0] = (UINT8) (Value32 >> 8);\r
+    Value->Data4[1] = (UINT8) Value32;\r
+    if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {\r
+      goto Done;\r
+    }\r
+\r
+    mGlobals.SourceFile.FileBufferPtr++;\r
+    //\r
+    // Read the last 6 bytes of the GUID\r
+    //\r
+    //\r
+    Len = GetHexChars (TempString, sizeof (TempString));\r
+    if ((Len == 0) || (Len > 12)) {\r
+      goto Done;\r
+    }\r
+    //\r
+    // Insert leading 0's to make life easier\r
+    //\r
+    if (Len != 12) {\r
+      From            = TempString + Len - 1;\r
+      To              = TempString + 11;\r
+      TempString[12]  = 0;\r
+      while (From >= TempString) {\r
+        *To = *From;\r
+        To--;\r
+        From--;\r
+      }\r
+\r
+      while (To >= TempString) {\r
+        *To = '0';\r
+        To--;\r
+      }\r
+    }\r
+    //\r
+    // Now parse each byte\r
+    //\r
+    TempString2[2] = 0;\r
+    for (Index = 0; Index < 6; Index++) {\r
+      //\r
+      // Copy the two characters from the input string to something\r
+      // we can parse.\r
+      //\r
+      TempString2[0]  = TempString[Index * 2];\r
+      TempString2[1]  = TempString[Index * 2 + 1];\r
+      sscanf (TempString2, "%x", &Value32);\r
+      Value->Data4[Index + 2] = (UINT8) Value32;\r
+    }\r
+\r
+    Status = TRUE;\r
+  } else {\r
+    //\r
+    // Unsupported GUID style\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+Done:\r
+  if (Status == FALSE) {\r
+    SetFilePosition (&FPos);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+GetFilePosition (\r
+  FILE_POSITION *Fpos\r
+  )\r
+{\r
+  Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr;\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+SetFilePosition (\r
+  FILE_POSITION *Fpos\r
+  )\r
+{\r
+  //\r
+  // Should check range of pointer\r
+  //\r
+  mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr;\r
+  return STATUS_SUCCESS;\r
+}\r