/* common */
#include "chartype.h"
#include "check.h"
+#include "inline.h"
#include "print.h"
#include "xmalloc.h"
static char* mline = mlinebuf;
static char* mptr;
-/* Flag: Expand macros in this line */
-static int ExpandMacros = 1;
-
/*****************************************************************************/
-static void keepch (char c)
+#ifdef HAVE_INLINE
+INLINE void KeepChar (char c)
/* Put character c into translation buffer. */
{
*mptr++ = c;
}
+#else
+#define KeepChar(c) *mptr++ = (c)
+#endif
-static void keepstr (const char* S)
+static void KeepStr (const char* S)
/* Put string str into translation buffer. */
{
unsigned Len = strlen (S);
+static void Stringize (const char* S)
+/* Stringize the given string: Add double quotes at start and end and preceed
+ * each occurance of " and \ by a backslash.
+ */
+{
+ KeepChar ('\"');
+ /* Replace any characters inside the string may not be part of a string
+ * unescaped.
+ */
+ while (*S) {
+ switch (*S) {
+ case '\"':
+ case '\\':
+ KeepChar ('\\');
+ /* FALLTHROUGH */
+ default:
+ KeepChar (*S);
+ break;
+ }
+ ++S;
+ }
+ KeepChar ('\"');
+}
+
+
+
+static void SwapLineBuffers (void)
+/* Swap both line buffers */
+{
+ /* Swap mline and line */
+ char* p = line;
+ line = mline;
+ mline = p;
+}
+
+
+
static void OldStyleComment (void)
/* Remove an old style C comment from line. */
{
/* Copy the characters inside the string */
while (CurC != '\0' && CurC != Quote) {
/* Keep an escaped char */
- if (CurC == '\\') {
+ if (CurC == '\\') {
*Target++ = CurC;
NextChar ();
}
Replacement = FindMacroArg (M, Ident);
if (Replacement) {
/* Macro arg, keep the replacement */
- keepstr (Replacement);
+ KeepStr (Replacement);
} else {
/* No macro argument, keep the original identifier */
- keepstr (Ident);
+ KeepStr (Ident);
}
} else if (CurC == '#' && IsIdent (NextC)) {
NextChar ();
SymName (Ident);
Replacement = FindMacroArg (M, Ident);
if (Replacement) {
- keepch ('\"');
- /* We have to escape any characters inside replacement that
- * may not be part of a string unescaped.
- */
- while (*Replacement) {
- switch (*Replacement) {
- case '\"':
- case '\\':
- case '\'':
- keepch ('\\');
- /* FALLTHROUGH */
- default:
- keepch (*Replacement);
- break;
- }
- ++Replacement;
- }
- keepch ('\"');
+ /* Make a valid string from Replacement */
+ Stringize (Replacement);
} else {
- keepch ('#');
- keepstr (Ident);
+ /* No replacement - keep the input */
+ KeepChar ('#');
+ KeepStr (Ident);
}
} else if (IsQuote (CurC)) {
mptr = CopyQuotedString (mptr);
} else {
- *mptr++ = CurC;
+ KeepChar (CurC);
NextChar ();
}
}
ArgStart = B;
NextChar ();
} else {
- /* Comma or right paren inside nested parenthesis */
+ /* Comma or right paren inside nested parenthesis */
if (CurC == ')') {
--ParCount;
}
*B++ = CurC;
- NextChar ();
+ NextChar ();
}
} else if (IsBlank (CurC)) {
/* Squeeze runs of blanks */
}
} else {
/* Just copy the replacement text */
- keepstr (M->Replacement);
+ KeepStr (M->Replacement);
}
}
done = 1;
while (CurC != '\0') {
if (IsBlank (CurC)) {
- keepch (' ');
+ KeepChar (' ');
SkipBlank ();
} else if (IsIdent (CurC)) {
SymName (Ident);
}
if (!IsIdent (CurC)) {
PPError ("Identifier expected");
- *mptr++ = '0';
+ KeepChar ('0');
} else {
SymName (Ident);
- *mptr++ = IsMacro (Ident)? '1' : '0';
+ KeepChar (IsMacro (Ident)? '1' : '0');
if (HaveParen) {
SkipBlank();
if (CurC != ')') {
PPError ("`)' expected");
- } else {
+ } else {
NextChar ();
}
}
if (MaybeMacro (Ident[0])) {
done = 0;
}
- keepstr (Ident);
+ KeepStr (Ident);
}
} else if (IsQuote (CurC)) {
mptr = CopyQuotedString (mptr);
} else if (CurC == '/' && NextC == '*') {
- keepch (' ');
+ KeepChar (' ');
OldStyleComment ();
} else if (ANSI == 0 && CurC == '/' && NextC == '/') {
- keepch (' ');
+ KeepChar (' ');
NewStyleComment ();
} else {
- *mptr++ = CurC;
+ KeepChar (CurC);
NextChar ();
}
}
- keepch ('\0');
+ KeepChar ('\0');
return done;
}
/* Loop substituting macros */
no_chg = 1;
while (CurC != '\0') {
- /* If we have an identifier, check if it's a macro */
+ /* If we have an identifier, check if it's a macro */
if (IsIdent (CurC)) {
SymName (Ident);
M = FindMacro (Ident);
ExpandMacro (M);
no_chg = 0;
} else {
- keepstr (Ident);
+ KeepStr (Ident);
}
} else if (IsQuote (CurC)) {
mptr = CopyQuotedString (mptr);
} else {
- *mptr++ = CurC;
+ KeepChar (CurC);
NextChar ();
}
}
-static void xlateline (void)
+static void PreprocessLine (void)
/* Translate one line. */
{
- int cnt;
- int Done;
+ unsigned I;
- Done = Pass1 (line, mline);
- if (ExpandMacros == 0) {
- Done = 1;
- ExpandMacros = 1; /* Reset to default */
- }
- cnt = 5;
- do {
+ /* Trim whitespace and remove comments. The function returns false if no
+ * identifiers were found that may be macros. If this is the case, no
+ * macro substitution is performed.
+ */
+ int Done = Pass1 (line, mline);
+
+ /* Repeatedly expand macros in the line */
+ for (I = 0; I < 5; ++I) {
/* Swap mline and line */
- char* p = line;
- line = mline;
- mline = p;
- if (Done)
- break;
- Done = Pass2 (line, mline);
- keepch ('\0');
- } while (--cnt);
+ SwapLineBuffers ();
+ if (Done) {
+ break;
+ }
+ /* Perform macro expansion */
+ Done = Pass2 (line, mline);
+ KeepChar ('\0');
+ }
/* Reinitialize line parsing */
InitLine (line);
/* Make sure the line infos for the tokens won't get removed */
if (sv1.LI) {
- UseLineInfo (sv1.LI);
+ UseLineInfo (sv1.LI);
}
if (sv2.LI) {
- UseLineInfo (sv2.LI);
+ UseLineInfo (sv2.LI);
}
- /* Remove the #if from the line and add two semicolons as sentinels */
+ /* Remove the #if from the line */
SkipBlank ();
S = line;
while (CurC != '\0') {
- *S++ = CurC;
- NextChar ();
+ *S++ = CurC;
+ NextChar ();
}
- *S++ = ';';
- *S++ = ';';
- *S = '\0';
+ *S = '\0';
/* Start over parsing from line */
InitLine (line);
Preprocessing = 1;
/* Expand macros in this line */
- xlateline ();
+ PreprocessLine ();
+
+ /* Add two semicolons as sentinels to the line, so the following
+ * expression evaluation will eat these two tokens but nothing from
+ * the following line.
+ */
+ strcat (line, ";;");
/* Prime the token pump (remove old tokens from the stream) */
NextToken ();
*/
mptr = mline;
while (CurC != '\0' && CurC != RTerm) {
- *mptr++ = CurC;
+ KeepChar (CurC);
NextChar ();
}
*mptr = '\0';
+static void DoPragma (void)
+/* Handle a #pragma line by converting the #pragma preprocessor directive into
+ * the _Pragma() compiler operator.
+ */
+{
+ /* Skip blanks following the #pragma directive */
+ SkipBlank ();
+
+ /* Copy the remainder of the line into mline removing comments and ws */
+ Pass1 (lptr, mline);
+
+ /* Convert the directive into the operator */
+ mptr = line;
+ KeepStr ("_Pragma (");
+ Stringize (mline);
+ KeepChar (')');
+ *mptr = '\0';
+
+ /* Initialize reading from line */
+ InitLine (line);
+}
+
+
+
void Preprocess (void)
/* Preprocess a line */
{
- int Skip;
- ident Directive;
+ int Skip;
+ ident Directive;
/* Skip white space at the beginning of the line */
SkipBlank ();
}
break;
- case PP_ELIF:
- if (IfIndex >= 0) {
- if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
-
- /* Handle as #else/#if combination */
- if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
- Skip = !Skip;
- }
- IfStack[IfIndex] |= IFCOND_ELSE;
- Skip = DoIf (Skip);
-
- /* #elif doesn't need a terminator */
- IfStack[IfIndex] &= ~IFCOND_NEEDTERM;
- } else {
- PPError ("Duplicate #else/#elif");
- }
+ case PP_ELIF:
+ if (IfIndex >= 0) {
+ if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
+
+ /* Handle as #else/#if combination */
+ if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
+ Skip = !Skip;
+ }
+ IfStack[IfIndex] |= IFCOND_ELSE;
+ Skip = DoIf (Skip);
+
+ /* #elif doesn't need a terminator */
+ IfStack[IfIndex] &= ~IFCOND_NEEDTERM;
+ } else {
+ PPError ("Duplicate #else/#elif");
+ }
} else {
PPError ("Unexpected #elif");
}
/* Remove any clauses on top of stack that do not
* need a terminating #endif.
*/
- while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
+ while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
--IfIndex;
}
break;
case PP_LINE:
- /* Not allowed in strict ANSI mode */
+ /* Not allowed in strict ANSI mode */
if (!Skip && ANSI) {
PPError ("Preprocessor directive expected");
ClearLine ();
- }
- break;
+ }
+ break;
case PP_PRAGMA:
- if (!Skip) {
- /* Don't expand macros in this line */
- ExpandMacros = 0;
- /* #pragma is handled on the scanner level */
- goto Done;
- }
+ if (!Skip) {
+ DoPragma ();
+ goto Done;
+ }
break;
case PP_UNDEF:
PPError ("Preprocessor directive expected");
ClearLine ();
}
- }
+ }
}
if (NextLine () == 0) {
}
return;
}
- SkipBlank ();
+ SkipBlank ();
}
+ PreprocessLine ();
+
Done:
- xlateline ();
Print (stdout, 2, "line: %s\n", line);
}