#include <errno.h>
#include <ctype.h>
+#include "../common/xmalloc.h"
+
#include "codegen.h"
#include "error.h"
#include "expr.h"
#include "global.h"
#include "ident.h"
-#include "include.h"
-#include "io.h"
+#include "incpath.h"
+#include "input.h"
#include "macrotab.h"
-#include "mem.h"
#include "scanner.h"
#include "util.h"
#include "preproc.h"
-static int Pass1 (char* from, char* to);
+static int Pass1 (const char* From, char* To);
+/* Preprocessor pass 1. Remove whitespace and comments. */
/*****************************************************************************/
-/* data */
+/* data */
/*****************************************************************************/
unsigned char Preprocessing = 0;
/* Management data for #if */
-#define N_IFDEF 16
+#define N_IFDEF 16
static int i_ifdef = -1;
static char s_ifdef[N_IFDEF];
-static void comment (void)
-/* Remove comment from line. */
+static void Comment (void)
+/* Remove a C comment from line. */
{
- unsigned StartingLine = ln;
+ /* Remember the current line number, so we can output better error
+ * messages if the comment is not terminated in the current file.
+ */
+ unsigned StartingLine = GetCurrentLine();
+
+ /* Skip the start of comment chars */
+ NextChar ();
+ NextChar ();
- gch ();
- gch ();
- while (*lptr != '*' || nch () != '/') {
- if (*lptr == '\0') {
- if (readline () == 0) {
+ /* Skip the comment */
+ while (CurC != '*' || NextC != '/') {
+ if (CurC == '\0') {
+ if (NextLine () == 0) {
PPError (ERR_EOF_IN_COMMENT, StartingLine);
return;
}
} else {
- if (*lptr == '/' && nch() == '*') {
+ if (CurC == '/' && NextC == '*') {
PPWarning (WARN_NESTED_COMMENT);
}
- ++lptr;
+ NextChar ();
}
}
- gch ();
- gch ();
+
+ /* Skip the end of comment chars */
+ NextChar ();
+ NextChar ();
}
-static void skipblank (void)
+static void SkipBlank (void)
/* Skip blanks and tabs in the input stream. */
{
- while (IsBlank (*lptr)) {
- ++lptr;
+ while (IsBlank (CurC)) {
+ NextChar ();
}
}
-static char* CopyQuotedString (int Quote, char* Target)
-/* Copy a single or double quoted string from lptr to Target. Return the
+static char* CopyQuotedString (char* Target)
+/* Copy a single or double quoted string from the input to Target. Return the
* new target pointer. Target will not be terminated after the copy.
*/
{
- /* Copy the starting quote */
- *Target++ = gch();
+ /* Remember the quote character, copy it to the target buffer and skip it */
+ char Quote = CurC;
+ *Target++ = CurC;
+ NextChar ();
/* Copy the characters inside the string */
- while (*lptr != '\0' && *lptr != Quote) {
+ while (CurC != '\0' && CurC != Quote) {
/* Keep an escaped char */
- if (*lptr == '\\') {
- *Target++ = gch();
+ if (CurC == '\\') {
+ *Target++ = CurC;
+ NextChar ();
}
/* Copy the character */
- *Target++ = cgch();
+ *Target++ = CurC;
+ NextChar ();
}
/* If we had a terminating quote, copy it */
- if (*lptr) {
- *Target++ = gch();
+ if (CurC != '\0') {
+ *Target++ = CurC;
+ NextChar ();
}
/* Return the new target pointer */
-static int macname (char *sname)
-/* Get macro symbol name. If error, print message and kill line. */
+static int MacName (char* Ident)
+/* Get macro symbol name. If error, print message and clear line. */
{
- if (issym (sname) == 0) {
+ if (IsSym (Ident) == 0) {
PPError (ERR_IDENT_EXPECTED);
- kill ();
+ ClearLine ();
return 0;
} else {
return 1;
static void ExpandMacroArgs (Macro* M)
/* Preprocessor pass 2. Perform macro substitution. */
{
- int C;
ident Ident;
const char* Replacement;
- char* SavePtr;
+ const char* SavePtr;
/* Save the current line pointer and setup the new ones */
SavePtr = lptr;
- lptr = M->Replacement;
+ InitLine (M->Replacement);
/* Copy the macro replacement checking for parameters to replace */
- while ((C = *lptr) != '\0') {
+ while (CurC != '\0') {
/* If the next token is an identifier, check for a macro arg */
- if (IsIdent (C)) {
- symname (Ident);
+ if (IsIdent (CurC)) {
+ SymName (Ident);
Replacement = FindMacroArg (M, Ident);
if (Replacement) {
/* Macro arg, keep the replacement */
/* No macro argument, keep the original identifier */
keepstr (Ident);
}
- } else if (C == '#' && IsIdent (nch ())) {
- ++lptr;
- symname (Ident);
+ } else if (CurC == '#' && IsIdent (NextC)) {
+ NextChar ();
+ SymName (Ident);
Replacement = FindMacroArg (M, Ident);
if (Replacement) {
keepch ('\"');
keepch ('#');
keepstr (Ident);
}
- } else if (IsQuoteChar(C)) {
- mptr = CopyQuotedString (C, mptr);
+ } else if (IsQuoteChar (CurC)) {
+ mptr = CopyQuotedString (mptr);
} else {
- *mptr++ = *lptr++;
+ *mptr++ = CurC;
+ NextChar ();
}
}
/* Reset the line pointer */
- lptr = SavePtr;
+ InitLine (SavePtr);
}
static int MacroCall (Macro* M)
/* Process a function like macro */
{
- unsigned ArgCount; /* Macro argument count */
+ unsigned ArgCount; /* Macro argument count */
unsigned ParCount; /* Number of open parenthesis */
char Buf[LINESIZE]; /* Argument buffer */
- char C;
const char* ArgStart;
char* B;
/* Expect an argument list */
- skipblank ();
- if (*lptr != '(') {
+ SkipBlank ();
+ if (CurC != '(') {
PPError (ERR_ILLEGAL_MACRO_CALL);
return 0;
}
/* Eat the left paren */
- ++lptr;
+ NextChar ();
/* Read the actual macro arguments and store pointers to these arguments
* into the array of actual arguments in the macro definition.
ArgStart = Buf;
B = Buf;
while (1) {
- C = *lptr;
- if (C == '(') {
- *B++ = gch ();
+ if (CurC == '(') {
+ /* Nested parenthesis */
+ *B++ = CurC;
+ NextChar ();
++ParCount;
- } else if (IsQuoteChar(C)) {
- B = CopyQuotedString (C, B);
- } else if (C == ',' || C == ')') {
+ } else if (IsQuoteChar (CurC)) {
+ B = CopyQuotedString (B);
+ } else if (CurC == ',' || CurC == ')') {
if (ParCount == 0) {
- /* End of actual argument */
- gch ();
+ /* End of actual argument */
*B++ = '\0';
- while (IsBlank(*ArgStart)) {
- ++ArgStart;
- }
+ while (IsBlank(*ArgStart)) {
+ ++ArgStart;
+ }
if (ArgCount < M->ArgCount) {
M->ActualArgs[ArgCount++] = ArgStart;
- } else if (C != ')' || *ArgStart != '\0' || M->ArgCount > 0) {
- /* Be sure not to count the single empty argument for a
- * macro that does not have arguments.
- */
+ } 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.
+ */
++ArgCount;
+ }
+
+ /* Check for end of macro param list */
+ if (CurC == ')') {
+ NextChar ();
+ break;
}
- /* Start the next one */
+ /* Start the next param */
ArgStart = B;
- if (C == ')') {
- break;
- }
+ NextChar ();
} else {
- *B++ = gch ();
- if (C == ')') {
+ /* Comma or right paren inside nested parenthesis */
+ if (CurC == ')') {
--ParCount;
}
+ *B++ = CurC;
+ NextChar ();
}
- } else if (IsBlank (C)) {
+ } else if (IsBlank (CurC)) {
/* Squeeze runs of blanks */
*B++ = ' ';
- skipblank ();
- } else if (C == '\0') {
+ SkipBlank ();
+ } else if (CurC == '\0') {
/* End of line inside macro argument list - read next line */
- if (readline () == 0) {
+ if (NextLine () == 0) {
return 0;
}
} else {
/* Just copy the character */
- *B++ = *lptr++;
+ *B++ = CurC;
+ NextChar ();
}
}
if (M->ArgCount >= 0) {
/* Function like macro */
if (MacroCall (M) == 0) {
- kill ();
+ ClearLine ();
}
} else {
/* Just copy the replacement text */
static void addmac (void)
/* Add a macro to the macro table. */
{
- char* saveptr;
- ident Ident;
- char Buf[LINESIZE];
- Macro* M;
+ char* saveptr;
+ ident Ident;
+ char Buf[LINESIZE];
+ Macro* M;
/* Read the macro name */
- skipblank ();
- if (!macname (Ident)) {
+ SkipBlank ();
+ if (!MacName (Ident)) {
return;
}
M = NewMacro (Ident);
/* Check if this is a function like macro */
- if (*lptr == '(') {
+ if (CurC == '(') {
/* Skip the left paren */
- gch ();
+ NextChar ();
/* Set the marker that this is a function like macro */
M->ArgCount = 0;
/* Read the formal parameter list */
while (1) {
- skipblank ();
- if (*lptr == ')')
+ SkipBlank ();
+ if (CurC == ')')
break;
- if (macname (Ident) == 0) {
+ if (MacName (Ident) == 0) {
return;
}
AddMacroArg (M, Ident);
- skipblank ();
- if (*lptr != ',')
+ SkipBlank ();
+ if (CurC != ',')
break;
- gch ();
+ NextChar ();
}
- if (*lptr != ')') {
+
+ /* Check for a right paren and eat it if we find one */
+ if (CurC != ')') {
PPError (ERR_RPAREN_EXPECTED);
- kill ();
+ ClearLine ();
return;
}
- gch ();
+ NextChar ();
}
/* Insert the macro into the macro table and allocate the ActualArgs array */
/* Remove whitespace and comments from the line, store the preprocessed
* line into Buf.
*/
- skipblank ();
+ SkipBlank ();
saveptr = mptr;
Pass1 (lptr, Buf);
mptr = saveptr;
-static int Pass1 (char* from, char* to)
-/* Preprocessor pass 1. Remove whitespace and comments. */
+static int Pass1 (const char* From, char* To)
+/* Preprocessor pass 1. Remove whitespace and comments. */
{
- int c;
- int done;
- ident Ident;
- int HaveParen;
+ int done;
+ ident Ident;
+ int HaveParen;
- lptr = from;
- mptr = to;
+ /* Initialize reading from "From" */
+ InitLine (From);
+
+ /* Target is "To" */
+ mptr = To;
+
+ /* Loop removing ws and comments */
done = 1;
- while ((c = *lptr) != 0) {
- if (IsBlank (c)) {
+ while (CurC != '\0') {
+ if (IsBlank (CurC)) {
keepch (' ');
- skipblank ();
- } else if (IsIdent (c)) {
- symname (Ident);
+ SkipBlank ();
+ } else if (IsIdent (CurC)) {
+ SymName (Ident);
if (Preprocessing && strcmp(Ident, "defined") == 0) {
- /* Handle the "defined" operator */
- skipblank();
- HaveParen = 0;
- if (*lptr == '(') {
- HaveParen = 1;
- ++lptr;
- skipblank();
- }
- if (!IsIdent(c)) {
- PPError (ERR_IDENT_EXPECTED);
- *mptr++ = '0';
- } else {
- symname (Ident);
- *mptr++ = IsMacro(Ident)? '1' : '0';
- if (HaveParen) {
- skipblank();
- if (*lptr != ')') {
- PPError (ERR_RPAREN_EXPECTED);
- } else {
- ++lptr;
- }
- }
- }
+ /* Handle the "defined" operator */
+ SkipBlank();
+ HaveParen = 0;
+ if (CurC == '(') {
+ HaveParen = 1;
+ NextChar ();
+ SkipBlank();
+ }
+ if (!IsIdent (CurC)) {
+ PPError (ERR_IDENT_EXPECTED);
+ *mptr++ = '0';
+ } else {
+ SymName (Ident);
+ *mptr++ = IsMacro (Ident)? '1' : '0';
+ if (HaveParen) {
+ SkipBlank();
+ if (CurC != ')') {
+ PPError (ERR_RPAREN_EXPECTED);
+ } else {
+ NextChar ();
+ }
+ }
+ }
} else {
- if (MaybeMacro(c)) {
- done = 0;
- }
- keepstr (Ident);
+ if (MaybeMacro (Ident[0])) {
+ done = 0;
+ }
+ keepstr (Ident);
}
- } else if (IsQuoteChar(c)) {
- mptr = CopyQuotedString (c, mptr);
- } else if (c == '/' && nch () == '*') {
+ } else if (IsQuoteChar (CurC)) {
+ mptr = CopyQuotedString (mptr);
+ } else if (CurC == '/' && NextC == '*') {
keepch (' ');
- comment ();
- } else if (ANSI == 0 && c == '/' && nch () == '/') {
+ Comment ();
+ } 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
* source line is denoted by a lf (\n) character.
*/
do {
- ++lptr;
- } while (*lptr != '\n' && *lptr != '\0');
- if (*lptr == '\n') {
- ++lptr;
+ NextChar ();
+ } while (CurC != '\n' && CurC != '\0');
+ if (CurC == '\n') {
+ NextChar ();
}
} else {
- *mptr++ = *lptr++;
+ *mptr++ = CurC;
+ NextChar ();
}
}
keepch ('\0');
-static int Pass2 (char *from, char *to)
+static int Pass2 (const char* From, char* To)
/* Preprocessor pass 2. Perform macro substitution. */
{
- int C;
- int no_chg;
- ident Ident;
- Macro* M;
+ int no_chg;
+ ident Ident;
+ Macro* M;
+
+ /* Initialize reading from "From" */
+ InitLine (From);
+
+ /* Target is "To" */
+ mptr = To;
- lptr = from;
- mptr = to;
+ /* Loop substituting macros */
no_chg = 1;
- while ((C = *lptr) != '\0') {
+ while (CurC != '\0') {
/* If we have an identifier, check if it's a macro */
- if (IsIdent (C)) {
- symname (Ident);
+ if (IsIdent (CurC)) {
+ SymName (Ident);
M = FindMacro (Ident);
if (M) {
- ExpandMacro (M);
- no_chg = 0;
+ ExpandMacro (M);
+ no_chg = 0;
} else {
- keepstr (Ident);
+ keepstr (Ident);
}
- } else if (IsQuoteChar(C)) {
- mptr = CopyQuotedString (C, mptr);
+ } else if (IsQuoteChar(CurC)) {
+ mptr = CopyQuotedString (mptr);
} else {
- *mptr++ = *lptr++;
+ *mptr++ = CurC;
+ NextChar ();
}
}
return no_chg;
{
int cnt;
int Done;
- char *p;
Done = Pass1 (line, mline);
if (ExpandMacros == 0) {
}
cnt = 5;
do {
- p = line;
+ /* Swap mline and line */
+ char* p = line;
line = mline;
mline = p;
if (Done)
Done = Pass2 (line, mline);
keepch ('\0');
} while (--cnt);
- lptr = line;
+
+ /* Reinitialize line parsing */
+ InitLine (line);
}
{
ident Ident;
- skipblank ();
- if (macname (Ident)) {
+ SkipBlank ();
+ if (MacName (Ident)) {
UndefineMacro (Ident);
}
}
Token sv2 = NextTok;
/* Remove the #if from the line and add two semicolons as sentinels */
- skipblank ();
+ SkipBlank ();
S = line;
- while ((*S++ = *lptr++) != '\0') ;
- strcat (line, ";;");
- lptr = line;
+ while (CurC != '\0') {
+ *S++ = CurC;
+ NextChar ();
+ }
+ *S++ = ';';
+ *S++ = ';';
+ *S = '\0';
+
+ /* Start over parsing from line */
+ InitLine (line);
/* Switch into special preprocessing mode */
Preprocessing = 1;
xlateline ();
/* Prime the token pump (remove old tokens from the stream) */
- gettok ();
- gettok ();
+ NextToken ();
+ NextToken ();
/* Call the expression parser */
constexpr (&lval);
{
ident Ident;
- skipblank ();
- if (macname (Ident) == 0) {
+ SkipBlank ();
+ if (MacName (Ident) == 0) {
return 0;
} else {
return setmflag (skip, flag, IsMacro(Ident));
static void doinclude (void)
/* Open an include file. */
{
- char name [80];
- unsigned count;
- char term;
- char c;
- char *p;
-
- if (ifile >= MAXFILES) {
- PPError (ERR_INCLUDE_NESTING);
- goto done;
- }
- mptr = mline;
- skipblank ();
- if (!strchr ("\"<", (term = cgch ()))) {
- PPError (ERR_INCLUDE_LTERM_EXPECTED);
- goto done;
- }
- if (term == '<') {
- term = '>'; /* get right terminator */
- }
+ char RTerm;
+ unsigned DirSpec;
- /* Get the name of the include file */
- count = 0;
- while ((c = *lptr) && (c != term) && count < sizeof (name)-1) {
- name [count++] = c;
- ++lptr;
- }
- if (c != term) {
- PPError (ERR_INCLUDE_RTERM_EXPECTED);
- goto done;
- }
- name [count] = '\0';
- /* Now search for the name */
- p = FindInclude (name, (term == '\"')? INC_USER : INC_SYS);
- if (p == 0) {
- PPError (ERR_INCLUDE_NOT_FOUND, name);
- goto done;
- }
+ /* Skip blanks */
+ SkipBlank ();
+
+ /* Get the next char and check for a valid file name terminator. Setup
+ * the include directory spec (SYS/USR) by looking at the terminator.
+ */
+ switch (CurC) {
- /* Save the existing file info */
- filetab[ifile].f_ln = ln;
- filetab[ifile].f_name = fin;
- filetab[ifile].f_iocb = inp;
- ++ifile;
+ case '\"':
+ RTerm = '\"';
+ DirSpec = INC_USER;
+ break;
- /* Assign the name and output it */
- fin = p;
- if (Verbose) {
- printf ("including '%s'\n", fin);
+ case '<':
+ RTerm = '>';
+ DirSpec = INC_SYS;
+ break;
+
+ default:
+ PPError (ERR_INCLUDE_LTERM_EXPECTED);
+ goto Done;
}
+ NextChar ();
- /* Try to open the include file */
- if ((inp = fopen (fin, "r")) == 0) {
- /* oops! restore old file */
- PPError (ERR_INCLUDE_OPEN_FAILURE, fin);
- xfree (fin);
- --ifile;
- inp = filetab[ifile].f_iocb;
- fin = filetab[ifile].f_name;
- } else {
- ln = 0;
+ /* Copy the filename into mline. Since mline has the same size as the
+ * input line, we don't need to check for an overflow here.
+ */
+ mptr = mline;
+ while (CurC != '\0' && CurC != RTerm) {
+ *mptr++ = CurC;
+ NextChar ();
}
+ *mptr = '\0';
+
+ /* Check if we got a terminator */
+ if (CurC != RTerm) {
+ /* No terminator found */
+ PPError (ERR_INCLUDE_RTERM_EXPECTED);
+ goto Done;
+ }
+
+ /* Open the include file */
+ OpenIncludeFile (mline, DirSpec);
-done:
- /* clear rest of line so next read will come from new file (if open) */
- kill ();
+Done:
+ /* Clear the remaining line so the next input will come from the new
+ * file (if open)
+ */
+ ClearLine ();
}
static void doerror (void)
/* Print an error */
{
- skipblank ();
- if (*lptr == '\0') {
+ SkipBlank ();
+ if (CurC == '\0') {
PPError (ERR_INVALID_USER_ERROR);
} else {
PPError (ERR_USER_ERROR, lptr);
}
/* clear rest of line */
- kill ();
+ ClearLine ();
}
/* stuff used to bum the keyword dispatching stuff */
enum {
- D_DEFINE,
- D_ELSE,
- D_ENDIF,
- D_ERROR,
- D_IF,
- D_IFDEF,
- D_IFNDEF,
- D_INCLUDE,
- D_LINE,
- D_PRAGMA,
- D_UNDEF,
- D_ILLEGAL,
+ 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", D_DEFINE },
- { "else", D_ELSE },
- { "endif", D_ENDIF },
- { "error", D_ERROR },
- { "if", D_IF },
- { "ifdef", D_IFDEF },
- { "ifndef", D_IFNDEF },
- { "include", D_INCLUDE },
- { "line", D_LINE },
- { "pragma", D_PRAGMA },
- { "undef", D_UNDEF },
- { 0, D_ILLEGAL }
+ { "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 }
};
-int searchtok (const char *sym, const struct tok_elt *toks)
+static int searchtok (const char *sym, const struct tok_elt *toks)
/* Search a token in a table */
{
while (toks->toknam && strcmp (toks->toknam, sym))
-void preprocess (void)
+void Preprocess (void)
/* Preprocess a line */
{
- int c;
int Skip;
- ident sname;
-
- /* Process compiler directives, skip empty lines */
- lptr = line;
+ ident Directive;
/* Skip white space at the beginning of the line */
- skipblank ();
+ SkipBlank ();
/* Check for stuff to skip */
Skip = 0;
- while ((c = *lptr) == '\0' || c == '#' || Skip) {
-
- /* Check for preprocessor lines lines */
- if (c == '#') {
- ++lptr;
- skipblank ();
- if (*lptr == '\0') {
- /* ignore the empty preprocessor directive */
- continue;
- }
- if (!issym (sname)) {
- PPError (ERR_CPP_DIRECTIVE_EXPECTED);
- kill ();
- } else {
- switch (searchtok (sname, pre_toks)) {
-
- case D_DEFINE:
- if (!Skip) {
- addmac ();
- }
- break;
-
- case D_ELSE:
- if (s_ifdef[i_ifdef] & 2) {
- if (s_ifdef[i_ifdef] & 4) {
- Skip = !Skip;
- }
- s_ifdef[i_ifdef] ^= 2;
- } else {
- PPError (ERR_UNEXPECTED_CPP_ELSE);
- }
- break;
-
- case D_ENDIF:
- if (i_ifdef >= 0) {
- Skip = s_ifdef[i_ifdef--] & 1;
- } else {
- PPError (ERR_UNEXPECTED_CPP_ENDIF);
- }
- break;
-
- case D_ERROR:
- if (!Skip) {
- doerror ();
- }
- break;
-
- case D_IF:
- Skip = doiff (Skip);
- break;
-
- case D_IFDEF:
- Skip = doifdef (Skip, 1);
- break;
-
- case D_IFNDEF:
- Skip = doifdef (Skip, 0);
- break;
-
- case D_INCLUDE:
- if (!Skip) {
- doinclude ();
- }
- break;
-
- case D_LINE:
- /* Not allowed in strict ANSI mode */
- if (ANSI) {
- PPError (ERR_CPP_DIRECTIVE_EXPECTED);
- kill ();
- }
- break;
-
- case D_PRAGMA:
- if (!Skip) {
- /* Don't expand macros in this line */
- ExpandMacros = 0;
- /* #pragma is handled on the scanner level */
- goto Done;
- }
- break;
-
- case D_UNDEF:
- if (!Skip) {
- doundef ();
- }
- break;
-
- default:
- PPError (ERR_CPP_DIRECTIVE_EXPECTED);
- kill ();
- }
+ while (CurC == '\0' || CurC == '#' || Skip) {
+
+ /* Check for preprocessor lines lines */
+ if (CurC == '#') {
+ NextChar ();
+ SkipBlank ();
+ if (CurC == '\0') {
+ /* Ignore the empty preprocessor directive */
+ continue;
+ }
+ if (!IsSym (Directive)) {
+ PPError (ERR_CPP_DIRECTIVE_EXPECTED);
+ ClearLine ();
+ } else {
+ switch (searchtok (Directive, pre_toks)) {
+
+ case PP_DEFINE:
+ if (!Skip) {
+ addmac ();
+ }
+ break;
+
+ case PP_ELSE:
+ if (s_ifdef[i_ifdef] & 2) {
+ if (s_ifdef[i_ifdef] & 4) {
+ Skip = !Skip;
+ }
+ s_ifdef[i_ifdef] ^= 2;
+ } else {
+ PPError (ERR_UNEXPECTED_CPP_ELSE);
+ }
+ break;
+
+ case PP_ENDIF:
+ if (i_ifdef >= 0) {
+ Skip = s_ifdef[i_ifdef--] & 1;
+ } else {
+ PPError (ERR_UNEXPECTED_CPP_ENDIF);
+ }
+ break;
+
+ case PP_ERROR:
+ if (!Skip) {
+ doerror ();
+ }
+ break;
+
+ case PP_IF:
+ Skip = doiff (Skip);
+ break;
+
+ case PP_IFDEF:
+ Skip = doifdef (Skip, 1);
+ break;
+
+ case PP_IFNDEF:
+ Skip = doifdef (Skip, 0);
+ break;
+
+ case PP_INCLUDE:
+ if (!Skip) {
+ doinclude ();
+ }
+ break;
+
+ case PP_LINE:
+ /* Not allowed in strict ANSI mode */
+ if (ANSI) {
+ PPError (ERR_CPP_DIRECTIVE_EXPECTED);
+ ClearLine ();
+ }
+ break;
+
+ case PP_PRAGMA:
+ if (!Skip) {
+ /* Don't expand macros in this line */
+ ExpandMacros = 0;
+ /* #pragma is handled on the scanner level */
+ goto Done;
+ }
+ break;
+
+ case PP_UNDEF:
+ if (!Skip) {
+ doundef ();
+ }
+ break;
+
+ default:
+ PPError (ERR_CPP_DIRECTIVE_EXPECTED);
+ ClearLine ();
+ }
}
}
- if (readline () == 0) {
+ if (NextLine () == 0) {
if (i_ifdef >= 0) {
- PPError (ERR_CPP_ENDIF_EXPECTED);
+ PPError (ERR_CPP_ENDIF_EXPECTED);
}
return;
}
- skipblank ();
+ SkipBlank ();
}
Done: