]> git.sur5r.net Git - cc65/blobdiff - src/ld65/expr.c
Add translation from PETSCII to screen codes.
[cc65] / src / ld65 / expr.c
index a59e1f2becd2696b76af6f6aa47616f68cca4637..2a08b5a9858c9adc913a7dcd00431913515d941c 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                 expr.c                                   */
+/*                                  expr.c                                   */
 /*                                                                           */
-/*                Expression evaluation for the ld65 linker                 */
+/*                 Expression evaluation for the ld65 linker                 */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2000 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 #include "global.h"
 #include "error.h"
 #include "fileio.h"
+#include "memarea.h"
 #include "segments.h"
 #include "expr.h"
 
 
 
 /*****************************************************************************/
-/*                                 Helpers                                  */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
 
-static ExprNode* NewExprNode (ObjData* O)
+ExprNode* NewExprNode (ObjData* O, unsigned char Op)
 /* Create a new expression node */
 {
     /* Allocate fresh memory */
     ExprNode* N = xmalloc (sizeof (ExprNode));
-    N->Op      = EXPR_NULL;
-    N->Left    = 0;
-    N->Right   = 0;
-    N->Obj     = O;
-    N->V.Val   = 0;
+    N->Op       = Op;
+    N->Left     = 0;
+    N->Right    = 0;
+    N->Obj      = O;
+    N->V.IVal   = 0;
 
     return N;
 }
@@ -78,19 +79,13 @@ static void FreeExprNode (ExprNode* E)
 
 
 
-/*****************************************************************************/
-/*                                          Code                                    */
-/*****************************************************************************/
-
-
-
 void FreeExpr (ExprNode* Root)
 /* Free the expression, Root is pointing to. */
 {
     if (Root) {
-       FreeExpr (Root->Left);
-       FreeExpr (Root->Right);
-       FreeExprNode (Root);
+        FreeExpr (Root->Left);
+        FreeExpr (Root->Right);
+        FreeExprNode (Root);
     }
 }
 
