]> git.sur5r.net Git - cc65/commitdiff
Much extended StudyExpr
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 23 Nov 2003 21:39:30 +0000 (21:39 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 23 Nov 2003 21:39:30 +0000 (21:39 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2681 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/expr.c
src/ca65/studyexpr.c
src/ca65/studyexpr.h

index 09e3dc3b94067043ea672318e6eba3e407940e29..dcb2f681e862a3c7b20d8966e4f529ad988c955f 100644 (file)
@@ -1132,6 +1132,8 @@ long ConstExpression (void)
  * not constant.
  */
 {
+    long Val;
+
 #if 1
     /* Read the expression */
     ExprNode* Expr = Expr0 ();
@@ -1142,18 +1144,23 @@ long ConstExpression (void)
 
     /* Study the expression */
     ExprDesc D;
-    InitExprDesc (&D);
-    StudyExpr (Expr, &D, 1);
+    ED_Init (&D);
+    StudyExpr (Expr, &D);
 
     /* Check if the expression is constant */
-    if (!ExprDescIsConst (&D)) {
+    if (ED_IsConst (&D)) {
+        Val = D.Val;
+    } else {
        Error ("Constant expression expected");
-       D.Val = 0;
+       Val = 0;
     }
 
-    /* Free the expression tree and return the value */
+    /* Free the expression tree and allocated memory for D */
     FreeExpr (Expr);
-    return D.Val;
+    ED_Done (&D);
+
+    /* Return the value */
+    return Val;
 }
 
 
@@ -1177,17 +1184,20 @@ ExprNode* SimplifyExpr (ExprNode* Expr)
 
         /* Create an expression description and initialize it */
         ExprDesc D;
-        InitExprDesc (&D);
+        ED_Init (&D);
 
         /* Study the expression */
-        StudyExpr (Expr, &D, 1);
+        StudyExpr (Expr, &D);
 
         /* Now check if we can generate a literal value */
-        if (ExprDescIsConst (&D)) {
+        if (ED_IsConst (&D)) {
             /* No external references */
             FreeExpr (Expr);
             Expr = GenLiteralExpr (D.Val);
         }
+
+        /* Free allocated memory */
+        ED_Done (&D);
     }
     return Expr;
 }
@@ -1381,20 +1391,22 @@ int IsConstExpr (ExprNode* Expr, long* Val)
  * expression is constant, the constant value is stored here.
  */
 {
+    int IsConst;
+
     /* Study the expression */
     ExprDesc D;
-    InitExprDesc (&D);
-    StudyExpr (Expr, &D, 1);
+    ED_Init (&D);
+    StudyExpr (Expr, &D);
 
     /* Check if the expression is constant */
-    if (ExprDescIsConst (&D)) {
-        if (Val) {
-            *Val = D.Val;
-        }
-        return 1;
-    } else {
-        return 0;
+    IsConst = ED_IsConst (&D);
+    if (IsConst && Val != 0) {
+        *Val = D.Val;
     }
+
+    /* Delete allocated memory and return the result */
+    ED_Done (&D);
+    return IsConst;
 }
 
 
@@ -1452,16 +1464,10 @@ static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
 
                     case EXPR_WORD0:
                     case EXPR_WORD1:
-                    case EXPR_FORCEWORD:
                         /* No need to look at the expression */
                         *AddrSize = ADDR_SIZE_ABS;
                         break;
 
-                    case EXPR_FORCEFAR:
-                        /* No need to look at the expression */
-                        *AddrSize = ADDR_SIZE_FAR;
-                        break;
-
                     default:
                         CheckAddrSize (N->Left, AddrSize);
                         break;
index e125dec99eefab42c563f253ca565ceea46b40b7..2421b35659265e89c18b4ff127570d4eef6e1068 100644 (file)
 
 
 
+#include <string.h>
+
 /* common */
 #include "check.h"
 #include "print.h"
 #include "shift.h"
+#include "xmalloc.h"
+
+/* ca65 */
+#include "error.h"
+#include "segment.h"
+#include "studyexpr.h"
+#include "symtab.h"
+#include "ulabel.h"
+
+
+
+/*****************************************************************************/
+/*                              struct ExprDesc                              */
+/*****************************************************************************/
+
+
+
+ExprDesc* ED_Init (ExprDesc* ED)
+/* Initialize an ExprDesc structure for use with StudyExpr */
+{
+    ED->Flags     = ED_OK;
+    ED->AddrSize  = ADDR_SIZE_DEFAULT;
+    ED->Val      = 0;
+    ED->SymCount  = 0;
+    ED->SymLimit  = 0;
+    ED->SymRef    = 0;
+    ED->SecCount  = 0;
+    ED->SecLimit  = 0;
+    ED->SecRef    = 0;
+    return ED;
+}
+
+
+
+void ED_Done (ExprDesc* ED)
+/* Delete allocated memory for an ExprDesc. */
+{
+    xfree (ED->SymRef);
+    xfree (ED->SecRef);
+}
+
+
+
+int ED_IsConst (const ExprDesc* D)
+/* Return true if the expression is constant */
+{
+    unsigned I;
+
+    if (D->Flags & ED_TOO_COMPLEX) {
+        return 0;
+    }
+    for (I = 0; I < D->SymCount; ++I) {
+        if (D->SymRef[I].Count != 0) {
+            return 0;
+        }
+    }
+    for (I = 0; I < D->SecCount; ++I) {
+        if (D->SecRef[I].Count != 0) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+
+
+static int ED_IsValid (const ExprDesc* D)
+/* Return true if the expression is valid, that is, the TOO_COMPLEX flag is
+ * not set
+ */
+{
+    return ((D->Flags & ED_TOO_COMPLEX) == 0);
+}
+
+
+
+static void ED_Invalidate (ExprDesc* D)
+/* Set the TOO_COMPLEX flag for D */
+{
+    D->Flags |= ED_TOO_COMPLEX;
+}
+
+
+
+static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
+/* Update the address size of the expression */
+{
+    if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
+        ED->AddrSize = AddrSize;
+    }
+}
+
+
+
+static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
+/* Find a symbol reference and return it. Return NULL if the reference does
+ * not exist.
+ */
+{
+    unsigned I;
+    ED_SymRef* SymRef;
+    for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) {
+        if (SymRef->Ref == Sym) {
+            return SymRef;
+        }
+    }
+    return 0;
+}
+
+
+
+static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
+/* Find a section reference and return it. Return NULL if the reference does
+ * not exist.
+ */
+{
+    unsigned I;
+    ED_SecRef* SecRef;
+    for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) {
+        if (SecRef->Ref == Sec) {
+            return SecRef;
+        }
+    }
+    return 0;
+}
+
+
+
+static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
+/* Allocate a new symbol reference and return it. The count of the new
+ * reference will be set to zero, and the reference itself to Sym.
+ */
+{
+    ED_SymRef* SymRef;
+
+    /* Make sure we have enough SymRef slots */
+    if (ED->SymCount >= ED->SymLimit) {
+        ED->SymLimit *= 2;
+        if (ED->SymLimit == 0) {
+            ED->SymLimit = 2;
+        }
+        ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0]));
+    }
+
+    /* Allocate a new slot */
+    SymRef = ED->SymRef + ED->SymCount++;
+
+    /* Initialize the new struct and return it */
+    SymRef->Count = 1;
+    SymRef->Ref   = Sym;
+    return SymRef;
+}
+
+
+
+static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
+/* Allocate a new section reference and return it. The count of the new
+ * reference will be set to zero, and the reference itself to Sec.
+ */
+{
+    ED_SecRef* SecRef;
+
+    /* Make sure we have enough SecRef slots */
+    if (ED->SecCount >= ED->SecLimit) {
+        ED->SecLimit *= 2;
+        if (ED->SecLimit == 0) {
+            ED->SecLimit = 2;
+        }
+        ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0]));
+    }
+
+    /* Allocate a new slot */
+    SecRef = ED->SecRef + ED->SecCount++;
+
+    /* Initialize the new struct and return it */
+    SecRef->Count = 0;
+    SecRef->Ref   = Sec;
+    return SecRef;
+}
+
+
+
+static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
+/* Get a symbol reference and return it. If the symbol reference does not
+ * exist, a new one is created and returned.
+ */
+{
+    ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
+    if (SymRef == 0) {
+        SymRef = ED_AllocSymRef (ED, Sym);
+    }
+    return SymRef;
+}
+
+
+
+static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
+/* Get a section reference and return it. If the section reference does not
+ * exist, a new one is created and returned.
+ */
+{
+    ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
+    if (SecRef == 0) {
+        SecRef = ED_AllocSecRef (ED, Sec);
+    }
+    return SecRef;
+}
+
+
+
+static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New)
+/* Merge the symbol references from New into ED */
+{
+    unsigned I;
+    for (I = 0; I < New->SymCount; ++I) {
+
+        /* Get a pointer to the SymRef entry */
+        const ED_SymRef* NewRef = New->SymRef + I;
+
+        /* Get the corresponding entry in ED */
+        ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref);
+
+        /* Sum up the references */
+        SymRef->Count += NewRef->Count;
+    }
+}
+
+
+
+static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New)
+/* Merge the section references from New into ED */
+{
+    unsigned I;
+    for (I = 0; I < New->SecCount; ++I) {
+
+        /* Get a pointer to the SymRef entry */
+        const ED_SecRef* NewRef = New->SecRef + I;
+
+        /* Get the corresponding entry in ED */
+        ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref);
+
+        /* Sum up the references */
+        SecRef->Count += NewRef->Count;
+    }
+}
+
+
+
+static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
+/* Merge all references from New into ED */
+{
+    ED_MergeSymRefs (ED, New);
+    ED_MergeSecRefs (ED, New);
+}
+
+
+
+static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
+/* Calculate ED = ED + Right, update address size in ED */
+{
+    ED->Val += Right->Val;
+    ED_MergeRefs (ED, Right);
+    ED_UpdateAddrSize (ED, Right->AddrSize);
+}
+
+
+
+static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
+/* Calculate ED = ED * Right, update address size in ED */
+{
+    unsigned I;
+
+    ED->Val *= Right->Val;
+    for (I = 0; I < ED->SymCount; ++I) {
+        ED->SymRef[I].Count *= Right->Val;
+    }
+    for (I = 0; I < ED->SecCount; ++I) {
+        ED->SecRef[I].Count *= Right->Val;
+    }
+    ED_UpdateAddrSize (ED, Right->AddrSize);
+}
+
+
+
+static void ED_Neg (ExprDesc* D)
+/* Negate an expression */
+{
+    unsigned I;
+
+    D->Val = -D->Val;
+    for (I = 0; I < D->SymCount; ++I) {
+        D->SymRef[I].Count = -D->SymRef[I].Count;
+    }
+    for (I = 0; I < D->SecCount; ++I) {
+        D->SecRef[I].Count = -D->SecRef[I].Count;
+    }
+}
+
+
+
+static void ED_Move (ExprDesc* From, ExprDesc* To)
+/* Move the data from one ExprDesc to another. Old data is freed, and From
+ * is prepared to that ED_Done may be called safely.
+ */
+{
+    /* Delete old data */
+    ED_Done (To);
+
+    /* Move the data */
+    *To = *From;
+
+    /* Cleanup From */
+    ED_Init (From);
+}
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
+/* Study an expression tree and place the contents into D */
+
+
+
+static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
+/* Study a binary expression subtree. This is a helper function for StudyExpr
+ * used for operations that succeed when both operands are known and constant.
+ * It evaluates the two subtrees and checks if they are constant. If they
+ * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
+ * Otherwise the first value is returned in D->Val, the second one in D->Right,
+ * so the actual operation can be done by the caller.
+ */
+{
+    ExprDesc Right;
+
+    /* Study the left side of the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* Study the right side of the expression */
+    ED_Init (&Right);
+    StudyExprInternal (Expr->Right, &Right);
+
+    /* Check if we can handle the operation */
+    if (ED_IsConst (D) && ED_IsConst (&Right)) {
+
+        /* Remember the constant value from Right */
+        D->Right = Right.Val;
+
+    } else {
+
+        /* Cannot evaluate */
+        ED_Invalidate (D);
+
+        /* Merge references and update address size */
+        ED_MergeRefs (D, &Right);
+        ED_UpdateAddrSize (D, Right.AddrSize);
+
+    }
+
+    /* Cleanup Right */
+    ED_Done (&Right);
+}
+
+
+
+static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
+/* Study a literal expression node */
+{
+    /* This one is easy */
+    D->Val = Expr->V.Val;
+}
+
+
+
+static void StudySymbol (ExprNode* Expr, ExprDesc* D)
+/* Study a symbol expression node */
+{
+    /* Get the symbol from the expression */
+    SymEntry* Sym = Expr->V.Sym;
+
+    /* If the symbol is defined somewhere, it has an expression associated.
+     * In this case, just study the expression associated with the symbol,
+     * but mark the symbol so if we encounter it twice, we know that we have
+     * a circular reference.
+     */
+    if (SymHasExpr (Sym)) {
+        if (SymHasUserMark (Sym)) {
+            if (Verbosity > 0) {
+                DumpExpr (Expr, SymResolve);
+            }
+            PError (GetSymPos (Sym),
+                    "Circular reference in definition of symbol `%s'",
+                    GetSymName (Sym));
+            ED_Invalidate (D);
+        } else {
+            SymMarkUser (Sym);
+            StudyExprInternal (GetSymExpr (Sym), D);
+            SymUnmarkUser (Sym);
+        }
+    } else {
+        /* The symbol is either undefined or an import. In both cases, track
+         * the symbols used and update the address size, but in case of an
+         * undefined symbol also set the "too complex" flag, since we cannot
+         * evaluate the final result.
+         */
+        ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
+        ++SymRef->Count;
+        ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
+        if (!SymIsImport (Sym)) {
+            /* Cannot handle */
+            ED_Invalidate (D);
+        }
+    }
+}
+
+
+
+static void StudySection (ExprNode* Expr, ExprDesc* D)
+/* Study a section expression node */
+{
+    /* Get the section reference */
+    ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
+
+    /* Update the data and the address size */
+    ++SecRef->Count;
+    ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref));
+}
+
+
+
+static void StudyULabel (ExprNode* Expr, ExprDesc* D)
+/* Study an unnamed label expression node */
+{
+    /* If we can resolve the label, study the expression associated with it,
+     * otherwise mark the expression as too complex to evaluate.
+     */
+    if (ULabCanResolve ()) {
+        /* We can resolve the label */
+        StudyExprInternal (ULabResolve (Expr->V.Val), D);
+    } else {
+        ED_Invalidate (D);
+    }
+}
+
+
+
+static void StudyPlus (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_PLUS binary expression node */
+{
+    ExprDesc Right;
+
+    /* Study the left side of the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* Study the right side of the expression */
+    ED_Init (&Right);
+    StudyExprInternal (Expr->Right, &Right);
+
+    /* Check if we can handle the operation */
+    if (ED_IsValid (D) || ED_IsValid (&Right)) {
+
+        /* Add both */
+        ED_Add (D, &Right);
+
+    } else {
+
+        /* Cannot evaluate */
+        ED_Invalidate (D);
+
+        /* Merge references and update address size */
+        ED_MergeRefs (D, &Right);
+        ED_UpdateAddrSize (D, Right.AddrSize);
+
+    }
+
+    /* Done */
+    ED_Done (&Right);
+}
+
+
+
+static void StudyMinus (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_MINUS binary expression node */
+{
+    ExprDesc Right;
+
+    /* Study the left side of the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* Study the right side of the expression */
+    ED_Init (&Right);
+    StudyExprInternal (Expr->Right, &Right);
+
+    /* Check if we can handle the operation */
+    if (ED_IsValid (D) || ED_IsValid (&Right)) {
+
+        /* Subtract both */
+        ED_Neg (&Right);
+        ED_Add (D, &Right);
+
+    } else {
+
+        /* Cannot evaluate */
+        ED_Invalidate (D);
+
+        /* Merge references and update address size */
+        ED_MergeRefs (D, &Right);
+        ED_UpdateAddrSize (D, Right.AddrSize);
+
+    }
+
+    /* Done */
+    ED_Done (&Right);
+}
+
+
+
+static void StudyMul (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_MUL binary expression node */
+{
+    ExprDesc Right;
+
+    /* Study the left side of the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* Study the right side of the expression */
+    ED_Init (&Right);
+    StudyExprInternal (Expr->Right, &Right);
+
+    /* We can handle the operation if at least one of both operands is const
+     * and the other one is valid.
+     */
+    if (ED_IsConst (D) && ED_IsValid (&Right)) {
+
+        /* Multiplicate both, result goes into Right */
+        ED_Mul (&Right, D);
+
+        /* Move result into D */
+        ED_Move (&Right, D);
+
+    } else if (ED_IsConst (&Right) && ED_IsValid (D)) {
+
+        /* Multiplicate both */
+        ED_Mul (D, &Right);
+
+    } else {
+
+        /* Cannot handle this operation */
+        ED_Invalidate (D);
+
+    }
+
+    /* If we could not handle the op, merge references and update address size */
+    if (!ED_IsValid (D)) {
+        ED_MergeRefs (D, &Right);
+        ED_UpdateAddrSize (D, Right.AddrSize);
+    }
+
+    /* Done */
+    ED_Done (&Right);
+}
+
+
+
+static void StudyDiv (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_DIV binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        if (D->Right == 0) {
+            Error ("Division by zero");
+            ED_Invalidate (D);
+        } else {
+            D->Val /= D->Right;
+        }
+    }
+}
+
+
+
+static void StudyMod (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_MOD binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        if (D->Right == 0) {
+            Error ("Modulo operation with zero");
+            ED_Invalidate (D);
+        } else {
+            D->Val %= D->Right;
+        }
+    }
+}
+
+
+
+static void StudyOr (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_OR binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val |= D->Right;
+    }
+}
+
+
+
+static void StudyXor (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_XOR binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val ^= D->Right;
+    }
+}
+
+
 
