More moves for Tool Packages
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1676 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
969
Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c
Normal file
969
Tools/CCode/Source/GenFfsFile/SimpleFileParsing.c
Normal file
@ -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
|
Reference in New Issue
Block a user