@@ -98,82 +93,125 @@ void FreeExpr (ExprNode* Root)
 
 int IsConstExpr (ExprNode* Root)
 /* Return true if the given expression is a constant expression, that is, one
- * with no references to external symbols.
- */
+** with no references to external symbols.
+*/
 {
-    int Const;
-    Export* E;
+    int         Const;
+    Export*     E;
+    Section*    S;
+    MemoryArea* M;
 
     if (EXPR_IS_LEAF (Root->Op)) {
-       switch (Root->Op) {
-
-           case EXPR_LITERAL:
-               return 1;
-
-           case EXPR_SYMBOL:
-               /* Get the referenced export */
-                       E = GetExprExport (Root);
-               /* If this export has a mark set, we've already encountered it.
-                * This means that the export is used to define it's own value,
-                * which in turn means, that we have a circular reference.
-                */
-               if (ExportHasMark (E)) {
-                   Error ("Circular reference for symbol `%s', %s(%lu)",
-                          E->Name, GetSourceFileName (E->Obj, E->Pos.Name),
-                          E->Pos.Line);
-                   Const = 0;
-               } else {
-                   MarkExport (E);
-                   Const = IsConstExport (E);
-                   UnmarkExport (E);
-               }
-               return Const;
-
-           default:
-               return 0;
-
-       }
+        switch (Root->Op) {
+
+            case EXPR_LITERAL:
+                return 1;
+
+            case EXPR_SYMBOL:
+                /* Get the referenced export */
+                E = GetExprExport (Root);
+                /* If this export has a mark set, we've already encountered it.
+                ** This means that the export is used to define it's own value,
+                ** which in turn means, that we have a circular reference.
+                */
+                if (ExportHasMark (E)) {
+                    CircularRefError (E);
+                    Const = 0;
+                } else {
+                    MarkExport (E);
+                    Const = IsConstExport (E);
+                    UnmarkExport (E);
+                }
+                return Const;
+
+            case EXPR_SECTION:
+                /* A section expression is const if the segment it is in is
+                ** not relocatable and already placed.
+                */
+                S = GetExprSection (Root);
+                M = S->Seg->MemArea;
+                return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;
+
+            case EXPR_SEGMENT:
+                /* A segment is const if it is not relocatable and placed */
+                M = Root->V.Seg->MemArea;
+                return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;
+
+            case EXPR_MEMAREA:
+                /* A memory area is const if it is not relocatable and placed */
+                return !Root->V.Mem->Relocatable &&
+                       (Root->V.Mem->Flags & MF_PLACED);
+
+            default:
+                /* Anything else is not const */
+                return 0;
+
+        }
+
     } else if (EXPR_IS_UNARY (Root->Op)) {
 
-       return IsConstExpr (Root->Left);
+        SegExprDesc D;
+
+        /* Special handling for the BANK pseudo function */
+        switch (Root->Op) {
+
+            case EXPR_BANK:
+                /* Get segment references for the expression */
+                GetSegExprVal (Root->Left, &D);
+
+                /* The expression is const if the expression contains exactly
+                ** one segment that is assigned to a memory area which has a
+                ** bank attribute that is constant.
+                */
+                return (D.TooComplex              == 0  &&
+                        D.Seg                     != 0  &&
+                        D.Seg->MemArea            != 0  &&
+                        D.Seg->MemArea->BankExpr  != 0  &&
+                        IsConstExpr (D.Seg->MemArea->BankExpr));
+
+            default:
+                /* All others handled normal */
+                return IsConstExpr (Root->Left);
+
+        }
 
     } else {
 
-       /* We must handle shortcut boolean expressions here */
-       switch (Root->Op) {
-
-           case EXPR_BAND:
-               if (IsConstExpr (Root->Left)) {
-                   /* lhs is const, if it is zero, don't eval right */
-                   if (GetExprVal (Root->Left) == 0) {
-                       return 1;
-                   } else {
-                       return IsConstExpr (Root->Right);
-                   }
-               } else {
-                   /* lhs not const --> tree not const */
-                   return 0;
-               }
-               break;
-
-           case EXPR_BOR:
-               if (IsConstExpr (Root->Left)) {
-                   /* lhs is const, if it is not zero, don't eval right */
-                   if (GetExprVal (Root->Left) != 0) {
-                       return 1;
-                   } else {
-                       return IsConstExpr (Root->Right);
-                   }
-               } else {
-                   /* lhs not const --> tree not const */
-                   return 0;
-               }
-               break;
-
-           default:
-               /* All others are handled normal */
-               return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
-       }
+        /* We must handle shortcut boolean expressions here */
+        switch (Root->Op) {
+
+            case EXPR_BOOLAND:
+                if (IsConstExpr (Root->Left)) {
+                    /* lhs is const, if it is zero, don't eval right */
+                    if (GetExprVal (Root->Left) == 0) {
+                        return 1;
+                    } else {
+                        return IsConstExpr (Root->Right);
+                    }
+                } else {
+                    /* lhs not const --> tree not const */
+                    return 0;
+                }
+                break;
+
+            case EXPR_BOOLOR:
+                if (IsConstExpr (Root->Left)) {
+                    /* lhs is const, if it is not zero, don't eval right */
+                    if (GetExprVal (Root->Left) != 0) {
+                        return 1;
+                    } else {
+                        return IsConstExpr (Root->Right);
+                    }
+                } else {
+                    /* lhs not const --> tree not const */
+                    return 0;
+                }
+                break;
+
+            default:
+                /* All others are handled normal */
+                return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
+        }
     }
 }
 
@@ -185,8 +223,16 @@ Import* GetExprImport (ExprNode* Expr)
     /* Check that this is really a symbol */
     PRECONDITION (Expr->Op == EXPR_SYMBOL);
 
-    /* Return the import */
-    return Expr->Obj->Imports [Expr->V.ImpNum];
+    /* If we have an object file, get the import from it, otherwise
+    ** (internally generated expressions), get the import from the
+    ** import pointer.
+    */
+    if (Expr->Obj) {
+        /* Return the Import */
+        return GetObjImport (Expr->Obj, Expr->V.ImpNum);
+    } else {
+        return Expr->V.Imp;
+    }
 }
 
 
@@ -197,8 +243,8 @@ Export* GetExprExport (ExprNode* Expr)
     /* Check that this is really a symbol */
     PRECONDITION (Expr->Op == EXPR_SYMBOL);
 
-    /* Return the export */
-    return Expr->Obj->Imports [Expr->V.ImpNum]->V.Exp;
+    /* Return the export for an import*/
+    return GetExprImport (Expr)->Exp;
 }
 
 
