diff --git a/src/cc65/macrotab.c b/src/cc65/macrotab.c index d835b7708..37b52351f 100644 --- a/src/cc65/macrotab.c +++ b/src/cc65/macrotab.c @@ -56,6 +56,9 @@ #define MACRO_TAB_SIZE 211 static Macro* MacroTab[MACRO_TAB_SIZE]; +/* The undefined macros list head */ +static Macro* UndefinedMacrosListHead; + /*****************************************************************************/ @@ -173,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 */ @@ -196,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 */ @@ -214,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 */ { diff --git a/src/cc65/macrotab.h b/src/cc65/macrotab.h index 0f9bff01a..6a09d7281 100644 --- a/src/cc65/macrotab.h +++ b/src/cc65/macrotab.h @@ -97,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 */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 3fd994e80..c545bf889 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -90,7 +90,6 @@ typedef struct MacroExp MacroExp; struct MacroExp { Collection ActualArgs; /* Actual arguments */ StrBuf Replacement; /* Replacement with arguments substituted */ - Macro* M; /* The macro we're handling */ }; @@ -193,12 +192,11 @@ static pptoken_t FindPPToken (const char* Ident) -static MacroExp* InitMacroExp (MacroExp* E, Macro* M) +static MacroExp* InitMacroExp (MacroExp* E) /* Initialize a MacroExp structure */ { InitCollection (&E->ActualArgs); SB_Init (&E->Replacement); - E->M = M; return E; } @@ -244,11 +242,11 @@ static StrBuf* ME_GetActual (MacroExp* E, unsigned Index) -static int ME_ArgIsVariadic (const MacroExp* E) +static int ME_ArgIsVariadic (const MacroExp* E, const Macro* M) /* Return true if the next actual argument we will add is a variadic one */ { - return (E->M->Variadic && - E->M->ArgCount == (int) CollCount (&E->ActualArgs) + 1); + return (M->Variadic && + M->ArgCount == (int) CollCount (&E->ActualArgs) + 1); } @@ -524,7 +522,7 @@ static int MacName (char* Ident) -static void ReadMacroArgs (MacroExp* E, int MultiLine) +static void ReadMacroArgs (MacroExp* E, const Macro* M, int MultiLine) /* Identify the arguments to a macro call as-is */ { int MissingParen = 0; @@ -576,7 +574,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine) } SB_AppendChar (&Arg, CurC); NextChar (); - } else if (CurC == ',' && ME_ArgIsVariadic (E)) { + } else if (CurC == ',' && ME_ArgIsVariadic (E, M)) { /* It's a comma, but we're inside a variadic macro argument, so ** just copy it and proceed. */ @@ -591,7 +589,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine) /* If this is not the single empty argument for a macro with ** an empty argument list, remember it. */ - if (CurC != ')' || SB_NotEmpty (&Arg) || E->M->ArgCount > 0) { + if (CurC != ')' || SB_NotEmpty (&Arg) || M->ArgCount > 0) { ME_AppendActual (E, &Arg); } @@ -607,7 +605,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine) } } else if (CurC == '\0') { /* End of input inside macro argument list */ - PPError ("Unterminated argument list invoking macro '%s'", E->M->Name); + PPError ("Unterminated argument list invoking macro '%s'", M->Name); MissingParen = 1; ClearLine (); break; @@ -619,7 +617,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine) } /* Compare formal and actual argument count */ - if (CollCount (&E->ActualArgs) != (unsigned) E->M->ArgCount) { + if (CollCount (&E->ActualArgs) != (unsigned) M->ArgCount) { if (!MissingParen) { /* Argument count mismatch */ @@ -628,7 +626,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine) /* Be sure to make enough empty arguments available */ SB_Clear (&Arg); - while (CollCount (&E->ActualArgs) < (unsigned) E->M->ArgCount) { + while (CollCount (&E->ActualArgs) < (unsigned) M->ArgCount) { ME_AppendActual (E, &Arg); } } @@ -639,7 +637,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine) -static void MacroArgSubst (MacroExp* E) +static void MacroArgSubst (MacroExp* E, Macro* M) /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */ { ident Ident; @@ -650,9 +648,9 @@ static void MacroArgSubst (MacroExp* E) /* Remember the current input and switch to the macro replacement. */ - int OldIndex = SB_GetIndex (&E->M->Replacement); - SB_Reset (&E->M->Replacement); - OldSource = InitLine (&E->M->Replacement); + int OldIndex = SB_GetIndex (&M->Replacement); + SB_Reset (&M->Replacement); + OldSource = InitLine (&M->Replacement); /* Argument handling loop */ while (CurC != '\0') { @@ -661,7 +659,7 @@ static void MacroArgSubst (MacroExp* E) if (IsSym (Ident)) { /* Check if it's a macro argument */ - if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { + if ((ArgIdx = FindMacroArg (M, Ident)) >= 0) { /* A macro argument. Get the corresponding actual argument. */ Arg = ME_GetActual (E, ArgIdx); @@ -720,7 +718,7 @@ static void MacroArgSubst (MacroExp* E) if (IsSym (Ident)) { /* Check if it's a macro argument */ - if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { + if ((ArgIdx = FindMacroArg (M, Ident)) >= 0) { /* Get the corresponding actual argument and add it. */ SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx)); @@ -733,7 +731,7 @@ static void MacroArgSubst (MacroExp* E) } } - } else if (CurC == '#' && E->M->ArgCount >= 0) { + } else if (CurC == '#' && M->ArgCount >= 0) { /* A # operator within a macro expansion of a function like ** macro. Read the following identifier and check if it's a @@ -741,7 +739,7 @@ static void MacroArgSubst (MacroExp* E) */ NextChar (); SkipWhitespace (0); - if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) { + if (!IsSym (Ident) || (ArgIdx = FindMacroArg (M, Ident)) < 0) { PPError ("'#' is not followed by a macro parameter"); } else { /* Make a valid string from Replacement */ @@ -767,7 +765,7 @@ static void MacroArgSubst (MacroExp* E) /* Switch back the input */ InitLine (OldSource); - SB_SetIndex (&E->M->Replacement, OldIndex); + SB_SetIndex (&M->Replacement, OldIndex); } @@ -783,65 +781,28 @@ static void ExpandMacro (StrBuf* Target, Macro* M, int MultiLine) #endif /* Initialize our MacroExp structure */ - InitMacroExp (&E, M); + InitMacroExp (&E); /* Check if this is a function like macro */ - if (E.M->ArgCount >= 0) { - - /* Since the macro could be undefined or redefined during its argument - ** parsing, we make a clone of the current one and stick to it. - */ - if (MultiLine) { - E.M = CloneMacro (E.M); - } + if (M->ArgCount >= 0) { /* Read the actual macro arguments (with the enclosing parentheses) */ - ReadMacroArgs (&E, MultiLine); - - /* Replace macro arguments handling the # and ## operators */ - MacroArgSubst (&E); - - /* Do macro replacement on the macro that already has the parameters - ** substituted. - */ - if (MultiLine) { - /* Check if the macro was undefined or redefined */ - M = FindMacro (E.M->Name); - if (M == 0 || MacroCmp (E.M, M) != 0) { - /* Use the cloned macro */ - M = E.M; - } - } - - /* Forbide repeated expansion of the same macro in use */ - M->Expanding = 1; - MacroReplacement (&E.Replacement, Target, 0); - M->Expanding = 0; - - } else { - - /* Handle # and ## operators for object like macros */ - MacroArgSubst (&E); - - /* Do macro replacement on the macro that already has the parameters - ** substituted. - */ - M->Expanding = 1; - MacroReplacement (&E.Replacement, Target, 0); - M->Expanding = 0; + ReadMacroArgs (&E, M, MultiLine); } + /* Replace macro arguments handling the # and ## operators */ + MacroArgSubst (&E, M); + + /* Forbide repeated expansion of the same macro in use */ + M->Expanding = 1; + MacroReplacement (&E.Replacement, Target, 0); + M->Expanding = 0; + #if 0 printf ("Done with %s(%u)\n", E.M->Name, V--); #endif - /* Free cloned macro */ - if (MultiLine && E.M->ArgCount >= 0) { - FreeMacro (E.M); - E.M = 0; - } - /* Free memory allocated for the macro expansion structure */ DoneMacroExp (&E); } @@ -1662,6 +1623,9 @@ void Preprocess (void) printf ("%s:%u: %.*s\n", GetCurrentFile (), GetCurrentLine (), (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } + + /* Free all undefined macros */ + FreeUndefinedMacros (); }