Modified way to keep undefined macro handling more consistent.

This commit is contained in:
acqn
2022-08-18 22:51:23 +08:00
parent 7971eec3cc
commit 47d5e74a6e
3 changed files with 70 additions and 80 deletions

View File

@@ -56,6 +56,9 @@
#define MACRO_TAB_SIZE 211 #define MACRO_TAB_SIZE 211
static Macro* MacroTab[MACRO_TAB_SIZE]; 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) Macro* UndefineMacro (const char* Name)
/* Search for the macro with the given name and remove it from the macro /* Search for the macro with the given name, if it exists, remove it from
** table if it exists. Return 1 if a macro was found and deleted, return ** the defined macro table and insert it to a list for pending deletion.
** 0 otherwise. ** 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 */ /* Get the hash value of the macro name */
@@ -196,11 +200,12 @@ int UndefineMacro (const char* Name)
L->Next = M->Next; L->Next = M->Next;
} }
/* Delete the macro */ /* Add this macro to pending deletion list */
FreeMacro (M); M->Next = UndefinedMacrosListHead;
UndefinedMacrosListHead = M;
/* Done */ /* Done */
return 1; return M;
} }
/* Next macro */ /* 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) Macro* FindMacro (const char* Name)
/* Find a macro with the given name. Return the macro definition or NULL */ /* Find a macro with the given name. Return the macro definition or NULL */
{ {

View File

@@ -97,12 +97,16 @@ void DefineTextMacro (const char* Name, const char* Val);
void InsertMacro (Macro* M); void InsertMacro (Macro* M);
/* Insert the given macro into the macro table. */ /* Insert the given macro into the macro table. */
int UndefineMacro (const char* Name); Macro* UndefineMacro (const char* Name);
/* Search for the macro with the given name and remove it from the macro /* Search for the macro with the given name, if it exists, remove it from
** table if it exists. Return 1 if a macro was found and deleted, return ** the defined macro table and insert it to a list for pending deletion.
** 0 otherwise. ** 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); Macro* FindMacro (const char* Name);
/* Find a macro with the given name. Return the macro definition or NULL */ /* Find a macro with the given name. Return the macro definition or NULL */

View File

@@ -90,7 +90,6 @@ typedef struct MacroExp MacroExp;
struct MacroExp { struct MacroExp {
Collection ActualArgs; /* Actual arguments */ Collection ActualArgs; /* Actual arguments */
StrBuf Replacement; /* Replacement with arguments substituted */ 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 */ /* Initialize a MacroExp structure */
{ {
InitCollection (&E->ActualArgs); InitCollection (&E->ActualArgs);
SB_Init (&E->Replacement); SB_Init (&E->Replacement);
E->M = M;
return E; 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 true if the next actual argument we will add is a variadic one */
{ {
return (E->M->Variadic && return (M->Variadic &&
E->M->ArgCount == (int) CollCount (&E->ActualArgs) + 1); 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 */ /* Identify the arguments to a macro call as-is */
{ {
int MissingParen = 0; int MissingParen = 0;
@@ -576,7 +574,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine)
} }
SB_AppendChar (&Arg, CurC); SB_AppendChar (&Arg, CurC);
NextChar (); 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 /* It's a comma, but we're inside a variadic macro argument, so
** just copy it and proceed. ** 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 /* If this is not the single empty argument for a macro with
** an empty argument list, remember it. ** 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); ME_AppendActual (E, &Arg);
} }
@@ -607,7 +605,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine)
} }
} else if (CurC == '\0') { } else if (CurC == '\0') {
/* End of input inside macro argument list */ /* 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; MissingParen = 1;
ClearLine (); ClearLine ();
break; break;
@@ -619,7 +617,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine)
} }
/* Compare formal and actual argument count */ /* Compare formal and actual argument count */
if (CollCount (&E->ActualArgs) != (unsigned) E->M->ArgCount) { if (CollCount (&E->ActualArgs) != (unsigned) M->ArgCount) {
if (!MissingParen) { if (!MissingParen) {
/* Argument count mismatch */ /* Argument count mismatch */
@@ -628,7 +626,7 @@ static void ReadMacroArgs (MacroExp* E, int MultiLine)
/* Be sure to make enough empty arguments available */ /* Be sure to make enough empty arguments available */
SB_Clear (&Arg); SB_Clear (&Arg);
while (CollCount (&E->ActualArgs) < (unsigned) E->M->ArgCount) { while (CollCount (&E->ActualArgs) < (unsigned) M->ArgCount) {
ME_AppendActual (E, &Arg); 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 */ /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */
{ {
ident Ident; ident Ident;
@@ -650,9 +648,9 @@ static void MacroArgSubst (MacroExp* E)
/* Remember the current input and switch to the macro replacement. */ /* Remember the current input and switch to the macro replacement. */
int OldIndex = SB_GetIndex (&E->M->Replacement); int OldIndex = SB_GetIndex (&M->Replacement);
SB_Reset (&E->M->Replacement); SB_Reset (&M->Replacement);
OldSource = InitLine (&E->M->Replacement); OldSource = InitLine (&M->Replacement);
/* Argument handling loop */ /* Argument handling loop */
while (CurC != '\0') { while (CurC != '\0') {
@@ -661,7 +659,7 @@ static void MacroArgSubst (MacroExp* E)
if (IsSym (Ident)) { if (IsSym (Ident)) {
/* Check if it's a macro argument */ /* 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. */ /* A macro argument. Get the corresponding actual argument. */
Arg = ME_GetActual (E, ArgIdx); Arg = ME_GetActual (E, ArgIdx);
@@ -720,7 +718,7 @@ static void MacroArgSubst (MacroExp* E)
if (IsSym (Ident)) { if (IsSym (Ident)) {
/* Check if it's a macro argument */ /* 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. */ /* Get the corresponding actual argument and add it. */
SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx)); 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 /* A # operator within a macro expansion of a function like
** macro. Read the following identifier and check if it's a ** macro. Read the following identifier and check if it's a
@@ -741,7 +739,7 @@ static void MacroArgSubst (MacroExp* E)
*/ */
NextChar (); NextChar ();
SkipWhitespace (0); 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"); PPError ("'#' is not followed by a macro parameter");
} else { } else {
/* Make a valid string from Replacement */ /* Make a valid string from Replacement */
@@ -767,7 +765,7 @@ static void MacroArgSubst (MacroExp* E)
/* Switch back the input */ /* Switch back the input */
InitLine (OldSource); 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 #endif
/* Initialize our MacroExp structure */ /* Initialize our MacroExp structure */
InitMacroExp (&E, M); InitMacroExp (&E);
/* Check if this is a function like macro */ /* Check if this is a function like macro */
if (E.M->ArgCount >= 0) { if (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);
}
/* Read the actual macro arguments (with the enclosing parentheses) */ /* Read the actual macro arguments (with the enclosing parentheses) */
ReadMacroArgs (&E, MultiLine); ReadMacroArgs (&E, M, MultiLine);
}
/* Replace macro arguments handling the # and ## operators */ /* Replace macro arguments handling the # and ## operators */
MacroArgSubst (&E); MacroArgSubst (&E, M);
/* 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 */ /* Forbide repeated expansion of the same macro in use */
M->Expanding = 1; M->Expanding = 1;
MacroReplacement (&E.Replacement, Target, 0); MacroReplacement (&E.Replacement, Target, 0);
M->Expanding = 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;
}
#if 0 #if 0
printf ("Done with %s(%u)\n", E.M->Name, V--); printf ("Done with %s(%u)\n", E.M->Name, V--);
#endif #endif
/* Free cloned macro */
if (MultiLine && E.M->ArgCount >= 0) {
FreeMacro (E.M);
E.M = 0;
}
/* Free memory allocated for the macro expansion structure */ /* Free memory allocated for the macro expansion structure */
DoneMacroExp (&E); DoneMacroExp (&E);
} }
@@ -1662,6 +1623,9 @@ void Preprocess (void)
printf ("%s:%u: %.*s\n", GetCurrentFile (), GetCurrentLine (), printf ("%s:%u: %.*s\n", GetCurrentFile (), GetCurrentLine (),
(int) SB_GetLen (Line), SB_GetConstBuf (Line)); (int) SB_GetLen (Line), SB_GetConstBuf (Line));
} }
/* Free all undefined macros */
FreeUndefinedMacros ();
} }