]> git.sur5r.net Git - cc65/blobdiff - src/cc65/preproc.c
Fixed a bug
[cc65] / src / cc65 / preproc.c
index 4877dad3b6a6b3c5a9a6e0f6cdbc2edfe61f8860..8a35d0f27c692e3bb475f098ba65d6a4878d9c77 100644 (file)
@@ -5,10 +5,14 @@
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <ctype.h>
 
-#include "../common/xmalloc.h"
+/* common */
+#include "chartype.h"
+#include "check.h"
+#include "print.h"
+#include "xmalloc.h"
 
+/* cc65 */
 #include "codegen.h"
 #include "error.h"
 #include "expr.h"
@@ -16,6 +20,7 @@
 #include "ident.h"
 #include "incpath.h"
 #include "input.h"
+#include "lineinfo.h"
 #include "macrotab.h"
 #include "scanner.h"
 #include "util.h"
@@ -35,18 +40,22 @@ static int Pass1 (const char* From, char* To);
 
 
 /*****************************************************************************/
-/*                                  data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
 
-/* Set when the pp calls expr() recursively */
+/* Set when the preprocessor calls expr() recursively */
 unsigned char Preprocessing = 0;
 
 /* Management data for #if */
-#define N_IFDEF                16
-static int i_ifdef = -1;
-static char s_ifdef[N_IFDEF];
+#define MAX_IFS         64
+#define IFCOND_NONE     0x00U
+#define IFCOND_SKIP     0x01U
+#define IFCOND_ELSE     0x02U
+#define IFCOND_NEEDTERM 0x04U
+static unsigned char IfStack[MAX_IFS];
+static int           IfIndex = -1;
 
 /* Buffer for macro expansion */
 static char mlinebuf [LINESIZE];
@@ -59,15 +68,84 @@ static int ExpandMacros = 1;
 
 
 /*****************************************************************************/
-/*                                  code                                    */
+/*                  Low level preprocessor token handling                   */
 /*****************************************************************************/
 
 
 
-static int keepch (char c)
+/* Types of preprocessor tokens */
+typedef enum {
+    PP_DEFINE,
+    PP_ELIF,
+    PP_ELSE,
+    PP_ENDIF,
+    PP_ERROR,
+    PP_IF,
+    PP_IFDEF,
+    PP_IFNDEF,
+    PP_INCLUDE,
+    PP_LINE,
+    PP_PRAGMA,
+    PP_UNDEF,
+    PP_ILLEGAL
+} pptoken_t;
+
+
+
+/* Preprocessor keyword to token mapping table */
+static const struct PPToken {
+    const char*        Key;            /* Keyword */
+    pptoken_t          Tok;            /* Token */
+} PPTokens[] = {
+    {          "define",       PP_DEFINE       },
+    {   "elif",         PP_ELIF         },
+    {          "else",         PP_ELSE         },
+    {          "endif",        PP_ENDIF        },
+    {          "error",        PP_ERROR        },
+    {          "if",           PP_IF           },
+    {          "ifdef",        PP_IFDEF        },
+    {          "ifndef",       PP_IFNDEF       },
+    {          "include",      PP_INCLUDE      },
+    {   "line",                PP_LINE         },
+    {          "pragma",       PP_PRAGMA       },
+    {          "undef",        PP_UNDEF        },
+};
+
+/* Number of preprocessor tokens */
+#define PPTOKEN_COUNT          (sizeof(PPTokens) / sizeof(PPTokens[0]))
+
+
+
+static int CmpToken (const void* Key, const void* Elem)
+/* Compare function for bsearch */
+{
+    return strcmp ((const char*) Key, ((const struct PPToken*) Elem)->Key);
+}
+
+
+
+static pptoken_t FindPPToken (const char* Ident)
+/* Find a preprocessor token and return ut. Return PP_ILLEGAL if the identifier
+ * is not a valid preprocessor token.
+ */
+{
+    struct PPToken* P;
+    P = bsearch (Ident, PPTokens, PPTOKEN_COUNT, sizeof (PPTokens[0]), CmpToken);
+    return P? P->Tok : PP_ILLEGAL;
+}
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+static void keepch (char c)
 /* Put character c into translation buffer. */
 {
-    return (*mptr++ = c);
+    *mptr++ = c;
 }
 
 
