]> git.sur5r.net Git - cc65/blobdiff - src/ca65/condasm.c
More lineinfo usage.
[cc65] / src / ca65 / condasm.c
index 831802c377ba1343ab48a24ed4925209539f9ee8..28c9f4bd4016cd515b0f19304b6f3db7adda5ae1 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000      Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 2000-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 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"
 
@@ -48,7 +51,7 @@
 
 
 /* Maximum count of nested .ifs */
-#define MAX_IFS                32
+#define MAX_IFS                256
 
 /* Set of bitmapped flags for the if descriptor */
 enum {
@@ -67,8 +70,8 @@ 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 */
@@ -87,7 +90,7 @@ static IfDesc* AllocIf (const char* Directive, int NeedTerm)
 
     /* Check for stack overflow */
     if (IfCount >= MAX_IFS) {
-               Error (ERR_IF_NESTING);
+               Fatal ("Too many nested .IFs");
     }
 
     /* Alloc one element */
@@ -95,7 +98,7 @@ static IfDesc* AllocIf (const char* Directive, int NeedTerm)
 
     /* Initialize elements */
     ID->Flags = NeedTerm? ifNeedTerm : ifNone;
-    ID->Pos   = CurPos;
+    ID->Pos   = CurTok.Pos;
     ID->Name  = Directive;
 
     /* Return the result */
@@ -119,11 +122,12 @@ static IfDesc* GetCurrentIf (void)
 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;
@@ -188,7 +192,7 @@ static void SetElse (IfDesc* ID, int E)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
@@ -201,33 +205,34 @@ void DoConditionals (void)
     int IfCond = GetCurrentIfCond ();
     do {
 
-       switch (Tok) {
+       switch (CurTok.Tok) {
 
            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);
                    SetElse (D, 1);
-                   D->Pos = CurPos;
+                   D->Pos = CurTok.Pos;
                    D->Name = ".ELSE";
                    IfCond = GetCurrentIfCond ();
                }
                NextTok ();
+               ExpectSep ();
                        break;
 
                    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);
@@ -243,6 +248,7 @@ void DoConditionals (void)
                     */
                    if (IfCond == 0) {
                        SetIfCond (D, ConstExpression ());
+                       ExpectSep ();
                    }
 
                    /* Get the new overall condition */
@@ -258,6 +264,7 @@ void DoConditionals (void)
                 * has been cleanup up, since we may be at end of file.
                 */
                NextTok ();
+               ExpectSep ();
 
                /* Get the new overall condition */
                IfCond = GetCurrentIfCond ();
@@ -268,6 +275,7 @@ void DoConditionals (void)
                NextTok ();
                if (IfCond) {
                    SetIfCond (D, ConstExpression ());
+                   ExpectSep ();
                }
                IfCond = GetCurrentIfCond ();
                break;
@@ -276,7 +284,12 @@ void DoConditionals (void)
                D = AllocIf (".IFBLANK", 1);
                NextTok ();
                if (IfCond) {
-                   SetIfCond (D, Tok == TOK_SEP);
+                    if (TokIsSep (CurTok.Tok)) {
+                        SetIfCond (D, 1);
+                    } else {
+                       SetIfCond (D, 0);
+                        SkipUntilSep ();
+                    }
                }
                IfCond = GetCurrentIfCond ();
                break;
@@ -286,8 +299,9 @@ void DoConditionals (void)
                NextTok ();
                if (IfCond) {
                    ExprNode* Expr = Expression();
-                   SetIfCond (D, IsConstExpr (Expr));
+                   SetIfCond (D, IsConstExpr (Expr, 0));
                    FreeExpr (Expr);
+                   ExpectSep ();
                }
                IfCond = GetCurrentIfCond ();
                break;
@@ -296,22 +310,23 @@ void DoConditionals (void)
                D = AllocIf (".IFDEF", 1);
                NextTok ();
                if (IfCond) {
-                   if (Tok != TOK_IDENT) {
-                       ErrorSkip (ERR_IDENT_EXPECTED);
-                   } else {
-                       SetIfCond (D, SymIsDef (SVal));
-                       NextTok ();
-                   }
+                           SymEntry* Sym = ParseAnySymName (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 (CurTok.Tok)) {
+                        SetIfCond (D, 0);
+                    } else {
+                       SetIfCond (D, 1);
+                        SkipUntilSep ();
+                    }
+               }
                IfCond = GetCurrentIfCond ();
                break;
 
@@ -320,8 +335,9 @@ void DoConditionals (void)
                NextTok ();
                if (IfCond) {
                    ExprNode* Expr = Expression();
-                   SetIfCond (D, !IsConstExpr (Expr));
+                   SetIfCond (D, !IsConstExpr (Expr, 0));
                    FreeExpr (Expr);
+                   ExpectSep ();
                }
                IfCond = GetCurrentIfCond ();
                break;
@@ -330,12 +346,9 @@ void DoConditionals (void)
                D = AllocIf (".IFNDEF", 1);
                NextTok ();
                if (IfCond) {
-                   if (Tok != TOK_IDENT) {
-                       ErrorSkip (ERR_IDENT_EXPECTED);
-                   } else {
-                       SetIfCond (D, !SymIsDef (SVal));
-                       NextTok ();
-                   }
+                   SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
+                   SetIfCond (D, Sym == 0 || !SymIsDef (Sym));
+                   ExpectSep ();
                }
                IfCond = GetCurrentIfCond ();
                break;
@@ -344,46 +357,104 @@ void DoConditionals (void)
                D = AllocIf (".IFNREF", 1);
                NextTok ();
                if (IfCond) {
-                   if (Tok != TOK_IDENT) {
-                       ErrorSkip (ERR_IDENT_EXPECTED);
-                   } else {
-                       SetIfCond (D, !SymIsRef (SVal));
-                       NextTok ();
-                   }
-               }
+                   SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
+                   SetIfCond (D, Sym == 0 || !SymIsRef (Sym));
+                   ExpectSep ();
+               }
                IfCond = GetCurrentIfCond ();
                break;
 
            case TOK_IFP02:
