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 */
|
/* common */
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
|
#include "debugflag.h"
|
||||||
#include "filestat.h"
|
#include "filestat.h"
|
||||||
#include "fname.h"
|
#include "fname.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
@@ -77,17 +78,6 @@ char NextC = '\0';
|
|||||||
/* Maximum count of nested includes */
|
/* Maximum count of nested includes */
|
||||||
#define MAX_INC_NESTING 16
|
#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 */
|
/* Struct that describes an active input file */
|
||||||
typedef struct AFile AFile;
|
typedef struct AFile AFile;
|
||||||
struct AFile {
|
struct AFile {
|
||||||
@@ -137,6 +127,8 @@ static IFile* NewIFile (const char* Name, InputType Type)
|
|||||||
IF->Size = 0;
|
IF->Size = 0;
|
||||||
IF->MTime = 0;
|
IF->MTime = 0;
|
||||||
IF->Type = Type;
|
IF->Type = Type;
|
||||||
|
IF->GFlags = IG_NONE;
|
||||||
|
SB_Init (&IF->GuardMacro);
|
||||||
memcpy (IF->Name, Name, Len+1);
|
memcpy (IF->Name, Name, Len+1);
|
||||||
|
|
||||||
/* Insert the new structure into the IFile collection */
|
/* Insert the new structure into the IFile collection */
|
||||||
@@ -280,7 +272,7 @@ void OpenMainFile (const char* Name)
|
|||||||
SetPPIfStack (&MainFile->IfStack);
|
SetPPIfStack (&MainFile->IfStack);
|
||||||
|
|
||||||
/* Begin PP for this file */
|
/* Begin PP for this file */
|
||||||
PreprocessBegin ();
|
PreprocessBegin (IF);
|
||||||
|
|
||||||
/* Allocate the input line buffer */
|
/* Allocate the input line buffer */
|
||||||
Line = NewStrBuf ();
|
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
|
/* 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 = FindFile (N);
|
||||||
if (IF == 0) {
|
if (IF == 0) {
|
||||||
IF = NewIFile (N, IT);
|
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 */
|
/* 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);
|
SetPPIfStack (&AF->IfStack);
|
||||||
|
|
||||||
/* Begin PP for this file */
|
/* Begin PP for this file */
|
||||||
PreprocessBegin ();
|
PreprocessBegin (IF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -356,27 +358,24 @@ void CloseIncludeFile (void)
|
|||||||
** NULL if this was the main file.
|
** 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 */
|
/* Determine the file that is active after closing this one. We never
|
||||||
unsigned AFileCount = CollCount (&AFiles);
|
** 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 */
|
/* End preprocessing for the current input file */
|
||||||
PRECONDITION (AFileCount > 0);
|
PreprocessEnd (NextInput->Input);
|
||||||
|
|
||||||
/* End preprocessor in this file */
|
|
||||||
PreprocessEnd ();
|
|
||||||
|
|
||||||
/* Get the current active input file */
|
|
||||||
Input = CollLast (&AFiles);
|
|
||||||
|
|
||||||
/* Close the current input file (we're just reading so no error check) */
|
/* Close the current input file (we're just reading so no error check) */
|
||||||
fclose (Input->F);
|
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 we had added an extra search path for this AFile, remove it */
|
||||||
if (Input->SearchPath) {
|
if (Input->SearchPath) {
|
||||||
PopSearchPath (UsrIncSearchPath);
|
PopSearchPath (UsrIncSearchPath);
|
||||||
@@ -385,10 +384,9 @@ void CloseIncludeFile (void)
|
|||||||
/* Delete the active file structure */
|
/* Delete the active file structure */
|
||||||
FreeAFile (Input);
|
FreeAFile (Input);
|
||||||
|
|
||||||
/* Use previous file with PP if it is not the main file */
|
/* If we've switched files, use the if stack from the previous file */
|
||||||
if (AFileCount > 0) {
|
if (Input != NextInput) {
|
||||||
Input = CollLast (&AFiles);
|
SetPPIfStack (&NextInput->IfStack);
|
||||||
SetPPIfStack (&Input->IfStack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,28 @@ typedef enum {
|
|||||||
IT_USRINC = 0x04, /* User include file (using "") */
|
IT_USRINC = 0x04, /* User include file (using "") */
|
||||||
} InputType;
|
} 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 */
|
/* The current input line */
|
||||||
extern StrBuf* Line;
|
extern StrBuf* Line;
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,10 @@
|
|||||||
#define IFCOND_SKIP 0x01U
|
#define IFCOND_SKIP 0x01U
|
||||||
#define IFCOND_ELSE 0x02U
|
#define IFCOND_ELSE 0x02U
|
||||||
#define IFCOND_NEEDTERM 0x04U
|
#define IFCOND_NEEDTERM 0x04U
|
||||||
|
#define IFCOND_ISGUARD 0x08U
|
||||||
|
|
||||||
|
/* Current input file */
|
||||||
|
static IFile* CurInput = 0;
|
||||||
|
|
||||||
/* Current PP if stack */
|
/* Current PP if stack */
|
||||||
static PPIfStack* PPStack;
|
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 */
|
/* Push a new if level onto the if stack */
|
||||||
{
|
{
|
||||||
/* Check for an overflow of 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 */
|
/* Push the #if condition */
|
||||||
++PPStack->Index;
|
++PPStack->Index;
|
||||||
if (Skip) {
|
if (Skip) {
|
||||||
PPStack->Stack[PPStack->Index] = IFCOND_SKIP | IFCOND_NEEDTERM;
|
PPStack->Stack[PPStack->Index] = IFCOND_SKIP | IFCOND_NEEDTERM | Flags;
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
PPStack->Stack[PPStack->Index] = IFCOND_NONE | IFCOND_NEEDTERM;
|
PPStack->Stack[PPStack->Index] = IFCOND_NONE | IFCOND_NEEDTERM | Flags;
|
||||||
return (Invert ^ Cond);
|
return (Invert ^ Cond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2794,29 +2798,40 @@ static int DoIf (int Skip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set the #if condition according to the expression result */
|
/* 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)
|
static int DoIfDef (int Skip, int Flag)
|
||||||
/* Process #ifdef if flag == 1, or #ifndef if flag == 0. */
|
/* 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;
|
ident Ident;
|
||||||
|
|
||||||
SkipWhitespace (0);
|
SkipWhitespace (0);
|
||||||
if (MacName (Ident)) {
|
if (MacName (Ident)) {
|
||||||
CheckForBadIdent (Ident, IS_Get (&Standard), 0);
|
CheckForBadIdent (Ident, IS_Get (&Standard), 0);
|
||||||
Value = IsMacro (Ident);
|
IsDef = IsMacro (Ident);
|
||||||
/* Check for extra tokens */
|
/* 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;
|
int PPSkip = 0;
|
||||||
ident Directive;
|
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);
|
int Whitespace = SkipWhitespace (0);
|
||||||
|
|
||||||
/* Check for stuff to skip */
|
/* Check for stuff to skip */
|
||||||
while (CurC == '\0' || CurC == '#' || PPSkip) {
|
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 */
|
/* Check for preprocessor lines lines */
|
||||||
if (CurC == '#') {
|
if (CurC == '#') {
|
||||||
|
unsigned IfCond;
|
||||||
|
/* Skip the hash and following white space */
|
||||||
NextChar ();
|
NextChar ();
|
||||||
SkipWhitespace (0);
|
SkipWhitespace (0);
|
||||||
|
|
||||||
if (CurC == '\0') {
|
if (CurC == '\0') {
|
||||||
/* Ignore the empty preprocessor directive */
|
/* Ignore the empty preprocessor directive */
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!IsSym (Directive)) {
|
if (!IsSym (Directive)) {
|
||||||
@@ -3089,20 +3117,25 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
PPError ("Preprocessor directive expected");
|
PPError ("Preprocessor directive expected");
|
||||||
}
|
}
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
} else {
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
switch (FindPPDirectiveType (Directive)) {
|
switch (FindPPDirectiveType (Directive)) {
|
||||||
|
|
||||||
case PPD_DEFINE:
|
case PPD_DEFINE:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
DoDefine ();
|
DoDefine ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_ELIF:
|
case PPD_ELIF:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (PPStack->Index >= 0) {
|
if (PPStack->Index >= 0) {
|
||||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) {
|
unsigned char PPCond = PPStack->Stack[PPStack->Index];
|
||||||
|
if ((PPCond & IFCOND_ELSE) == 0) {
|
||||||
/* Handle as #else/#if combination */
|
/* Handle as #else/#if combination */
|
||||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_SKIP) == 0) {
|
if ((PPCond & IFCOND_SKIP) == 0) {
|
||||||
PPSkip = !PPSkip;
|
PPSkip = !PPSkip;
|
||||||
}
|
}
|
||||||
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
||||||
@@ -3110,6 +3143,11 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
|
|
||||||
/* #elif doesn't need a terminator */
|
/* #elif doesn't need a terminator */
|
||||||
PPStack->Stack[PPStack->Index] &= ~IFCOND_NEEDTERM;
|
PPStack->Stack[PPStack->Index] &= ~IFCOND_NEEDTERM;
|
||||||
|
|
||||||
|
/* An include guard cannot have a #elif */
|
||||||
|
if (PPCond & IFCOND_ISGUARD) {
|
||||||
|
CurInput->GFlags &= ~IG_ISGUARDED;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PPError ("Duplicate #else/#elif");
|
PPError ("Duplicate #else/#elif");
|
||||||
}
|
}
|
||||||
@@ -3119,13 +3157,20 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_ELSE:
|
case PPD_ELSE:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (PPStack->Index >= 0) {
|
if (PPStack->Index >= 0) {
|
||||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) {
|
unsigned char PPCond = PPStack->Stack[PPStack->Index];
|
||||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_SKIP) == 0) {
|
if ((PPCond & IFCOND_ELSE) == 0) {
|
||||||
|
if ((PPCond & IFCOND_SKIP) == 0) {
|
||||||
PPSkip = !PPSkip;
|
PPSkip = !PPSkip;
|
||||||
}
|
}
|
||||||
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
PPStack->Stack[PPStack->Index] |= IFCOND_ELSE;
|
||||||
|
|
||||||
|
/* An include guard cannot have a #else */
|
||||||
|
if (PPCond & IFCOND_ISGUARD) {
|
||||||
|
CurInput->GFlags &= ~IG_ISGUARDED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for extra tokens */
|
/* Check for extra tokens */
|
||||||
CheckExtraTokens ("else");
|
CheckExtraTokens ("else");
|
||||||
} else {
|
} else {
|
||||||
@@ -3137,6 +3182,7 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_ENDIF:
|
case PPD_ENDIF:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (PPStack->Index >= 0) {
|
if (PPStack->Index >= 0) {
|
||||||
/* Remove any clauses on top of stack that do not
|
/* Remove any clauses on top of stack that do not
|
||||||
** need a terminating #endif.
|
** need a terminating #endif.
|
||||||
@@ -3150,7 +3196,11 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
CHECK (PPStack->Index >= 0);
|
CHECK (PPStack->Index >= 0);
|
||||||
|
|
||||||
/* Remove the clause that needs a terminator */
|
/* Remove the clause that needs a terminator */
|
||||||
PPSkip = (PPStack->Stack[PPStack->Index--] & IFCOND_SKIP) != 0;
|
IfCond = PPStack->Stack[PPStack->Index--];
|
||||||
|
PPSkip = (IfCond & IFCOND_SKIP) != 0;
|
||||||
|
if (IfCond & IFCOND_ISGUARD) {
|
||||||
|
CurInput->GFlags |= IG_GUARDCLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for extra tokens */
|
/* Check for extra tokens */
|
||||||
CheckExtraTokens ("endif");
|
CheckExtraTokens ("endif");
|
||||||
@@ -3160,36 +3210,43 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_ERROR:
|
case PPD_ERROR:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
DoError ();
|
DoError ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_IF:
|
case PPD_IF:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
PPSkip = DoIf (PPSkip);
|
PPSkip = DoIf (PPSkip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_IFDEF:
|
case PPD_IFDEF:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
PPSkip = DoIfDef (PPSkip, 1);
|
PPSkip = DoIfDef (PPSkip, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_IFNDEF:
|
case PPD_IFNDEF:
|
||||||
PPSkip = DoIfDef (PPSkip, 0);
|
PPSkip = DoIfDef (PPSkip, 0);
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_INCLUDE:
|
case PPD_INCLUDE:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
DoInclude ();
|
DoInclude ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_LINE:
|
case PPD_LINE:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
DoLine ();
|
DoLine ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_PRAGMA:
|
case PPD_PRAGMA:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
if ((ModeFlags & MSM_IN_ARG_LIST) == 0) {
|
if ((ModeFlags & MSM_IN_ARG_LIST) == 0) {
|
||||||
DoPragma ();
|
DoPragma ();
|
||||||
@@ -3201,12 +3258,14 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_UNDEF:
|
case PPD_UNDEF:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
DoUndef ();
|
DoUndef ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPD_WARNING:
|
case PPD_WARNING:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
/* #warning is a non standard extension */
|
/* #warning is a non standard extension */
|
||||||
if (IS_Get (&Standard) > STD_C99) {
|
if (IS_Get (&Standard) > STD_C99) {
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
@@ -3221,14 +3280,13 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
if (!PPSkip) {
|
if (!PPSkip) {
|
||||||
PPError ("Preprocessor directive expected");
|
PPError ("Preprocessor directive expected");
|
||||||
}
|
}
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
if (NextLine () == 0) {
|
if (NextLine () == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3236,6 +3294,15 @@ static int ParseDirectives (unsigned ModeFlags)
|
|||||||
Whitespace = SkipWhitespace (0) || Whitespace;
|
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;
|
return Whitespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3346,6 +3413,7 @@ void Preprocess (void)
|
|||||||
OLine = PLine;
|
OLine = PLine;
|
||||||
ParseDirectives (MSM_MULTILINE);
|
ParseDirectives (MSM_MULTILINE);
|
||||||
OLine = 0;
|
OLine = 0;
|
||||||
|
CurInput->GFlags &= ~IG_NEWFILE;
|
||||||
|
|
||||||
/* Add the source info to preprocessor output if needed */
|
/* Add the source info to preprocessor output if needed */
|
||||||
AddPreLine (PLine);
|
AddPreLine (PLine);
|
||||||
@@ -3414,9 +3482,13 @@ void ContinueLine (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PreprocessBegin (void)
|
void PreprocessBegin (IFile* Input)
|
||||||
/* Initialize preprocessor with current file */
|
/* 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 */
|
/* Reset #if depth */
|
||||||
PPStack->Index = -1;
|
PPStack->Index = -1;
|
||||||
|
|
||||||
@@ -3429,9 +3501,14 @@ void PreprocessBegin (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PreprocessEnd (void)
|
void PreprocessEnd (IFile* Input)
|
||||||
/* Preprocessor done with current file */
|
/* 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 */
|
/* Check for missing #endif */
|
||||||
while (PPStack->Index >= 0) {
|
while (PPStack->Index >= 0) {
|
||||||
if ((PPStack->Stack[PPStack->Index] & IFCOND_NEEDTERM) != 0) {
|
if ((PPStack->Stack[PPStack->Index] & IFCOND_NEEDTERM) != 0) {
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ struct PPIfStack {
|
|||||||
int Index;
|
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);
|
void Preprocess (void);
|
||||||
/* Preprocess a line */
|
/* 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);
|
void InitPreprocess (void);
|
||||||
/* Init preprocessor */
|
/* Init preprocessor */
|
||||||
|
|
||||||
void DonePreprocess (void);
|
void DonePreprocess (void);
|
||||||
/* Done with preprocessor */
|
/* Done with preprocessor */
|
||||||
|
|
||||||
void HandleSpecialMacro (Macro* M, const char* Name);
|
void SetPPIfStack (PPIfStack* Stack);
|
||||||
/* Handle special "magic" macros that may change */
|
/* 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