Merge pull request #2743 from kugelfuhr/kugelfuhr/include-guard
Do not read a file twice if it has an include guard
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "coll.h"
|
||||
#include "debugflag.h"
|
||||
#include "filestat.h"
|
||||
#include "fname.h"
|
||||
#include "print.h"
|
||||
@@ -77,17 +78,6 @@ char NextC = '\0';
|
||||
/* Maximum count of nested includes */
|
||||
#define MAX_INC_NESTING 16
|
||||
|
||||
/* Struct that describes an input file */
|
||||
typedef struct IFile IFile;
|
||||
struct IFile {
|
||||
unsigned Index; /* File index */
|
||||
unsigned Usage; /* Usage counter */
|
||||
unsigned long Size; /* File size */
|
||||
unsigned long MTime; /* Time of last modification */
|
||||
InputType Type; /* Type of input file */
|
||||
char Name[1]; /* Name of file (dynamically allocated) */
|
||||
};
|
||||
|
||||
/* Struct that describes an active input file */
|
||||
typedef struct AFile AFile;
|
||||
struct AFile {
|
||||
@@ -132,11 +122,13 @@ static IFile* NewIFile (const char* Name, InputType Type)
|
||||
IFile* IF = (IFile*) xmalloc (sizeof (IFile) + Len);
|
||||
|
||||
/* Initialize the fields */
|
||||
IF->Index = CollCount (&IFiles) + 1;
|
||||
IF->Usage = 0;
|
||||
IF->Size = 0;
|
||||
IF->MTime = 0;
|
||||
IF->Type = Type;
|
||||
IF->Index = CollCount (&IFiles) + 1;
|
||||
IF->Usage = 0;
|
||||
IF->Size = 0;
|
||||
IF->MTime = 0;
|
||||
IF->Type = Type;
|
||||
IF->GFlags = IG_NONE;
|
||||
SB_Init (&IF->GuardMacro);
|
||||
memcpy (IF->Name, Name, Len+1);
|
||||
|
||||
/* Insert the new structure into the IFile collection */
|
||||
@@ -280,7 +272,7 @@ void OpenMainFile (const char* Name)
|
||||
SetPPIfStack (&MainFile->IfStack);
|
||||
|
||||
/* Begin PP for this file */
|
||||
PreprocessBegin ();
|
||||
PreprocessBegin (IF);
|
||||
|
||||
/* Allocate the input line buffer */
|
||||
Line = NewStrBuf ();
|
||||
@@ -318,11 +310,21 @@ void OpenIncludeFile (const char* Name, InputType IT)
|
||||
}
|
||||
|
||||
/* Search the list of all input files for this file. If we don't find
|
||||
** it, create a new IFile object.
|
||||
** it, create a new IFile object. If we do already know the file and it
|
||||
** has an include guard, check for the include guard before opening the
|
||||
** file.
|
||||
*/
|
||||
IF = FindFile (N);
|
||||
if (IF == 0) {
|
||||
IF = NewIFile (N, IT);
|
||||
} else if ((IF->GFlags & IG_ISGUARDED) != 0 &&
|
||||
IsMacro (SB_GetConstBuf (&IF->GuardMacro))) {
|
||||
if (Debug) {
|
||||
printf ("Include guard %s found for \"%s\" - won't include it again\n",
|
||||
SB_GetConstBuf (&IF->GuardMacro),
|
||||
Name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* We don't need N any longer, since we may now use IF->Name */
|
||||
@@ -346,7 +348,7 @@ void OpenIncludeFile (const char* Name, InputType IT)
|
||||
SetPPIfStack (&AF->IfStack);
|
||||
|
||||
/* Begin PP for this file */
|
||||
PreprocessBegin ();
|
||||
PreprocessBegin (IF);
|
||||
}
|
||||
|
||||
|
||||
@@ -356,27 +358,24 @@ void CloseIncludeFile (void)
|
||||
** NULL if this was the main file.
|
||||
*/
|
||||
{
|
||||
AFile* Input;
|
||||
/* Get the currently active input file and remove it from set of active
|
||||
** files. CollPop will FAIL if the collection is empty so no need to
|
||||
** check this here.
|
||||
*/
|
||||
AFile* Input = CollPop (&AFiles);
|
||||
|
||||
/* Get the number of active input files */
|
||||
unsigned AFileCount = CollCount (&AFiles);
|
||||
/* Determine the file that is active after closing this one. We never
|
||||
** actually close the main file, since it is needed for errors found after
|
||||
** compilation is completed.
|
||||
*/
|
||||
AFile* NextInput = (CollCount (&AFiles) > 0)? CollLast (&AFiles) : Input;
|
||||
|
||||
/* Must have an input file when called */
|
||||
PRECONDITION (AFileCount > 0);
|
||||
|
||||
/* End preprocessor in this file */
|
||||
PreprocessEnd ();
|
||||
|
||||
/* Get the current active input file */
|
||||
Input = CollLast (&AFiles);
|
||||
/* End preprocessing for the current input file */
|
||||
PreprocessEnd (NextInput->Input);
|
||||
|
||||
/* Close the current input file (we're just reading so no error check) */
|
||||
fclose (Input->F);
|
||||
|
||||
/* Delete the last active file from the active file collection */
|
||||
--AFileCount;
|
||||
CollDelete (&AFiles, AFileCount);
|
||||
|
||||
/* If we had added an extra search path for this AFile, remove it */
|
||||
if (Input->SearchPath) {
|
||||
PopSearchPath (UsrIncSearchPath);
|
||||
@@ -385,10 +384,9 @@ void CloseIncludeFile (void)
|
||||
/* Delete the active file structure */
|
||||
FreeAFile (Input);
|
||||
|
||||
/* Use previous file with PP if it is not the main file */
|
||||
if (AFileCount > 0) {
|
||||
Input = CollLast (&AFiles);
|
||||
SetPPIfStack (&Input->IfStack);
|
||||
/* If we've switched files, use the if stack from the previous file */
|
||||
if (Input != NextInput) {
|
||||
SetPPIfStack (&NextInput->IfStack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,28 @@ typedef enum {
|
||||
IT_USRINC = 0x04, /* User include file (using "") */
|
||||
} InputType;
|
||||
|
||||
/* A bitmapped set of flags for include guard processing in the preprocessor */
|
||||
typedef enum {
|
||||
IG_NONE = 0x00,
|
||||
IG_NEWFILE = 0x01, /* File processing started */
|
||||
IG_ISGUARDED = 0x02, /* File contains an include guard */
|
||||
IG_GUARDCLOSED = 0x04, /* Include guard was closed */
|
||||
IG_COMPLETE = IG_ISGUARDED | IG_GUARDCLOSED,
|
||||
} GuardFlags;
|
||||
|
||||
/* Struct that describes an input file */
|
||||
typedef struct IFile IFile;
|
||||
struct IFile {
|
||||
unsigned Index; /* File index */
|
||||
unsigned Usage; /* Usage counter */
|
||||
unsigned long Size; /* File size */
|
||||
unsigned long MTime; /* Time of last modification */
|
||||
InputType Type; /* Type of input file */
|
||||
GuardFlags GFlags; /* Flags for include guard processing */
|
||||
StrBuf GuardMacro; /* Include guard macro name */
|
||||
char Name[1]; /* Name of file (dynamically allocated) */
|
||||
};
|
||||
|
||||
/* The current input line */
|
||||
extern StrBuf* Line;
|
||||
|
||||
|
||||
@@ -93,6 +93,10 @@
|
||||
#define IFCOND_SKIP 0x01U
|
||||
#define IFCOND_ELSE 0x02U
|
||||
#define IFCOND_NEEDTERM 0x04U
|
||||
#define IFCOND_ISGUARD 0x08U
|
||||
|
||||
/* Current input file */
|
||||
static IFile* CurInput = 0;
|
||||
|
||||
/* Current PP if stack */
|
||||
static PPIfStack* PPStack;
|
||||
@@ -2701,7 +2705,7 @@ Error_Handler:
|
||||
|
||||
|
||||
|
||||
static int PushIf (int Skip, int Invert, int Cond)
|
||||
static int PushIf (int Skip, int Invert, int Cond, unsigned Flags)
|
||||
/* Push a new if level onto the if stack */
|
||||
{
|
||||
/* Check for an overflow of the if stack */
|
||||
@@ -2713,10 +2717,10 @@ static int PushIf (int Skip, int Invert, int Cond)
|
||||
/* Push the #if condition */
|
||||
++PPStack->Index;
|
||||
if (Skip) {
|
||||
PPStack->Stack[PPStack->Index] = IFCOND_SKIP | IFCOND_NEEDTERM;
|
||||
PPStack->Stack[PPStack->Index] = IFCOND_SKIP | IFCOND_NEEDTERM | Flags;
|
||||
return 1;
|
||||
} else {
|
||||
PPStack->Stack[PPStack->Index] = IFCOND_NONE | IFCOND_NEEDTERM;
|
||||
PPStack->Stack[PPStack->Index] = IFCOND_NONE | IFCOND_NEEDTERM | Flags;
|
||||
return (Invert ^ Cond);
|
||||
}
|
||||
}
|
||||
@@ -2794,29 +2798,40 @@ static int DoIf (int Skip)
|
||||
}
|
||||
|
||||
/* Set the #if condition according to the expression result */
|
||||
return PushIf (Skip, 1, Expr.IVal != 0);
|
||||
return PushIf (Skip, 1, Expr.IVal != 0, IFCOND_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int DoIfDef (int skip, int flag)
|
||||
/* Process #ifdef if flag == 1, or #ifndef if flag == 0. */
|
||||
static int DoIfDef (int Skip, int Flag)
|
||||
/* Process #ifdef if Flag == 1, or #ifndef if Flag == 0. */
|
||||
{
|
||||
int Value = 0;
|
||||
int IsDef = 0;
|
||||
unsigned GuardFlag = IFCOND_NONE;
|
||||
|
||||
if (!skip) {
|
||||
if (!Skip) {
|
||||
ident Ident;
|
||||
|
||||
SkipWhitespace (0);
|
||||
if (MacName (Ident)) {
|
||||
CheckForBadIdent (Ident, IS_Get (&Standard), 0);
|
||||
Value = IsMacro (Ident);
|
||||
IsDef = IsMacro (Ident);
|
||||
/* Check for extra tokens */
|
||||
CheckExtraTokens (flag ? "ifdef" : "ifndef");
|
||||
CheckExtraTokens (Flag ? "ifdef" : "ifndef");
|
||||
/* Check if this is an include guard. This is the case if we have
|
||||
** a #ifndef directive at the start of a new file and the macro
|
||||
** is not defined. If so, remember it.
|
||||
*/
|
||||
if (Flag == 0 && (CurInput->GFlags & IG_NEWFILE) != 0 && !IsDef) {
|
||||
CurInput->GFlags |= IG_ISGUARDED;
|
||||
SB_CopyStr (&CurInput->GuardMacro, Ident);
|
||||
SB_Terminate (&CurInput->GuardMacro);
|
||||
GuardFlag = IFCOND_ISGUARD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PushIf (skip, flag, Value);
|
||||
return PushIf (Skip, Flag, IsDef, GuardFlag);
|
||||
}
|
||||
|
||||
|
||||
@@ -3070,18 +3085,31 @@ static int ParseDirectives (unsigned ModeFlags)
|
||||
int PPSkip = 0;
|
||||
ident Directive;
|
||||
|
||||
/* Skip white space at the beginning of the first line */
|
||||
/* Skip white space at the beginning of the line */
|
||||
int Whitespace = SkipWhitespace (0);
|
||||
|
||||
/* Check for stuff to skip */
|
||||
while (CurC == '\0' || CurC == '#' || PPSkip) {
|
||||
|
||||
/* If a #ifndef that was assumed to be an include guard was closed
|
||||
** recently, we may not have anything else following in the file
|
||||
** besides whitespace otherwise the assumption was false and we don't
|
||||
** actually have an include guard.
|
||||
*/
|
||||
if (CurC != '\0' && (CurInput->GFlags & IG_COMPLETE) == IG_COMPLETE) {
|
||||
CurInput->GFlags &= ~IG_ISGUARDED;
|
||||
}
|
||||
|
||||
/* Check for preprocessor lines lines */
|
||||
if (CurC == '#') {
|
||||
unsigned IfCond;
|
||||
/* Skip the hash and following white space */
|
||||
NextChar ();
|
||||
SkipWhitespace (0);
|
||||
|
||||
if (CurC == '\0') {
|
||||
/* Ignore the empty preprocessor directive */
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
continue;
|
||||
}
|
||||
if (!IsSym (Directive)) {
|
||||
@@ -3089,145 +3117,175 @@ static int ParseDirectives (unsigned ModeFlags)
|
||||
PPError ("Preprocessor directive expected");
|
||||
}
|
||||
ClearLine ();
|
||||
} else {
|
||||
switch (FindPPDirectiveType (Directive)) {
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
continue;
|
||||
}
|
||||
switch (FindPPDirectiveType (Directive)) {
|
||||
|
||||
case PPD_DEFINE:
|
||||
if (!PPSkip) {
|
||||
DoDefine ();
|
||||
}
|
||||
break;
|
||||
case PPD_DEFINE:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
DoDefine ();
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_ELIF:
|
||||
if (PPStack->Index >= 0) {
|
||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) {
|
||||
/* Handle as #else/#if combination */
|
||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_SKIP) == 0) {
|
||||
PPSkip = !PPSkip;
|
||||
}
|
||||
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
||||
PPSkip = DoIf (PPSkip);
|
||||
case PPD_ELIF:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (PPStack->Index >= 0) {
|
||||
unsigned char PPCond = PPStack->Stack[PPStack->Index];
|
||||
if ((PPCond & IFCOND_ELSE) == 0) {
|
||||
/* Handle as #else/#if combination */
|
||||
if ((PPCond & IFCOND_SKIP) == 0) {
|
||||
PPSkip = !PPSkip;
|
||||
}
|
||||
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
||||
PPSkip = DoIf (PPSkip);
|
||||
|
||||
/* #elif doesn't need a terminator */
|
||||
PPStack->Stack[PPStack->Index] &= ~IFCOND_NEEDTERM;
|
||||
} else {
|
||||
PPError ("Duplicate #else/#elif");
|
||||
/* #elif doesn't need a terminator */
|
||||
PPStack->Stack[PPStack->Index] &= ~IFCOND_NEEDTERM;
|
||||
|
||||
/* An include guard cannot have a #elif */
|
||||
if (PPCond & IFCOND_ISGUARD) {
|
||||
CurInput->GFlags &= ~IG_ISGUARDED;
|
||||
}
|
||||
} else {
|
||||
PPError ("Unexpected #elif");
|
||||
PPError ("Duplicate #else/#elif");
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
PPError ("Unexpected #elif");
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_ELSE:
|
||||
if (PPStack->Index >= 0) {
|
||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) {
|
||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_SKIP) == 0) {
|
||||
PPSkip = !PPSkip;
|
||||
}
|
||||
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
||||
|
||||
/* Check for extra tokens */
|
||||
CheckExtraTokens ("else");
|
||||
} else {
|
||||
PPError ("Duplicate #else");
|
||||
case PPD_ELSE:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (PPStack->Index >= 0) {
|
||||
unsigned char PPCond = PPStack->Stack[PPStack->Index];
|
||||
if ((PPCond & IFCOND_ELSE) == 0) {
|
||||
if ((PPCond & IFCOND_SKIP) == 0) {
|
||||
PPSkip = !PPSkip;
|
||||
}
|
||||
} else {
|
||||
PPError ("Unexpected '#else'");
|
||||
}
|
||||
break;
|
||||
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
||||
|
||||
case PPD_ENDIF:
|
||||
if (PPStack->Index >= 0) {
|
||||
/* Remove any clauses on top of stack that do not
|
||||
** need a terminating #endif.
|
||||
*/
|
||||
while (PPStack->Index >= 0 &&
|
||||
(PPStack->Stack[PPStack->Index] & IFCOND_NEEDTERM) == 0) {
|
||||
--PPStack->Index;
|
||||
/* An include guard cannot have a #else */
|
||||
if (PPCond & IFCOND_ISGUARD) {
|
||||
CurInput->GFlags &= ~IG_ISGUARDED;
|
||||
}
|
||||
|
||||
/* Stack may not be empty here or something is wrong */
|
||||
CHECK (PPStack->Index >= 0);
|
||||
|
||||
/* Remove the clause that needs a terminator */
|
||||
PPSkip = (PPStack->Stack[PPStack->Index--] & IFCOND_SKIP) != 0;
|
||||
|
||||
/* Check for extra tokens */
|
||||
CheckExtraTokens ("endif");
|
||||
CheckExtraTokens ("else");
|
||||
} else {
|
||||
PPError ("Unexpected '#endif'");
|
||||
PPError ("Duplicate #else");
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
PPError ("Unexpected '#else'");
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_ERROR:
|
||||
if (!PPSkip) {
|
||||
DoError ();
|
||||
case PPD_ENDIF:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (PPStack->Index >= 0) {
|
||||
/* Remove any clauses on top of stack that do not
|
||||
** need a terminating #endif.
|
||||
*/
|
||||
while (PPStack->Index >= 0 &&
|
||||
(PPStack->Stack[PPStack->Index] & IFCOND_NEEDTERM) == 0) {
|
||||
--PPStack->Index;
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_IF:
|
||||
PPSkip = DoIf (PPSkip);
|
||||
break;
|
||||
/* Stack may not be empty here or something is wrong */
|
||||
CHECK (PPStack->Index >= 0);
|
||||
|
||||
case PPD_IFDEF:
|
||||
PPSkip = DoIfDef (PPSkip, 1);
|
||||
break;
|
||||
|
||||
case PPD_IFNDEF:
|
||||
PPSkip = DoIfDef (PPSkip, 0);
|
||||
break;
|
||||
|
||||
case PPD_INCLUDE:
|
||||
if (!PPSkip) {
|
||||
DoInclude ();
|
||||
/* Remove the clause that needs a terminator */
|
||||
IfCond = PPStack->Stack[PPStack->Index--];
|
||||
PPSkip = (IfCond & IFCOND_SKIP) != 0;
|
||||
if (IfCond & IFCOND_ISGUARD) {
|
||||
CurInput->GFlags |= IG_GUARDCLOSED;
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_LINE:
|
||||
if (!PPSkip) {
|
||||
DoLine ();
|
||||
}
|
||||
break;
|
||||
/* Check for extra tokens */
|
||||
CheckExtraTokens ("endif");
|
||||
} else {
|
||||
PPError ("Unexpected '#endif'");
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_PRAGMA:
|
||||
if (!PPSkip) {
|
||||
if ((ModeFlags & MSM_IN_ARG_LIST) == 0) {
|
||||
DoPragma ();
|
||||
return Whitespace;
|
||||
} else {
|
||||
PPError ("Embedded #pragma directive within macro arguments is unsupported");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PPD_ERROR:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
DoError ();
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_UNDEF:
|
||||
if (!PPSkip) {
|
||||
DoUndef ();
|
||||
}
|
||||
break;
|
||||
case PPD_IF:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
PPSkip = DoIf (PPSkip);
|
||||
break;
|
||||
|
||||
case PPD_WARNING:
|
||||
/* #warning is a non standard extension */
|
||||
if (IS_Get (&Standard) > STD_C99) {
|
||||
if (!PPSkip) {
|
||||
DoWarning ();
|
||||
}
|
||||
case PPD_IFDEF:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
PPSkip = DoIfDef (PPSkip, 1);
|
||||
break;
|
||||
|
||||
case PPD_IFNDEF:
|
||||
PPSkip = DoIfDef (PPSkip, 0);
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
break;
|
||||
|
||||
case PPD_INCLUDE:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
DoInclude ();
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_LINE:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
DoLine ();
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_PRAGMA:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
if ((ModeFlags & MSM_IN_ARG_LIST) == 0) {
|
||||
DoPragma ();
|
||||
return Whitespace;
|
||||
} else {
|
||||
if (!PPSkip) {
|
||||
PPError ("Preprocessor directive expected");
|
||||
}
|
||||
ClearLine ();
|
||||
PPError ("Embedded #pragma directive within macro arguments is unsupported");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case PPD_UNDEF:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
DoUndef ();
|
||||
}
|
||||
break;
|
||||
|
||||
case PPD_WARNING:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
/* #warning is a non standard extension */
|
||||
if (IS_Get (&Standard) > STD_C99) {
|
||||
if (!PPSkip) {
|
||||
DoWarning ();
|
||||
}
|
||||
} else {
|
||||
if (!PPSkip) {
|
||||
PPError ("Preprocessor directive expected");
|
||||
}
|
||||
ClearLine ();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
if (!PPSkip) {
|
||||
PPError ("Preprocessor directive expected");
|
||||
}
|
||||
ClearLine ();
|
||||
}
|
||||
}
|
||||
if (NextLine () == 0) {
|
||||
break;
|
||||
@@ -3236,6 +3294,15 @@ static int ParseDirectives (unsigned ModeFlags)
|
||||
Whitespace = SkipWhitespace (0) || Whitespace;
|
||||
}
|
||||
|
||||
/* If a #ifndef that was assumed to be an include guard was closed
|
||||
** recently, we may not have anything else following in the file
|
||||
** besides whitespace otherwise the assumption was false and we don't
|
||||
** actually have an include guard.
|
||||
*/
|
||||
if (CurC != '\0' && (CurInput->GFlags & IG_COMPLETE) == IG_COMPLETE) {
|
||||
CurInput->GFlags &= ~IG_ISGUARDED;
|
||||
}
|
||||
|
||||
return Whitespace;
|
||||
}
|
||||
|
||||
@@ -3346,6 +3413,7 @@ void Preprocess (void)
|
||||
OLine = PLine;
|
||||
ParseDirectives (MSM_MULTILINE);
|
||||
OLine = 0;
|
||||
CurInput->GFlags &= ~IG_NEWFILE;
|
||||
|
||||
/* Add the source info to preprocessor output if needed */
|
||||
AddPreLine (PLine);
|
||||
@@ -3414,9 +3482,13 @@ void ContinueLine (void)
|
||||
|
||||
|
||||
|
||||
void PreprocessBegin (void)
|
||||
/* Initialize preprocessor with current file */
|
||||
void PreprocessBegin (IFile* Input)
|
||||
/* Initialize the preprocessor for a new input file */
|
||||
{
|
||||
/* Remember the new input file and flag it as new */
|
||||
CurInput = Input;
|
||||
CurInput->GFlags |= IG_NEWFILE;
|
||||
|
||||
/* Reset #if depth */
|
||||
PPStack->Index = -1;
|
||||
|
||||
@@ -3429,9 +3501,14 @@ void PreprocessBegin (void)
|
||||
|
||||
|
||||
|
||||
void PreprocessEnd (void)
|
||||
/* Preprocessor done with current file */
|
||||
void PreprocessEnd (IFile* Input)
|
||||
/* Preprocessor done with current file. The parameter is the file we're
|
||||
** switching back to.
|
||||
*/
|
||||
{
|
||||
/* Switch back to the old input file */
|
||||
CurInput = Input;
|
||||
|
||||
/* Check for missing #endif */
|
||||
while (PPStack->Index >= 0) {
|
||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_NEEDTERM) != 0) {
|
||||
|
||||
@@ -54,6 +54,9 @@ struct PPIfStack {
|
||||
int Index;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
struct IFile;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -62,29 +65,31 @@ struct PPIfStack {
|
||||
|
||||
|
||||
|
||||
void HandleSpecialMacro (Macro* M, const char* Name);
|
||||
/* Handle special "magic" macros that may change */
|
||||
|
||||
void Preprocess (void);
|
||||
/* Preprocess a line */
|
||||
|
||||
void SetPPIfStack (PPIfStack* Stack);
|
||||
/* Specify which PP #if stack to use */
|
||||
|
||||
void ContinueLine (void);
|
||||
/* Continue the current line ended with a '\\' */
|
||||
|
||||
void PreprocessBegin (void);
|
||||
/* Initialize preprocessor with current file */
|
||||
|
||||
void PreprocessEnd (void);
|
||||
/* Preprocessor done with current file */
|
||||
|
||||
void InitPreprocess (void);
|
||||
/* Init preprocessor */
|
||||
|
||||
void DonePreprocess (void);
|
||||
/* Done with preprocessor */
|
||||
|
||||
void HandleSpecialMacro (Macro* M, const char* Name);
|
||||
/* Handle special "magic" macros that may change */
|
||||
void SetPPIfStack (PPIfStack* Stack);
|
||||
/* Specify which PP #if stack to use */
|
||||
|
||||
void ContinueLine (void);
|
||||
/* Continue the current line ended with a '\\' */
|
||||
|
||||
void PreprocessBegin (struct IFile* Input);
|
||||
/* Initialize the preprocessor for a new input file */
|
||||
|
||||
void PreprocessEnd (struct IFile* Input);
|
||||
/* Preprocessor done with current file. The parameter is the file we're
|
||||
** switching back to.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user