@@ -210,14 +256,14 @@ Section* GetExprSection (ExprNode* Expr)
     PRECONDITION (Expr->Op == EXPR_SECTION);
 
     /* If we have an object file, get the section from it, otherwise
-     * (internally generated expressions), get the section from the
-     * section pointer.
-     */
+    ** (internally generated expressions), get the section from the
+    ** section pointer.
+    */
     if (Expr->Obj) {
-       /* Return the export */
-       return Expr->Obj->Sections [Expr->V.SegNum];
+        /* Return the export */
+        return CollAt (&Expr->Obj->Sections, Expr->V.SecNum);
     } else {
-       return Expr->V.Sec;
+        return Expr->V.Sec;
     }
 }
 
@@ -226,166 +272,299 @@ Section* GetExprSection (ExprNode* Expr)
 long GetExprVal (ExprNode* Expr)
 /* Get the value of a constant expression */
 {
-    long Right, Left, Val;
-    Section* S;
-    Export* E;
+    long        Right;
+    long        Left;
+    long        Val;
+    Section*    S;
+    Export*     E;
+    SegExprDesc D;
 
     switch (Expr->Op) {
 
-               case EXPR_LITERAL:
-           return Expr->V.Val;
-
-               case EXPR_SYMBOL:
-           /* Get the referenced export */
-                   E = GetExprExport (Expr);
-           /* If this export has a mark set, we've already encountered it.
-            * This means that the export is used to define it's own value,
-            * which in turn means, that we have a circular reference.
-            */
-           if (ExportHasMark (E)) {
-               CircularRefError (E);
-               Val = 0;
-           } else {
-               MarkExport (E);
-               Val = GetExportVal (E);
-               UnmarkExport (E);
-           }
-           return Val;
+        case EXPR_LITERAL:
+            return Expr->V.IVal;
+
+        case EXPR_SYMBOL:
+            /* Get the referenced export */
+            E = GetExprExport (Expr);
+            /* If this export has a mark set, we've already encountered it.
+            ** This means that the export is used to define it's own value,
+            ** which in turn means, that we have a circular reference.
+            */
+            if (ExportHasMark (E)) {
+                CircularRefError (E);
+                Val = 0;
+            } else {
+                MarkExport (E);
+                Val = GetExportVal (E);
+                UnmarkExport (E);
+            }
+            return Val;
 
         case EXPR_SECTION:
-                   S = GetExprSection (Expr);
-           return S->Offs + S->Seg->PC;
+            S = GetExprSection (Expr);
+            return S->Offs + S->Seg->PC;
 
-       case EXPR_SEGMENT:
-                   return Expr->V.Seg->PC;
+        case EXPR_SEGMENT:
+            return Expr->V.Seg->PC;
 
         case EXPR_MEMAREA:
             return Expr->V.Mem->Start;
 
-               case EXPR_PLUS:
-           return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
+        case EXPR_PLUS:
+            return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
 
-               case EXPR_MINUS:
-           return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
+        case EXPR_MINUS:
+            return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
 
-               case EXPR_MUL:
-           return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
+        case EXPR_MUL:
+            return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
 
-               case EXPR_DIV:
-           Left  = GetExprVal (Expr->Left);
-           Right = GetExprVal (Expr->Right);
-           if (Right == 0) {
-               Error ("Division by zero");
-           }
-           return Left / Right;
+        case EXPR_DIV:
+            Left  = GetExprVal (Expr->Left);
+            Right = GetExprVal (Expr->Right);
+            if (Right == 0) {
+                Error ("Division by zero");
+            }
+            return Left / Right;
 
-               case EXPR_MOD:
-           Left  = GetExprVal (Expr->Left);
-           Right = GetExprVal (Expr->Right);
-           if (Right == 0) {
-               Error ("Modulo operation with zero");
-           }
-           return Left % Right;
+        case EXPR_MOD:
+            Left  = GetExprVal (Expr->Left);
+            Right = GetExprVal (Expr->Right);
+            if (Right == 0) {
+                Error ("Modulo operation with zero");
+            }
+            return Left % Right;
 
-               case EXPR_OR:
-                   return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
+        case EXPR_OR:
+            return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
 
-               case EXPR_XOR:
-                   return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
+        case EXPR_XOR:
+            return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
 
-               case EXPR_AND:
-                   return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
+        case EXPR_AND:
+            return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
 
-               case EXPR_SHL:
-                   return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
+        case EXPR_SHL:
+            return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
 
-               case EXPR_SHR:
-                   return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
+        case EXPR_SHR:
+            return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
 
-               case EXPR_EQ:
-                   return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
+        case EXPR_EQ:
+            return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
 
-               case EXPR_NE:
-                   return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
+        case EXPR_NE:
+            return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
 
-               case EXPR_LT:
-           return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
+        case EXPR_LT:
+            return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
 
-               case EXPR_GT:
-           return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
+        case EXPR_GT:
+            return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
 
-               case EXPR_LE:
-           return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
+        case EXPR_LE:
+            return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
 
-               case EXPR_GE:
-           return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
+        case EXPR_GE:
+            return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
 
-               case EXPR_UNARY_MINUS:
-           return -GetExprVal (Expr->Left);
+        case EXPR_BOOLAND:
+            return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
 
-               case EXPR_NOT:
-           return ~GetExprVal (Expr->Left);
+        case EXPR_BOOLOR:
+            return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
 
-               case EXPR_BYTE0:
-           return GetExprVal (Expr->Left) & 0xFF;
+        case EXPR_BOOLXOR:
+            return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
 
-               case EXPR_BYTE1:
-           return (GetExprVal (Expr->Left) >> 8) & 0xFF;
+        case EXPR_MAX:
+            Left = GetExprVal (Expr->Left);
+            Right = GetExprVal (Expr->Right);
+            return (Left > Right)? Left : Right;
 
-               case EXPR_BYTE2:
-           return (GetExprVal (Expr->Left) >> 16) & 0xFF;
+        case EXPR_MIN:
+            Left = GetExprVal (Expr->Left);
+            Right = GetExprVal (Expr->Right);
+            return (Left < Right)? Left : Right;
 
-               case EXPR_BYTE3:
-           return (GetExprVal (Expr->Left) >> 24) & 0xFF;
+        case EXPR_UNARY_MINUS:
+            return -GetExprVal (Expr->Left);
+
+        case EXPR_NOT:
+            return ~GetExprVal (Expr->Left);
 
         case EXPR_SWAP:
-           Left = GetExprVal (Expr->Left);
-           return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
+            Left = GetExprVal (Expr->Left);
+            return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
+
+        case EXPR_BOOLNOT:
+            return !GetExprVal (Expr->Left);
+
+        case EXPR_BANK:
+            GetSegExprVal (Expr->Left, &D);
+            if (D.TooComplex || D.Seg == 0) {
+                Error ("Argument for .BANK is not segment relative or too complex");
+            }
+            if (D.Seg->MemArea == 0) {
+                Error ("Segment '%s' is referenced by .BANK but "
+                       "not assigned to a memory area",
+                       GetString (D.Seg->Name));
+            }
+            if (D.Seg->MemArea->BankExpr == 0) {
+                Error ("Memory area '%s' is referenced by .BANK but "
+                       "has no BANK attribute",
+                       GetString (D.Seg->MemArea->Name));
+            }
+            return GetExprVal (D.Seg->MemArea->BankExpr);
+
+        case EXPR_BYTE0:
+            return GetExprVal (Expr->Left) & 0xFF;
+
+        case EXPR_BYTE1:
+            return (GetExprVal (Expr->Left) >> 8) & 0xFF;
+
+        case EXPR_BYTE2:
+            return (GetExprVal (Expr->Left) >> 16) & 0xFF;
+
+        case EXPR_BYTE3:
+            return (GetExprVal (Expr->Left) >> 24) & 0xFF;
+
+        case EXPR_WORD0:
+            return GetExprVal (Expr->Left) & 0xFFFF;
+
+        case EXPR_WORD1:
+            return (GetExprVal (Expr->Left) >> 16) & 0xFFFF;
+
+        case EXPR_FARADDR:
+            return GetExprVal (Expr->Left) & 0xFFFFFF;
+
+        case EXPR_DWORD:
+            return GetExprVal (Expr->Left) & 0xFFFFFFFF;
+
+        default:
+            Internal ("Unknown expression Op type: %u", Expr->Op);
+            /* NOTREACHED */
+            return 0;
+    }
+}
+
 
