From feccee87a78e68d575dbdf44b34ca0cb5a21ea8d Mon Sep 17 00:00:00 2001 From: lhauch Date: Thu, 5 Oct 2006 23:12:07 +0000 Subject: Restructuring for better separation of Tool packages. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1674 6f19259b-4bc3-4df7-8a09-765794883524 --- .../TianoTools/GenFfsFile/SimpleFileParsing.c | 969 +++++++++++++++++++++ 1 file changed, 969 insertions(+) create mode 100644 Tools/CodeTools/TianoTools/GenFfsFile/SimpleFileParsing.c (limited to 'Tools/CodeTools/TianoTools/GenFfsFile/SimpleFileParsing.c') diff --git a/Tools/CodeTools/TianoTools/GenFfsFile/SimpleFileParsing.c b/Tools/CodeTools/TianoTools/GenFfsFile/SimpleFileParsing.c new file mode 100644 index 0000000000..5fa5a22096 --- /dev/null +++ b/Tools/CodeTools/TianoTools/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 +#include +#include +#include + +#include + +#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 -- cgit v1.2.3