-/* ca65 */
-#include "error.h"
-#include "segment.h"
-#include "studyexpr.h"
-#include "symtab.h"
-#include "ulabel.h"
+static void StudyAnd (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_AND binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val &= D->Right;
+    }
+}
 
 
 
-/*****************************************************************************/
-/*                                          Code                                    */
-/*****************************************************************************/
+static void StudyShl (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_SHL binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
 
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = shl_l (D->Val, D->Right);
+    }
+}
 
 
-ExprDesc* InitExprDesc (ExprDesc* ED)
-/* Initialize an ExprDesc structure for use with StudyExpr */
+
+static void StudyShr (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_SHR binary expression node */
 {
-    ED->Val       = 0;
-    ED->TooComplex = 0;
-    ED->SymCount   = 0;
-    ED->SecCount   = 0;
-    return ED;
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = shr_l (D->Val, D->Right);
+    }
 }
 
 
 
-int ExprDescIsConst (const ExprDesc* ED)
-/* Return true if the expression is constant */
+static void StudyEQ (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_EQ binary expression node */
 {
-    return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0);
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val == D->Right);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
 }
 
 
 
-static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
-/* Study a binary expression subtree. Helper function for StudyExpr. */
-{
-    StudyExpr (Expr->Left, D, 1);
-    if (ExprDescIsConst (D)) {
-        D->Left = D->Val;
-        D->Val = 0;
-        StudyExpr (Expr->Right, D, 1);
-        if (!ExprDescIsConst (D)) {
-            D->TooComplex = 1;
+static void StudyNE (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_NE binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val != D->Right);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyLT (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_LT binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val < D->Right);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyGT (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_GT binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val > D->Right);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyLE (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_LE binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val <= D->Right);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyGE (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_GE binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val >= D->Right);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BOOLAND binary expression node */
+{
+    StudyExprInternal (Expr->Left, D);
+    if (ED_IsConst (D)) {
+        if (D->Val != 0) {   /* Shortcut op */
+            ED_Done (D);
+            ED_Init (D);
+            StudyExprInternal (Expr->Right, D);
+            if (ED_IsConst (D)) {
+                D->Val = (D->Val != 0);
+            } else {
+                ED_Invalidate (D);
+            }
         }
     } else {
-        D->TooComplex = 1;
+        ED_Invalidate (D);
     }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
 }
 
 
 
-void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
-/* Study an expression tree and place the contents into D */
+static void StudyBoolOr (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BOOLOR binary expression node */
 {
-    SymEntry* Sym;
-    unsigned  Sec;
-    ExprDesc  SD;
-    ExprDesc  SD1;
+    StudyExprInternal (Expr->Left, D);
+    if (ED_IsConst (D)) {
+        if (D->Val == 0) {   /* Shortcut op */
+            ED_Done (D);
+            ED_Init (D);
+            StudyExprInternal (Expr->Right, D);
+            if (ED_IsConst (D)) {
+                D->Val = (D->Val != 0);
+            } else {
+                ED_Invalidate (D);
+            }
+        } else {
+            D->Val = 1;
+        }
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BOOLXOR binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val != 0) ^ (D->Right != 0);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_UNARY_MINUS expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* If it is valid, negate it */
+    if (ED_IsValid (D)) {
+        ED_Neg (D);
+    }
+}
+
+
+
+static void StudyNot (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_NOT expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = ~D->Val;
+    } else {
+        ED_Invalidate (D);
+    }
+}
+
+
+
+static void StudySwap (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_SWAP expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00);
+    } else {
+        ED_Invalidate (D);
+    }
+}
+
+
+
+static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BOOLNOT expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val == 0);
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is 0 or 1 */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BYTE0 expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val & 0xFF);
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is a zero page expression */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
 
