Merge pull request #1834 from acqn/PPFix

[cc65] Minor improvements, fixes and cleanups with the preprocessor
This commit is contained in:
Bob Andrews
2022-08-21 19:18:46 +02:00
committed by GitHub

View File

@@ -67,6 +67,17 @@
/* Macro scanner mode flags */
#define MSM_NONE 0x00U /* Default */
#define MSM_MULTILINE 0x01U /* Read from multiple lines */
#define MSM_IN_DIRECTIVE 0x02U /* In PP directives scan */
#define MSM_IN_ARG_LIST 0x04U /* In macro argument scan */
#define MSM_IN_ARG_EXPANSION 0x08U /* In expansion on arguments */
#define MSM_OP_DEFINED 0x10U /* Handle the defined operator */
#define MSM_OP_HAS_INCLUDE 0x20U /* Handle the __has_include operator */
#define MSM_OP_HAS_C_ATTRIBUTE 0x40U /* Handle the __has_c_attribute operator */
#define MSM_TOK_HEADER 0x80U /* Support header tokens */
/* Management data for #if */ /* Management data for #if */
#define IFCOND_NONE 0x00U #define IFCOND_NONE 0x00U
#define IFCOND_SKIP 0x01U #define IFCOND_SKIP 0x01U
@@ -105,13 +116,16 @@ static void TranslationPhase3 (StrBuf* Source, StrBuf* Target);
** non-newline whitespace sequences. ** non-newline whitespace sequences.
*/ */
static int ParseDirectives (int InArgList); static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFlags);
/* Handle directives. Return 1 if there are directives parsed, -1 if new lines /* Preprocess a single line. Handle specified tokens and operators, remove
** are read, otherwise 0. ** whitespace and comments, then do macro replacement.
*/ */
static void MacroReplacement (StrBuf* Source, StrBuf* Target, int MultiLine); static int ParseDirectives (unsigned ModeFlags);
/* Perform macro replacement. */ /* Handle directives. Return 1 if any whitespace or newlines are parsed. */
static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags);
/* Scan for and perform macro replacement */
@@ -121,67 +135,67 @@ static void MacroReplacement (StrBuf* Source, StrBuf* Target, int MultiLine);
/* Types of preprocessor tokens */ /* Types of preprocessor directives */
typedef enum { typedef enum {
PP_ILLEGAL = -1, PPD_ILLEGAL = -1,
PP_DEFINE, PPD_DEFINE,
PP_ELIF, PPD_ELIF,
PP_ELSE, PPD_ELSE,
PP_ENDIF, PPD_ENDIF,
PP_ERROR, PPD_ERROR,
PP_IF, PPD_IF,
PP_IFDEF, PPD_IFDEF,
PP_IFNDEF, PPD_IFNDEF,
PP_INCLUDE, PPD_INCLUDE,
PP_LINE, PPD_LINE,
PP_PRAGMA, PPD_PRAGMA,
PP_UNDEF, PPD_UNDEF,
PP_WARNING, PPD_WARNING,
} pptoken_t; } ppdirective_t;
/* Preprocessor keyword to token mapping table */ /* Preprocessor directive tokens mapping table */
static const struct PPToken { static const struct PPDType {
const char* Key; /* Keyword */ const char* Tok; /* Token */
pptoken_t Tok; /* Token */ ppdirective_t Type; /* Type */
} PPTokens[] = { } PPDTypes[] = {
{ "define", PP_DEFINE }, { "define", PPD_DEFINE },
{ "elif", PP_ELIF }, { "elif", PPD_ELIF },
{ "else", PP_ELSE }, { "else", PPD_ELSE },
{ "endif", PP_ENDIF }, { "endif", PPD_ENDIF },
{ "error", PP_ERROR }, { "error", PPD_ERROR },
{ "if", PP_IF }, { "if", PPD_IF },
{ "ifdef", PP_IFDEF }, { "ifdef", PPD_IFDEF },
{ "ifndef", PP_IFNDEF }, { "ifndef", PPD_IFNDEF },
{ "include", PP_INCLUDE }, { "include", PPD_INCLUDE },
{ "line", PP_LINE }, { "line", PPD_LINE },
{ "pragma", PP_PRAGMA }, { "pragma", PPD_PRAGMA },
{ "undef", PP_UNDEF }, { "undef", PPD_UNDEF },
{ "warning", PP_WARNING }, { "warning", PPD_WARNING },
}; };
/* Number of preprocessor tokens */ /* Number of preprocessor directive types */
#define PPTOKEN_COUNT (sizeof(PPTokens) / sizeof(PPTokens[0])) #define PPDTOKEN_COUNT (sizeof(PPDTypes) / sizeof(PPDTypes[0]))
static int CmpToken (const void* Key, const void* Elem) static int CmpToken (const void* Key, const void* Elem)
/* Compare function for bsearch */ /* Compare function for bsearch */
{ {
return strcmp ((const char*) Key, ((const struct PPToken*) Elem)->Key); return strcmp ((const char*) Key, ((const struct PPDType*) Elem)->Tok);
} }
static pptoken_t FindPPToken (const char* Ident) static ppdirective_t FindPPDirectiveType (const char* Ident)
/* Find a preprocessor token and return it. Return PP_ILLEGAL if the identifier /* Find a preprocessor directive type and return it. Return PPD_ILLEGAL if the
** is not a valid preprocessor token. ** identifier is not a valid preprocessor directive token.
*/ */
{ {
struct PPToken* P; struct PPDType* P;
P = bsearch (Ident, PPTokens, PPTOKEN_COUNT, sizeof (PPTokens[0]), CmpToken); P = bsearch (Ident, PPDTypes, PPDTOKEN_COUNT, sizeof (PPDTypes[0]), CmpToken);
return P? P->Tok : PP_ILLEGAL; return P? P->Type : PPD_ILLEGAL;
} }
@@ -257,6 +271,26 @@ static int ME_ArgIsVariadic (const MacroExp* E, const Macro* M)
static int MacName (char* Ident)
/* Get a macro symbol name into Ident. If we have an error, print a
** diagnostic message and clear the line.
*/
{
if (IsSym (Ident) == 0) {
if (CurC != '\0') {
PPError ("Macro name must be an identifier");
} else {
PPError ("Missing macro name");
}
ClearLine ();
return 0;
} else {
return 1;
}
}
static void AddPreLine (StrBuf* Str) static void AddPreLine (StrBuf* Str)
/* Add newlines to the string buffer */ /* Add newlines to the string buffer */
{ {
@@ -265,7 +299,7 @@ static void AddPreLine (StrBuf* Str)
return; return;
} }
if (FileChanged || PendingNewLines > 4) { if (FileChanged || PendingNewLines > 6) {
/* Output #line directives as source info */ /* Output #line directives as source info */
StrBuf Comment = AUTO_STRBUF_INITIALIZER; StrBuf Comment = AUTO_STRBUF_INITIALIZER;
if (SB_NotEmpty (Str) && SB_LookAtLast (Str) != '\n') { if (SB_NotEmpty (Str) && SB_LookAtLast (Str) != '\n') {
@@ -502,26 +536,6 @@ static int CheckExtraTokens (const char* Name)
static int MacName (char* Ident)
/* Get a macro symbol name into Ident. If we have an error, print a
** diagnostic message and clear the line.
*/
{
if (IsSym (Ident) == 0) {
if (CurC != '\0') {
PPError ("Macro name must be an identifier");
} else {
PPError ("Missing macro name");
}
ClearLine ();
return 0;
} else {
return 1;
}
}
static void ReadMacroArgs (MacroExp* E, const Macro* M, 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 */
{ {
@@ -545,7 +559,7 @@ static void ReadMacroArgs (MacroExp* E, const Macro* M, int MultiLine)
Newlines += PendingNewLines - OldPendingNewLines; Newlines += PendingNewLines - OldPendingNewLines;
PendingNewLines = OldPendingNewLines; PendingNewLines = OldPendingNewLines;
OldPendingNewLines = 0; OldPendingNewLines = 0;
Skipped = ParseDirectives (1) || Skipped; Skipped = ParseDirectives (MSM_IN_ARG_LIST) || Skipped;
Skipped = SkipWhitespace (MultiLine) || Skipped; Skipped = SkipWhitespace (MultiLine) || Skipped;
} }
PendingNewLines += Newlines; PendingNewLines += Newlines;
@@ -637,7 +651,7 @@ static void ReadMacroArgs (MacroExp* E, const Macro* M, int MultiLine)
static void MacroArgSubst (MacroExp* E, Macro* M) static void SubstMacroArgs (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;
@@ -792,7 +806,7 @@ static void ExpandMacro (StrBuf* Target, Macro* M, int MultiLine)
} }
/* Replace macro arguments handling the # and ## operators */ /* Replace macro arguments handling the # and ## operators */
MacroArgSubst (&E, M); SubstMacroArgs (&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;
@@ -809,122 +823,89 @@ static void ExpandMacro (StrBuf* Target, Macro* M, int MultiLine)
/*****************************************************************************/ static void MacroReplacement (StrBuf* Source, StrBuf* Target, unsigned ModeFlags)
/* Preprocessing */ /* Scan for and perform macro replacement */
/*****************************************************************************/
static void TranslationPhase3 (StrBuf* Source, StrBuf* Target)
/* Mimic Translation Phase 3. Handle old and new style comments. Collapse
** non-newline whitespace sequences.
*/
{ {
/* Switch to the new input source */
StrBuf* OldSource = InitLine (Source);
/* Loop removing ws and comments */
while (CurC != '\0') {
int HasWhiteSpace = 0;
while (1) {
/* Squeeze runs of blanks */
if (IsSpace (CurC)) {
NextChar ();
HasWhiteSpace = 1;
} else if (CurC == '/' && NextC == '*') {
OldStyleComment ();
HasWhiteSpace = 1;
} else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
NewStyleComment ();
HasWhiteSpace = 1;
} else {
/* No more white space */
break;
}
}
if (HasWhiteSpace) {
SB_AppendChar (Target, ' ');
} else if (IsQuote (CurC)) {
CopyQuotedString (Target);
} else {
SB_AppendChar (Target, CurC);
NextChar ();
}
}
/* Terminate the new input line */
SB_Terminate (Target);
/* Switch back to the old source */
InitLine (OldSource);
}
static void ProcessSingleLine (StrBuf* Source,
StrBuf* Target,
int HandleDefined,
int HandleHeader)
/* Process a single line. Remove whitespace, old and new style comments.
** Recognize and handle the "defined" operator if HandleDefined is true.
** Recognize and handle header name tokens if HandleHeader is true.
*/
{
int OldIndex = SB_GetIndex (Source);
ident Ident; ident Ident;
int HaveParen;
/* Operate on the new input source */ /* Remember the current input and switch to Source */
StrBuf* OldSource = InitLine (Source); StrBuf* OldSource = InitLine (Source);
SkipWhitespace (0); /* Loop substituting macros */
/* Loop removing ws and comments */
while (CurC != '\0') { while (CurC != '\0') {
if (SkipWhitespace (0)) { /* If we have an identifier, check if it's a macro */
/* Squeeze runs of blanks */ if (IsSym (Ident)) {
if (!IsSpace (SB_LookAtLast (Target))) { if ((ModeFlags & MSM_OP_DEFINED) != 0 && strcmp (Ident, "defined") == 0) {
SB_AppendChar (Target, ' ');
}
} else if (IsSym (Ident)) {
if (HandleDefined && strcmp (Ident, "defined") == 0) {
/* Handle the "defined" operator */ /* Handle the "defined" operator */
int HaveParen = 0;
SkipWhitespace (0); SkipWhitespace (0);
HaveParen = 0;
if (CurC == '(') { if (CurC == '(') {
HaveParen = 1; HaveParen = 1;
NextChar (); NextChar ();
SkipWhitespace (0); SkipWhitespace (0);
} }
if (IsSym (Ident)) { if (IsSym (Ident)) {
SB_AppendChar (Target, IsMacro (Ident)? '1' : '0'); /* Eat the identifier */
SB_AppendChar (Target, IsMacro (Ident) ? '1' : '0');
if (HaveParen) { if (HaveParen) {
SkipWhitespace (0); SkipWhitespace (0);
if (CurC != ')') { if (CurC != ')') {
PPError ("')' expected"); PPError ("')' expected");
ClearLine ();
} else { } else {
NextChar (); NextChar ();
} }
} }
} else { } else {
PPError ("Identifier expected"); PPError ("Macro name must be an identifier");
ClearLine ();
SB_AppendChar (Target, '0'); SB_AppendChar (Target, '0');
} }
} else { } else {
/* Check if it's an expandable macro */
Macro* M = FindMacro (Ident); Macro* M = FindMacro (Ident);
if (M != 0 && !M->Expanding) { if (M != 0 && !M->Expanding) {
/* Check if this is a function-like macro */ /* Check if this is a function-like macro */
if (M->ArgCount >= 0) { if (M->ArgCount >= 0) {
int Whitespace = SkipWhitespace (0); int MultiLine = (ModeFlags & MSM_MULTILINE) != 0;
int Whitespace = SkipWhitespace (MultiLine);
if (CurC != '(') { if (CurC != '(') {
/* Function-like macro without an argument list is not replaced */ /* Function-like macro without an argument list is not replaced */
SB_AppendStr (Target, M->Name); SB_AppendStr (Target, M->Name);
if (Whitespace) { if (Whitespace > 0) {
SB_AppendChar (Target, ' '); SB_AppendChar (Target, ' ');
} }
/* Directives can only be found in an argument list
** that spans multiple lines.
*/
if (MultiLine) {
if (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);
}
} else { } else {
/* Function-like macro */ /* Function-like macro */
ExpandMacro (Target, M, 0); if (OLine == 0) {
OLine = Target;
ExpandMacro (Target, M, MultiLine);
OLine = 0;
} else {
ExpandMacro (Target, M, MultiLine);
}
} }
} else { } else {
/* Object-like macro */ /* Object-like macro */
@@ -935,99 +916,26 @@ static void ProcessSingleLine (StrBuf* Source,
SB_AppendStr (Target, Ident); SB_AppendStr (Target, Ident);
} }
} }
} else if (HandleHeader && (CurC == '<' || CurC == '\"')) {
CopyHeaderNameToken (Target);
} else if (IsQuote (CurC)) {
CopyQuotedString (Target);
} else { } else {
SB_AppendChar (Target, CurC); if ((ModeFlags & MSM_TOK_HEADER) != 0 && (CurC == '<' || CurC == '\"')) {
NextChar (); CopyHeaderNameToken (Target);
} else if (IsQuote (CurC)) {
CopyQuotedString (Target);
} else {
int Whitespace = SkipWhitespace (0);
if (Whitespace) {
SB_AppendChar (Target, ' ');
} else {
SB_AppendChar (Target, CurC);
NextChar ();
}
}
} }
} }
/* Switch back to the old source */ /* Drop whitespace at the end */
InitLine (OldSource); if (IsBlank (SB_LookAtLast (Target))) {
SB_Drop (Target, 1);
/* Restore the source input index */
SB_SetIndex (Source, OldIndex);
}
static void MacroReplacement (StrBuf* Source, StrBuf* Target, int MultiLine)
/* Perform macro replacement. */
{
ident Ident;
Macro* M;
/* Remember the current input and switch to Source */
StrBuf* OldSource = InitLine (Source);
/* Loop substituting macros */
while (CurC != '\0') {
/* If we have an identifier, check if it's a macro */
if (IsSym (Ident)) {
/* Check if it's a macro */
if ((M = FindMacro (Ident)) != 0 && !M->Expanding) {
/* Check if this is a function-like macro */
if (M->ArgCount >= 0) {
int Whitespace = SkipWhitespace (MultiLine);
if (CurC != '(') {
/* Function-like macro without an argument list is not replaced */
SB_AppendStr (Target, M->Name);
if (Whitespace > 0) {
SB_AppendChar (Target, ' ');
}
/* Directives can only be found in an argument list
** that spans multiple lines.
*/
if (MultiLine) {
if (CurC == '#') {
/* If we were going to support #pragma in
** macro argument list, it would be output
** to OLine.
*/
if (OLine == 0) {
OLine = Target;
ParseDirectives (0);
OLine = 0;
} else {
ParseDirectives (0);
}
}
/* Add the source info to preprocessor output if needed */
AddPreLine (Target);
}
} else {
/* Function-like macro */
if (OLine == 0) {
OLine = Target;
ExpandMacro (Target, M, MultiLine);
OLine = 0;
} else {
ExpandMacro (Target, M, MultiLine);
}
}
} else {
/* Object-like macro */
ExpandMacro (Target, M, 0);
}
} else {
/* An identifier, keep it */
SB_AppendStr (Target, Ident);
}
} else if (IsQuote (CurC)) {
CopyQuotedString (Target);
} else {
int Whitespace = SkipWhitespace (0);
if (Whitespace) {
SB_AppendChar (Target, ' ');
} else {
SB_AppendChar (Target, CurC);
NextChar ();
}
}
} }
/* Switch back the input */ /* Switch back the input */
@@ -1036,6 +944,12 @@ static void MacroReplacement (StrBuf* Source, StrBuf* Target, int MultiLine)
/*****************************************************************************/
/* Directives */
/*****************************************************************************/
static void DoDefine (void) static void DoDefine (void)
/* Process #define directive */ /* Process #define directive */
{ {
@@ -1254,7 +1168,7 @@ static int DoIf (int Skip)
/* Macro-replace a single line with support for the "defined" operator */ /* Macro-replace a single line with support for the "defined" operator */
SB_Clear (MLine); SB_Clear (MLine);
ProcessSingleLine (Line, MLine, 1, 0); PreprocessDirective (Line, MLine, MSM_OP_DEFINED);
/* Read from the processed line */ /* Read from the processed line */
SB_Reset (MLine); SB_Reset (MLine);
@@ -1318,7 +1232,7 @@ static void DoInclude (void)
/* Macro-replace a single line with special support for <filename> */ /* Macro-replace a single line with special support for <filename> */
SB_Clear (MLine); SB_Clear (MLine);
ProcessSingleLine (Line, MLine, 0, 1); PreprocessDirective (Line, MLine, MSM_TOK_HEADER);
/* Read from the processed line */ /* Read from the processed line */
SB_Reset (MLine); SB_Reset (MLine);
@@ -1340,7 +1254,7 @@ static void DoInclude (void)
break; break;
default: default:
PPError ("'\"' or '<' expected"); PPError ("#include expects \"FILENAME\" or <FILENAME>");
goto Done; goto Done;
} }
NextChar (); NextChar ();
@@ -1360,7 +1274,7 @@ static void DoInclude (void)
CheckExtraTokens ("include"); CheckExtraTokens ("include");
/* Open the include file */ /* Open the include file */
OpenIncludeFile (SB_GetConstBuf (&Filename), IT); OpenIncludeFile (SB_GetConstBuf (&Filename), IT);
} else if (CurC == '\0') { } else {
/* No terminator found */ /* No terminator found */
PPError ("#include expects \"FILENAME\" or <FILENAME>"); PPError ("#include expects \"FILENAME\" or <FILENAME>");
} }
@@ -1394,7 +1308,7 @@ static void DoPragma (void)
/* Macro-replace a single line */ /* Macro-replace a single line */
SB_Clear (MLine); SB_Clear (MLine);
ProcessSingleLine (Line, MLine, 0, 0); PreprocessDirective (Line, MLine, MSM_NONE);
/* Convert #pragma to _Pragma () */ /* Convert #pragma to _Pragma () */
SB_AppendStr (PragmaLine, "_Pragma ("); SB_AppendStr (PragmaLine, "_Pragma (");
@@ -1442,7 +1356,7 @@ static void DoWarning (void)
static int ParseDirectives (int InArgList) 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. */
{ {
int PPSkip = 0; int PPSkip = 0;
@@ -1468,15 +1382,15 @@ static int ParseDirectives (int InArgList)
} }
ClearLine (); ClearLine ();
} else { } else {
switch (FindPPToken (Directive)) { switch (FindPPDirectiveType (Directive)) {
case PP_DEFINE: case PPD_DEFINE:
if (!PPSkip) { if (!PPSkip) {
DoDefine (); DoDefine ();
} }
break; break;
case PP_ELIF: case PPD_ELIF:
if (PPStack->Index >= 0) { if (PPStack->Index >= 0) {
if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) { if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) {
/* Handle as #else/#if combination */ /* Handle as #else/#if combination */
@@ -1496,7 +1410,7 @@ static int ParseDirectives (int InArgList)
} }
break; break;
case PP_ELSE: case PPD_ELSE:
if (PPStack->Index >= 0) { if (PPStack->Index >= 0) {
if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) { if ((PPStack->Stack[PPStack->Index] & IFCOND_ELSE) == 0) {
if ((PPStack->Stack[PPStack->Index] & IFCOND_SKIP) == 0) { if ((PPStack->Stack[PPStack->Index] & IFCOND_SKIP) == 0) {
@@ -1514,7 +1428,7 @@ static int ParseDirectives (int InArgList)
} }
break; break;
case PP_ENDIF: case PPD_ENDIF:
if (PPStack->Index >= 0) { if (PPStack->Index >= 0) {
/* Remove any clauses on top of stack that do not /* Remove any clauses on top of stack that do not
** need a terminating #endif. ** need a terminating #endif.
@@ -1537,40 +1451,40 @@ static int ParseDirectives (int InArgList)
} }
break; break;
case PP_ERROR: case PPD_ERROR:
if (!PPSkip) { if (!PPSkip) {
DoError (); DoError ();
} }
break; break;
case PP_IF: case PPD_IF:
PPSkip = DoIf (PPSkip); PPSkip = DoIf (PPSkip);
break; break;
case PP_IFDEF: case PPD_IFDEF:
PPSkip = DoIfDef (PPSkip, 1); PPSkip = DoIfDef (PPSkip, 1);
break; break;
case PP_IFNDEF: case PPD_IFNDEF:
PPSkip = DoIfDef (PPSkip, 0); PPSkip = DoIfDef (PPSkip, 0);
break; break;
case PP_INCLUDE: case PPD_INCLUDE:
if (!PPSkip) { if (!PPSkip) {
DoInclude (); DoInclude ();
} }
break; break;
case PP_LINE: case PPD_LINE:
/* Should do something in C99 at least, but we ignore it */ /* Should do something in C99 at least, but we ignore it */
if (!PPSkip) { if (!PPSkip) {
ClearLine (); ClearLine ();
} }
break; break;
case PP_PRAGMA: case PPD_PRAGMA:
if (!PPSkip) { if (!PPSkip) {
if (!InArgList) { if ((ModeFlags & MSM_IN_ARG_LIST) == 0) {
DoPragma (); DoPragma ();
} else { } else {
PPError ("Embedded #pragma directive within macro arguments is unsupported"); PPError ("Embedded #pragma directive within macro arguments is unsupported");
@@ -1578,13 +1492,13 @@ static int ParseDirectives (int InArgList)
} }
break; break;
case PP_UNDEF: case PPD_UNDEF:
if (!PPSkip) { if (!PPSkip) {
DoUndef (); DoUndef ();
} }
break; break;
case PP_WARNING: case PPD_WARNING:
/* #warning is a non standard extension */ /* #warning is a non standard extension */
if (IS_Get (&Standard) > STD_C99) { if (IS_Get (&Standard) > STD_C99) {
if (!PPSkip) { if (!PPSkip) {
@@ -1619,6 +1533,77 @@ static int ParseDirectives (int InArgList)
/*****************************************************************************/
/* Preprocessing */
/*****************************************************************************/
static void TranslationPhase3 (StrBuf* Source, StrBuf* Target)
/* Mimic Translation Phase 3. Handle old and new style comments. Collapse
** non-newline whitespace sequences.
*/
{
/* Switch to the new input source */
StrBuf* OldSource = InitLine (Source);
/* Loop removing ws and comments */
while (CurC != '\0') {
int HasWhiteSpace = 0;
while (1) {
/* Squeeze runs of blanks */
if (IsSpace (CurC)) {
NextChar ();
HasWhiteSpace = 1;
} else if (CurC == '/' && NextC == '*') {
OldStyleComment ();
HasWhiteSpace = 1;
} else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
NewStyleComment ();
HasWhiteSpace = 1;
} else {
/* No more white space */
break;
}
}
if (HasWhiteSpace) {
SB_AppendChar (Target, ' ');
} else if (IsQuote (CurC)) {
CopyQuotedString (Target);
} else {
SB_AppendChar (Target, CurC);
NextChar ();
}
}
/* Terminate the new input line */
SB_Terminate (Target);
/* Switch back to the old source */
InitLine (OldSource);
}
static void PreprocessDirective (StrBuf* Source, StrBuf* Target, unsigned ModeFlags)
/* Preprocess a single line. Handle specified tokens and operators, remove
** whitespace and comments, then do macro replacement.
*/
{
int OldIndex = SB_GetIndex (Source);
MacroExp E;
SkipWhitespace (0);
InitMacroExp (&E);
MacroReplacement (Source, Target, ModeFlags | MSM_IN_DIRECTIVE);
DoneMacroExp (&E);
/* Restore the source input index */
SB_SetIndex (Source, OldIndex);
}
void Preprocess (void) void Preprocess (void)
/* Preprocess lines count of which is affected by directives */ /* Preprocess lines count of which is affected by directives */
{ {
@@ -1629,7 +1614,7 @@ void Preprocess (void)
/* Parse any directives */ /* Parse any directives */
OLine = PLine; OLine = PLine;
ParseDirectives (0); ParseDirectives (MSM_MULTILINE);
OLine = 0; OLine = 0;
/* Add the source info to preprocessor output if needed */ /* Add the source info to preprocessor output if needed */
@@ -1639,7 +1624,7 @@ void Preprocess (void)
AppendIndent (PLine, SB_GetIndex (Line)); AppendIndent (PLine, SB_GetIndex (Line));
/* Expand macros if any */ /* Expand macros if any */
MacroReplacement (Line, PLine, 1); MacroReplacement (Line, PLine, MSM_MULTILINE);
/* Add the source info to preprocessor output if needed */ /* Add the source info to preprocessor output if needed */
AddPreLine (PLine); AddPreLine (PLine);