mirror of
https://github.com/cc65/cc65.git
synced 2024-11-19 06:31:31 +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:
parent
f3df91260a
commit
5db55826f0
@ -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) {
|
||||||
@ -355,7 +362,7 @@ static int MacroCall (Macro* M)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for end of macro param list */
|
/* Check for end of macro param list */
|
||||||
if (CurC == ')') {
|
if (CurC == ')') {
|
||||||
NextChar ();
|
NextChar ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -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_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:
|
case PP_ELSE:
|
||||||
if (s_ifdef[i_ifdef] & 2) {
|
if (IfIndex >= 0) {
|
||||||
if (s_ifdef[i_ifdef] & 4) {
|
if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
|
||||||
Skip = !Skip;
|
if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
|
||||||
}
|
Skip = !Skip;
|
||||||
s_ifdef[i_ifdef] ^= 2;
|
}
|
||||||
|
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,34 +940,34 @@ 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 ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PP_PRAGMA:
|
case PP_PRAGMA:
|
||||||
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user