#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 */
{
-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.
segment.o \
spool.o \
struct.o \
+ studyexpr.o \
symentry.o \
symbol.o \
symtab.o \
segment.obj \
spool.obj \
struct.obj \
+ studyexpr.obj \
symbol.obj \
symentry.obj \
symtab.obj \
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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;
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+