-    /* Initialize SD. This is not needed in all cases, but it's rather cheap
-     * and simplifies the code below.
-     */
-    InitExprDesc (&SD);
 
+static void StudyByte1 (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BYTE1 expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val >> 8) & 0xFF;
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is a zero page expression */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyByte2 (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BYTE2 expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val >> 16) & 0xFF;
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is a zero page expression */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyByte3 (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BYTE3 expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val >> 24) & 0xFF;
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is a zero page expression */
+    D->AddrSize = ADDR_SIZE_ZP;
+}
+
+
+
+static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_WORD0 expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val & 0xFFFFL);
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is an absolute expression */
+    D->AddrSize = ADDR_SIZE_ABS;
+}
+
+
+
+static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_WORD1 expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val = (D->Val >> 16) & 0xFFFFL;
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is an absolute expression */
+    D->AddrSize = ADDR_SIZE_ABS;
+}
+
+
+
+static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
+/* Study an expression tree and place the contents into D */
+{
     /* Study this expression node */
     switch (Expr->Op) {
 
        case EXPR_LITERAL:
-            D->Val += (Sign * Expr->V.Val);
+            StudyLiteral (Expr, D);
            break;
 
        case EXPR_SYMBOL:
-            Sym = Expr->V.Sym;
-            if (SymIsImport (Sym)) {
-                if (D->SymCount == 0) {
-                    D->SymCount += Sign;
-                    D->SymRef = Sym;
-                } else if (D->SymRef == Sym) {
-                    /* Same symbol */
-                    D->SymCount += Sign;
-                } else {
-                    /* More than one import */
-                    D->TooComplex = 1;
-                }
-            } else if (SymHasExpr (Sym)) {
-                if (SymHasUserMark (Sym)) {
-                    if (Verbosity > 0) {
-                        DumpExpr (Expr, SymResolve);
-                    }
-                    PError (GetSymPos (Sym),
-                            "Circular reference in definition of symbol `%s'",
-                            GetSymName (Sym));
-                    D->TooComplex = 1;
-                } else {
-                    SymMarkUser (Sym);
-                    StudyExpr (GetSymExpr (Sym), D, Sign);
-                    SymUnmarkUser (Sym);
-                }
-            } else {
-                D->TooComplex = 1;
-            }
+            StudySymbol (Expr, D);
             break;
 
        case EXPR_SECTION:
-            Sec = Expr->V.SegNum;
-            if (D->SecCount == 0) {
-                D->SecCount += Sign;
-                D->SecRef = Sec;
-            } else if (D->SecRef == Sec) {
-                /* Same section */
-                D->SecCount += Sign;
-            } else {
-                /* More than one section */
-                D->TooComplex = 1;
-            }
+            StudySection (Expr, D);
            break;
 
        case EXPR_ULABEL:
-            if (ULabCanResolve ()) {
-                /* We can resolve the label */
-                StudyExpr (ULabResolve (Expr->V.Val), D, Sign);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyULabel (Expr, D);
             break;
 
        case EXPR_PLUS:
-                   StudyExpr (Expr->Left, D, Sign);
-                   StudyExpr (Expr->Right, D, Sign);
+            StudyPlus (Expr, D);
            break;
 
        case EXPR_MINUS:
-           StudyExpr (Expr->Left, D, Sign);
-           StudyExpr (Expr->Right, D, -Sign);
+                   StudyMinus (Expr, D);
            break;
 
         case EXPR_MUL:
-            InitExprDesc (&SD1);
-            StudyExpr (Expr->Left, &SD, 1);
-            StudyExpr (Expr->Right, &SD1, 1);
-            if (SD.TooComplex == 0 && SD1.TooComplex == 0) {
-                /* First calculate SD = SD*SD1 if possible */
-                if (ExprDescIsConst (&SD)) {
-                    /* Left is a constant */
-                    SD1.Val      *= SD.Val;
-                    SD1.SymCount *= SD.Val;
-                    SD1.SecCount *= SD.Val;
-                    SD = SD1;
-                } else if (ExprDescIsConst (&SD1)) {
-                    /* Right is constant */
-                    SD.Val      *= SD1.Val;
-                    SD.SymCount *= SD1.Val;
-                    SD.SecCount *= SD1.Val;
-                } else {
-                    D->TooComplex = 1;
-                }
-                /* Now calculate D * Sign * SD */
-                if (!D->TooComplex) {
-                    if ((D->SymCount == 0 || SD.SymCount == 0 || D->SymRef == SD.SymRef) &&
-                        (D->SecCount == 0 || SD.SecCount == 0 || D->SecRef == SD.SecRef)) {
-                        D->Val      += (Sign * SD.Val);
-                        if (D->SymCount == 0) {
-                            D->SymRef = SD.SymRef;
-                        }
-                        D->SymCount += (Sign * SD.SymCount);
-                        if (D->SecCount == 0) {
-                            D->SecRef = SD.SecRef;
-                        }
-                        D->SecCount += (Sign * SD.SecCount);
-                    }
-                } else {
-                    D->TooComplex = 1;
-                }
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyMul (Expr, D);
             break;
 
         case EXPR_DIV:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                if (SD.Val == 0) {
-                    Error ("Division by zero");
-                    D->TooComplex = 1;
-                } else {
-                    D->Val += Sign * (SD.Left / SD.Val);
-                }
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyDiv (Expr, D);
             break;
 
         case EXPR_MOD:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                if (SD.Val == 0) {
-                    Error ("Modulo operation with zero");
-                    D->TooComplex = 1;
-                } else {
-                    D->Val += Sign * (SD.Left % SD.Val);
-                }
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyMod (Expr, D);
             break;
 
         case EXPR_OR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left | SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyOr (Expr, D);
             break;
 
         case EXPR_XOR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left ^ SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyXor (Expr, D);
             break;
 
         case EXPR_AND:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left & SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyAnd (Expr, D);
             break;
 
         case EXPR_SHL:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val));
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyShl (Expr, D);
             break;
 
         case EXPR_SHR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val));
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyShr (Expr, D);
             break;
 
         case EXPR_EQ:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left == SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyEQ (Expr, D);
             break;
 
         case EXPR_NE:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left != SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyNE (Expr, D);
             break;
 
         case EXPR_LT:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left < SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyLT (Expr, D);
             break;
 
         case EXPR_GT:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left > SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyGT (Expr, D);
             break;
 
         case EXPR_LE:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left <= SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyLE (Expr, D);
             break;
 
         case EXPR_GE:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left >= SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyGE (Expr, D);
             break;
 
         case EXPR_BOOLAND:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                if (SD.Val != 0) {   /* Shortcut op */
-                    SD.Val = 0;
-                    StudyExpr (Expr->Right, &SD, 1);
-                    if (ExprDescIsConst (&SD)) {
-                        D->Val += Sign * (SD.Val != 0);
-                    } else {
-                        D->TooComplex = 1;
-                    }
-                }
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyBoolAnd (Expr, D);
             break;
 
         case EXPR_BOOLOR:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                if (SD.Val == 0) {   /* Shortcut op */
-                    StudyExpr (Expr->Right, &SD, 1);
-                    if (ExprDescIsConst (&SD)) {
-                        D->Val += Sign * (SD.Val != 0);
-                    } else {
-                        D->TooComplex = 1;
-                    }
-                } else {
-                    D->Val += Sign;
-                }
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyBoolOr (Expr, D);
             break;
 
         case EXPR_BOOLXOR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0));
