diff --git a/src/cc65/compile.c b/src/cc65/compile.c index d6069e914..11dcbced0 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -396,9 +396,10 @@ void Compile (const char* FileName) DefineNumericMacro ("__EAGERLY_INLINE_FUNCS__", 1); } - /* Placeholders for __FILE__ and __LINE__ macros */ + /* Placeholders for __FILE__, __LINE__ and __COUNTER__ macros */ DefineTextMacro ("__FILE__", ""); DefineTextMacro ("__LINE__", ""); + DefineTextMacro ("__COUNTER__", ""); /* __TIME__ and __DATE__ macros */ Time = time (0); diff --git a/src/cc65/input.c b/src/cc65/input.c index c6037091f..0e8fc3276 100644 --- a/src/cc65/input.c +++ b/src/cc65/input.c @@ -106,6 +106,9 @@ static Collection AFiles = STATIC_COLLECTION_INITIALIZER; /* Input stack used when preprocessing. */ static Collection InputStack = STATIC_COLLECTION_INITIALIZER; +/* Counter for the __COUNTER__ macro */ +static unsigned MainFileCounter; + /*****************************************************************************/ @@ -280,6 +283,9 @@ void OpenMainFile (const char* Name) ** the main file before the first line is read. */ UpdateLineInfo (MainFile->Input, MainFile->Line, Line); + + /* Initialize the __COUNTER__ counter */ + MainFileCounter = 0; } @@ -658,6 +664,14 @@ void SetCurrentFilename (const char* Name) +unsigned GetCurrentCounter (void) +/* Return the counter number in the current input file */ +{ + return MainFileCounter++; +} + + + static void WriteEscaped (FILE* F, const char* Name) /* Write a file name to a dependency file escaping spaces */ { diff --git a/src/cc65/input.h b/src/cc65/input.h index cf529e169..fb24bbaa8 100644 --- a/src/cc65/input.h +++ b/src/cc65/input.h @@ -128,6 +128,9 @@ void SetCurrentLine (unsigned LineNum); void SetCurrentFilename (const char* Name); /* Set the presumed name of the current input file */ +unsigned GetCurrentCounter (void); +/* Return the counter number in the current input file */ + void CreateDependencies (void); /* Create dependency files requested by the user */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 91aa503fc..020df011a 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -1630,9 +1630,15 @@ static int ParseDirectives (unsigned ModeFlags) void HandleSpecialMacro (Macro* M, const char* Name) -/* Handle special mandatory macros */ +/* Handle special "magic" macros that may change */ { - if (strcmp (Name, "__LINE__") == 0) { + if (strcmp (Name, "__COUNTER__") == 0) { + /* Replace __COUNTER__ with the current counter number */ + if (IS_Get (&Standard) < STD_CC65) { + PPWarning ("__COUNTER__ is a cc65 extension"); + } + SB_Printf (&M->Replacement, "%u", GetCurrentCounter ()); + } else if (strcmp (Name, "__LINE__") == 0) { /* Replace __LINE__ with the current line number */ SB_Printf (&M->Replacement, "%u", GetCurrentLine ()); } else if (strcmp (Name, "__FILE__") == 0) { diff --git a/src/cc65/preproc.h b/src/cc65/preproc.h index 2143dde98..a4619e545 100644 --- a/src/cc65/preproc.h +++ b/src/cc65/preproc.h @@ -91,7 +91,7 @@ void DonePreprocess (void); /* Done with preprocessor */ void HandleSpecialMacro (Macro* M, const char* Name); -/* Handle special mandatory macros */ +/* Handle special "magic" macros that may change */ diff --git a/test/val/counter.c b/test/val/counter.c new file mode 100644 index 000000000..4efa18359 --- /dev/null +++ b/test/val/counter.c @@ -0,0 +1,60 @@ +/* Tests for predefined macro __COUNTER__ */ + +#include + +static int failures = 0; + +#if __COUNTER__ /* 0 */ +# error __COUNTER__ should begin at 0! +#elif __COUNTER__ == 1 /* 1 */ +# define CONCAT(a,b) CONCAT_impl_(a,b) +# define CONCAT_impl_(a,b) a##b +#endif + +#line 42 "What is the answer?" +int CONCAT(ident,__COUNTER__)[0+__LINE__] = {__LINE__}, CONCAT(ident,__COUNTER__)[0+__LINE__] = {__LINE__}; /* 2,3 */ + +#if __COUNTER__ == 4 ? 1 || __COUNTER__ : 0 && __COUNTER__ /* 4,5,6 */ +_Static_assert(__COUNTER__ == 7, "__COUNTER__ should be 7 here!"); /* 7 */ +# define GET_COUNTER() __COUNTER__ +# define GET_LINE() __LINE__ +# warning __COUNTER__ in #warning is just output as text and will never increase! +#else +# if __COUNTER__ + __COUNTER__ + __COUNTER__ /* Skipped as a whole and not incrementing */ +# endif +# error __COUNTER__ is skipped along with the whole #error line and will never increase anyways! */ +#endif + +#include "counter.h" +#include "counter.h" + +_Static_assert(GET_COUNTER() == 10, "__COUNTER__ should be 10 here!"); /* 10 */ + +int main(void) +{ + if (ident2[0] != 42) { + printf("Expected ident2[0]: %s, got: %s\n", 42, ident2[0]); + ++failures; + } + + if (ident3[0] != 42) { + printf("Expected ident3[0]: %s, got: %s\n", 42, ident3[0]); + ++failures; + } + + if (ident8 != 8) { + printf("Expected ident8: %s, got: %s\n", 8, ident8); + ++failures; + } + + if (ident9 != 9) { + printf("Expected ident9: %s, got: %s\n", 9, ident9); + ++failures; + } + + if (failures != 0) { + printf("Failures: %d\n", failures); + } + + return failures; +} diff --git a/test/val/counter.h b/test/val/counter.h new file mode 100644 index 000000000..b6b5a98e2 --- /dev/null +++ b/test/val/counter.h @@ -0,0 +1,4 @@ +/* Tests for predefined macro __COUNTER__ */ + +#line GET_COUNTER() /* 1st: 8; 2nd: 9 */ +int CONCAT(ident,GET_LINE()) = GET_LINE();