1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

Changed handling on nested macro replacement to match up with the behavior of other major C compilers, which is unspecified by the C standard.

This commit is contained in:
acqn 2022-08-22 14:34:50 +08:00
parent 95e5471cd6
commit 2f6b5621cc

View File

@ -158,8 +158,8 @@ static int ParseDirectives (unsigned ModeFlags);
/* Handle directives. Return 1 if any whitespace or newlines are parsed. */
static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags);
/* Scan for and perform macro replacement. Return the count of identifiers in
** the replacement result.
/* Scan for and perform macro replacement. Return the count of identifiers and
** right parentheses in the replacement result.
*/
static MacroExp* InitMacroExp (MacroExp* E);
@ -492,6 +492,40 @@ static void ME_RemoveToken (unsigned Idx, unsigned Count, MacroExp* E)
static void ME_HandleSemiNestedMacro (unsigned NameIdx, unsigned LastIdx, MacroExp* E)
/* Unhide the macro name from all hidesets if it was expanded with an unhidden
** right parenthesis. This is unspecified but allowed behavior according to
** ISO/IEC 9899:2018, 6.10.3.4ff.
*/
{
unsigned I;
for (I = 0; I < CollCount (&E->HideSets); ++I) {
HiddenMacro* MHS = CollAtUnchecked (&E->HideSets, I);
HideRange* This;
HideRange** Prev;
for (Prev = &MHS->HS, This = *Prev; This != 0; This = *Prev) {
if (NameIdx < This->End) {
if (NameIdx >= This->Start && LastIdx >= This->End) {
This->End = NameIdx;
if (This->End == This->Start) {
/* Remove */
(*Prev) = This->Next;
FreeHideRange (This);
continue;
}
}
Prev = &This->Next;
} else {
break;
}
}
}
}
static void ME_AddArgHideSets (unsigned Idx, const MacroExp* A, MacroExp* Parent)
/* Propagate the macro hide sets of the substituted argument starting as the
** Idx'th identifier of the result.
@ -1214,7 +1248,7 @@ static int CheckExtraTokens (const char* Name)
static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, int MultiLine)
/* Identify the arguments to a macro call as-is. Return the total count of
** identifiers in the read argument list.
** identifiers and right parentheses in the read argument list.
*/
{
unsigned Idx = 0;
@ -1316,6 +1350,8 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
/* Check for end of macro param list */
if (CurC == ')') {
/* Count right parens */
++Idx;
NextChar ();
break;
}
@ -1366,6 +1402,9 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
} else if (Ident[0] == ')') {
/* Closing nested parenthesis */
--Parens;
/* Count right parens */
++CountInArg;
}
/* Just copy the punctuator */
SB_AppendStr (&Arg.Tokens, Ident);
@ -1403,7 +1442,9 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
/* Deallocate argument resources */
DoneMacroExp (&Arg);
/* Return the total count of identifiers in the argument list */
/* Return the total count of identifiers and right parentheses in the
** argument list.
*/
return Idx;
}
@ -1411,7 +1452,7 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, Macro* M, unsigned IdentCount)
/* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff.
** Return the count of identifiers found in the result.
** Return the count of identifiers and right parentheses in the result.
*/
{
unsigned Idx = NameIdx;
@ -1431,6 +1472,14 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M
SB_Reset (&M->Replacement);
OldSource = InitLine (&M->Replacement);
/* If the macro expansion replaces an function-like macro with an argument
** list containing a right parenthesis outside the hidesets of previously
** replaced macros, stop those hidesets from this replacement. This is not
** required by the standard but just to match up with other major C
** compilers.
*/
ME_HandleSemiNestedMacro (NameIdx, NameIdx + IdentCount, E);
/* Substitution loop */
while (CurC != '\0') {
int NeedPaste = 0;
@ -1637,6 +1686,14 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M
CopyQuotedString (&Buf);
} else {
if (GetPunc (Ident)) {
/* Count right parens. This is OK since they cannot be pasted
** to form different punctuators with others.
*/
if (Ident[0] == ')') {
/* Adjust tracking */
ME_OffsetHideSets (Idx, 1, E);
++Idx;
}
SB_AppendStr (&Buf, Ident);
} else if (CurC != '\0') {
SB_AppendChar (&Buf, CurC);
@ -1681,18 +1738,18 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M
InitLine (OldSource);
SB_SetIndex (&M->Replacement, OldIndex);
/* Return the count of substituted identifiers */
/* Return the count of substituted identifiers and right parentheses */
return Idx - NameIdx;
}
static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M, int MultiLine)
/* Expand a macro into Target. Return the count of identifiers in the result
** of the expansion.
/* Expand a macro into Target. Return the count of identifiers and right
** parentheses in the result of the expansion.
*/
{
/* Count of identifiers */
/* Count of identifiers and right parentheses */
unsigned Count = 0;
#if DEV_CC65_DEBUG
@ -1732,8 +1789,8 @@ static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M
static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags)
/* Scan for and perform macro replacement. Return the count of identifiers in
** the replacement result.
/* Scan for and perform macro replacement. Return the count of identifiers and
** right parentheses in the replacement result.
*/
{
unsigned Count = 0;
@ -1778,6 +1835,8 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
PPError ("')' expected");
ClearLine ();
} else {
/* Eat the right parenthesis */
ME_RemoveToken (Count, 1, E);
NextChar ();
}
}
@ -1916,6 +1975,10 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
*/
if (!Skipped) {
if (GetPunc (Ident)) {
if (Ident[0] == ')') {
/* Count right parens */
++Count;
}
SB_AppendStr (Target, Ident);
} else {
SB_AppendChar (Target, CurC);
@ -1977,7 +2040,7 @@ Loop:
/* Switch back the input */
InitLine (OldSource);
/* Return the count of identifiers */
/* Return the count of identifiers and right parentheses */
return Count;
}