-            }
+            StudyBoolXor (Expr, D);
             break;
 
         case EXPR_UNARY_MINUS:
-            StudyExpr (Expr->Left, D, -Sign);
+            StudyUnaryMinus (Expr, D);
             break;
 
         case EXPR_NOT:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += (Sign * ~SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyNot (Expr, D);
             break;
 
         case EXPR_SWAP:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * (((SD.Val >> 8) & 0x00FF) | ((SD.Val << 8) & 0xFF00));
-            } else {
-                D->TooComplex = 1;
-            }
+            StudySwap (Expr, D);
             break;
 
         case EXPR_BOOLNOT:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * (SD.Val != 0);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_FORCEWORD:
-        case EXPR_FORCEFAR:
-            /* Ignore */
-            StudyExpr (Expr->Left, D, Sign);
+            StudyBoolNot (Expr, D);
             break;
 
         case EXPR_BYTE0:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * (SD.Val & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyByte0 (Expr, D);
             break;
 
         case EXPR_BYTE1:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 8) & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyByte1 (Expr, D);
             break;
 
         case EXPR_BYTE2:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 16) & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyByte2 (Expr, D);
             break;
 
         case EXPR_BYTE3:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 24) & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyByte3 (Expr, D);
             break;
 
         case EXPR_WORD0:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * (SD.Val & 0xFFFF);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyWord0 (Expr, D);
             break;
 
         case EXPR_WORD1:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 16) & 0xFFFF);