+                       D = AllocIf (".IFP02", 1);
+               NextTok ();
+               if (IfCond) {
+                   SetIfCond (D, GetCPU() == CPU_6502);
+               }
+               IfCond = GetCurrentIfCond ();
+               ExpectSep ();
                break;
 
            case TOK_IFP816:
+               D = AllocIf (".IFP816", 1);
+               NextTok ();
+               if (IfCond) {
+                           SetIfCond (D, GetCPU() == CPU_65816);
+               }
+               IfCond = GetCurrentIfCond ();
+               ExpectSep ();
                break;
 
            case TOK_IFPC02:
+               D = AllocIf (".IFPC02", 1);
+               NextTok ();
+               if (IfCond) {
+                           SetIfCond (D, GetCPU() == CPU_65C02);
+               }
+               IfCond = GetCurrentIfCond ();
+               ExpectSep ();
+               break;
+
+           case TOK_IFPSC02:
+               D = AllocIf (".IFPSC02", 1);
+               NextTok ();
+               if (IfCond) {
+                           SetIfCond (D, GetCPU() == CPU_65SC02);
+               }
+               IfCond = GetCurrentIfCond ();
+               ExpectSep ();
                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 = ParseAnySymName (SYM_FIND_EXISTING);
+                   SetIfCond (D, Sym != 0 && SymIsRef (Sym));
+                   ExpectSep ();
                }
                IfCond = GetCurrentIfCond ();
                break;
 
            default:
-               // Skip tokens
+               /* Skip tokens */
                NextTok ();
 
        }
 
-    } while (IfCond == 0 && Tok != TOK_EOF);
+    } while (IfCond == 0 && CurTok.Tok != TOK_EOF);
+}
+
+
+
+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 (CurTok.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;
+    }
 }
 
 
@@ -402,17 +473,36 @@ void CheckOpenIfs (void)
            /* There are no open .IFs */
            break;
        }
-         
-       if (D->Pos.Name != CurPos.Name) {
+
+       if (D->Pos.Name != CurTok.Pos.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 ();
     }
 }
 
 
 
+