@@ -75,15 +153,15 @@ static int keepch (char c)
 static void keepstr (const char* S)
 /* Put string str into translation buffer. */
 {
-    while (*S) {
-       keepch (*S++);
-    }
+    unsigned Len = strlen (S);
+    memcpy (mptr, S, Len);
+    mptr += Len;
 }
 
 
 
-static void Comment (void)
-/* Remove a C comment from line. */
+static void OldStyleComment (void)
+/* Remove an old style C comment from line. */
 {
     /* Remember the current line number, so we can output better error
      * messages if the comment is not terminated in the current file.
@@ -98,13 +176,13 @@ static void Comment (void)
     while (CurC != '*' || NextC != '/') {
        if (CurC == '\0') {
            if (NextLine () == 0) {
-               PPError ("End-of-file reached in comment starting at line %u",
-                        StartingLine);
+               PPError ("End-of-file reached in comment starting at line %u",
+                        StartingLine);
                return;
            }
        } else {
            if (CurC == '/' && NextC == '*') {
-               PPWarning ("`/*' found inside a comment");
+               PPWarning ("`/*' found inside a comment");
            }
            NextChar ();
        }
@@ -117,6 +195,24 @@ static void Comment (void)
 
 
 
+static void NewStyleComment (void)
+/* Remove a new style C comment from line. */
+{
+    /* Beware: Because line continuation chars are handled when reading
+     * lines, we may only skip til the end of the source line, which
+     * may not be the same as the end of the input line. The end of the
+     * source line is denoted by a lf (\n) character.
+     */
+    do {
+       NextChar ();
+    } while (CurC != '\n' && CurC != '\0');
+    if (CurC == '\n') {
+       NextChar ();
+    }
+}
+
+
+
 static void SkipBlank (void)
 /* Skip blanks and tabs in the input stream. */
 {
@@ -162,18 +258,20 @@ static char* CopyQuotedString (char* Target)
 
 
 /*****************************************************************************/
-/*                               Macro stuff                                */
+/*                               Macro stuff                                */
 /*****************************************************************************/
 
 
 
 static int MacName (char* Ident)
-/* Get macro symbol name.  If error, print message and clear line. */
+/* Get a macro symbol name into Ident.  If we have an error, print a
+ * diagnostic message and clear the line.
+ */
 {
     if (IsSym (Ident) == 0) {
-       PPError ("Identifier expected");
+       PPError ("Identifier expected");
        ClearLine ();
-       return 0;
+       return 0;
     } else {
        return 1;
     }
@@ -182,7 +280,7 @@ static int MacName (char* Ident)
 
 
 static void ExpandMacroArgs (Macro* M)
-/* Preprocessor pass 2.  Perform macro substitution. */
+/* Expand the arguments of a macro */
 {
     ident      Ident;
     const char* Replacement;
@@ -194,34 +292,48 @@ static void ExpandMacroArgs (Macro* M)
 
     /* Copy the macro replacement checking for parameters to replace */
     while (CurC != '\0') {
-       /* If the next token is an identifier, check for a macro arg */
+       /* If the next token is an identifier, check for a macro arg */
        if (IsIdent (CurC)) {
            SymName (Ident);
-           Replacement = FindMacroArg (M, Ident);
-           if (Replacement) {
-               /* Macro arg, keep the replacement */
+           Replacement = FindMacroArg (M, Ident);
+           if (Replacement) {
+               /* Macro arg, keep the replacement */
                keepstr (Replacement);
            } else {
-               /* No macro argument, keep the original identifier */
+               /* No macro argument, keep the original identifier */
                keepstr (Ident);
            }
        } else if (CurC == '#' && IsIdent (NextC)) {
                    NextChar ();
            SymName (Ident);
-           Replacement = FindMacroArg (M, Ident);
+           Replacement = FindMacroArg (M, Ident);
                    if (Replacement) {
                keepch ('\"');
-               keepstr (Replacement);
+                /* We have to escape any characters inside replacement that
+                 * may not be part of a string unescaped.
+                 */
+                while (*Replacement) {
+                    switch (*Replacement) {
+                        case '\"':
+                        case '\\':
+                            keepch ('\\');
+                        /* FALLTHROUGH */
+                        default:
+                            keepch (*Replacement);
+                            break;
+                    }
+                    ++Replacement;
+                }
                keepch ('\"');
            } else {
                keepch ('#');
                keepstr (Ident);
            }
-       } else if (IsQuoteChar (CurC)) {
+       } else if (IsQuote (CurC)) {
            mptr = CopyQuotedString (mptr);
        } else {
            *mptr++ = CurC;
-           NextChar ();
+           NextChar ();
        }
     }
 
@@ -234,7 +346,7 @@ static void ExpandMacroArgs (Macro* M)
 static int MacroCall (Macro* M)
 /* Process a function like macro */
 {
-    unsigned   ArgCount;       /* Macro argument count */
+    int         ArgCount;              /* Macro argument count */
     unsigned   ParCount;       /* Number of open parenthesis */
     char       Buf[LINESIZE];  /* Argument buffer */
     const char* ArgStart;
@@ -259,68 +371,74 @@ static int MacroCall (Macro* M)
     B       = Buf;
     while (1) {
                if (CurC == '(') {
-           /* Nested parenthesis */
+           /* Nested parenthesis */
            *B++ = CurC;
-           NextChar ();
+           NextChar ();
            ++ParCount;
-       } else if (IsQuoteChar (CurC)) {
+       } else if (IsQuote (CurC)) {
            B = CopyQuotedString (B);
        } else if (CurC == ',' || CurC == ')') {
            if (ParCount == 0) {
-               /* End of actual argument */
+               /* End of actual argument */
                *B++ = '\0';
-               while (IsBlank(*ArgStart)) {
-                   ++ArgStart;
-               }
+               while (IsBlank(*ArgStart)) {
+                   ++ArgStart;
+               }
                if (ArgCount < M->ArgCount) {
                    M->ActualArgs[ArgCount++] = ArgStart;
                        } else if (CurC != ')' || *ArgStart != '\0' || M->ArgCount > 0) {
-                   /* Be sure not to count the single empty argument for a
-                    * macro that does not have arguments.
-                    */
+                   /* Be sure not to count the single empty argument for a
+                    * macro that does not have arguments.
+                    */
                    ++ArgCount;
-               }
+               }
 
-               /* Check for end of macro param list */
-               if (CurC == ')') {
-                   NextChar ();
-                   break;
-               }
+               /* Check for end of macro param list */
+               if (CurC == ')') {
+                   NextChar ();
+                   break;
+               }
 
                        /* Start the next param */
                ArgStart = B;
-               NextChar ();
+               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 */
+           /* Squeeze runs of blanks */
            *B++ = ' ';
            SkipBlank ();
+       } else if (CurC == '/' && NextC == '*') {
+           *B++ = ' ';
+           OldStyleComment ();
+       } else if (ANSI == 0 && CurC == '/' && NextC == '/') {
+           *B++ = ' ';
+           NewStyleComment ();
        } else if (CurC == '\0') {
-           /* End of line inside macro argument list - read next line */
+           /* End of line inside macro argument list - read next line */
            if (NextLine () == 0) {
                return 0;
            }
        } else {
-           /* Just copy the character */
+           /* Just copy the character */
            *B++ = CurC;
-           NextChar ();
+           NextChar ();
        }
     }
 
     /* Compare formal argument count with actual */
     if (M->ArgCount != ArgCount) {
-       PPError ("Macro argument count mismatch");
-       /* Be sure to make enough empty arguments available */
-       while (ArgCount < M->ArgCount) {
-           M->ActualArgs [ArgCount++] = "";
-       }
+       PPError ("Macro argument count mismatch");
+       /* Be sure to make enough empty arguments available */
+       while (ArgCount < M->ArgCount) {
+           M->ActualArgs [ArgCount++] = "";
+       }
     }
 
     /* Preprocess the line, replacing macro parameters */
@@ -337,20 +455,20 @@ static void ExpandMacro (Macro* M)
 {
     /* Check if this is a function like macro */
     if (M->ArgCount >= 0) {
-       /* Function like macro */
+       /* Function like macro */
                if (MacroCall (M) == 0) {
            ClearLine ();
        }
     } else {
-       /* Just copy the replacement text */
+       /* Just copy the replacement text */
        keepstr (M->Replacement);
     }
 }
 
 
 
-static void addmac (void)
-/* Add a macro to the macro table. */
+static void DefineMacro (void)
+/* Handle a macro definition. */
 {
     char*      saveptr;
     ident      Ident;
@@ -377,9 +495,9 @@ static void addmac (void)
        NextChar ();
 
                /* Set the marker that this is a function like macro */
-       M->ArgCount = 0;
+       M->ArgCount = 0;
 
-       /* Read the formal parameter list */
+       /* Read the formal parameter list */
        while (1) {
            SkipBlank ();
            if (CurC == ')')
@@ -387,14 +505,14 @@ static void addmac (void)
            if (MacName (Ident) == 0) {
                return;
            }
-           AddMacroArg (M, Ident);
+           AddMacroArg (M, Ident);
            SkipBlank ();
            if (CurC != ',')
                break;
            NextChar ();
        }
 
-       /* Check for a right paren and eat it if we find one */
+       /* Check for a right paren and eat it if we find one */
        if (CurC != ')') {
                    PPError ("`)' expected");
            ClearLine ();
@@ -421,16 +539,16 @@ static void addmac (void)
      * Print a diagnostic if not.
      */
     if (Existing) {
-       if (MacroCmp (M, Existing) != 0) {
-           PPError ("Macro redefinition is not identical");
-       }
+       if (MacroCmp (M, Existing) != 0) {
+           PPError ("Macro redefinition is not identical");
+       }
     }
 }
 
 
 
 /*****************************************************************************/
-
+/*                              Preprocessing                               */
 /*****************************************************************************/
 
 
@@ -486,24 +604,14 @@ static int Pass1 (const char* From, char* To)
                }
                keepstr (Ident);
            }
-       } else if (IsQuoteChar (CurC)) {
+       } else if (IsQuote (CurC)) {
            mptr = CopyQuotedString (mptr);
        } else if (CurC == '/' && NextC == '*') {
            keepch (' ');
-           Comment ();
+           OldStyleComment ();
        } else if (ANSI == 0 && CurC == '/' && NextC == '/') {
            keepch (' ');
-           /* Beware: Because line continuation chars are handled when reading
-            * lines, we may only skip til the end of the source line, which
-            * may not be the same as the end of the input line. The end of the
-            * source line is denoted by a lf (\n) character.
-            */
-           do {
-               NextChar ();
-           } while (CurC != '\n' && CurC != '\0');
-           if (CurC == '\n') {
-               NextChar ();
-           }
+           NewStyleComment ();
        } else {
            *mptr++ = CurC;
            NextChar ();
@@ -541,7 +649,7 @@ static int Pass2 (const char* From, char* To)
            } else {
                keepstr (Ident);
            }
-       } else if (IsQuoteChar(CurC)) {
+       } else if (IsQuote (CurC)) {
            mptr = CopyQuotedString (mptr);
        } else {
            *mptr++ = CurC;
@@ -582,8 +690,8 @@ static void xlateline (void)
 
 
 
-static void doundef (void)
-/* Process #undef directive */
+static void DoUndef (void)
+/* Process the #undef directive */
 {
     ident Ident;
 
@@ -595,32 +703,50 @@ static void doundef (void)
 
 
 
-static int setmflag (int skip, int flag, int cond)
-/* setmflag( skip, flag, cond ) */
+static int PushIf (int Skip, int Invert, int Cond)
+/* Push a new if level onto the if stack */
 {
-    if (skip) {
-       s_ifdef[++i_ifdef] = 3;
-       return (1);
+    /* Check for an overflow of the if stack */
+    if (IfIndex >= MAX_IFS-1) {
+       PPError ("Too many nested #if clauses");
+       return 1;
+    }
+
+    /* Push the #if condition */
+    ++IfIndex;
+    if (Skip) {
+       IfStack[IfIndex] = IFCOND_SKIP | IFCOND_NEEDTERM;
+       return 1;
     } else {
-       s_ifdef[++i_ifdef] = 6;
-       return (flag ^ cond);
+       IfStack[IfIndex] = IFCOND_NONE | IFCOND_NEEDTERM;
+       return (Invert ^ Cond);
     }
 }
 
 
 
-static int doiff (int skip)
+static int DoIf (int Skip)
 /* Process #if directive */
 {
-    struct expent lval;
+    ExprDesc lval;
     char* S;
 
     /* We're about to abuse the compiler expression parser to evaluate the
      * #if expression. Save the current tokens to come back here later.
+     * NOTE: Yes, this is a hack, but it saves a complete separate expression
+     * evaluation for the preprocessor.
      */
     Token sv1 = CurTok;
     Token sv2 = NextTok;
 
+    /* Make sure the line infos for the tokens won't get removed */
+    if (sv1.LI) {
+       UseLineInfo (sv1.LI);
+    }
+    if (sv2.LI) {
+       UseLineInfo (sv2.LI);
+    }
+
     /* Remove the #if from the line and add two semicolons as sentinels */
     SkipBlank ();
     S = line;
@@ -646,7 +772,7 @@ static int doiff (int skip)
     NextToken ();
 
     /* Call the expression parser */
-    constexpr (&lval);
+    ConstExpr (&lval);
 
     /* End preprocessing mode */
     Preprocessing = 0;
@@ -656,12 +782,12 @@ static int doiff (int skip)
     NextTok = sv2;
 
     /* Set the #if condition according to the expression result */
-    return (setmflag (skip, 1, lval.e_const != 0));
+    return PushIf (Skip, 1, lval.ConstVal != 0);
 }
 
 
 
-static int doifdef (int skip, int flag)
+static int DoIfDef (int skip, int flag)
 /* Process #ifdef if flag == 1, or #ifndef if flag == 0. */
 {
     ident Ident;
@@ -670,13 +796,13 @@ static int doifdef (int skip, int flag)
     if (MacName (Ident) == 0) {
                return 0;
     } else {
-       return setmflag (skip, flag, IsMacro(Ident));
+       return PushIf (skip, flag, IsMacro(Ident));
     }
 }
 
 
 
-static void doinclude (void)
+static void DoInclude (void)
 /* Open an include file. */
 {
     char       RTerm;
@@ -736,7 +862,7 @@ Done:
 
 
 
-static void doerror (void)
+static void DoError (void)
 /* Print an error */
 {
     SkipBlank ();
@@ -746,57 +872,12 @@ static void doerror (void)
         PPError ("#error: %s", lptr);
     }
 
-    /* clear rest of line */
+    /* Clear the rest of line */
     ClearLine ();
 }
 
 
 
-/* C preprocessor. */
-
-/* stuff used to bum the keyword dispatching stuff */
-enum {
-    PP_DEFINE,
-    PP_ELSE,
-    PP_ENDIF,
-    PP_ERROR,
-    PP_IF,
-    PP_IFDEF,
-    PP_IFNDEF,
-    PP_INCLUDE,
-    PP_LINE,
-    PP_PRAGMA,
-    PP_UNDEF,
-    PP_ILLEGAL
-};
-
-static const struct tok_elt pre_toks[] = {
-    {          "define",       PP_DEFINE       },
-    {          "else",         PP_ELSE         },
-    {          "endif",        PP_ENDIF        },
-    {          "error",        PP_ERROR        },
-    {          "if",           PP_IF           },
-    {          "ifdef",        PP_IFDEF        },
-    {          "ifndef",       PP_IFNDEF       },
-    {          "include",      PP_INCLUDE      },
-    {   "line",                PP_LINE         },
-    {          "pragma",       PP_PRAGMA       },
-    {          "undef",        PP_UNDEF        },
-    {          0,              PP_ILLEGAL      }
-};
-
-
-
-static int searchtok (const char *sym, const struct tok_elt *toks)
-/* Search a token in a table */
-{
-    while (toks->toknam && strcmp (toks->toknam, sym))
-       ++toks;
-    return (toks->toknbr);
-}
-
-
-
 void Preprocess (void)
 /* Preprocess a line */
 {
@@ -822,28 +903,64 @@ void Preprocess (void)
                        PPError ("Preprocessor directive expected");
                        ClearLine ();
                    } else {
-                       switch (searchtok (Directive, pre_toks)) {
+                       switch (FindPPToken (Directive)) {
 
                            case PP_DEFINE:
                                if (!Skip) {
-                                   addmac ();
+                                   DefineMacro ();
                                }
                                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");
+                           }
+                       } else {
+                           PPError ("Unexpected #elif");
+                       }
+                       break;
+
                            case PP_ELSE:
-                               if (s_ifdef[i_ifdef] & 2) {
-                                   if (s_ifdef[i_ifdef] & 4) {
-                                       Skip = !Skip;
-                                   }
-                                   s_ifdef[i_ifdef] ^= 2;
+                               if (IfIndex >= 0) {
+                           if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
+                               if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
+                                   Skip = !Skip;
+                               }
+                               IfStack[IfIndex] |= IFCOND_ELSE;
+                           } else {
+                               PPError ("Duplicate #else");
+                           }
                                } else {
                                    PPError ("Unexpected `#else'");
                                }
                                break;
 
                            case PP_ENDIF:
-                               if (i_ifdef >= 0) {
-                                   Skip = s_ifdef[i_ifdef--] & 1;
+                               if (IfIndex >= 0) {
+                           /* Remove any clauses on top of stack that do not
+                            * need a terminating #endif.
+                            */
+                           while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
+                               --IfIndex;
+                           }
+
+                           /* Stack may not be empty here or something is wrong */
+                           CHECK (IfIndex >= 0);
+
+                           /* Remove the clause that needs a terminator */
+                           Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0;
                                } else {
                                    PPError ("Unexpected `#endif'");
                                }
@@ -851,34 +968,34 @@ void Preprocess (void)
 
                            case PP_ERROR:
                                if (!Skip) {
-                                   doerror ();
+                                   DoError ();
                        }
                        break;
 
                            case PP_IF:
-                       Skip = doiff (Skip);
+                       Skip = DoIf (Skip);
                        break;
 
                            case PP_IFDEF:
-                       Skip = doifdef (Skip, 1);
+                       Skip = DoIfDef (Skip, 1);
                        break;
 
                            case PP_IFNDEF:
-                       Skip = doifdef (Skip, 0);
+                       Skip = DoIfDef (Skip, 0);
                        break;
 
                            case PP_INCLUDE:
                        if (!Skip) {
-                           doinclude ();
+                           DoInclude ();
                        }
                        break;
 
                            case PP_LINE:
-                       /* Not allowed in strict ANSI mode */
-                       if (ANSI) {
-                           PPError ("Preprocessor directive expected");
-                           ClearLine ();
-                       }
+                       /* Not allowed in strict ANSI mode */
+                       if (!Skip && ANSI) {
+                           PPError ("Preprocessor directive expected");
+                           ClearLine ();
+                       }
                        break;
 
                            case PP_PRAGMA:
@@ -892,7 +1009,7 @@ void Preprocess (void)
 
                            case PP_UNDEF:
                        if (!Skip) {
-                           doundef ();
+                           DoUndef ();
                        }
                        break;
 
@@ -904,7 +1021,7 @@ void Preprocess (void)
 
        }
        if (NextLine () == 0) {
-           if (i_ifdef >= 0) {
+           if (IfIndex >= 0) {
                PPError ("`#endif' expected");
            }
            return;
@@ -914,8 +1031,6 @@ void Preprocess (void)
 
 Done:
     xlateline ();
-    if (Verbose > 1) {
-       printf ("line: %s\n", line);
-    }
+    Print (stdout, 2, "line: %s\n", line);
 }