-       case EXPR_BAND:
-           return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
 
-       case EXPR_BOR:
-           return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
+static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign)
+/* Check if the given expression consists of a segment reference and only
+** constant values, additions and subtractions. If anything else is found,
+** set D->TooComplex to true.
+** Internal, recursive routine.
+*/
+{
+    Export* E;
+
+    switch (Expr->Op) {
 
-       case EXPR_BXOR:
-           return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
+        case EXPR_LITERAL:
+            D->Val += (Sign * Expr->V.IVal);
+            break;
+
+        case EXPR_SYMBOL:
+            /* Get the referenced export */
+            E = GetExprExport (Expr);
+            /* If this export has a mark set, we've already encountered it.
+            ** This means that the export is used to define it's own value,
+            ** which in turn means, that we have a circular reference.
+            */
+            if (ExportHasMark (E)) {
+                CircularRefError (E);
+            } else {
+                MarkExport (E);
+                GetSegExprValInternal (E->Expr, D, Sign);
+                UnmarkExport (E);
+            }
+            break;
 
-       case EXPR_BNOT:
-                   return !GetExprVal (Expr->Left);
+        case EXPR_SECTION:
+            if (D->Seg) {
+                /* We cannot handle more than one segment reference in o65 */
+                D->TooComplex = 1;
+            } else {
+                /* Get the section from the expression */
+                Section* S = GetExprSection (Expr);
+                /* Remember the segment reference */
+                D->Seg = S->Seg;
+                /* Add the offset of the section to the constant value */
+                D->Val += Sign * (S->Offs + D->Seg->PC);
+            }
+            break;
+
+        case EXPR_SEGMENT:
+            if (D->Seg) {
+                /* We cannot handle more than one segment reference in o65 */
+                D->TooComplex = 1;
+            } else {
+                /* Remember the segment reference */
+                D->Seg = Expr->V.Seg;
+                /* Add the offset of the segment to the constant value */
+                D->Val += (Sign * D->Seg->PC);
+            }
+            break;
+
+        case EXPR_PLUS:
+            GetSegExprValInternal (Expr->Left, D, Sign);
+            GetSegExprValInternal (Expr->Right, D, Sign);
+            break;
+
+        case EXPR_MINUS:
+            GetSegExprValInternal (Expr->Left, D, Sign);
+            GetSegExprValInternal (Expr->Right, D, -Sign);
+            break;
 
         default:
-                   Internal ("Unknown expression Op type: %u", Expr->Op);
-           /* NOTREACHED */
-           return 0;
+            /* Expression contains illegal operators */
+            D->TooComplex = 1;
+            break;
+
     }
 }
 
 
 
