]> git.sur5r.net Git - cc65/commitdiff
Moved StudyExpr + helpers into its own module
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 19 Nov 2003 22:54:30 +0000 (22:54 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 19 Nov 2003 22:54:30 +0000 (22:54 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2675 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/expr.c
src/ca65/make/gcc.mak
src/ca65/make/watcom.mak
src/ca65/studyexpr.c [new file with mode: 0644]
src/ca65/studyexpr.h [new file with mode: 0644]

index 3a13f4c8f01aa574ef453a1323bbfc7d28c18a09..09e3dc3b94067043ea672318e6eba3e407940e29 100644 (file)
@@ -55,6 +55,7 @@
 #include "objfile.h"
 #include "segment.h"
 #include "struct.h"
+#include "studyexpr.h"
 #include "symbol.h"
 #include "symtab.h"
 #include "toklist.h"
  */
 #define        MAX_FREE_NODES  64
 static ExprNode*       FreeExprNodes = 0;
-static unsigned                FreeNodeCount = 0;
-
-/* Structure for parsing expression trees */
-typedef struct ExprDesc ExprDesc;
-struct ExprDesc {
-    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 */
-    SymEntry*   SymRef;         /* Symbol reference if any */
-    unsigned    SecRef;                /* Section reference if any */
-};
-
-
-
-
-/*****************************************************************************/
-/*                                 Forwards                                  */
-/*****************************************************************************/
-
-
-
-static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
-/* Study an expression tree and place the contents into D */
+static unsigned                FreeNodeCount = 0;
 
 
 
 /*****************************************************************************/
-/*                                 Helpers                                  */
+/*                                 Helpers                                  */
 /*****************************************************************************/
 
 
 
-static ExprDesc* InitExprDesc (ExprDesc* ED)
-/* Initialize an ExprDesc structure for use with StudyExpr */
-{
-    ED->Val       = 0;
-    ED->TooComplex = 0;
-    ED->SymCount   = 0;
-    ED->SecCount   = 0;
-    return ED;
-}
-
-
-
-static int ExprDescIsConst (const ExprDesc* ED)
-/* Return true if the expression is constant */
-{
-    return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0);
-}
-
-
-
 static ExprNode* NewExprNode (unsigned Op)
 /* Create a new expression node */
 {
@@ -1150,419 +1107,6 @@ static ExprNode* Expr0 (void)
 
 
 
-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;
-        }
-    } else {
-        D->TooComplex = 1;
-    }
-}
-
-
-
-static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
-/* Study an expression tree and place the contents into D */
-{
-    SymEntry* Sym;
-    unsigned  Sec;
-    ExprDesc  SD;
-    ExprDesc  SD1;
-
-    /* Initialize SD. This is not needed in all cases, but it's rather cheap
-     * and simplifies the code below.
-     */
-    InitExprDesc (&SD);
-
-    /* Study this expression node */
-    switch (Expr->Op) {
-
-       case EXPR_LITERAL:
-            D->Val += (Sign * Expr->V.Val);
-           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;
-            }
-            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;
-            }
-           break;
-
-       case EXPR_ULABEL:
-            if (ULabCanResolve ()) {
-                /* We can resolve the label */
-                StudyExpr (ULabResolve (Expr->V.Val), D, Sign);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-       case EXPR_PLUS:
-                   StudyExpr (Expr->Left, D, Sign);
-                   StudyExpr (Expr->Right, D, Sign);
-           break;
-
-       case EXPR_MINUS:
-           StudyExpr (Expr->Left, D, Sign);
-           StudyExpr (Expr->Right, D, -Sign);
-           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;
-            }
-            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;
-            }
-            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;
-            }
-            break;
-
-        case EXPR_OR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left | SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_XOR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left ^ SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_AND:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left & SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_SHL:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val));
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_SHR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val));
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_EQ:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left == SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_NE:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left != SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_LT:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left < SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_GT:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left > SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_LE:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left <= SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_GE:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * (SD.Left >= SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            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;
-            }
-            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;
-            }
-            break;
-
-        case EXPR_BOOLXOR:
-            StudyBinaryExpr (Expr, &SD);
-            if (!SD.TooComplex) {
-                D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0));
-            }
-            break;
-
-        case EXPR_UNARY_MINUS:
-            StudyExpr (Expr->Left, D, -Sign);
-            break;
-
-        case EXPR_NOT:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += (Sign * ~SD.Val);
-            } else {
-                D->TooComplex = 1;
-            }
-            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;
-            }
-            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);
-            break;
-
-        case EXPR_BYTE0:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * (SD.Val & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_BYTE1:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 8) & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_BYTE2:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 16) & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_BYTE3:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 24) & 0xFF);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_WORD0:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * (SD.Val & 0xFFFF);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        case EXPR_WORD1:
-            StudyExpr (Expr->Left, &SD, 1);
-            if (ExprDescIsConst (&SD)) {
-                D->Val += Sign * ((SD.Val >> 16) & 0xFFFF);
-            } else {
-                D->TooComplex = 1;
-            }
-            break;
-
-        default:
-           Internal ("Unknown Op type: %u", Expr->Op);
-           break;
-    }
-}
-
-
-
 ExprNode* Expression (void)
 /* Evaluate an expression, build the expression tree on the heap and return
  * a pointer to the root of the tree.
index baaf3257c6cadccaefff0fd852f44fab2ab8c874..2d3669649180edfa828853d1364e52b5fb4b1210 100644 (file)
@@ -40,6 +40,7 @@ OBJS =  anonname.o      \
         segment.o       \
         spool.o         \
         struct.o        \
+        studyexpr.o     \
         symentry.o      \
         symbol.o        \
         symtab.o       \
index dd04e44dfcf344cfcdba9edff8e627bb894b09f8..f9e73406ccd3292a04ae585053169883583ea0a0 100644 (file)
@@ -89,6 +89,7 @@ OBJS =        anonname.obj    \
         segment.obj     \
         spool.obj       \
         struct.obj      \
+        studyexpr.obj   \
        symbol.obj      \
         symentry.obj    \
        symtab.obj      \
diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c
new file mode 100644 (file)
index 0000000..e125dec
--- /dev/null
@@ -0,0 +1,488 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                studyexpr.c                                */
+/*                                                                           */
+/*                         Study an expression tree                          */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2003      Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+/* common */
+#include "check.h"
+#include "print.h"
+#include "shift.h"
+
+/* ca65 */
+#include "error.h"
+#include "segment.h"
+#include "studyexpr.h"
+#include "symtab.h"
+#include "ulabel.h"
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+ExprDesc* InitExprDesc (ExprDesc* ED)
+/* Initialize an ExprDesc structure for use with StudyExpr */
+{
+    ED->Val       = 0;
+    ED->TooComplex = 0;
+    ED->SymCount   = 0;
+    ED->SecCount   = 0;
+    return ED;
+}
+
+
+
+int ExprDescIsConst (const ExprDesc* ED)
+/* Return true if the expression is constant */
+{
+    return (ED->TooComplex == 0 && ED->SymCount == 0 && ED->SecCount == 0);
+}
+
+
+
+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;
+        }
+    } else {
+        D->TooComplex = 1;
+    }
+}
+
+
+
+void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign)
+/* Study an expression tree and place the contents into D */
+{
+    SymEntry* Sym;
+    unsigned  Sec;
+    ExprDesc  SD;
+    ExprDesc  SD1;
+
+    /* Initialize SD. This is not needed in all cases, but it's rather cheap
+     * and simplifies the code below.
+     */
+    InitExprDesc (&SD);
+
+    /* Study this expression node */
+    switch (Expr->Op) {
+
+       case EXPR_LITERAL:
+            D->Val += (Sign * Expr->V.Val);
+           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;
+            }
+            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;
+            }
+           break;
+
+       case EXPR_ULABEL:
+            if (ULabCanResolve ()) {
+                /* We can resolve the label */
+                StudyExpr (ULabResolve (Expr->V.Val), D, Sign);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+       case EXPR_PLUS:
+                   StudyExpr (Expr->Left, D, Sign);
+                   StudyExpr (Expr->Right, D, Sign);
+           break;
+
+       case EXPR_MINUS:
+           StudyExpr (Expr->Left, D, Sign);
+           StudyExpr (Expr->Right, D, -Sign);
+           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;
+            }
+            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;
+            }
+            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;
+            }
+            break;
+
+        case EXPR_OR:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left | SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_XOR:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left ^ SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_AND:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left & SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_SHL:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += (Sign * shl_l (SD.Left, (unsigned) SD.Val));
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_SHR:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += (Sign * shr_l (SD.Left, (unsigned) SD.Val));
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_EQ:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left == SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_NE:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left != SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_LT:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left < SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_GT:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left > SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_LE:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left <= SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_GE:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * (SD.Left >= SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            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;
+            }
+            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;
+            }
+            break;
+
+        case EXPR_BOOLXOR:
+            StudyBinaryExpr (Expr, &SD);
+            if (!SD.TooComplex) {
+                D->Val += Sign * ((SD.Left != 0) ^ (SD.Val != 0));
+            }
+            break;
+
+        case EXPR_UNARY_MINUS:
+            StudyExpr (Expr->Left, D, -Sign);
+            break;
+
+        case EXPR_NOT:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += (Sign * ~SD.Val);
+            } else {
+                D->TooComplex = 1;
+            }
+            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;
+            }
+            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);
+            break;
+
+        case EXPR_BYTE0:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += Sign * (SD.Val & 0xFF);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_BYTE1:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += Sign * ((SD.Val >> 8) & 0xFF);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_BYTE2:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += Sign * ((SD.Val >> 16) & 0xFF);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_BYTE3:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += Sign * ((SD.Val >> 24) & 0xFF);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_WORD0:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += Sign * (SD.Val & 0xFFFF);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        case EXPR_WORD1:
+            StudyExpr (Expr->Left, &SD, 1);
+            if (ExprDescIsConst (&SD)) {
+                D->Val += Sign * ((SD.Val >> 16) & 0xFFFF);
+            } else {
+                D->TooComplex = 1;
+            }
+            break;
+
+        default:
+           Internal ("Unknown Op type: %u", Expr->Op);
+           break;
+    }
+}
+
+
+
diff --git a/src/ca65/studyexpr.h b/src/ca65/studyexpr.h
new file mode 100644 (file)
index 0000000..8921733
--- /dev/null
@@ -0,0 +1,88 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                studyexpr.h                                */
+/*                                                                           */
+/*                         Study an expression tree                          */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2003      Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef STUDYEXPR_H
+#define STUDYEXPR_H
+
+
+
+/* common */
+#include "exprdefs.h"
+
+
+
+/*****************************************************************************/
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+/* Structure for parsing expression trees */
+typedef struct ExprDesc ExprDesc;
+struct ExprDesc {
+    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 */
+};
+
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+ExprDesc* InitExprDesc (ExprDesc* ED);
+/* Initialize an ExprDesc structure for use with StudyExpr */
+
+int ExprDescIsConst (const ExprDesc* ED);
+/* Return true if the expression is constant */
+
+void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
+/* Study an expression tree and place the contents into D */
+
+
+
+/* End of studyexpr.h */
+#endif
+
+
+