Modified way to keep undefined macro handling more consistent.
This commit is contained in:
@@ -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 */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
#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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user