-            } else {
-                D->TooComplex = 1;
-            }
+            StudyWord1 (Expr, D);
             break;
 
         default:
@@ -486,3 +1211,70 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
 
 
 
+void StudyExpr (ExprNode* Expr, ExprDesc* D)
+/* Study an expression tree and place the contents into D */
+{
+    unsigned I;
+
+    /* Call the internal function */
+    StudyExprInternal (Expr, D);
+
+    /* Remove symbol references with count zero */
+    I = 0;
+    while (I < D->SymCount) {
+        if (D->SymRef[I].Count == 0) {
+            /* Delete the entry */
+            --D->SymCount;
+            memmove (D->SymRef + I, D->SymRef + I + 1,
+                     (D->SymCount - I) * sizeof (D->SymRef[0]));
+        } else {
+            /* Next entry */
+            ++I;
+        }
+    }
+
+    /* Remove section references with count zero */
+    I = 0;
+    while (I < D->SecCount) {
+        if (D->SecRef[I].Count == 0) {
+            /* Delete the entry */
+            --D->SecCount;
+            memmove (D->SecRef + I, D->SecRef + I + 1,
+                     (D->SecCount - I) * sizeof (D->SecRef[0]));
+        } else {
+            /* Next entry */
+            ++I;
+        }
+    }
+
+    /* If we don't have an address size, assign one of the expression is a
+     * constant.
+     */
+    if (D->AddrSize == ADDR_SIZE_DEFAULT) {
+        if (ED_IsConst (D)) {
+            if ((D->Val & ~0xFFL) == 0) {
+                D->AddrSize = ADDR_SIZE_ZP;
+            } else if ((D->Val & ~0xFFFFL) == 0) {
+                D->AddrSize = ADDR_SIZE_ABS;
+            } else if ((D->Val & 0xFFFFFFL) == 0) {
+                D->AddrSize = ADDR_SIZE_FAR;
+            } else {
+                D->AddrSize = ADDR_SIZE_LONG;
+            }
+        }
+    }
+
+#if 0
+    printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
+    if (!ED_IsValid (D)) {
+        printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
+    } else {
+        printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
+        printf ("%u symbols:\n", D->SymCount);
+        printf ("%u sections:\n", D->SecCount);
+    }
+#endif
+}
+
+
+
index 8921733b48e5c8c19b99aa96e26608dae4d1a123..6bac754f5796d6d88e766180f9235396806fb410 100644 (file)
 
 
 
