1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-01 13:41:34 +00:00

Merge pull request #1817 from acqn/PPFix

[cc65] More preprocessor fixes
This commit is contained in:
Bob Andrews 2022-08-19 21:37:16 +02:00 committed by GitHub
commit 03421694b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 785 additions and 307 deletions

View File

@ -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).

View File

@ -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);

View File

@ -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)";
}
}

View File

@ -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 */

View File

@ -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 */
{

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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 ();

View File

@ -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
View 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
View 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