]> git.sur5r.net Git - cc65/blobdiff - src/ca65/expr.c
Free expression trees when they're no longer needed
[cc65] / src / ca65 / expr.c
index f6b4125477107df62223b3e8ddce84bcf1aa6e58..b5beb8e780c2203384c0a810e842274519ba2e74 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2000 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 #include <string.h>
+#include <time.h>
 
 /* common */
 #include "check.h"
+#include "cpu.h"
 #include "exprdefs.h"
+#include "print.h"
 #include "tgttrans.h"
+#include "version.h"
 #include "xmalloc.h"
 
 /* ca65 */
 #include "error.h"
+#include "expr.h"
 #include "global.h"
 #include "instr.h"
 #include "nexttok.h"
-#include "objcode.h"
+/* #include "objcode.h" */
 #include "objfile.h"
+#include "segment.h"
 #include "symtab.h"
 #include "toklist.h"
 #include "ulabel.h"
-#include "expr.h"
 
 
 
@@ -79,7 +84,7 @@ static unsigned               FreeNodeCount = 0;
 
 
 
-static ExprNode* NewExprNode (void)
+static ExprNode* NewExprNode (unsigned Op)
 /* Create a new expression node */
 {
     ExprNode* N;
@@ -93,7 +98,7 @@ static ExprNode* NewExprNode (void)
        /* Allocate fresh memory */
         N = xmalloc (sizeof (ExprNode));
     }
-    N->Op = EXPR_NULL;
+    N->Op = Op;
     N->Left = N->Right = 0;
     N->Obj = 0;
 
