mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
Merge pull request #1868 from acqn/PPFix
[cc65] Fixed and improved C preprocessor
This commit is contained in:
commit
b2238fdcd4
@ -67,6 +67,9 @@
|
|||||||
/* The current input line */
|
/* The current input line */
|
||||||
StrBuf* Line;
|
StrBuf* Line;
|
||||||
|
|
||||||
|
/* The input line to reuse as the next line */
|
||||||
|
static StrBuf* CurReusedLine;
|
||||||
|
|
||||||
/* Current and next input character */
|
/* Current and next input character */
|
||||||
char CurC = '\0';
|
char CurC = '\0';
|
||||||
char NextC = '\0';
|
char NextC = '\0';
|
||||||
@ -403,24 +406,6 @@ static void GetInputChar (void)
|
|||||||
/* NextC is '\0' by default */
|
/* NextC is '\0' by default */
|
||||||
NextC = '\0';
|
NextC = '\0';
|
||||||
|
|
||||||
/* Drop all pushed fragments that don't have data left */
|
|
||||||
if (CurrentInputStack != 0) {
|
|
||||||
while (SB_GetIndex (Line) >= SB_GetLen (Line)) {
|
|
||||||
/* Cannot read more from this line, check next line on stack if any */
|
|
||||||
if (CollCount (CurrentInputStack) == 0) {
|
|
||||||
/* This is THE line */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
FreeStrBuf (Line);
|
|
||||||
Line = CollPop (CurrentInputStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NextC comes from next fragment */
|
|
||||||
if (CollCount (CurrentInputStack) > 0) {
|
|
||||||
NextC = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get CurC from the line */
|
/* Get CurC from the line */
|
||||||
CurC = SB_LookAt (Line, SB_GetIndex (Line));
|
CurC = SB_LookAt (Line, SB_GetIndex (Line));
|
||||||
}
|
}
|
||||||
@ -461,13 +446,17 @@ void PushLine (StrBuf* L)
|
|||||||
/* Save the current input line and use a new one */
|
/* Save the current input line and use a new one */
|
||||||
{
|
{
|
||||||
PRECONDITION (CurrentInputStack != 0);
|
PRECONDITION (CurrentInputStack != 0);
|
||||||
if (SB_GetIndex (L) < SB_GetLen (L)) {
|
CollAppend (CurrentInputStack, Line);
|
||||||
CollAppend (CurrentInputStack, Line);
|
Line = L;
|
||||||
Line = L;
|
GetInputChar ();
|
||||||
GetInputChar ();
|
}
|
||||||
} else {
|
|
||||||
FreeStrBuf (L);
|
|
||||||
}
|
|
||||||
|
void ReuseInputLine (void)
|
||||||
|
/* Save and reuse the current line as the next line */
|
||||||
|
{
|
||||||
|
CurReusedLine = Line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -475,16 +464,6 @@ void PushLine (StrBuf* L)
|
|||||||
void ClearLine (void)
|
void ClearLine (void)
|
||||||
/* Clear the current input line */
|
/* Clear the current input line */
|
||||||
{
|
{
|
||||||
if (CurrentInputStack != 0) {
|
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Remove all pushed fragments from the input stack */
|
|
||||||
for (I = 0; I < CollCount (CurrentInputStack); ++I) {
|
|
||||||
FreeStrBuf (Line);
|
|
||||||
Line = CollPop (CurrentInputStack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the contents of Line */
|
/* Clear the contents of Line */
|
||||||
SB_Clear (Line);
|
SB_Clear (Line);
|
||||||
CurC = '\0';
|
CurC = '\0';
|
||||||
@ -515,12 +494,47 @@ int NextLine (void)
|
|||||||
int C;
|
int C;
|
||||||
AFile* Input;
|
AFile* Input;
|
||||||
|
|
||||||
/* Clear the current line */
|
/* Overwrite the next input line with the pushed line if there is one */
|
||||||
ClearLine ();
|
if (CurReusedLine != 0) {
|
||||||
SB_Clear (Line);
|
/* Use data move to resolve the issue that Line may be impersistent */
|
||||||
|
if (Line != CurReusedLine) {
|
||||||
|
SB_Move (Line, CurReusedLine);
|
||||||
|
}
|
||||||
|
/* Continue with this Line */
|
||||||
|
InitLine (Line);
|
||||||
|
CurReusedLine = 0;
|
||||||
|
|
||||||
/* Must have an input file when called */
|
return 1;
|
||||||
if (CollCount(&AFiles) == 0) {
|
}
|
||||||
|
|
||||||
|
/* If there are pushed input lines, read from them */
|
||||||
|
if (CurrentInputStack != 0 && CollCount (CurrentInputStack) > 0) {
|
||||||
|
/* Drop all pushed fragments that have no data left until one can be
|
||||||
|
** used as input.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
/* Use data move to resolve the issue that Line may be impersistent */
|
||||||
|
if (Line != CollLast (CurrentInputStack)) {
|
||||||
|
SB_Move (Line, CollPop (CurrentInputStack));
|
||||||
|
} else {
|
||||||
|
CollPop (CurrentInputStack);
|
||||||
|
}
|
||||||
|
} while (CollCount (CurrentInputStack) > 0 &&
|
||||||
|
SB_GetIndex (Line) >= SB_GetLen (Line));
|
||||||
|
|
||||||
|
if (SB_GetIndex (Line) < SB_GetLen (Line)) {
|
||||||
|
InitLine (Line);
|
||||||
|
|
||||||
|
/* Successive */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, clear the current line */
|
||||||
|
ClearLine ();
|
||||||
|
|
||||||
|
/* Must have an input file when going on */
|
||||||
|
if (CollCount (&AFiles) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +104,9 @@ Collection* UseInputStack (Collection* InputStack);
|
|||||||
void PushLine (StrBuf* L);
|
void PushLine (StrBuf* L);
|
||||||
/* Save the current input line and use a new one */
|
/* Save the current input line and use a new one */
|
||||||
|
|
||||||
|
void ReuseInputLine (void);
|
||||||
|
/* Save and reuse the current line as the next line */
|
||||||
|
|
||||||
void ClearLine (void);
|
void ClearLine (void);
|
||||||
/* Clear the current input line */
|
/* Clear the current input line */
|
||||||
|
|
||||||
|
@ -806,6 +806,21 @@ static int MacName (char* Ident)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CheckForBadIdent (const char* Ident, int Std, const Macro* M)
|
||||||
|
/* Check for and warning on problematic identifiers */
|
||||||
|
{
|
||||||
|
if (Std >= STD_C99 &&
|
||||||
|
(M == 0 || !M->Variadic) &&
|
||||||
|
strcmp (Ident, "__VA_ARGS__") == 0) {
|
||||||
|
/* __VA_ARGS__ cannot be used as a macro parameter name in post-C89
|
||||||
|
** mode.
|
||||||
|
*/
|
||||||
|
PPWarning ("__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void AddPreLine (StrBuf* Str)
|
static void AddPreLine (StrBuf* Str)
|
||||||
/* Add newlines to the string buffer */
|
/* Add newlines to the string buffer */
|
||||||
{
|
{
|
||||||
@ -878,7 +893,7 @@ static void Stringize (StrBuf* Source, StrBuf* Target)
|
|||||||
|
|
||||||
|
|
||||||
static void OldStyleComment (void)
|
static void OldStyleComment (void)
|
||||||
/* Remove an old style C comment from line. */
|
/* Remove an old style C comment from line */
|
||||||
{
|
{
|
||||||
/* Remember the current line number, so we can output better error
|
/* Remember the current line number, so we can output better error
|
||||||
** messages if the comment is not terminated in the current file.
|
** messages if the comment is not terminated in the current file.
|
||||||
@ -897,6 +912,7 @@ static void OldStyleComment (void)
|
|||||||
StartingLine);
|
StartingLine);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
++PendingNewLines;
|
||||||
} else {
|
} else {
|
||||||
if (CurC == '/' && NextC == '*') {
|
if (CurC == '/' && NextC == '*') {
|
||||||
PPWarning ("'/*' found inside a comment");
|
PPWarning ("'/*' found inside a comment");
|
||||||
@ -913,7 +929,7 @@ static void OldStyleComment (void)
|
|||||||
|
|
||||||
|
|
||||||
static void NewStyleComment (void)
|
static void NewStyleComment (void)
|
||||||
/* Remove a new style C comment from line. */
|
/* Remove a new style C comment from line */
|
||||||
{
|
{
|
||||||
/* Diagnose if this is unsupported */
|
/* Diagnose if this is unsupported */
|
||||||
if (IS_Get (&Standard) < STD_C99 && !AllowNewComments) {
|
if (IS_Get (&Standard) < STD_C99 && !AllowNewComments) {
|
||||||
@ -1552,7 +1568,10 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
|
|||||||
/* If this is not the single empty argument for a macro with an
|
/* If this is not the single empty argument for a macro with an
|
||||||
** empty argument list, remember it.
|
** empty argument list, remember it.
|
||||||
*/
|
*/
|
||||||
if (CurC != ')' || SB_NotEmpty (&Arg.Tokens) || M->ParamCount > 0) {
|
if (CurC != ')' ||
|
||||||
|
CollCount (&E->Args) > 0 ||
|
||||||
|
SB_NotEmpty (&Arg.Tokens) ||
|
||||||
|
M->ParamCount > 0) {
|
||||||
MacroExp* A = ME_AppendArg (E, &Arg);
|
MacroExp* A = ME_AppendArg (E, &Arg);
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
@ -1670,11 +1689,23 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Compare formal and actual argument count */
|
/* Compare formal and actual argument count */
|
||||||
if (CollCount (&E->Args) != (unsigned) M->ParamCount) {
|
if (CollCount (&E->Args) < (unsigned) M->ParamCount) {
|
||||||
|
/* Check further only when the parentheses are paired */
|
||||||
if (Parens == 0) {
|
if (Parens == 0) {
|
||||||
/* Argument count mismatch */
|
/* Specially casing variable argument */
|
||||||
PPError ("Macro argument count mismatch");
|
if (M->Variadic &&
|
||||||
|
M->ParamCount > 0 &&
|
||||||
|
CollCount (&E->Args) + 1 == (unsigned) M->ParamCount) {
|
||||||
|
/* The variable argument is left out entirely */
|
||||||
|
E->Flags |= MES_NO_VA_COMMA;
|
||||||
|
if (IS_Get (&Standard) < STD_CC65) {
|
||||||
|
PPWarning ("ISO C does not permit leaving out the comma before the variable argument");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Too few argument */
|
||||||
|
PPError ("Macro \"%s\" passed only %u arguments, but requires %u",
|
||||||
|
M->Name, CollCount (&E->Args), (unsigned) M->ParamCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Be sure to make enough empty arguments available */
|
/* Be sure to make enough empty arguments available */
|
||||||
@ -1684,6 +1715,10 @@ static unsigned ReadMacroArgs (unsigned NameIdx, MacroExp* E, const Macro* M, in
|
|||||||
while (CollCount (&E->Args) < (unsigned) M->ParamCount) {
|
while (CollCount (&E->Args) < (unsigned) M->ParamCount) {
|
||||||
ME_AppendArg (E, &Arg);
|
ME_AppendArg (E, &Arg);
|
||||||
}
|
}
|
||||||
|
} else if (Parens == 0 && CollCount (&E->Args) > (unsigned) M->ParamCount) {
|
||||||
|
/* Too many arguments */
|
||||||
|
PPError ("Macro \"%s\" passed %u arguments, but takes just %u",
|
||||||
|
M->Name, CollCount (&E->Args), (unsigned) M->ParamCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deallocate argument resources */
|
/* Deallocate argument resources */
|
||||||
@ -2071,6 +2106,12 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
|
|
||||||
/* If we have an identifier, check if it's a macro */
|
/* If we have an identifier, check if it's a macro */
|
||||||
if (IsSym (Ident)) {
|
if (IsSym (Ident)) {
|
||||||
|
/* Check for bad identifier names */
|
||||||
|
if ((ModeFlags & (MSM_MULTILINE | MSM_IN_DIRECTIVE | MSM_IN_ARG_LIST)) != 0 &&
|
||||||
|
(CollCount (&CurRescanStack->Lines) == 1 || CurC == '\0')) {
|
||||||
|
CheckForBadIdent (Ident, IS_Get (&Standard), 0);
|
||||||
|
}
|
||||||
|
|
||||||
if ((ModeFlags & MSM_OP_DEFINED) != 0 && strcmp (Ident, "defined") == 0) {
|
if ((ModeFlags & MSM_OP_DEFINED) != 0 && strcmp (Ident, "defined") == 0) {
|
||||||
/* Handle the "defined" operator */
|
/* Handle the "defined" operator */
|
||||||
int HaveParen = 0;
|
int HaveParen = 0;
|
||||||
@ -2118,7 +2159,6 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
|
|
||||||
/* Check if this is a function-like macro */
|
/* Check if this is a function-like macro */
|
||||||
if (M->ParamCount >= 0) {
|
if (M->ParamCount >= 0) {
|
||||||
int OldPendingNewLines = PendingNewLines;
|
|
||||||
int HaveSpace = SkipWhitespace (MultiLine) > 0;
|
int HaveSpace = SkipWhitespace (MultiLine) > 0;
|
||||||
|
|
||||||
/* A function-like macro name without an immediately
|
/* A function-like macro name without an immediately
|
||||||
@ -2141,32 +2181,50 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
ME_SetTokLens (E, strlen (M->Name));
|
ME_SetTokLens (E, strlen (M->Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Since we have already got on hold of the next
|
||||||
|
** line, we have to reuse it as the next line
|
||||||
|
** instead of reading a new line from the source.
|
||||||
|
*/
|
||||||
|
if (PendingNewLines > 0 && MultiLine) {
|
||||||
|
unsigned I = SB_GetIndex (Line);
|
||||||
|
|
||||||
|
/* There is no way a function-like macro call
|
||||||
|
** detection could span multiple lines within
|
||||||
|
** the range of another just expanded macro.
|
||||||
|
*/
|
||||||
|
CHECK (CollCount (&CurRescanStack->Lines) == 1);
|
||||||
|
|
||||||
|
/* Revert one newline */
|
||||||
|
--PendingNewLines;
|
||||||
|
|
||||||
|
/* Align indention */
|
||||||
|
while (I > 0) {
|
||||||
|
--I;
|
||||||
|
if (SB_GetBuf (Line)[I] == '\n') {
|
||||||
|
++I;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SB_GetBuf (Line)[I] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set start index */
|
||||||
|
SB_SetIndex (Line, I);
|
||||||
|
|
||||||
|
/* Add newlines */
|
||||||
|
AddPreLine (Target);
|
||||||
|
|
||||||
|
/* Reuse this line as the next line */
|
||||||
|
ReuseInputLine ();
|
||||||
|
|
||||||
|
/* Quit this loop */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Append back the whitespace */
|
/* Append back the whitespace */
|
||||||
if (HaveSpace) {
|
if (HaveSpace) {
|
||||||
SB_AppendChar (Target, ' ');
|
SB_AppendChar (Target, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since we have already got on hold of the next
|
|
||||||
** line, we have to go on preprocessing them.
|
|
||||||
*/
|
|
||||||
if (MultiLine) {
|
|
||||||
if (OldPendingNewLines < PendingNewLines && CurC == '#') {
|
|
||||||
/* If we were going to support #pragma in
|
|
||||||
** macro argument list, it would be output
|
|
||||||
** to OLine.
|
|
||||||
*/
|
|
||||||
if (OLine == 0) {
|
|
||||||
OLine = Target;
|
|
||||||
ParseDirectives (ModeFlags);
|
|
||||||
OLine = 0;
|
|
||||||
} else {
|
|
||||||
ParseDirectives (ModeFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Add the source info to preprocessor output if needed */
|
|
||||||
AddPreLine (Target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop */
|
/* Loop */
|
||||||
goto Loop;
|
goto Loop;
|
||||||
}
|
}
|
||||||
@ -2200,8 +2258,36 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
InitLine (TmpTarget);
|
InitLine (TmpTarget);
|
||||||
PushRescanLine (CurRescanStack, TmpTarget, LastTokLen);
|
PushRescanLine (CurRescanStack, TmpTarget, LastTokLen);
|
||||||
|
|
||||||
|
/* Add a space before a '#' at the beginning of the line */
|
||||||
|
if (CurC == '#' &&
|
||||||
|
NextC != '#' &&
|
||||||
|
(SB_IsEmpty (Target) || SB_LookAtLast (Target) == '\n')) {
|
||||||
|
SB_AppendChar (Target, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
/* Switch the buffers */
|
/* Switch the buffers */
|
||||||
TmpTarget = NewStrBuf ();
|
TmpTarget = NewStrBuf ();
|
||||||
|
} else if (PendingNewLines > 0 && MultiLine) {
|
||||||
|
/* Cancel remaining check for pp-tokens separation
|
||||||
|
** if there is since ther have been newlines that
|
||||||
|
** can always separate them.
|
||||||
|
*/
|
||||||
|
if (CurRescanStack->PrevTok != 0) {
|
||||||
|
FreeStrBuf (CurRescanStack->PrevTok);
|
||||||
|
CurRescanStack->PrevTok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Squeeze whitespace */
|
||||||
|
SkipWhitespace (0);
|
||||||
|
|
||||||
|
/* Add indention to preprocessor output if needed */
|
||||||
|
if (CurC != '\0' && CollCount (&CurRescanStack->Lines) == 1) {
|
||||||
|
/* Add newlines */
|
||||||
|
AddPreLine (Target);
|
||||||
|
|
||||||
|
/* Align indention */
|
||||||
|
AppendIndent (Target, SB_GetIndex (Line));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since we are rescanning, we needn't add the
|
/* Since we are rescanning, we needn't add the
|
||||||
@ -2241,7 +2327,24 @@ static unsigned ReplaceMacros (StrBuf* Source, StrBuf* Target, MacroExp* E, unsi
|
|||||||
} else if (IsQuotedString ()) {
|
} else if (IsQuotedString ()) {
|
||||||
CopyQuotedString (Target);
|
CopyQuotedString (Target);
|
||||||
} else {
|
} else {
|
||||||
Skipped = SkipWhitespace (0);
|
/* We want to squeeze whitespace until the end of the current
|
||||||
|
** input line, so we have to deal with such cases specially.
|
||||||
|
*/
|
||||||
|
if (CollCount (&CurRescanStack->Lines) > 1) {
|
||||||
|
RescanInputStack* RIS = CurRescanStack;
|
||||||
|
|
||||||
|
/* Temporarily disable input popping */
|
||||||
|
CurRescanStack = 0;
|
||||||
|
Skipped = SkipWhitespace (0);
|
||||||
|
CurRescanStack = RIS;
|
||||||
|
|
||||||
|
if (CurC == '\0') {
|
||||||
|
/* Now we are at the end of the input line */
|
||||||
|
goto Loop;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Skipped = SkipWhitespace (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Punctuators must be checked after whitespace since comments
|
/* Punctuators must be checked after whitespace since comments
|
||||||
** introducers may be misinterpreted as division operators.
|
** introducers may be misinterpreted as division operators.
|
||||||
@ -2284,6 +2387,19 @@ Loop:
|
|||||||
if (CurC == '\0' && CollCount (&CurRescanStack->Lines) > 1) {
|
if (CurC == '\0' && CollCount (&CurRescanStack->Lines) > 1) {
|
||||||
/* Check for rescan sequence end and pp-token pasting */
|
/* Check for rescan sequence end and pp-token pasting */
|
||||||
Skipped = SkipWhitespace (0) || Skipped;
|
Skipped = SkipWhitespace (0) || Skipped;
|
||||||
|
|
||||||
|
/* Add indention to preprocessor output if needed */
|
||||||
|
if (CurC != '\0' &&
|
||||||
|
PendingNewLines > 0 &&
|
||||||
|
(ModeFlags & MSM_MULTILINE) != 0 &&
|
||||||
|
CollCount (&CurRescanStack->Lines) == 1) {
|
||||||
|
/* Add newlines */
|
||||||
|
AddPreLine (Target);
|
||||||
|
|
||||||
|
/* Align indention */
|
||||||
|
AppendIndent (Target, SB_GetIndex (Line));
|
||||||
|
Skipped = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append a space if there hasn't been one */
|
/* Append a space if there hasn't been one */
|
||||||
@ -2338,6 +2454,7 @@ static int ParseMacroReplacement (StrBuf* Source, Macro* M)
|
|||||||
int HasWhiteSpace = 0;
|
int HasWhiteSpace = 0;
|
||||||
unsigned Len;
|
unsigned Len;
|
||||||
ident Ident;
|
ident Ident;
|
||||||
|
int Std = IS_Get (&Standard);
|
||||||
|
|
||||||
/* Skip whitespace before the macro replacement */
|
/* Skip whitespace before the macro replacement */
|
||||||
SkipWhitespace (0);
|
SkipWhitespace (0);
|
||||||
@ -2355,6 +2472,9 @@ static int ParseMacroReplacement (StrBuf* Source, Macro* M)
|
|||||||
SB_AppendChar (&M->Replacement, ' ');
|
SB_AppendChar (&M->Replacement, ' ');
|
||||||
} else if (IsQuotedString ()) {
|
} else if (IsQuotedString ()) {
|
||||||
CopyQuotedString (&M->Replacement);
|
CopyQuotedString (&M->Replacement);
|
||||||
|
} else if (IsSym (Ident)) {
|
||||||
|
CheckForBadIdent (Ident, Std, M);
|
||||||
|
SB_AppendStr (&M->Replacement, Ident);
|
||||||
} else {
|
} else {
|
||||||
if (M->ParamCount >= 0 && GetPunc (Ident)) {
|
if (M->ParamCount >= 0 && GetPunc (Ident)) {
|
||||||
Len = strlen (Ident);
|
Len = strlen (Ident);
|
||||||
@ -2423,7 +2543,7 @@ static void DoDefine (void)
|
|||||||
ident Ident;
|
ident Ident;
|
||||||
Macro* M = 0;
|
Macro* M = 0;
|
||||||
Macro* Existing;
|
Macro* Existing;
|
||||||
int C89;
|
int Std;
|
||||||
|
|
||||||
/* Read the macro name */
|
/* Read the macro name */
|
||||||
SkipWhitespace (0);
|
SkipWhitespace (0);
|
||||||
@ -2431,8 +2551,8 @@ static void DoDefine (void)
|
|||||||
goto Error_Handler;
|
goto Error_Handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember if we're in C89 mode */
|
/* Remember the language standard we are in */
|
||||||
C89 = (IS_Get (&Standard) == STD_C89);
|
Std = IS_Get (&Standard);
|
||||||
|
|
||||||
/* Check for forbidden macro names */
|
/* Check for forbidden macro names */
|
||||||
if (strcmp (Ident, "defined") == 0) {
|
if (strcmp (Ident, "defined") == 0) {
|
||||||
@ -2440,6 +2560,9 @@ static void DoDefine (void)
|
|||||||
goto Error_Handler;
|
goto Error_Handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for and warn on special identifiers */
|
||||||
|
CheckForBadIdent (Ident, Std, 0);
|
||||||
|
|
||||||
/* Create a new macro definition */
|
/* Create a new macro definition */
|
||||||
M = NewMacro (Ident);
|
M = NewMacro (Ident);
|
||||||
|
|
||||||
@ -2464,7 +2587,7 @@ static void DoDefine (void)
|
|||||||
/* The next token must be either an identifier, or - if not in
|
/* The next token must be either an identifier, or - if not in
|
||||||
** C89 mode - the ellipsis.
|
** C89 mode - the ellipsis.
|
||||||
*/
|
*/
|
||||||
if (!C89 && CurC == '.') {
|
if (Std >= STD_C99 && CurC == '.') {
|
||||||
/* Ellipsis */
|
/* Ellipsis */
|
||||||
NextChar ();
|
NextChar ();
|
||||||
if (CurC != '.' || NextC != '.') {
|
if (CurC != '.' || NextC != '.') {
|
||||||
@ -2486,11 +2609,8 @@ static void DoDefine (void)
|
|||||||
goto Error_Handler;
|
goto Error_Handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* __VA_ARGS__ is only allowed in post-C89 mode */
|
/* Check for and warn on special identifiers */
|
||||||
if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) {
|
CheckForBadIdent (Ident, Std, 0);
|
||||||
PPWarning ("'__VA_ARGS__' can only appear in the expansion "
|
|
||||||
"of a C99 variadic macro");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the macro parameter */
|
/* Add the macro parameter */
|
||||||
AddMacroParam (M, Ident);
|
AddMacroParam (M, Ident);
|
||||||
@ -2665,6 +2785,7 @@ static int DoIfDef (int skip, int flag)
|
|||||||
|
|
||||||
SkipWhitespace (0);
|
SkipWhitespace (0);
|
||||||
if (MacName (Ident)) {
|
if (MacName (Ident)) {
|
||||||
|
CheckForBadIdent (Ident, IS_Get (&Standard), 0);
|
||||||
Value = IsMacro (Ident);
|
Value = IsMacro (Ident);
|
||||||
/* Check for extra tokens */
|
/* Check for extra tokens */
|
||||||
CheckExtraTokens (flag ? "ifdef" : "ifndef");
|
CheckExtraTokens (flag ? "ifdef" : "ifndef");
|
||||||
@ -2871,6 +2992,7 @@ static void DoUndef (void)
|
|||||||
|
|
||||||
SkipWhitespace (0);
|
SkipWhitespace (0);
|
||||||
if (MacName (Ident)) {
|
if (MacName (Ident)) {
|
||||||
|
CheckForBadIdent (Ident, IS_Get (&Standard), 0);
|
||||||
UndefineMacro (Ident);
|
UndefineMacro (Ident);
|
||||||
}
|
}
|
||||||
/* Check for extra tokens */
|
/* Check for extra tokens */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user