1
0
mirror of https://github.com/cc65/cc65.git synced 2024-10-01 15:54:59 +00:00

Removed an invalid data access.

Check nested #ifs for overflow.
Lots of cleanups and rewriting of code sections.
Streamlined and extended #if stack handling.
Added #elif preprocessor directive.


git-svn-id: svn://svn.cc65.org/cc65/trunk@859 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-09-07 09:54:33 +00:00
parent f3df91260a
commit 5db55826f0

View File

@ -8,6 +8,7 @@
/* common */ /* common */
#include "chartype.h" #include "chartype.h"
#include "check.h"
#include "print.h" #include "print.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -44,13 +45,17 @@ static int Pass1 (const char* From, char* To);
/* Set when the pp calls expr() recursively */ /* Set when the preprocessor calls expr() recursively */
unsigned char Preprocessing = 0; unsigned char Preprocessing = 0;
/* Management data for #if */ /* Management data for #if */
#define N_IFDEF 16 #define MAX_IFS 64
static int i_ifdef = -1; #define IFCOND_NONE 0x00U
static char s_ifdef[N_IFDEF]; #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 */ /* Buffer for macro expansion */
static char mlinebuf [LINESIZE]; static char mlinebuf [LINESIZE];
@ -71,6 +76,7 @@ static int ExpandMacros = 1;
/* Types of preprocessor tokens */ /* Types of preprocessor tokens */
typedef enum { typedef enum {
PP_DEFINE, PP_DEFINE,
PP_ELIF,
PP_ELSE, PP_ELSE,
PP_ENDIF, PP_ENDIF,
PP_ERROR, PP_ERROR,
@ -92,6 +98,7 @@ static const struct PPToken {
pptoken_t Tok; /* Token */ pptoken_t Tok; /* Token */
} PPTokens[] = { } PPTokens[] = {
{ "define", PP_DEFINE }, { "define", PP_DEFINE },
{ "elif", PP_ELIF },
{ "else", PP_ELSE }, { "else", PP_ELSE },
{ "endif", PP_ENDIF }, { "endif", PP_ENDIF },
{ "error", PP_ERROR }, { "error", PP_ERROR },
@ -135,10 +142,10 @@ static pptoken_t FindPPToken (const char* Ident)
static int keepch (char c) static void keepch (char c)
/* Put character c into translation buffer. */ /* Put character c into translation buffer. */
{ {
return (*mptr++ = c); *mptr++ = c;
} }
@ -146,9 +153,9 @@ static int keepch (char c)
static void keepstr (const char* S) static void keepstr (const char* S)
/* Put string str into translation buffer. */ /* Put string str into translation buffer. */
{ {
while (*S) { unsigned Len = strlen (S);
keepch (*S++); memcpy (mptr, S, Len);
} mptr += Len;
} }
@ -239,8 +246,8 @@ static char* CopyQuotedString (char* Target)
static int MacName (char* Ident) static int MacName (char* Ident)
/* Get macro symbol name. If we have an error, print a diagnostic message /* Get a macro symbol name into Ident. If we have an error, print a
* and clear line. * diagnostic message and clear the line.
*/ */
{ {
if (IsSym (Ident) == 0) { if (IsSym (Ident) == 0) {
@ -503,7 +510,7 @@ static void DefineMacro (void)
/*****************************************************************************/ /*****************************************************************************/
/* Preprocessing */
/*****************************************************************************/ /*****************************************************************************/
@ -655,8 +662,8 @@ static void xlateline (void)
static void doundef (void) static void DoUndef (void)
/* Process #undef directive */ /* Process the #undef directive */
{ {
ident Ident; ident Ident;
@ -668,21 +675,29 @@ static void doundef (void)
static int setmflag (int skip, int flag, int cond) static int PushIf (int Skip, int Invert, int Cond)
/* setmflag( skip, flag, cond ) */ /* Push a new if level onto the if stack */
{ {
if (skip) { /* Check for an overflow of the if stack */
s_ifdef[++i_ifdef] = 3; if (IfIndex >= MAX_IFS-1) {
return (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 { } else {
s_ifdef[++i_ifdef] = 6; IfStack[IfIndex] = IFCOND_NONE | IFCOND_NEEDTERM;
return (flag ^ cond); return (Invert ^ Cond);
} }
} }
static int doiff (int skip) static int DoIf (int Skip)
/* Process #if directive */ /* Process #if directive */
{ {
ExprDesc lval; ExprDesc lval;
@ -739,12 +754,12 @@ static int doiff (int skip)
NextTok = sv2; NextTok = sv2;
/* Set the #if condition according to the expression result */ /* Set the #if condition according to the expression result */
return (setmflag (skip, 1, lval.ConstVal != 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. */ /* Process #ifdef if flag == 1, or #ifndef if flag == 0. */
{ {
ident Ident; ident Ident;
@ -753,13 +768,13 @@ static int doifdef (int skip, int flag)
if (MacName (Ident) == 0) { if (MacName (Ident) == 0) {
return 0; return 0;
} else { } 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. */ /* Open an include file. */
{ {
char RTerm; char RTerm;
@ -819,7 +834,7 @@ Done:
static void doerror (void) static void DoError (void)
/* Print an error */ /* Print an error */
{ {
SkipBlank (); SkipBlank ();
@ -829,7 +844,7 @@ static void doerror (void)
PPError ("#error: %s", lptr); PPError ("#error: %s", lptr);
} }
/* clear rest of line */ /* Clear the rest of line */
ClearLine (); ClearLine ();
} }
@ -868,20 +883,56 @@ void Preprocess (void)
} }
break; break;
case PP_ELSE: case PP_ELIF:
if (s_ifdef[i_ifdef] & 2) { if (IfIndex >= 0) {
if (s_ifdef[i_ifdef] & 4) { if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
/* Handle as #else/#if combination */
if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
Skip = !Skip; Skip = !Skip;
} }
s_ifdef[i_ifdef] ^= 2; 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 (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 { } else {
PPError ("Unexpected `#else'"); PPError ("Unexpected `#else'");
} }
break; break;
case PP_ENDIF: case PP_ENDIF:
if (i_ifdef >= 0) { if (IfIndex >= 0) {
Skip = s_ifdef[i_ifdef--] & 1; /* 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 { } else {
PPError ("Unexpected `#endif'"); PPError ("Unexpected `#endif'");
} }
@ -889,31 +940,31 @@ void Preprocess (void)
case PP_ERROR: case PP_ERROR:
if (!Skip) { if (!Skip) {
doerror (); DoError ();
} }
break; break;
case PP_IF: case PP_IF:
Skip = doiff (Skip); Skip = DoIf (Skip);
break; break;
case PP_IFDEF: case PP_IFDEF:
Skip = doifdef (Skip, 1); Skip = DoIfDef (Skip, 1);
break; break;
case PP_IFNDEF: case PP_IFNDEF:
Skip = doifdef (Skip, 0); Skip = DoIfDef (Skip, 0);
break; break;
case PP_INCLUDE: case PP_INCLUDE:
if (!Skip) { if (!Skip) {
doinclude (); DoInclude ();
} }
break; break;
case PP_LINE: case PP_LINE:
/* Not allowed in strict ANSI mode */ /* Not allowed in strict ANSI mode */
if (ANSI) { if (!Skip && ANSI) {
PPError ("Preprocessor directive expected"); PPError ("Preprocessor directive expected");
ClearLine (); ClearLine ();
} }
@ -930,7 +981,7 @@ void Preprocess (void)
case PP_UNDEF: case PP_UNDEF:
if (!Skip) { if (!Skip) {
doundef (); DoUndef ();
} }
break; break;
@ -942,7 +993,7 @@ void Preprocess (void)
} }
if (NextLine () == 0) { if (NextLine () == 0) {
if (i_ifdef >= 0) { if (IfIndex >= 0) {
PPError ("`#endif' expected"); PPError ("`#endif' expected");
} }
return; return;