/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+/* ca65 */
#include "error.h"
#include "expr.h"
-#include "scanner.h"
+#include "instr.h"
+#include "nexttok.h"
+#include "symbol.h"
#include "symtab.h"
#include "condasm.h"
/* Maximum count of nested .ifs */
-#define MAX_IFS 32
+#define MAX_IFS 256
/* Set of bitmapped flags for the if descriptor */
enum {
/* One .IF descriptor */
-typedef struct IfDesc_ IfDesc;
-struct IfDesc_ {
+typedef struct IfDesc IfDesc;
+struct IfDesc {
unsigned Flags; /* Bitmapped flags, see above */
FilePos Pos; /* File position of the .IF */
const char* Name; /* Name of the directive */
/* Check for stack overflow */
if (IfCount >= MAX_IFS) {
- Error (ERR_IF_NESTING);
+ Fatal ("Too many nested .IFs");
}
/* Alloc one element */
static void FreeIf (void)
/* Free all .IF descriptors until we reach one with the NeedTerm bit set */
{
- int Done = 0;
+ int Done;
do {
IfDesc* D = GetCurrentIf();
if (D == 0) {
- Error (ERR_UNEXPECTED, ".ENDIF");
+ Error (" Unexpected .ENDIF");
+ Done = 1;
} else {
Done = (D->Flags & ifNeedTerm) != 0;
--IfCount;
case TOK_ELSE:
D = GetCurrentIf ();
if (D == 0) {
- Error (ERR_UNEXPECTED, ".ELSE");
+ Error ("Unexpected .ELSE");
} else if (GetElse(D)) {
/* We already had a .ELSE ! */
- Error (ERR_DUPLICATE_ELSE);
+ Error ("Duplicate .ELSE");
} else {
/* Allow an .ELSE */
InvertIfCond (D);
case TOK_ELSEIF:
D = GetCurrentIf ();
if (D == 0) {
- Error (ERR_UNEXPECTED, ".ELSEIF");
+ Error ("Unexpected .ELSEIF");
} else if (GetElse(D)) {
/* We already had a .ELSE */
- Error (ERR_DUPLICATE_ELSE);
+ Error ("Duplicate .ELSE");
} else {
/* Handle as if there was an .ELSE first */
InvertIfCond (D);
D = AllocIf (".IFBLANK", 1);
NextTok ();
if (IfCond) {
- SetIfCond (D, Tok == TOK_SEP);
+ if (TokIsSep (Tok)) {
+ SetIfCond (D, 1);
+ } else {
+ SetIfCond (D, 0);
+ SkipUntilSep ();
+ }
}
IfCond = GetCurrentIfCond ();
break;
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
- SetIfCond (D, IsConstExpr (Expr));
+ SetIfCond (D, IsConstExpr (Expr, 0));
FreeExpr (Expr);
}
IfCond = GetCurrentIfCond ();
D = AllocIf (".IFDEF", 1);
NextTok ();
if (IfCond) {
- if (Tok != TOK_IDENT) {
- ErrorSkip (ERR_IDENT_EXPECTED);
- } else {
- SetIfCond (D, SymIsDef (SVal));
- NextTok ();
- }
+ SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SetIfCond (D, Sym != 0 && SymIsDef (Sym));
}
IfCond = GetCurrentIfCond ();
break;
case TOK_IFNBLANK:
- D = AllocIf (".IFNBLANK", 1);
+ D = AllocIf (".IFNBLANK", 1);
NextTok ();
if (IfCond) {
- SetIfCond (D, Tok != TOK_SEP);
- }
+ if (TokIsSep (Tok)) {
+ SetIfCond (D, 0);
+ } else {
+ SetIfCond (D, 1);
+ SkipUntilSep ();
+ }
+ }
IfCond = GetCurrentIfCond ();
break;
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
- SetIfCond (D, !IsConstExpr (Expr));
+ SetIfCond (D, !IsConstExpr (Expr, 0));
FreeExpr (Expr);
}
IfCond = GetCurrentIfCond ();
D = AllocIf (".IFNDEF", 1);
NextTok ();
if (IfCond) {
- if (Tok != TOK_IDENT) {
- ErrorSkip (ERR_IDENT_EXPECTED);
- } else {
- SetIfCond (D, !SymIsDef (SVal));
- NextTok ();
- }
+ SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SetIfCond (D, Sym == 0 || !SymIsDef (Sym));
}
IfCond = GetCurrentIfCond ();
break;
D = AllocIf (".IFNREF", 1);
NextTok ();
if (IfCond) {
- if (Tok != TOK_IDENT) {
- ErrorSkip (ERR_IDENT_EXPECTED);
- } else {
- SetIfCond (D, !SymIsRef (SVal));
- NextTok ();
- }
- }
+ SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SetIfCond (D, Sym == 0 || !SymIsRef (Sym));
+ }
IfCond = GetCurrentIfCond ();
break;
case TOK_IFP02:
+ D = AllocIf (".IFP02", 1);
+ NextTok ();
+ if (IfCond) {
+ SetIfCond (D, GetCPU() == CPU_6502);
+ }
+ IfCond = GetCurrentIfCond ();
break;
case TOK_IFP816:
+ D = AllocIf (".IFP816", 1);
+ NextTok ();
+ if (IfCond) {
+ SetIfCond (D, GetCPU() == CPU_65816);
+ }
+ IfCond = GetCurrentIfCond ();
break;
case TOK_IFPC02:
+ D = AllocIf (".IFPC02", 1);
+ NextTok ();
+ if (IfCond) {
+ SetIfCond (D, GetCPU() == CPU_65C02);
+ }
+ IfCond = GetCurrentIfCond ();
+ break;
+
+ case TOK_IFPSC02:
+ D = AllocIf (".IFPSC02", 1);
+ NextTok ();
+ if (IfCond) {
+ SetIfCond (D, GetCPU() == CPU_65SC02);
+ }
+ IfCond = GetCurrentIfCond ();
break;
case TOK_IFREF:
D = AllocIf (".IFREF", 1);
NextTok ();
if (IfCond) {
- if (Tok != TOK_IDENT) {
- ErrorSkip (ERR_IDENT_EXPECTED);
- } else {
- SetIfCond (D, SymIsRef (SVal));
- NextTok ();
- }
+ SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SetIfCond (D, Sym != 0 && SymIsRef (Sym));
}
IfCond = GetCurrentIfCond ();
break;
default:
- // Skip tokens
+ /* Skip tokens */
NextTok ();
}
+int CheckConditionals (void)
+/* Check if the current token is one that starts a conditional directive, and
+ * call DoConditionals if so. Return true if a conditional directive was found,
+ * return false otherwise.
+ */
+{
+ switch (Tok) {
+ case TOK_ELSE:
+ case TOK_ELSEIF:
+ case TOK_ENDIF:
+ case TOK_IF:
+ case TOK_IFBLANK:
+ case TOK_IFCONST:
+ case TOK_IFDEF:
+ case TOK_IFNBLANK:
+ case TOK_IFNCONST:
+ case TOK_IFNDEF:
+ case TOK_IFNREF:
+ case TOK_IFP02:
+ case TOK_IFP816:
+ case TOK_IFPC02:
+ case TOK_IFPSC02:
+ case TOK_IFREF:
+ DoConditionals ();
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+
void CheckOpenIfs (void)
/* Called from the scanner before closing an input file. Will check for any
* open .ifs in this file.
/* There are no open .IFs */
break;
}
-
+
if (D->Pos.Name != CurPos.Name) {
/* The .if is from another file, bail out */
break;
}
/* Start of .if is in the file we're about to leave */
- PError (&D->Pos, ERR_OPEN_IF);
+ PError (&D->Pos, "Conditional assembly branch was never closed");
+ FreeIf ();
+ }
+}
+
+
+
+unsigned GetIfStack (void)
+/* Get the current .IF stack pointer */
+{
+ return IfCount;
+}
+
+
+
+void CleanupIfStack (unsigned SP)
+/* Cleanup the .IF stack, remove anything above the given stack pointer */
+{
+ while (IfCount > SP) {
FreeIf ();
}
}