@@ -158,7 +163,7 @@ static int FuncBlank (void)
     } else {
        /* Skip any tokens */
        int Braces = 0;
-       while (Tok != TOK_SEP && Tok != TOK_EOF) {
+       while (!TokIsSep (Tok)) {
            if (Tok == TOK_LPAREN) {
                ++Braces;
            } else if (Tok == TOK_RPAREN) {
@@ -198,18 +203,69 @@ static int FuncConst (void)
 static int FuncDefined (void)
 /* Handle the .DEFINED builtin function */
 {
+    static const char* Keys[] = {
+               "ANY",
+       "GLOBAL",
+        "LOCAL",
+    };
+
+    char Name [sizeof (SVal)];
     int Result = 0;
+    int Scope;
 
+    /* First argument is a symbol name */
     if (Tok != TOK_IDENT) {
        Error (ERR_IDENT_EXPECTED);
        if (Tok != TOK_RPAREN) {
            NextTok ();
        }
+        return 0;
+    }
+
+    /* Remember the name, then skip it */
+    strcpy (Name, SVal);
+    NextTok ();
+
+    /* Comma and scope spec may follow */
+    if (Tok == TOK_COMMA) {
+
+        /* Skip the comma */
+        NextTok ();
+
+        /* An identifier must follow */
+        if (Tok != TOK_IDENT) {
+            Error (ERR_IDENT_EXPECTED);
+            return 0;
+        }
+
+        /* Get the scope, then skip it */
+        Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
+        NextTok ();
+
+        /* Check if we got a valid keyword */
+        if (Scope < 0) {
+            Error (ERR_ILLEGAL_SCOPE);
+            return 0;
+        }
+
+        /* Map the scope */
+        switch (Scope) {
+            case 0:     Scope = SCOPE_ANY;    break;
+            case 1:     Scope = SCOPE_GLOBAL; break;
+            case 2:     Scope = SCOPE_LOCAL;  break;
+            default:    Internal ("Invalid scope: %d", Scope);
+        }
+
     } else {
-       Result = SymIsDef (SVal);
-       NextTok ();
+
+        /* Any scope */
+        Scope = SCOPE_ANY;
+
     }
 
+    /* Search for the symbol */
+    Result = SymIsDef (SVal, Scope);
+
     /* Done */
     return Result;
 }
@@ -231,7 +287,7 @@ static int DoMatch (enum TC EqualityLevel)
     while (Tok != TOK_COMMA) {
 
        /* We may not end-of-line of end-of-file here */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+       if (TokIsSep (Tok)) {
            Error (ERR_UNEXPECTED_EOL);
            return 0;
        }
@@ -262,7 +318,7 @@ static int DoMatch (enum TC EqualityLevel)
     while (Tok != TOK_RPAREN) {
 
        /* We may not end-of-line of end-of-file here */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+       if (TokIsSep (Tok)) {
            Error (ERR_UNEXPECTED_EOL);
            return 0;
        }
@@ -324,7 +380,7 @@ static int FuncReferenced (void)
            NextTok ();
        }
     } else {
-       Result = SymIsRef (SVal);
+       Result = SymIsRef (SVal, SCOPE_ANY);
        NextTok ();
     }
 
@@ -359,7 +415,7 @@ static int FuncStrAt (void)
     Index = ConstExpression ();
 
     /* Must be a valid index */
-    if (Index >= strlen (Str)) {
+    if (Index >= (long) strlen (Str)) {
        Error (ERR_RANGE);
        return 0;
     }
@@ -415,7 +471,7 @@ static int FuncTCount (void)
         * will check for the closing paren, we don't need to print an error
         * here, just bail out.
         */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+       if (TokIsSep (Tok)) {
            break;
        }
 
@@ -459,7 +515,7 @@ static ExprNode* Function (int (*F) (void))
     if (Tok != TOK_LPAREN) {
        Error (ERR_LPAREN_EXPECTED);
        SkipUntilSep ();
-       return LiteralExpr (0);
+       return GenLiteralExpr (0);
     }
     NextTok ();
 
@@ -470,7 +526,7 @@ static ExprNode* Function (int (*F) (void))
     ConsumeRParen ();
 
     /* Return an expression node with the boolean code */
-    return LiteralExpr (Result);
+    return GenLiteralExpr (Result);
 }
 
 
@@ -483,12 +539,12 @@ static ExprNode* Factor (void)
     switch (Tok) {
 
        case TOK_INTCON:
-           N = LiteralExpr (IVal);
+           N = GenLiteralExpr (IVal);
                    NextTok ();
            break;
 
        case TOK_CHARCON:
-           N = LiteralExpr (TgtTranslateChar (IVal));
+           N = GenLiteralExpr (TgtTranslateChar (IVal));
                    NextTok ();
            break;
 
@@ -496,32 +552,28 @@ static ExprNode* Factor (void)
            NextTok ();
            if (Tok != TOK_IDENT) {
                Error (ERR_IDENT_EXPECTED);
-               N = LiteralExpr (0);    /* Dummy */
+               N = GenLiteralExpr (0); /* Dummy */
            } else {
-               S = SymRefGlobal (SVal);
+               S = SymRef (SVal, SCOPE_GLOBAL);
                if (SymIsConst (S)) {
                    /* Use the literal value instead */
-                   N = LiteralExpr (GetSymVal (S));
+                   N = GenLiteralExpr (GetSymVal (S));
                } else {
                    /* Create symbol node */
-                   N = NewExprNode ();
-                   N->Op    = EXPR_SYMBOL;
-                   N->V.Sym = S;
+                   N = GenSymExpr (S);
                }
                NextTok ();
            }
            break;
 
         case TOK_IDENT:
-           S = SymRef (SVal);
+           S = SymRef (SVal, SCOPE_LOCAL);
            if (SymIsConst (S)) {
                /* Use the literal value instead */
-               N = LiteralExpr (GetSymVal (S));
+               N = GenLiteralExpr (GetSymVal (S));
            } else {
                /* Create symbol node */
-               N = NewExprNode ();
-               N->Op    = EXPR_SYMBOL;
-               N->V.Sym = S;
+               N = GenSymExpr (S);
            }
            NextTok ();
            break;
@@ -533,36 +585,32 @@ static ExprNode* Factor (void)
 
        case TOK_MINUS:
            NextTok ();
-           N = NewExprNode ();
+           N = NewExprNode (EXPR_UNARY_MINUS);
                    N->Left = Factor ();
-                   N->Op   = EXPR_UNARY_MINUS;
            break;
 
        case TOK_NOT:
            NextTok ();
-           N = NewExprNode ();
+           N = NewExprNode (EXPR_NOT);
            N->Left = Factor ();
-           N->Op   = EXPR_NOT;
            break;
 
        case TOK_STAR:
        case TOK_PC:
            NextTok ();
-                   N = CurrentPC ();
+                   N = GenCurrentPC ();
            break;
 
        case TOK_LT:
            NextTok ();
-           N = NewExprNode ();
+           N = NewExprNode (EXPR_BYTE0);
            N->Left = Factor ();
-           N->Op   = EXPR_BYTE0;
            break;
 
        case TOK_GT:
            NextTok ();
-           N = NewExprNode ();
+           N = NewExprNode (EXPR_BYTE1);
            N->Left = Factor ();
-           N->Op   = EXPR_BYTE1;
            break;
 
        case TOK_LPAREN:
@@ -580,7 +628,7 @@ static ExprNode* Factor (void)
            break;
 
        case TOK_CPU:
-           N = LiteralExpr (GetCPU());
+           N = GenLiteralExpr (CPUIsets[CPU]);
            NextTok ();
            break;
 
@@ -608,6 +656,17 @@ static ExprNode* Factor (void)
            N = Function (FuncTCount);
            break;
 
+       case TOK_TIME:
+           N = GenLiteralExpr (time (0));
+           NextTok ();
+           break;
+
+        case TOK_VERSION:
+            N = GenLiteralExpr (VERSION);
+            NextTok ();
+            break;
+
+
        case TOK_XMATCH:
            N = Function (FuncXMatch);
            break;
@@ -615,9 +674,9 @@ static ExprNode* Factor (void)
        default:
            if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
                /* A character constant */
-               N = LiteralExpr (TgtTranslateChar (SVal[0]));
+               N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
            } else {
-               N = LiteralExpr (0);    /* Dummy */
+               N = GenLiteralExpr (0); /* Dummy */
                Error (ERR_SYNTAX);
            }
            NextTok ();
@@ -630,32 +689,29 @@ static ExprNode* Factor (void)
 
 static ExprNode* Term (void)
 {
-    ExprNode* Root;
-
     /* Read left hand side */
-    Root = Factor ();
+    ExprNode* Root = Factor ();
 
     /* Handle multiplicative operations */
     while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
           Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
           Tok == TOK_SHR) {
 
-       /* Create a new node and insert the left expression */
+       /* Create the new node */
        ExprNode* Left = Root;
-       Root = NewExprNode ();
-       Root->Left = Left;
-
-       /* Determine the operator token */
        switch (Tok) {
-                   case TOK_MUL:       Root->Op = EXPR_MUL;    break;
-           case TOK_DIV:       Root->Op = EXPR_DIV;    break;
-           case TOK_MOD:       Root->Op = EXPR_MOD;    break;
-                   case TOK_AND:       Root->Op = EXPR_AND;    break;
-                   case TOK_XOR:       Root->Op = EXPR_XOR;    break;
-                   case TOK_SHL:       Root->Op = EXPR_SHL;    break;
-                   case TOK_SHR:       Root->Op = EXPR_SHR;    break;
+                   case TOK_MUL:       Root = NewExprNode (EXPR_MUL);  break;
+                   case TOK_DIV:       Root = NewExprNode (EXPR_DIV);  break;
+                   case TOK_MOD:       Root = NewExprNode (EXPR_MOD);  break;
+                   case TOK_AND:       Root = NewExprNode (EXPR_AND);  break;
+                   case TOK_XOR:       Root = NewExprNode (EXPR_XOR);  break;
+                   case TOK_SHL:       Root = NewExprNode (EXPR_SHL);  break;
+                   case TOK_SHR:       Root = NewExprNode (EXPR_SHR);  break;
            default:            Internal ("Invalid token");
        }
+       Root->Left = Left;
+
+        /* Skip the operator token */
        NextTok ();
 
        /* Parse the right hand side */
@@ -671,26 +727,23 @@ static ExprNode* Term (void)
 
 static ExprNode* SimpleExpr (void)
 {
-    ExprNode* Root;
-
     /* Read left hand side */
-    Root = Term ();
+    ExprNode* Root = Term ();
 
     /* Handle additive operations */
     while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
 
-       /* Create a new node and insert the left expression */
+       /* Create the new node */
        ExprNode* Left = Root;
-       Root = NewExprNode ();
-       Root->Left = Left;
-
-       /* Determine the operator token */
        switch (Tok) {
-                   case TOK_PLUS:      Root->Op = EXPR_PLUS;   break;
-           case TOK_MINUS:     Root->Op = EXPR_MINUS;  break;
-           case TOK_OR:        Root->Op = EXPR_OR;     break;
+                   case TOK_PLUS:      Root = NewExprNode (EXPR_PLUS);         break;
+                   case TOK_MINUS:     Root = NewExprNode (EXPR_MINUS);        break;
+                   case TOK_OR:        Root = NewExprNode (EXPR_OR);           break;
            default:            Internal ("Invalid token");
        }
+       Root->Left = Left;
+
+        /* Skip the operator token */
        NextTok ();
 
        /* Parse the right hand side */
@@ -714,21 +767,20 @@ static ExprNode* BoolExpr (void)
     while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
           Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
 
-       /* Create a new node and insert the left expression */
+       /* Create the new node */
        ExprNode* Left = Root;
-       Root = NewExprNode ();
-       Root->Left = Left;
-
-       /* Determine the operator token */
        switch (Tok) {
-           case TOK_EQ:        Root->Op = EXPR_EQ;     break;
-           case TOK_NE:        Root->Op = EXPR_NE;     break;
-           case TOK_LT:        Root->Op = EXPR_LT;     break;
-           case TOK_GT:        Root->Op = EXPR_GT;     break;
-           case TOK_LE:        Root->Op = EXPR_LE;     break;
-           case TOK_GE:        Root->Op = EXPR_GE;     break;
+                   case TOK_EQ:        Root = NewExprNode (EXPR_EQ);   break;
+                   case TOK_NE:        Root = NewExprNode (EXPR_NE);   break;
+                   case TOK_LT:        Root = NewExprNode (EXPR_LT);   break;
+                   case TOK_GT:        Root = NewExprNode (EXPR_GT);   break;
+                   case TOK_LE:        Root = NewExprNode (EXPR_LE);   break;
+                   case TOK_GE:        Root = NewExprNode (EXPR_GE);   break;
            default:            Internal ("Invalid token");
        }
+       Root->Left = Left;
+
+        /* Skip the operator token */
        NextTok ();
 
        /* Parse the right hand side */
@@ -751,17 +803,16 @@ static ExprNode* Expr2 (void)
     /* Handle booleans */
     while (Tok == TOK_BAND || Tok == TOK_BXOR) {
 
-       /* Create a new node and insert the left expression */
+       /* Create the new node */
        ExprNode* Left = Root;
-       Root = NewExprNode ();
-       Root->Left = Left;
-
-       /* Determine the operator token */
        switch (Tok) {
-           case TOK_BAND:      Root->Op = EXPR_BAND;   break;
-           case TOK_BXOR:      Root->Op = EXPR_BXOR;   break;
+                   case TOK_BAND:      Root = NewExprNode (EXPR_BAND); break;
+                   case TOK_BXOR:      Root = NewExprNode (EXPR_BXOR); break;
            default:            Internal ("Invalid token");
        }
+       Root->Left = Left;
+
+        /* Skip the operator token */
        NextTok ();
 
        /* Parse the right hand side */
@@ -784,16 +835,15 @@ static ExprNode* Expr1 (void)
     /* Handle booleans */
     while (Tok == TOK_BOR) {
 
-       /* Create a new node and insert the left expression */
+       /* Create the new node */
        ExprNode* Left = Root;
-       Root = NewExprNode ();
-       Root->Left = Left;
-
-       /* Determine the operator token */
        switch (Tok) {
-           case TOK_BOR:       Root->Op = EXPR_BOR;    break;
+                   case TOK_BOR:       Root = NewExprNode (EXPR_BOR);  break;
            default:            Internal ("Invalid token");
        }
+       Root->Left = Left;
+
+        /* Skip the operator token */
        NextTok ();
 
        /* Parse the right hand side */
@@ -815,14 +865,10 @@ static ExprNode* Expr0 (void)
     /* Handle booleans */
     if (Tok == TOK_BNOT) {
 
-               /* Create a new node */
-       Root = NewExprNode ();
+       /* Create the new node */
+        Root = NewExprNode (EXPR_BNOT);
 
-       /* Determine the operator token */
-       switch (Tok) {
-           case TOK_BNOT:      Root->Op = EXPR_BNOT;   break;
-           default:            Internal ("Invalid token");
-       }
+        /* Skip the operator token */
        NextTok ();
 
        /* Parse the left hand side, allow more BNOTs */
@@ -845,8 +891,8 @@ static ExprNode* SimplifyExpr (ExprNode* Root)
 /* Try to simplify the given expression tree */
 {
     if (Root) {
-       SimplifyExpr (Root->Left);
-       SimplifyExpr (Root->Right);
+               Root->Left  = SimplifyExpr (Root->Left);
+       Root->Right = SimplifyExpr (Root->Right);
        if (IsConstExpr (Root)) {
            /* The complete expression is constant */
            Root->V.Val = GetExprVal (Root);
@@ -877,52 +923,88 @@ long ConstExpression (void)
  * not constant.
  */
 {
+    long Val;
+
     /* Read the expression, and call finalize (exception here, since we
      * expect a const).
      */
     ExprNode* Expr = FinalizeExpr (Expression ());
 
-    /* Return the value */
+    /* Get the value */
     if (IsConstExpr (Expr)) {
-       return GetExprVal (Expr);
+       Val = GetExprVal (Expr);
     } else {
        Error (ERR_CONSTEXPR_EXPECTED);
-       return 0;
+       Val = 0;
+    }
+
+    /* Free the expression tree and return the value */
+    FreeExpr (Expr);
+    return Val;
+}
+
+
+
+void FreeExpr (ExprNode* Root)
+/* Free the expression, Root is pointing to. */
+{
+    if (Root) {
+       FreeExpr (Root->Left);
+       FreeExpr (Root->Right);
+        if (Root->Op == EXPR_SYMBOL) {
+            /* Remove the symbol reference */
+            SymDelRef (Root->V.Sym, Root);
+        }
+       FreeExprNode (Root);
     }
 }
 
 
 
-ExprNode* LiteralExpr (long Val)
+ExprNode* GenLiteralExpr (long Val)
 /* Return an expression tree that encodes the given literal value */
 {
-    ExprNode* Expr = NewExprNode ();
-    Expr->Op = EXPR_LITERAL;
+    ExprNode* Expr = NewExprNode (EXPR_LITERAL);
     Expr->V.Val = Val;
     return Expr;
 }
 
 
 
-ExprNode* CurrentPC (void)
+ExprNode* GenSymExpr (SymEntry* Sym)
+/* Return an expression node that encodes the given symbol */
+{
+    ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
+    Expr->V.Sym = Sym;
+    SymAddRef (Sym, Expr);
+    return Expr;
+}
+
+
+
+static ExprNode* GenSectionExpr (unsigned SegNum)
+/* Return an expression node for the given section */
+{
+    ExprNode* Expr = NewExprNode (EXPR_SECTION);
+    Expr->V.SegNum = SegNum;
+    return Expr;
+}
+
+
+
+ExprNode* GenCurrentPC (void)
 /* Return the current program counter as expression */
 {
-    ExprNode* Left;
     ExprNode* Root;
 
     if (RelocMode) {
        /* Create SegmentBase + Offset */
-       Left = NewExprNode ();
-       Left->Op = EXPR_SEGMENT;
-       Left->V.SegNum = GetSegNum ();
-
-       Root = NewExprNode ();
-       Root->Left  = Left;
-       Root->Right = LiteralExpr (GetPC ());
-       Root->Op = EXPR_PLUS;
+       Root = NewExprNode (EXPR_PLUS);
+       Root->Left  = GenSectionExpr (GetSegNum ());
+       Root->Right = GenLiteralExpr (GetPC ());
     } else {
-       /* Absolute mode, just return PC value */
-       Root = LiteralExpr (GetPC ());
+       /* Absolute mode, just return PC value */
+       Root = GenLiteralExpr (GetPC ());
     }
 
     return Root;
@@ -930,45 +1012,37 @@ ExprNode* CurrentPC (void)
 
 
 
-ExprNode* SwapExpr (ExprNode* Expr)
+ExprNode* GenSwapExpr (ExprNode* Expr)
 /* Return an extended expression with lo and hi bytes swapped */
 {
-    ExprNode* N = NewExprNode ();
-    N->Op = EXPR_SWAP;
+    ExprNode* N = NewExprNode (EXPR_SWAP);
     N->Left = Expr;
     return N;
 }
 
 
 
-ExprNode* BranchExpr (unsigned Offs)
+ExprNode* GenBranchExpr (unsigned Offs)
 /* Return an expression that encodes the difference between current PC plus
  * offset and the target expression (that is, Expression() - (*+Offs) ).
  */
 {
     ExprNode* N;
     ExprNode* Root;
-    ExprNode* Left;
 
     /* Create *+Offs */
     if (RelocMode) {
-       Left = NewExprNode ();
-       Left->Op = EXPR_SEGMENT;
-       Left->V.SegNum = GetSegNum ();
-
-       N = NewExprNode ();
-       N->Left  = Left;
-       N->Right = LiteralExpr (GetPC () + Offs);
-       N->Op = EXPR_PLUS;
+       N = NewExprNode (EXPR_PLUS);
+       N->Left  = GenSectionExpr (GetSegNum ());
+       N->Right = GenLiteralExpr (GetPC () + Offs);
     } else {
-       N = LiteralExpr (GetPC () + Offs);
+       N = GenLiteralExpr (GetPC () + Offs);
     }
 
     /* Create the root node */
-    Root = NewExprNode ();
+    Root = NewExprNode (EXPR_MINUS);
     Root->Left = Expression ();
     Root->Right = N;
-    Root->Op = EXPR_MINUS;
 
     /* Return the result */
     return SimplifyExpr (Root);
@@ -976,14 +1050,10 @@ ExprNode* BranchExpr (unsigned Offs)
 
 
 
-ExprNode* ULabelExpr (unsigned Num)
+ExprNode* GenULabelExpr (unsigned Num)
 /* Return an expression for an unnamed label with the given index */
 {
-    /* Get an expression node */
-    ExprNode* Node = NewExprNode ();
-
-    /* Set the values */
-    Node->Op   = EXPR_ULABEL;
+    ExprNode* Node = NewExprNode (EXPR_ULABEL);
     Node->V.Val        = Num;
 
     /* Return the new node */
@@ -992,26 +1062,40 @@ ExprNode* ULabelExpr (unsigned Num)
 
 
 
-void FreeExpr (ExprNode* Root)
-/* Free the expression, Root is pointing to. */
+ExprNode* GenByteExpr (ExprNode* Expr)
+/* Force the given expression into a byte and return the result */
 {
-    if (Root) {
-       FreeExpr (Root->Left);
-       FreeExpr (Root->Right);
-       FreeExprNode (Root);
-    }
+    /* Use the low byte operator to force the expression into byte size */
+    ExprNode* Root = NewExprNode (EXPR_BYTE0);
+    Root->Left  = Expr;
+
+    /* Return the result */
+    return Root;
 }
 
 
 
-ExprNode* ForceWordExpr (ExprNode* Expr)
+ExprNode* GenWordExpr (ExprNode* Expr)
 /* Force the given expression into a word and return the result. */
 {
-    /* And the expression by $FFFF to force it into word size */
-    ExprNode* Root = NewExprNode ();
+    /* AND the expression by $FFFF to force it into word size */
+    ExprNode* Root = NewExprNode (EXPR_AND);
+    Root->Left  = Expr;
+    Root->Right        = GenLiteralExpr (0xFFFF);
+
+    /* Return the result */
+    return Root;
+}
+
+
+
+ExprNode* GenNE (ExprNode* Expr, long Val)
+/* Generate an expression that compares Expr and Val for inequality */
+{
+    /* Generate a compare node */
+    ExprNode* Root = NewExprNode (EXPR_NE);
     Root->Left  = Expr;
-    Root->Op    = EXPR_AND;
-    Root->Right        = LiteralExpr (0xFFFF);
+    Root->Right        = GenLiteralExpr (Val);
 
     /* Return the result */
     return Root;
@@ -1036,7 +1120,7 @@ int IsConstExpr (ExprNode* Root)
            case EXPR_SYMBOL:
                Sym = Root->V.Sym;
                if (SymHasUserMark (Sym)) {
-                   if (Verbose) {
+                   if (Verbosity > 0) {
                        DumpExpr (Root);
                    }
                    PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
@@ -1069,7 +1153,7 @@ int IsConstExpr (ExprNode* Root)
                    } else {
                        return IsConstExpr (Root->Right);
                    }
-               } else {
+               } else {
                    /* lhs not const --> tree not const */
                    return 0;
                }
@@ -1112,13 +1196,13 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte)
                    case EXPR_SYMBOL:
                        if (SymIsZP (N->V.Sym)) {
                            *IsByte = 1;
-                       } else if (SymHasExpr (N->V.Sym)) {
+                       } else if (SymHasExpr (N->V.Sym)) {
                            /* Check if this expression is a byte expression */
                            *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
                        }
                        break;
 
-                   case EXPR_SEGMENT:
+                   case EXPR_SECTION:
                        if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
                            *IsByte = 1;
                        }
@@ -1307,31 +1391,31 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
 
        case EXPR_SYMBOL:
            if (SymHasExpr (Expr->V.Sym)) {
-               /* The symbol has an expression tree */
-               SymEntry* Sym = Expr->V.Sym;
-               if (SymHasUserMark (Sym)) {
-                   /* Circular definition */
-                   if (Verbose) {
-                       DumpExpr (Expr);
-                   }
-                   PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
-                   return LiteralExpr (0);             /* Return a dummy value */
-               }
-               SymMarkUser (Sym);
-               Expr = RemoveSyms (GetSymExpr (Sym), 1);
-               SymUnmarkUser (Sym);
-               return Expr;
+               /* The symbol has an expression tree */
+               SymEntry* Sym = Expr->V.Sym;
+               if (SymHasUserMark (Sym)) {
+                   /* Circular definition */
+                   if (Verbosity) {
+                       DumpExpr (Expr);
+                   }
+                   PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
+                   return GenLiteralExpr (0);          /* Return a dummy value */
+               }
+               SymMarkUser (Sym);
+               Expr = RemoveSyms (GetSymExpr (Sym), 1);
+               SymUnmarkUser (Sym);
+               return Expr;
            } else if (SymIsConst (Expr->V.Sym)) {
-               /* The symbol is a constant */
-               return LiteralExpr (GetSymVal (Expr->V.Sym));
+               /* The symbol is a constant */
+               return GenLiteralExpr (GetSymVal (Expr->V.Sym));
            }
            break;
 
        case EXPR_ULABEL:
            if (ULabCanResolve ()) {
-               ExprNode* NewExpr = ULabResolve (Expr->V.Val);
-               FreeExpr (Expr);
-               Expr = NewExpr;
+               ExprNode* NewExpr = ULabResolve (Expr->V.Val);
+               FreeExpr (Expr);
+               Expr = NewExpr;
            }
            break;
 
@@ -1340,33 +1424,34 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
     /* Clone the current node if needed */
     if (MustClone) {
 
-       /* Create a new node */
-               ExprNode* Clone = NewExprNode ();
-
-       /* Clone the operation */
-       Clone->Op = Expr->Op;
+               ExprNode* Clone;
 
-       /* Clone the attribute if needed */
+       /* Clone the expression tree */
        switch (Expr->Op) {
 
            case EXPR_LITERAL:
+                Clone = GenLiteralExpr (Expr->V.Val);
+                break;
+
            case EXPR_ULABEL:
-               Clone->V.Val = Expr->V.Val;
-               break;
+                Clone = GenULabelExpr (Expr->V.Val);
+                break;
 
            case EXPR_SYMBOL:
-               Clone->V.Sym = Expr->V.Sym;
-               break;
+                Clone = GenSymExpr (Expr->V.Sym);
+                break;
 
-           case EXPR_SEGMENT:
-               Clone->V.SegNum = Expr->V.SegNum;
-               break;
+           case EXPR_SECTION:
+                Clone = GenSectionExpr (Expr->V.SegNum);
+                break;
 
-       }
+            default:
+                Clone = NewExprNode (Expr->Op);
+                Clone->Left  = RemoveSyms (Expr->Left, 1);
+                Clone->Right = RemoveSyms (Expr->Right, 1);
+                break;
 
-       /* Clone the tree nodes */
-               Clone->Left = RemoveSyms (Expr->Left, MustClone);
-       Clone->Right = RemoveSyms (Expr->Right, MustClone);
+       }
 
        /* Done */
        return Clone;
@@ -1374,12 +1459,11 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
     } else {
 
        /* Nothing to clone */
-       Expr->Left = RemoveSyms (Expr->Left, MustClone);
-       Expr->Right = RemoveSyms (Expr->Right, MustClone);
+               Expr->Left  = RemoveSyms (Expr->Left, 0);
+       Expr->Right = RemoveSyms (Expr->Right, 0);
 
        /* Done */
        return Expr;
-
     }
 }
 
@@ -1419,7 +1503,7 @@ static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
            return Left;
        } else {
            /* Check for SEG - SEG which is now possible */
-           if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
+           if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
                Left->V.SegNum == Right->V.SegNum) {
                /* SEG - SEG, remove it completely */
                FreeExprNode (Left);
@@ -1461,13 +1545,12 @@ ExprNode* FinalizeExpr (ExprNode* Expr)
     Expr = ConstExtract (Expr, &Val, 1);
     if (Expr == 0) {
        /* Reduced to a literal value */
-       Expr = LiteralExpr (Val);
+       Expr = GenLiteralExpr (Val);
     } else if (Val) {
        /* Extracted a value */
-       N = NewExprNode ();
-       N->Op = EXPR_PLUS;
+       N = NewExprNode (EXPR_PLUS);
        N->Left = Expr;
-       N->Right = LiteralExpr (Val);
+       N->Right = GenLiteralExpr (Val);
        Expr = N;
     }
     return Expr;
@@ -1487,34 +1570,34 @@ ExprNode* CloneExpr (ExprNode* Expr)
         return 0;
     }
 
-    /* Get a new node */
-    Clone = NewExprNode ();
-
-    /* Clone the operation */
-    Clone->Op = Expr->Op;
-
-    /* Clone the attribute if needed */
+    /* Clone the node */
     switch (Expr->Op) {
 
        case EXPR_LITERAL:
+            Clone = GenLiteralExpr (Expr->V.Val);
+            break;
+
        case EXPR_ULABEL:
-           Clone->V.Val = Expr->V.Val;
+           Clone = GenULabelExpr (Expr->V.Val);
            break;
 
        case EXPR_SYMBOL:
-           Clone->V.Sym = Expr->V.Sym;
+           Clone = GenSymExpr (Expr->V.Sym);
            break;
 
-       case EXPR_SEGMENT:
-           Clone->V.SegNum = Expr->V.SegNum;
+       case EXPR_SECTION:
+           Clone = GenSectionExpr (Expr->V.SegNum);
            break;
 
+        default:
+            /* Generate a new node */
+            Clone = NewExprNode (Expr->Op);
+            /* Clone the tree nodes */
+            Clone->Left = CloneExpr (Expr->Left);
+            Clone->Right = CloneExpr (Expr->Right);
+            break;
     }
 
-    /* Clone the tree nodes */
-    Clone->Left = CloneExpr (Expr->Left);
-    Clone->Right = CloneExpr (Expr->Right);
-
     /* Done */
     return Clone;
 }
@@ -1545,10 +1628,10 @@ void WriteExpr (ExprNode* Expr)
         case EXPR_SYMBOL:
            /* Maybe we should use a code here? */
            CHECK (SymIsImport (Expr->V.Sym));  /* Safety */
-           ObjWrite16 (GetSymIndex (Expr->V.Sym));
+           ObjWriteVar (GetSymIndex (Expr->V.Sym));
            break;
 
-        case EXPR_SEGMENT:
+        case EXPR_SECTION:
            ObjWrite8 (Expr->V.SegNum);
            break;
 
@@ -1567,3 +1650,4 @@ void WriteExpr (ExprNode* Expr)
 
 
 
+