1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-26 08:32:00 +00:00

Fix a problem with conditional assembly: The scanner has to be switched into

raw token mode when skipping a section of input because otherwise pseudo
functions may trigger errors.


git-svn-id: svn://svn.cc65.org/cc65/trunk@5033 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2011-06-05 14:28:56 +00:00
parent 6a56201046
commit 6a48359d23
3 changed files with 115 additions and 107 deletions

View File

@ -56,16 +56,19 @@
/* Set of bitmapped flags for the if descriptor */ /* Set of bitmapped flags for the if descriptor */
enum { enum {
ifNone = 0x0000, /* No flag */ ifNone = 0x0000, /* No flag */
ifCond = 0x0001, /* IF condition was true */ ifCond = 0x0001, /* IF condition was true */
ifElse = 0x0002, /* We had a .ELSE branch */ ifElse = 0x0002, /* We had a .ELSE branch */
ifNeedTerm = 0x0004 /* Need .ENDIF termination */ ifNeedTerm = 0x0004, /* Need .ENDIF termination */
}; };
/* The overall .IF condition */
int IfCond = 1;
/*****************************************************************************/ /*****************************************************************************/
/* struct IfDesc */ /* struct IfDesc */
/*****************************************************************************/ /*****************************************************************************/
@ -95,7 +98,7 @@ static IfDesc* AllocIf (const char* Directive, int NeedTerm)
} }
/* Alloc one element */ /* Alloc one element */
ID = &IfStack [IfCount++]; ID = &IfStack[IfCount++];
/* Initialize elements */ /* Initialize elements */
ID->Flags = NeedTerm? ifNeedTerm : ifNone; ID->Flags = NeedTerm? ifNeedTerm : ifNone;
@ -115,7 +118,7 @@ static IfDesc* GetCurrentIf (void)
if (IfCount == 0) { if (IfCount == 0) {
return 0; return 0;
} else { } else {
return &IfStack [IfCount-1]; return &IfStack[IfCount-1];
} }
} }
@ -126,12 +129,12 @@ static void FreeIf (void)
{ {
int Done; int Done;
do { do {
IfDesc* D = GetCurrentIf(); IfDesc* ID = GetCurrentIf();
if (D == 0) { if (ID == 0) {
Error (" Unexpected .ENDIF"); Error (" Unexpected .ENDIF");
Done = 1; Done = 1;
} else { } else {
Done = (D->Flags & ifNeedTerm) != 0; Done = (ID->Flags & ifNeedTerm) != 0;
--IfCount; --IfCount;
} }
} while (!Done); } while (!Done);
@ -139,16 +142,17 @@ static void FreeIf (void)
static int GetCurrentIfCond (void) static void CalcOverallIfCond (void)
/* Return the current condition based on all conditions on the stack */ /* Caclulate the overall condition based on all conditions on the stack */
{ {
unsigned Count; unsigned Count;
IfCond = 1;
for (Count = 0; Count < IfCount; ++Count) { for (Count = 0; Count < IfCount; ++Count) {
if ((IfStack[Count].Flags & ifCond) == 0) { if ((IfStack[Count].Flags & ifCond) == 0) {
return 0; IfCond = 0;
break;
} }
} }
return 1;
} }
@ -165,30 +169,24 @@ static void SetIfCond (IfDesc* ID, int C)
static void InvertIfCond (IfDesc* ID) static void ElseClause (IfDesc* ID, const char* Directive)
/* Invert the current condition */ /* Enter an .ELSE clause */
{ {
ID->Flags ^= ifCond; /* Check if we have an open .IF - otherwise .ELSE is not allowed */
} if (ID == 0) {
Error ("Unexpected %s", Directive);
return;
static int GetElse (const IfDesc* ID)
/* Return true if we had a .ELSE */
{
return (ID->Flags & ifElse) != 0;
}
static void SetElse (IfDesc* ID, int E)
/* Set the .ELSE flag */
{
if (E) {
ID->Flags |= ifElse;
} else {
ID->Flags &= ~ifElse;
} }
/* Check for a duplicate else, then remember that we had one */
if (ID->Flags & ifElse) {
/* We already had a .ELSE ! */
Error ("Duplicate .ELSE");
}
ID->Flags |= ifElse;
/* Condition is inverted now */
ID->Flags ^= ifCond;
} }
@ -204,82 +202,72 @@ void DoConditionals (void)
{ {
IfDesc* D; IfDesc* D;
int IfCond = GetCurrentIfCond ();
do { do {
switch (CurTok.Tok) { switch (CurTok.Tok) {
case TOK_ELSE: case TOK_ELSE:
D = GetCurrentIf (); D = GetCurrentIf ();
if (D == 0) {
Error ("Unexpected .ELSE"); /* Allow an .ELSE */
} else if (GetElse(D)) { ElseClause (D, ".ELSE");
/* We already had a .ELSE ! */
Error ("Duplicate .ELSE"); /* Remember the data for the .ELSE */
} else { GetFullLineInfo (&D->LineInfos, 0);
/* Allow an .ELSE */ D->Name = ".ELSE";
InvertIfCond (D);
SetElse (D, 1); /* Calculate the new overall condition */
GetFullLineInfo (&D->LineInfos, 0); CalcOverallIfCond ();
D->Name = ".ELSE";
IfCond = GetCurrentIfCond (); /* Skip .ELSE */
}
NextTok (); NextTok ();
ExpectSep (); ExpectSep ();
break; break;
case TOK_ELSEIF: case TOK_ELSEIF:
D = GetCurrentIf (); D = GetCurrentIf ();
if (D == 0) { /* Handle as if there was an .ELSE first */
Error ("Unexpected .ELSEIF"); ElseClause (D, ".ELSEIF");
} else if (GetElse(D)) {
/* We already had a .ELSE */
Error ("Duplicate .ELSE");
} else {
/* Handle as if there was an .ELSE first */
InvertIfCond (D);
SetElse (D, 1);
/* Allocate and prepare a new descriptor */ /* Allocate and prepare a new descriptor */
D = AllocIf (".ELSEIF", 0); D = AllocIf (".ELSEIF", 0);
NextTok (); NextTok ();
/* Ignore the new condition if we are inside a false .ELSE /* Ignore the new condition if we are inside a false .ELSE
* branch. This way we won't get any errors about undefined * branch. This way we won't get any errors about undefined
* symbols or similar... * symbols or similar...
*/ */
if (IfCond == 0) { if (IfCond == 0) {
SetIfCond (D, ConstExpression ()); SetIfCond (D, ConstExpression ());
ExpectSep (); ExpectSep ();
} }
/* Get the new overall condition */ /* Get the new overall condition */
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
} break;
break;
case TOK_ENDIF: case TOK_ENDIF:
/* We're done with this .IF.. - remove the descriptor(s) */ /* We're done with this .IF.. - remove the descriptor(s) */
FreeIf (); FreeIf ();
/* Be sure not to read the next token until the .IF stack /* Be sure not to read the next token until the .IF stack
* has been cleanup up, since we may be at end of file. * has been cleanup up, since we may be at end of file.
*/ */
NextTok (); NextTok ();
ExpectSep (); ExpectSep ();
/* Get the new overall condition */ /* Get the new overall condition */
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IF: case TOK_IF:
D = AllocIf (".IF", 1); D = AllocIf (".IF", 1);
NextTok (); NextTok ();
if (IfCond) { if (IfCond) {
SetIfCond (D, ConstExpression ()); SetIfCond (D, ConstExpression ());
ExpectSep (); ExpectSep ();
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFBLANK: case TOK_IFBLANK:
@ -293,7 +281,7 @@ void DoConditionals (void)
SkipUntilSep (); SkipUntilSep ();
} }
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFCONST: case TOK_IFCONST:
@ -305,7 +293,7 @@ void DoConditionals (void)
FreeExpr (Expr); FreeExpr (Expr);
ExpectSep (); ExpectSep ();
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFDEF: case TOK_IFDEF:
@ -315,7 +303,7 @@ void DoConditionals (void)
SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
SetIfCond (D, Sym != 0 && SymIsDef (Sym)); SetIfCond (D, Sym != 0 && SymIsDef (Sym));
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFNBLANK: case TOK_IFNBLANK:
@ -329,7 +317,7 @@ void DoConditionals (void)
SkipUntilSep (); SkipUntilSep ();
} }
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFNCONST: case TOK_IFNCONST:
@ -341,7 +329,7 @@ void DoConditionals (void)
FreeExpr (Expr); FreeExpr (Expr);
ExpectSep (); ExpectSep ();
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFNDEF: case TOK_IFNDEF:
@ -352,7 +340,7 @@ void DoConditionals (void)
SetIfCond (D, Sym == 0 || !SymIsDef (Sym)); SetIfCond (D, Sym == 0 || !SymIsDef (Sym));
ExpectSep (); ExpectSep ();
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFNREF: case TOK_IFNREF:
@ -363,7 +351,7 @@ void DoConditionals (void)
SetIfCond (D, Sym == 0 || !SymIsRef (Sym)); SetIfCond (D, Sym == 0 || !SymIsRef (Sym));
ExpectSep (); ExpectSep ();
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
case TOK_IFP02: case TOK_IFP02:
@ -372,8 +360,8 @@ void DoConditionals (void)
if (IfCond) { if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502); SetIfCond (D, GetCPU() == CPU_6502);
} }
IfCond = GetCurrentIfCond ();
ExpectSep (); ExpectSep ();
CalcOverallIfCond ();
break; break;
case TOK_IFP816: case TOK_IFP816:
@ -382,8 +370,8 @@ void DoConditionals (void)
if (IfCond) { if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65816); SetIfCond (D, GetCPU() == CPU_65816);
} }
IfCond = GetCurrentIfCond ();
ExpectSep (); ExpectSep ();
CalcOverallIfCond ();
break; break;
case TOK_IFPC02: case TOK_IFPC02:
@ -392,8 +380,8 @@ void DoConditionals (void)
if (IfCond) { if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65C02); SetIfCond (D, GetCPU() == CPU_65C02);
} }
IfCond = GetCurrentIfCond ();
ExpectSep (); ExpectSep ();
CalcOverallIfCond ();
break; break;
case TOK_IFPSC02: case TOK_IFPSC02:
@ -402,8 +390,8 @@ void DoConditionals (void)
if (IfCond) { if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65SC02); SetIfCond (D, GetCPU() == CPU_65SC02);
} }
IfCond = GetCurrentIfCond ();
ExpectSep (); ExpectSep ();
CalcOverallIfCond ();
break; break;
case TOK_IFREF: case TOK_IFREF:
@ -414,7 +402,7 @@ void DoConditionals (void)
SetIfCond (D, Sym != 0 && SymIsRef (Sym)); SetIfCond (D, Sym != 0 && SymIsRef (Sym));
ExpectSep (); ExpectSep ();
} }
IfCond = GetCurrentIfCond (); CalcOverallIfCond ();
break; break;
default: default:
@ -488,6 +476,9 @@ void CheckOpenIfs (void)
LIError (&D->LineInfos, "Conditional assembly branch was never closed"); LIError (&D->LineInfos, "Conditional assembly branch was never closed");
FreeIf (); FreeIf ();
} }
/* Calculate the new overall .IF condition */
CalcOverallIfCond ();
} }
@ -506,6 +497,9 @@ void CleanupIfStack (unsigned SP)
while (IfCount > SP) { while (IfCount > SP) {
FreeIf (); FreeIf ();
} }
/* Calculate the new overall .IF condition */
CalcOverallIfCond ();
} }

View File

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2011, Ullrich von Bassewitz */
/* Römerstraße 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -38,6 +38,17 @@
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* The overall .IF condition */
extern int IfCond;
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/

View File

@ -42,6 +42,7 @@
#include "strbuf.h" #include "strbuf.h"
/* ca65 */ /* ca65 */
#include "condasm.h"
#include "error.h" #include "error.h"
#include "expr.h" #include "expr.h"
#include "global.h" #include "global.h"
@ -661,8 +662,10 @@ void NextTok (void)
/* Get the next raw token */ /* Get the next raw token */
NextRawTok (); NextRawTok ();
/* In raw mode, pass the token unchanged */ /* In raw mode, or when output is suppressed via conditional assembly,
if (RawMode == 0) { * pass the token unchanged.
*/
if (RawMode == 0 && IfCond) {
/* Execute token handling functions */ /* Execute token handling functions */
switch (CurTok.Tok) { switch (CurTok.Tok) {