+/* Flags */
+#define ED_OK           0x00            /* Nothing special */
+#define ED_TOO_COMPLEX  0x01            /* Expression is too complex */
+
+/* Symbol reference */
+typedef struct ED_SymRef ED_SymRef;
+struct ED_SymRef {
+    long                Count;          /* Number of references */
+    struct SymEntry*    Ref;            /* Actual reference */
+};
+
+/* Section reference */
+typedef struct ED_SecRef ED_SecRef;
+struct ED_SecRef {
+    long                Count;          /* Number of references */
+    unsigned            Ref;            /* Actual reference */
+};
+
 /* Structure for parsing expression trees */
 typedef struct ExprDesc ExprDesc;
 struct ExprDesc {
+    unsigned short      Flags;          /* See ED_xxx */
+    unsigned char       AddrSize;       /* Address size of the expression */
     long                Val;           /* The offset value */
-    long                Left;           /* Left value for StudyBinaryExpr */
-    int                        TooComplex;     /* Expression is too complex to evaluate */
-    long                SymCount;       /* Symbol reference count */
-    long                SecCount;       /* Section reference count */
-    struct SymEntry*    SymRef;         /* Symbol reference if any */
-    unsigned            SecRef;                /* Section reference if any */
-};
+    long                Right;          /* Right value for StudyBinaryExpr */
 
+    /* Symbol reference management */
+    unsigned            SymCount;       /* Number of symbols referenced */
+    unsigned            SymLimit;       /* Memory allocated */
+    ED_SymRef*          SymRef;         /* Symbol references */
+
+    /* Section reference management */
+    unsigned            SecCount;       /* Number of sections referenced */
+    unsigned            SecLimit;       /* Memory allocated */
+    ED_SecRef*          SecRef;         /* Section references */
+};
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                              struct ExprDesc                              */
 /*****************************************************************************/
 
 
 
-ExprDesc* InitExprDesc (ExprDesc* ED);
+ExprDesc* ED_Init (ExprDesc* ED);
 /* Initialize an ExprDesc structure for use with StudyExpr */
 
-int ExprDescIsConst (const ExprDesc* ED);
+void ED_Done (ExprDesc* ED);
+/* Delete allocated memory for an ExprDesc. */
+
+int ED_IsConst (const ExprDesc* ED);
 /* Return true if the expression is constant */
 
-void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+void StudyExpr (ExprNode* Expr, ExprDesc* D);
 /* Study an expression tree and place the contents into D */