mirror of
https://github.com/cc65/cc65.git
synced 2025-01-10 03:30:05 +00:00
Merge pull request #1817 from acqn/PPFix
[cc65] More preprocessor fixes
This commit is contained in:
commit
03421694b2
@ -1202,17 +1202,34 @@ The compiler defines several macros at startup:
|
||||
|
||||
This macro is defined if the target is the Commodore Plus/4 (-t plus4).
|
||||
|
||||
<tag><tt>__STDC_HOSTED__</tt></tag>
|
||||
|
||||
This macro is expands to the integer constant 1.
|
||||
|
||||
<tag><tt>__SIM6502__</tt></tag>
|
||||
|
||||
This macro is defined if the target is sim65 in 6502 mode (-t sim6502).
|
||||
|
||||
<tag><tt>__SIM65C02__</tt></tag>
|
||||
|
||||
This macro is defined if the target is sim65 in 65C02 mode (-t sim65c02).
|
||||
|
||||
<tag><tt>__STDC_HOSTED__</tt></tag>
|
||||
|
||||
This macro expands to the integer constant 1.
|
||||
|
||||
<tag><tt>__STDC_NO_ATOMICS__</tt></tag>
|
||||
|
||||
This macro expands to the integer constant 1 if the language standard is cc65 (--standard cc65).
|
||||
|
||||
<tag><tt>__STDC_NO_COMPLEX__</tt></tag>
|
||||
|
||||
This macro expands to the integer constant 1 if the language standard is cc65 (--standard cc65).
|
||||
|
||||
<tag><tt>__STDC_NO_THREADS__</tt></tag>
|
||||
|
||||
This macro expands to the integer constant 1 if the language standard is cc65 (--standard cc65).
|
||||
|
||||
<tag><tt>__STDC_NO_VLA__</tt></tag>
|
||||
|
||||
This macro expands to the integer constant 1 if the language standard is cc65 (--standard cc65).
|
||||
|
||||
<tag><tt>__SUPERVISION__</tt></tag>
|
||||
|
||||
This macro is defined if the target is the Supervision (-t supervision).
|
||||
|
@ -82,8 +82,11 @@ static void Parse (void)
|
||||
SymEntry* Entry;
|
||||
FuncDesc* FuncDef = 0;
|
||||
|
||||
/* Go... */
|
||||
NextToken ();
|
||||
/* Initialization for deferred operations */
|
||||
InitDeferredOps ();
|
||||
|
||||
/* Fill up the next token with a bogus semicolon and start the tokenizer */
|
||||
NextTok.Tok = TOK_SEMI;
|
||||
NextToken ();
|
||||
|
||||
/* Parse until end of input */
|
||||
@ -338,6 +341,9 @@ static void Parse (void)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Done with deferred operations */
|
||||
DoneDeferredOps ();
|
||||
}
|
||||
|
||||
|
||||
@ -403,7 +409,13 @@ void Compile (const char* FileName)
|
||||
/* DefineNumericMacro ("__STDC__", 1); <- not now */
|
||||
DefineNumericMacro ("__STDC_HOSTED__", 1);
|
||||
|
||||
InitDeferredOps ();
|
||||
/* Stuff unsupported */
|
||||
if (IS_Get (&Standard) > STD_C99) {
|
||||
DefineNumericMacro ("__STDC_NO_ATOMICS__", 1);
|
||||
DefineNumericMacro ("__STDC_NO_COMPLEX__", 1);
|
||||
DefineNumericMacro ("__STDC_NO_THREADS__", 1);
|
||||
DefineNumericMacro ("__STDC_NO_VLA__", 1);
|
||||
}
|
||||
|
||||
/* Create the base lexical level */
|
||||
EnterGlobalLevel ();
|
||||
@ -423,6 +435,9 @@ void Compile (const char* FileName)
|
||||
/* Generate the code generator preamble */
|
||||
g_preamble ();
|
||||
|
||||
/* Init preprocessor */
|
||||
InitPreprocess ();
|
||||
|
||||
/* Open the input file */
|
||||
OpenMainFile (FileName);
|
||||
|
||||
@ -433,10 +448,8 @@ void Compile (const char* FileName)
|
||||
OpenOutputFile ();
|
||||
|
||||
/* Preprocess each line and write it to the output file */
|
||||
while (NextLine ()) {
|
||||
Preprocess ();
|
||||
WriteOutput ("%.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
}
|
||||
while (PreprocessNextLine ())
|
||||
{ /* Nothing */ }
|
||||
|
||||
/* Close the output file */
|
||||
CloseOutputFile ();
|
||||
@ -494,9 +507,11 @@ void Compile (const char* FileName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DoneDeferredOps ();
|
||||
/* Done with preprocessor */
|
||||
DonePreprocess ();
|
||||
|
||||
if (Debug) {
|
||||
PrintMacroStats (stdout);
|
||||
|
115
src/cc65/input.c
115
src/cc65/input.c
@ -54,6 +54,7 @@
|
||||
#include "input.h"
|
||||
#include "lineinfo.h"
|
||||
#include "output.h"
|
||||
#include "preproc.h"
|
||||
|
||||
|
||||
|
||||
@ -91,6 +92,8 @@ struct AFile {
|
||||
FILE* F; /* Input file stream */
|
||||
IFile* Input; /* Points to corresponding IFile */
|
||||
int SearchPath; /* True if we've added a path for this file */
|
||||
PPIfStack IfStack; /* PP #if stack */
|
||||
int MissingNL; /* Last input line was missing a newline */
|
||||
};
|
||||
|
||||
/* List of all input files */
|
||||
@ -156,6 +159,8 @@ static AFile* NewAFile (IFile* IF, FILE* F)
|
||||
AF->Line = 0;
|
||||
AF->F = F;
|
||||
AF->Input = IF;
|
||||
AF->IfStack.Index = -1;
|
||||
AF->MissingNL = 0;
|
||||
|
||||
/* Increment the usage counter of the corresponding IFile. If this
|
||||
** is the first use, set the file data and output debug info if
|
||||
@ -257,6 +262,12 @@ void OpenMainFile (const char* Name)
|
||||
/* Allocate a new AFile structure for the file */
|
||||
MainFile = NewAFile (IF, F);
|
||||
|
||||
/* Use this file with PP */
|
||||
SetPPIfStack (&MainFile->IfStack);
|
||||
|
||||
/* Begin PP for this file */
|
||||
PreprocessBegin ();
|
||||
|
||||
/* Allocate the input line buffer */
|
||||
Line = NewStrBuf ();
|
||||
|
||||
@ -274,6 +285,7 @@ void OpenIncludeFile (const char* Name, InputType IT)
|
||||
char* N;
|
||||
FILE* F;
|
||||
IFile* IF;
|
||||
AFile* AF;
|
||||
|
||||
/* Check for the maximum include nesting */
|
||||
if (CollCount (&AFiles) > MAX_INC_NESTING) {
|
||||
@ -311,12 +323,18 @@ void OpenIncludeFile (const char* Name, InputType IT)
|
||||
Print (stdout, 1, "Opened include file '%s'\n", IF->Name);
|
||||
|
||||
/* Allocate a new AFile structure */
|
||||
(void) NewAFile (IF, F);
|
||||
AF = NewAFile (IF, F);
|
||||
|
||||
/* Use this file with PP */
|
||||
SetPPIfStack (&AF->IfStack);
|
||||
|
||||
/* Begin PP for this file */
|
||||
PreprocessBegin ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CloseIncludeFile (void)
|
||||
void CloseIncludeFile (void)
|
||||
/* Close an include file and switch to the higher level file. Set Input to
|
||||
** NULL if this was the main file.
|
||||
*/
|
||||
@ -329,14 +347,18 @@ static void CloseIncludeFile (void)
|
||||
/* Must have an input file when called */
|
||||
PRECONDITION (AFileCount > 0);
|
||||
|
||||
/* End preprocessor in this file */
|
||||
PreprocessEnd ();
|
||||
|
||||
/* Get the current active input file */
|
||||
Input = (AFile*) CollLast (&AFiles);
|
||||
Input = CollLast (&AFiles);
|
||||
|
||||
/* 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 */
|
||||
CollDelete (&AFiles, AFileCount-1);
|
||||
--AFileCount;
|
||||
CollDelete (&AFiles, AFileCount);
|
||||
|
||||
/* If we had added an extra search path for this AFile, remove it */
|
||||
if (Input->SearchPath) {
|
||||
@ -345,6 +367,12 @@ static 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -436,47 +464,49 @@ StrBuf* InitLine (StrBuf* Buf)
|
||||
|
||||
|
||||
int NextLine (void)
|
||||
/* Get a line from the current input. Returns 0 on end of file. */
|
||||
/* Get a line from the current input. Returns 0 on end of file with no new
|
||||
** input bytes.
|
||||
*/
|
||||
{
|
||||
int C;
|
||||
AFile* Input;
|
||||
|
||||
/* Clear the current line */
|
||||
ClearLine ();
|
||||
SB_Clear (Line);
|
||||
|
||||
/* If there is no file open, bail out, otherwise get the current input file */
|
||||
if (CollCount (&AFiles) == 0) {
|
||||
/* Must have an input file when called */
|
||||
if (CollCount(&AFiles) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the current input file */
|
||||
Input = CollLast (&AFiles);
|
||||
|
||||
/* Read characters until we have one complete line */
|
||||
while (1) {
|
||||
|
||||
/* Read the next character */
|
||||
int C = fgetc (Input->F);
|
||||
C = fgetc (Input->F);
|
||||
|
||||
/* Check for EOF */
|
||||
if (C == EOF) {
|
||||
|
||||
/* Accept files without a newline at the end */
|
||||
if (SB_NotEmpty (Line)) {
|
||||
if (!Input->MissingNL || SB_NotEmpty (Line)) {
|
||||
|
||||
/* Accept files without a newline at the end */
|
||||
++Input->Line;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Leave the current file */
|
||||
CloseIncludeFile ();
|
||||
/* Assume no new line */
|
||||
Input->MissingNL = 1;
|
||||
|
||||
/* If there is no file open, bail out, otherwise get the
|
||||
** previous input file and start over.
|
||||
*/
|
||||
if (CollCount (&AFiles) == 0) {
|
||||
return 0;
|
||||
}
|
||||
Input = CollLast (&AFiles);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assume no new line */
|
||||
Input->MissingNL = 1;
|
||||
|
||||
/* Check for end of line */
|
||||
if (C == '\n') {
|
||||
|
||||
@ -497,6 +527,7 @@ int NextLine (void)
|
||||
if (SB_LookAtLast (Line) == '\\') {
|
||||
Line->Buf[Line->Len-1] = '\n';
|
||||
} else {
|
||||
Input->MissingNL = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -517,6 +548,38 @@ int NextLine (void)
|
||||
/* Create line information for this line */
|
||||
UpdateLineInfo (Input->Input, Input->Line, Line);
|
||||
|
||||
/* Done */
|
||||
return C != EOF || SB_NotEmpty (Line);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int PreprocessNextLine (void)
|
||||
/* Get a line from opened input files and do preprocess. Returns 0 on end of
|
||||
** main file.
|
||||
*/
|
||||
{
|
||||
while (NextLine() == 0) {
|
||||
|
||||
/* If there is no input file open, bail out. Otherwise get the previous
|
||||
** input file and start over.
|
||||
*/
|
||||
if (CollCount (&AFiles) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Leave the current file */
|
||||
CloseIncludeFile ();
|
||||
}
|
||||
|
||||
/* Do preprocess anyways */
|
||||
Preprocess ();
|
||||
|
||||
/* Write it to the output file if in preprocess-only mode */
|
||||
if (PreprocessOnly) {
|
||||
WriteOutput ("%.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return 1;
|
||||
}
|
||||
@ -539,14 +602,8 @@ const char* GetCurrentFile (void)
|
||||
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
||||
return AF->Input->Name;
|
||||
} else {
|
||||
/* No open file. Use the main file if we have one. */
|
||||
unsigned IFileCount = CollCount (&IFiles);
|
||||
if (IFileCount > 0) {
|
||||
const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
|
||||
return IF->Name;
|
||||
} else {
|
||||
return "(outside file scope)";
|
||||
}
|
||||
/* No open file */
|
||||
return "(outside file scope)";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -84,6 +84,11 @@ void OpenMainFile (const char* Name);
|
||||
void OpenIncludeFile (const char* Name, InputType IT);
|
||||
/* Open an include file and insert it into the tables. */
|
||||
|
||||
void CloseIncludeFile (void);
|
||||
/* Close an include file and switch to the higher level file. Set Input to
|
||||
** NULL if this was the main file.
|
||||
*/
|
||||
|
||||
void NextChar (void);
|
||||
/* Read the next character from the input stream and make CurC and NextC
|
||||
** valid. If end of line is reached, both are set to NUL, no more lines
|
||||
@ -99,7 +104,14 @@ StrBuf* InitLine (StrBuf* Buf);
|
||||
*/
|
||||
|
||||
int NextLine (void);
|
||||
/* Get a line from the current input. Returns 0 on end of file. */
|
||||
/* Get a line from the current input. Returns 0 on end of file with no new
|
||||
** input bytes.
|
||||
*/
|
||||
|
||||
int PreprocessNextLine (void);
|
||||
/* Get a line from opened input files and do preprocess. Returns 0 on end of
|
||||
** main file.
|
||||
*/
|
||||
|
||||
const char* GetInputFile (const struct IFile* IF);
|
||||
/* Return a filename from an IFile struct */
|
||||
|
@ -56,6 +56,9 @@
|
||||
#define MACRO_TAB_SIZE 211
|
||||
static Macro* MacroTab[MACRO_TAB_SIZE];
|
||||
|
||||
/* The undefined macros list head */
|
||||
static Macro* UndefinedMacrosListHead;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -108,6 +111,29 @@ void FreeMacro (Macro* M)
|
||||
|
||||
|
||||
|
||||
Macro* CloneMacro (const Macro* M)
|
||||
/* Clone a macro definition. The function is not insert the macro into the
|
||||
** macro table, thus the cloned instance cannot be freed with UndefineMacro.
|
||||
** Use FreeMacro for that.
|
||||
*/
|
||||
{
|
||||
Macro* New = NewMacro (M->Name);
|
||||
unsigned I;
|
||||
|
||||
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
|
||||
/* Copy the argument */
|
||||
const char* Arg = CollAtUnchecked (&M->FormalArgs, I);
|
||||
CollAppend (&New->FormalArgs, xstrdup (Arg));
|
||||
}
|
||||
New->ArgCount = M->ArgCount;
|
||||
New->Variadic = M->Variadic;
|
||||
SB_Copy (&New->Replacement, &M->Replacement);
|
||||
|
||||
return New;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DefineNumericMacro (const char* Name, long Val)
|
||||
/* Define a macro for a numeric constant */
|
||||
{
|
||||
@ -150,10 +176,11 @@ void InsertMacro (Macro* M)
|
||||
|
||||
|
||||
|
||||
int UndefineMacro (const char* Name)
|
||||
/* Search for the macro with the given name and remove it from the macro
|
||||
** table if it exists. Return 1 if a macro was found and deleted, return
|
||||
** 0 otherwise.
|
||||
Macro* UndefineMacro (const char* Name)
|
||||
/* Search for the macro with the given name, if it exists, remove it from
|
||||
** the defined macro table and insert it to a list for pending deletion.
|
||||
** Return the macro if it was found and removed, return 0 otherwise.
|
||||
** To safely free the removed macro, use FreeUndefinedMacros().
|
||||
*/
|
||||
{
|
||||
/* Get the hash value of the macro name */
|
||||
@ -173,11 +200,12 @@ int UndefineMacro (const char* Name)
|
||||
L->Next = M->Next;
|
||||
}
|
||||
|
||||
/* Delete the macro */
|
||||
FreeMacro (M);
|
||||
/* Add this macro to pending deletion list */
|
||||
M->Next = UndefinedMacrosListHead;
|
||||
UndefinedMacrosListHead = M;
|
||||
|
||||
/* Done */
|
||||
return 1;
|
||||
return M;
|
||||
}
|
||||
|
||||
/* Next macro */
|
||||
@ -191,6 +219,23 @@ int UndefineMacro (const char* Name)
|
||||
|
||||
|
||||
|
||||
void FreeUndefinedMacros (void)
|
||||
/* Free all undefined macros */
|
||||
{
|
||||
Macro* Next;
|
||||
|
||||
while (UndefinedMacrosListHead != 0) {
|
||||
Next = UndefinedMacrosListHead->Next;
|
||||
|
||||
/* Delete the macro */
|
||||
FreeMacro (UndefinedMacrosListHead);
|
||||
|
||||
UndefinedMacrosListHead = Next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Macro* FindMacro (const char* Name)
|
||||
/* Find a macro with the given name. Return the macro definition or NULL */
|
||||
{
|
||||
|
@ -82,6 +82,12 @@ void FreeMacro (Macro* M);
|
||||
** table, use UndefineMacro for that.
|
||||
*/
|
||||
|
||||
Macro* CloneMacro (const Macro* M);
|
||||
/* Clone a macro definition. The function is not insert the macro into the
|
||||
** macro table, thus the cloned instance cannot be freed with UndefineMacro.
|
||||
** Use FreeMacro for that.
|
||||
*/
|
||||
|
||||
void DefineNumericMacro (const char* Name, long Val);
|
||||
/* Define a macro for a numeric constant */
|
||||
|
||||
@ -91,12 +97,16 @@ void DefineTextMacro (const char* Name, const char* Val);
|
||||
void InsertMacro (Macro* M);
|
||||
/* Insert the given macro into the macro table. */
|
||||
|
||||
int UndefineMacro (const char* Name);
|
||||
/* Search for the macro with the given name and remove it from the macro
|
||||
** table if it exists. Return 1 if a macro was found and deleted, return
|
||||
** 0 otherwise.
|
||||
Macro* UndefineMacro (const char* Name);
|
||||
/* Search for the macro with the given name, if it exists, remove it from
|
||||
** the defined macro table and insert it to a list for pending deletion.
|
||||
** Return the macro if it was found and removed, return 0 otherwise.
|
||||
** To safely free the removed macro, use FreeUndefinedMacros().
|
||||
*/
|
||||
|
||||
void FreeUndefinedMacros (void);
|
||||
/* Free all undefined macros */
|
||||
|
||||
Macro* FindMacro (const char* Name);
|
||||
/* Find a macro with the given name. Return the macro definition or NULL */
|
||||
|
||||
|
@ -90,12 +90,14 @@ static void PPExprInit (PPExpr* Expr)
|
||||
|
||||
|
||||
static void PPErrorSkipLine (void)
|
||||
/* Skip the remain tokens till the end of the line and set the expression
|
||||
** parser error flag.
|
||||
/* Set the expression parser error flag, skip the remain tokens till the end
|
||||
** of the line, clear the current and the next tokens.
|
||||
*/
|
||||
{
|
||||
SkipTokens (0, 0);
|
||||
PPEvaluationFailed = 1;
|
||||
SkipTokens (0, 0);
|
||||
CurTok.Tok = TOK_CEOF;
|
||||
NextTok.Tok = TOK_CEOF;
|
||||
}
|
||||
|
||||
|
||||
@ -148,6 +150,10 @@ static void PPhiePrimary (PPExpr* Expr)
|
||||
Expr->IVal = 0;
|
||||
break;
|
||||
|
||||
case TOK_CEOF:
|
||||
/* Error recovery */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Illegal expression in PP mode */
|
||||
PPError ("Preprocessor expression expected");
|
||||
@ -252,6 +258,10 @@ void PPhie10 (PPExpr* Expr)
|
||||
Expr->IVal = !Expr->IVal;
|
||||
break;
|
||||
|
||||
case TOK_CEOF:
|
||||
/* Error recovery */
|
||||
break;
|
||||
|
||||
case TOK_STAR:
|
||||
case TOK_AND:
|
||||
case TOK_SIZEOF:
|
||||
@ -286,7 +296,7 @@ static void PPhie_internal (const token_t* Ops, /* List of generators */
|
||||
/* Get the right hand side */
|
||||
hienext (&Rhs);
|
||||
|
||||
if (PPEvaluationEnabled) {
|
||||
if (PPEvaluationEnabled && !PPEvaluationFailed) {
|
||||
|
||||
/* If either side is unsigned, the result is unsigned */
|
||||
Expr->Flags |= Rhs.Flags & PPEXPR_UNSIGNED;
|
||||
@ -407,7 +417,7 @@ static void PPhie_compare (const token_t* Ops, /* List of generators */
|
||||
/* Get the right hand side */
|
||||
hienext (&Rhs);
|
||||
|
||||
if (PPEvaluationEnabled) {
|
||||
if (PPEvaluationEnabled && !PPEvaluationFailed) {
|
||||
|
||||
/* If either side is unsigned, the comparison is unsigned */
|
||||
Expr->Flags |= Rhs.Flags & PPEXPR_UNSIGNED;
|
||||
@ -501,7 +511,7 @@ static void PPhie7 (PPExpr* Expr)
|
||||
PPhie8 (&Rhs);
|
||||
|
||||
/* Evaluate */
|
||||
if (PPEvaluationEnabled) {
|
||||
if (PPEvaluationEnabled && !PPEvaluationFailed) {
|
||||
/* To shift by a negative value is equivalent to shift to the
|
||||
** opposite direction.
|
||||
*/
|
||||
@ -761,46 +771,57 @@ static void PPhie1 (PPExpr* Expr)
|
||||
|
||||
case TOK_ASSIGN:
|
||||
PPError ("Token \"=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_PLUS_ASSIGN:
|
||||
PPError ("Token \"+=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_MINUS_ASSIGN:
|
||||
PPError ("Token \"-=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_MUL_ASSIGN:
|
||||
PPError ("Token \"*=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_DIV_ASSIGN:
|
||||
PPError ("Token \"/=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_MOD_ASSIGN:
|
||||
PPError ("Token \"%%=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_SHL_ASSIGN:
|
||||
PPError ("Token \"<<=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_SHR_ASSIGN:
|
||||
PPError ("Token \">>=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_AND_ASSIGN:
|
||||
PPError ("Token \"&=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_OR_ASSIGN:
|
||||
PPError ("Token \"|=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
case TOK_XOR_ASSIGN:
|
||||
PPError ("Token \"^=\" is not valid in preprocessor expressions");
|
||||
PPErrorSkipLine ();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -827,12 +848,13 @@ static void PPhie0 (PPExpr* Expr)
|
||||
|
||||
|
||||
|
||||
void ParsePPExpr (PPExpr* Expr)
|
||||
void ParsePPExprInLine (PPExpr* Expr)
|
||||
/* Parse a line for PP expression */
|
||||
{
|
||||
/* Initialize the parser status */
|
||||
PPEvaluationFailed = 0;
|
||||
PPEvaluationEnabled = 1;
|
||||
NextLineDisabled = 1;
|
||||
|
||||
/* Parse */
|
||||
PPExprInit (Expr);
|
||||
@ -841,5 +863,9 @@ void ParsePPExpr (PPExpr* Expr)
|
||||
/* If the evaluation fails, the result is always zero */
|
||||
if (PPEvaluationFailed) {
|
||||
Expr->IVal = 0;
|
||||
PPEvaluationFailed = 0;
|
||||
}
|
||||
|
||||
/* Restore parser status */
|
||||
NextLineDisabled = 0;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ struct PPExpr
|
||||
|
||||
|
||||
|
||||
void ParsePPExpr (PPExpr* Expr);
|
||||
void ParsePPExprInLine (PPExpr* Expr);
|
||||
/* Parse a line for PP expression */
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -39,7 +39,25 @@
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* code */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Maximum #if depth per file */
|
||||
#define MAX_PP_IFS 256
|
||||
|
||||
/* Data struct used for per-file-directive handling */
|
||||
typedef struct PPIfStack PPIfStack;
|
||||
struct PPIfStack {
|
||||
unsigned char Stack[MAX_PP_IFS];
|
||||
int Index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -47,6 +65,21 @@
|
||||
void Preprocess (void);
|
||||
/* Preprocess a line */
|
||||
|
||||
void SetPPIfStack (PPIfStack* Stack);
|
||||
/* Specify which PP #if stack to use */
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
|
||||
/* End of preproc.h */
|
||||
|
@ -69,6 +69,7 @@
|
||||
|
||||
Token CurTok; /* The current token */
|
||||
Token NextTok; /* The next token */
|
||||
int NextLineDisabled; /* Disabled to read next line */
|
||||
|
||||
|
||||
|
||||
@ -188,10 +189,10 @@ static int SkipWhite (void)
|
||||
{
|
||||
while (1) {
|
||||
while (CurC == '\0') {
|
||||
if (NextLine () == 0) {
|
||||
/* If reading next line fails or is forbidden, bail out */
|
||||
if (NextLineDisabled || PreprocessNextLine () == 0) {
|
||||
return 0;
|
||||
}
|
||||
Preprocess ();
|
||||
}
|
||||
if (IsSpace (CurC)) {
|
||||
NextChar ();
|
||||
|
@ -210,6 +210,7 @@ struct Token {
|
||||
|
||||
extern Token CurTok; /* The current token */
|
||||
extern Token NextTok; /* The next token */
|
||||
extern int NextLineDisabled; /* Disabled to read next line */
|
||||
|
||||
|
||||
|
||||
|
12
test/val/bug1643.c
Normal file
12
test/val/bug1643.c
Normal file
@ -0,0 +1,12 @@
|
||||
/* bug #1643, macro expansion in #include */
|
||||
|
||||
#define MKSTR(a) MKSTR_IMPL(a)
|
||||
#define MKSTR_IMPL(a) #a
|
||||
#define BUG1643_H bug1643.h
|
||||
|
||||
#include MKSTR(BUG1643_H)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return BUG1643_RESULT;
|
||||
}
|
13
test/val/bug1643.h
Normal file
13
test/val/bug1643.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* bug #1643, macro expansion in #include */
|
||||
|
||||
#define STDIO_H <stdio.h>
|
||||
#include STDIO_H
|
||||
|
||||
#ifdef string
|
||||
#undef string
|
||||
#endif
|
||||
|
||||
#define string 0!%^&*/_=
|
||||
#include <string.h>
|
||||
|
||||
#define BUG1643_RESULT 0
|
Loading…
x
Reference in New Issue
Block a user