mirror of
https://github.com/cc65/cc65.git
synced 2025-01-13 09:31:53 +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:
parent
95e5471cd6
commit
2f6b5621cc
@ -158,8 +158,8 @@ static int ParseDirectives (unsigned ModeFlags);
|
|||||||
/* Handle directives. Return 1 if any whitespace or newlines are parsed. */
|
/* Handle directives. Return 1 if any whitespace or newlines are parsed. */
|
||||||
|
|
||||||
static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags);
|
static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags);
|
||||||
/* Scan for and perform macro replacement. Return the count of identifiers in
|
/* Scan for and perform macro replacement. Return the count of identifiers and
|
||||||
** the replacement result.
|
** right parentheses in the replacement result.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static MacroExp* InitMacroExp (MacroExp* E);
|
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)
|
static void ME_AddArgHideSets (unsigned Idx, const MacroExp* A, MacroExp* Parent)
|
||||||
/* Propagate the macro hide sets of the substituted argument starting as the
|
/* Propagate the macro hide sets of the substituted argument starting as the
|
||||||
** Idx'th identifier of the result.
|
** 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)
|
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
|
/* 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;
|
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 */
|
/* Check for end of macro param list */
|
||||||
if (CurC == ')') {
|
if (CurC == ')') {
|
||||||
|
/* Count right parens */
|
||||||
|
++Idx;
|
||||||
NextChar ();
|
NextChar ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1366,6 +1402,9 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
|
|||||||
} else if (Ident[0] == ')') {
|
} else if (Ident[0] == ')') {
|
||||||
/* Closing nested parenthesis */
|
/* Closing nested parenthesis */
|
||||||
--Parens;
|
--Parens;
|
||||||
|
|
||||||
|
/* Count right parens */
|
||||||
|
++CountInArg;
|
||||||
}
|
}
|
||||||
/* Just copy the punctuator */
|
/* Just copy the punctuator */
|
||||||
SB_AppendStr (&Arg.Tokens, Ident);
|
SB_AppendStr (&Arg.Tokens, Ident);
|
||||||
@ -1403,7 +1442,9 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
|
|||||||
/* Deallocate argument resources */
|
/* Deallocate argument resources */
|
||||||
DoneMacroExp (&Arg);
|
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;
|
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)
|
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.
|
/* 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;
|
unsigned Idx = NameIdx;
|
||||||
@ -1431,6 +1472,14 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M
|
|||||||
SB_Reset (&M->Replacement);
|
SB_Reset (&M->Replacement);
|
||||||
OldSource = InitLine (&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 */
|
/* Substitution loop */
|
||||||
while (CurC != '\0') {
|
while (CurC != '\0') {
|
||||||
int NeedPaste = 0;
|
int NeedPaste = 0;
|
||||||
@ -1637,6 +1686,14 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M
|
|||||||
CopyQuotedString (&Buf);
|
CopyQuotedString (&Buf);
|
||||||
} else {
|
} else {
|
||||||
if (GetPunc (Ident)) {
|
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);
|
SB_AppendStr (&Buf, Ident);
|
||||||
} else if (CurC != '\0') {
|
} else if (CurC != '\0') {
|
||||||
SB_AppendChar (&Buf, CurC);
|
SB_AppendChar (&Buf, CurC);
|
||||||
@ -1681,18 +1738,18 @@ static unsigned SubstMacroArgs (unsigned NameIdx, StrBuf* Target, MacroExp* E, M
|
|||||||
InitLine (OldSource);
|
InitLine (OldSource);
|
||||||
SB_SetIndex (&M->Replacement, OldIndex);
|
SB_SetIndex (&M->Replacement, OldIndex);
|
||||||
|
|
||||||
/* Return the count of substituted identifiers */
|
/* Return the count of substituted identifiers and right parentheses */
|
||||||
return Idx - NameIdx;
|
return Idx - NameIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned ExpandMacro (unsigned Idx, StrBuf* Target, MacroExp* E, Macro* M, int MultiLine)
|
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
|
/* Expand a macro into Target. Return the count of identifiers and right
|
||||||
** of the expansion.
|
** parentheses in the result of the expansion.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Count of identifiers */
|
/* Count of identifiers and right parentheses */
|
||||||
unsigned Count = 0;
|
unsigned Count = 0;
|
||||||
|
|
||||||
#if DEV_CC65_DEBUG
|
#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)
|
static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsigned ModeFlags)
|
||||||
/* Scan for and perform macro replacement. Return the count of identifiers in
|
/* Scan for and perform macro replacement. Return the count of identifiers and
|
||||||
** the replacement result.
|
** right parentheses in the replacement result.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
unsigned Count = 0;
|
unsigned Count = 0;
|
||||||
@ -1778,6 +1835,8 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
PPError ("')' expected");
|
PPError ("')' expected");
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
} else {
|
} else {
|
||||||
|
/* Eat the right parenthesis */
|
||||||
|
ME_RemoveToken (Count, 1, E);
|
||||||
NextChar ();
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1916,6 +1975,10 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
*/
|
*/
|
||||||
if (!Skipped) {
|
if (!Skipped) {
|
||||||
if (GetPunc (Ident)) {
|
if (GetPunc (Ident)) {
|
||||||
|
if (Ident[0] == ')') {
|
||||||
|
/* Count right parens */
|
||||||
|
++Count;
|
||||||
|
}
|
||||||
SB_AppendStr (Target, Ident);
|
SB_AppendStr (Target, Ident);
|
||||||
} else {
|
} else {
|
||||||
SB_AppendChar (Target, CurC);
|
SB_AppendChar (Target, CurC);
|
||||||
@ -1977,7 +2040,7 @@ Loop:
|
|||||||
/* Switch back the input */
|
/* Switch back the input */
|
||||||
InitLine (OldSource);
|
InitLine (OldSource);
|
||||||
|
|
||||||
/* Return the count of identifiers */
|
/* Return the count of identifiers and right parentheses */
|
||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user