+void GetSegExprVal (ExprNode* Expr, SegExprDesc* D)
+/* Check if the given expression consists of a segment reference and only
+** constant values, additions and subtractions. If anything else is found,
+** set D->TooComplex to true. The function will initialize D.
+*/
+{
+    /* Initialize the given structure */
+    D->Val        = 0;
+    D->TooComplex = 0;
+    D->Seg        = 0;
+
+    /* Call our recursive calculation routine */
+    GetSegExprValInternal (Expr, D, 1);
+}
+
+
+
 ExprNode* LiteralExpr (long Val, ObjData* O)
 /* Return an expression tree that encodes the given literal value */
 {
-    ExprNode* Expr = NewExprNode (O);
-    Expr->Op = EXPR_LITERAL;
-    Expr->V.Val = Val;
+    ExprNode* Expr = NewExprNode (O, EXPR_LITERAL);
+    Expr->V.IVal = Val;
     return Expr;
 }
 
 
 
-ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O)
+ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O)
 /* Return an expression tree that encodes an offset into a memory area */
 {
     ExprNode* Root;
 
-    ExprNode* Expr = NewExprNode (O);
-    Expr->Op = EXPR_MEMAREA;
+    ExprNode* Expr = NewExprNode (O, EXPR_MEMAREA);
     Expr->V.Mem = Mem;
 
     if (Offs != 0) {
-        Root = NewExprNode (O);
-        Root->Op = EXPR_PLUS;
+        Root = NewExprNode (O, EXPR_PLUS);
         Root->Left = Expr;
         Root->Right = LiteralExpr (Offs, O);
     } else {
@@ -402,13 +581,11 @@ ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O)
 {
     ExprNode* Root;
 
-    ExprNode* Expr = NewExprNode (O);
-    Expr->Op = EXPR_SEGMENT;
+    ExprNode* Expr = NewExprNode (O, EXPR_SEGMENT);
     Expr->V.Seg = Seg;
 
     if (Offs != 0) {
-        Root = NewExprNode (O);
-        Root->Op = EXPR_PLUS;
+        Root = NewExprNode (O, EXPR_PLUS);
         Root->Left = Expr;
         Root->Right = LiteralExpr (Offs, O);
     } else {
@@ -425,13 +602,11 @@ ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O)
 {
     ExprNode* Root;
 
-    ExprNode* Expr = NewExprNode (O);
-    Expr->Op = EXPR_SECTION;
+    ExprNode* Expr = NewExprNode (O, EXPR_SECTION);
     Expr->V.Sec = Sec;
 
     if (Offs != 0) {
-        Root = NewExprNode (O);
-        Root->Op = EXPR_PLUS;
+        Root = NewExprNode (O, EXPR_PLUS);
         Root->Left = Expr;
         Root->Right = LiteralExpr (Offs, O);
     } else {
@@ -451,41 +626,40 @@ ExprNode* ReadExpr (FILE* F, ObjData* O)
     /* Read the node tag and handle NULL nodes */
     unsigned char Op = Read8 (F);
     if (Op == EXPR_NULL) {
-       return 0;
+        return 0;
     }
 
     /* Create a new node */
-    Expr = NewExprNode (O);
-    Expr->Op = Op;
+    Expr = NewExprNode (O, Op);
 
     /* Check the tag and handle the different expression types */
     if (EXPR_IS_LEAF (Op)) {
-       switch (Op) {
+        switch (Op) {
 
-           case EXPR_LITERAL:
-               Expr->V.Val = Read32Signed (F);
-               break;
+            case EXPR_LITERAL:
+                Expr->V.IVal = Read32Signed (F);
+                break;
 
-           case EXPR_SYMBOL:
-               /* Read the import number */
-               Expr->V.ImpNum = Read16 (F);
-               break;
+            case EXPR_SYMBOL:
+                /* Read the import number */
+                Expr->V.ImpNum = ReadVar (F);
+                break;
 
-           case EXPR_SECTION:
-               /* Read the segment number */
-               Expr->V.SegNum = Read8 (F);
-               break;
+            case EXPR_SECTION:
+                /* Read the section number */
+                Expr->V.SecNum = ReadVar (F);
+                break;
 
-           default:
-               Error ("Invalid expression op: %02X", Op);
+            default:
+                Error ("Invalid expression op: %02X", Op);
 
-       }
+        }
 
     } else {
 
-       /* Not a leaf node */
-       Expr->Left = ReadExpr (F, O);
-       Expr->Right = ReadExpr (F, O);
+        /* Not a leaf node */
+        Expr->Left = ReadExpr (F, O);
+        Expr->Right = ReadExpr (F, O);
 
     }
 
@@ -500,60 +674,43 @@ int EqualExpr (ExprNode* E1, ExprNode* E2)
 {
     /* If one pointer is NULL, both must be NULL */
     if ((E1 == 0) ^ (E2 == 0)) {
-       return 0;
+        return 0;
     }
     if (E1 == 0) {
-       return 1;
+        return 1;
     }
 
     /* Both pointers not NULL, check OP */
     if (E1->Op != E2->Op) {
-       return 0;
+        return 0;
     }
 
     /* OPs are identical, check data for leafs, or subtrees */
     switch (E1->Op) {
 
-       case EXPR_LITERAL:
-           /* Value must be identical */
-           return (E1->V.Val == E2->V.Val);
+        case EXPR_LITERAL:
+            /* Value must be identical */
+            return (E1->V.IVal == E2->V.IVal);
 
-       case EXPR_SYMBOL:
-           /* Import number must be identical */
-           return (E1->V.ImpNum == E2->V.ImpNum);
+        case EXPR_SYMBOL:
+            /* Import must be identical */
+            return (GetExprImport (E1) == GetExprImport (E2));
 
-       case EXPR_SECTION:
-                   /* Section must be identical */
-                   return (GetExprSection (E1) == GetExprSection (E2));
+        case EXPR_SECTION:
+            /* Section must be identical */
+            return (GetExprSection (E1) == GetExprSection (E2));
 
-       case EXPR_SEGMENT:
-                   /* Segment must be identical */
-                   return (E1->V.Seg == E2->V.Seg);
+        case EXPR_SEGMENT:
+            /* Segment must be identical */
+            return (E1->V.Seg == E2->V.Seg);
 
-       case EXPR_MEMAREA:
-                   /* Memory area must be identical */
-                   return (E1->V.Mem == E2->V.Mem );
+        case EXPR_MEMAREA:
+            /* Memory area must be identical */
+            return (E1->V.Mem == E2->V.Mem);
 
-       default:
-           /* Not a leaf node */
-                   return EqualExpr (E1->Left, E2->Left) && EqualExpr (E1->Right, E2->Right);
+        default:
+            /* Not a leaf node */
+            return EqualExpr (E1->Left, E2->Left) && EqualExpr (E1->Right, E2->Right);
     }
 
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-