summaryrefslogtreecommitdiff
path: root/Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c')
-rw-r--r--Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c969
1 files changed, 969 insertions, 0 deletions
diff --git a/Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c b/Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c
new file mode 100644
index 0000000000..5fa5a22096
--- /dev/null
+++ b/Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c
@@ -0,0 +1,969 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. 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.
+
+Module Name:
+
+ SimpleFileParsing.c
+
+Abstract:
+
+ Generic but simple file parsing routines.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#define MAX_PATH 255
+#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop.
+#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars
+#define MAX_LINE_LEN 400
+
+#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'
+
+//
+// We keep a linked list of these for the source files we process
+//
+typedef struct _SOURCE_FILE {
+ FILE *Fptr;
+ T_CHAR *FileBuffer;
+ T_CHAR *FileBufferPtr;
+ UINT32 FileSize;
+ INT8 FileName[MAX_PATH];
+ UINT32 LineNum;
+ BOOLEAN EndOfFile;
+ BOOLEAN SkipToHash;
+ struct _SOURCE_FILE *Previous;
+ struct _SOURCE_FILE *Next;
+ T_CHAR ControlCharacter;
+} SOURCE_FILE;
+
+//
+// Here's all our module globals.
+//
+static struct {
+ SOURCE_FILE SourceFile;
+ BOOLEAN Verbose;
+} mGlobals;
+
+static
+UINT32
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ );
+
+static
+UINT32
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ UINT32 Len
+ );
+
+static
+UINT32
+t_strlen (
+ T_CHAR *Str
+ );
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ T_CHAR TChar,
+ BOOLEAN StopAfterNewline
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+//
+// static
+// T_CHAR *
+// GetQuotedString (
+// SOURCE_FILE *SourceFile,
+// BOOLEAN Optional
+// );
+//
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ );
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ );
+
+static
+STATUS
+ParseFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+FILE *
+FindFile (
+ IN INT8 *FileName,
+ OUT INT8 *FoundFileName,
+ IN UINT32 FoundFileNameLen
+ );
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATUS
+SFPInit (
+ VOID
+ )
+{
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));
+ return STATUS_SUCCESS;
+}
+
+UINT32
+SFPGetLineNumber (
+ VOID
+ )
+{
+ return mGlobals.SourceFile.LineNum;
+}
+
+/*++
+
+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
+
+--*/
+T_CHAR *
+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 (
+ IN INT8 *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 (
+ T_CHAR *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.
+
+--*/
+{
+ UINT32 Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+BOOLEAN
+SFPGetNextToken (
+ T_CHAR *Str,
+ UINT32 Len
+ )
+{
+ UINT32 Index;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ 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 (
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+ T_CHAR *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 (
+ UINT32 *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
+
+--*/
+{
+ //
+ // UINT32 Len;
+ //
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (isdigit (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 (mGlobals.SourceFile.FileBufferPtr[2])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += 2;
+ sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);
+ while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ } else {
+ *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
+ while (isdigit (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 UINT32 NestDepth = 0;
+ INT8 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.Verbose) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", 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 (FoundFileName, "r")) == NULL) {
+ //
+ // Try to find it among the paths if it has a parent (that is, it is included
+ // by someone else).
+ //
+ Error (NULL, 0, 0, SourceFile->FileName, "file not found");
+ 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
+ )
+{
+ //
+ // Get the file size, and then read the entire thing into memory.
+ // Allocate space for a terminator character.
+ //
+ fseek (SourceFile->Fptr, 0, SEEK_END);
+ SourceFile->FileSize = ftell (SourceFile->Fptr);
+ fseek (SourceFile->Fptr, 0, SEEK_SET);
+ SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));
+ if (SourceFile->FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
+ SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = 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 from the file to the screen.
+
+Arguments:
+ SourceFile - structure that we use to keep track of an input file.
+
+Returns:
+ Nothing.
+
+--*/
+{
+ BOOLEAN InComment;
+
+ RewindFile (SourceFile);
+ InComment = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ //
+ // If a line-feed, then no longer in a comment
+ //
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ InComment = 0;
+ } 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++;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
+ SourceFile->FileBufferPtr += 2;
+ 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);
+}
+
+#if 0
+static
+T_CHAR *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ )
+{
+ T_CHAR *String;
+ T_CHAR *Start;
+ T_CHAR *Ptr;
+ UINT32 Len;
+ BOOLEAN PreviousBackslash;
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ if (!Optional) {
+ 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)) {
+ 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 = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", 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 (T_CHAR)) {
+ SourceFile->EndOfFile = TRUE;
+ return TRUE;
+ }
+
+ if (SourceFile->EndOfFile) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#if 0
+static
+void
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ )
+{
+ INT8 IncludeFileName[MAX_PATH];
+ INT8 *To;
+ UINT32 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 = UNICODE_TO_ASCII(SourceFile->FileBufferPtr[0]);
+ //
+ *To = (T_CHAR) SourceFile->FileBufferPtr[0];
+ To++;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if (!ReportedError) {
+ *To = 0;
+ memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (IncludedSourceFile.FileName, IncludeFileName);
+ //
+ // IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;
+ //
+ ProcessIncludeFile (&IncludedSourceFile, SourceFile);
+ //
+ // printf ("including file '%s'\n", IncludeFileName);
+ //
+ }
+
+ 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;
+ }
+}
+
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ UINT32 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++;
+ if (mGlobals.Verbose) {
+ printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
+ }
+ 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
+UINT32
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+
+ Len = 0;
+ while (*Str == *Buffer) {
+ Buffer++;
+ Str++;
+ Len++;
+ }
+
+ if (*Str) {
+ return 0;
+ }
+
+ return Len;
+}
+
+static
+UINT32
+t_strlen (
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+ Len = 0;
+ while (*Str) {
+ Len++;
+ Str++;
+ }
+
+ return Len;
+}
+
+static
+UINT32
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ UINT32 Len
+ )
+{
+ while (Len > 0) {
+ if (*Str1 != *Str2) {
+ return Len;
+ }
+
+ Len--;
+ Str1++;
+ Str2++;
+ }
+
+ return 0;
+}
+
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ )
+{
+ T_CHAR *SaveDest;
+ SaveDest = Dest;
+ while (*Src) {
+ *Dest = *Src;
+ Dest++;
+ Src++;
+ }
+
+ *Dest = 0;
+ return SaveDest;
+}
+
+#if 0
+static
+BOOLEAN
+IsValidIdentifierChar (
+ INT8 Char,
+ BOOLEAN FirstChar
+ )
+{
+ //
+ // If it's the first character of an identifier, then
+ // it must be one of [A-Za-z_].
+ //
+ if (FirstChar) {
+ if (isalpha (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ } else {
+ //
+ // If it's not the first character, then it can
+ // be one of [A-Za-z_0-9]
+ //
+ if (isalnum (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ SourceFile->LineNum = 1;
+ SourceFile->FileBufferPtr = SourceFile->FileBuffer;
+ SourceFile->EndOfFile = 0;
+}
+
+#if 0
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ T_CHAR TChar,
+ BOOLEAN StopAfterNewline
+ )
+{
+ while (!EndOfFile (SourceFile)) {
+ //
+ // Check for the character of interest
+ //
+ if (SourceFile->FileBufferPtr[0] == TChar) {
+ return TRUE;
+ } else {
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->LineNum++;
+ if (StopAfterNewline) {
+ SourceFile->FileBufferPtr++;
+ if (SourceFile->FileBufferPtr[0] == 0) {
+ SourceFile->FileBufferPtr++;
+ }
+
+ return FALSE;
+ }
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+ }
+
+ return FALSE;
+}
+#endif