/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
-#include "../common/exprdefs.h"
+#include <string.h>
+#include <time.h>
+/* common */
+#include "check.h"
+#include "cpu.h"
+#include "exprdefs.h"
+#include "print.h"
+#include "tgttrans.h"
+#include "version.h"
+#include "xmalloc.h"
+
+/* ca65 */
#include "error.h"
+#include "expr.h"
#include "global.h"
#include "instr.h"
-#include "mem.h"
#include "nexttok.h"
-#include "objcode.h"
+/* #include "objcode.h" */
#include "objfile.h"
+#include "segment.h"
#include "symtab.h"
#include "toklist.h"
#include "ulabel.h"
-#include "expr.h"
-static ExprNode* NewExprNode (void)
+static ExprNode* NewExprNode (unsigned Op)
/* Create a new expression node */
{
ExprNode* N;
FreeExprNodes = N->Left;
} else {
/* Allocate fresh memory */
- N = Xmalloc (sizeof (ExprNode));
+ N = xmalloc (sizeof (ExprNode));
}
- N->Op = EXPR_NULL;
+ N->Op = Op;
N->Left = N->Right = 0;
N->Obj = 0;
FreeExprNodes = E;
} else {
/* Free the memory */
- Xfree (E);
+ xfree (E);
}
}
}
-/*****************************************************************************/
-/* Dump an expression tree on stdout for debugging */
-/*****************************************************************************/
-
-
-
-static void InternalDumpExpr (ExprNode* Expr)
-/* Dump an expression in UPN */
-{
- if (Expr == 0) {
- return;
- }
- InternalDumpExpr (Expr->Left);
- InternalDumpExpr (Expr->Right);
-
- switch (Expr->Op) {
-
- case EXPR_LITERAL:
- case EXPR_ULABEL:
- printf (" $%04lX", Expr->V.Val & 0xFFFF);
- break;
-
- case EXPR_SYMBOL:
- printf (" %s", GetSymName (Expr->V.Sym));
- break;
-
- case EXPR_SEGMENT:
- printf (" SEG");
- break;
-
- case EXPR_PLUS:
- printf (" +");
- break;
-
- case EXPR_MINUS:
- printf (" -");
- break;
-
- case EXPR_MUL:
- printf (" *");
- break;
-
- case EXPR_DIV:
- printf (" /");
- break;
-
- case EXPR_MOD:
- printf (" %%");
- break;
-
- case EXPR_OR:
- printf (" OR");
- break;
-
- case EXPR_XOR:
- printf (" XOR");
- break;
-
- case EXPR_AND:
- printf (" AND");
- break;
-
- case EXPR_SHL:
- printf (" SHL");
- break;
-
- case EXPR_SHR:
- printf (" SHR");
- break;
-
- case EXPR_EQ:
- printf (" =");
- break;
-
- case EXPR_NE:
- printf ("<>");
- break;
-
- case EXPR_LT:
- printf (" <");
- break;
-
- case EXPR_GT:
- printf (" >");
- break;
-
- case EXPR_UNARY_MINUS:
- printf (" NEG");
- break;
-
- case EXPR_NOT:
- printf (" ~");
- break;
-
- case EXPR_LOBYTE:
- printf (" LO");
- break;
-
- case EXPR_HIBYTE:
- printf (" HI");
- break;
-
- case EXPR_SWAP:
- printf (" SWAP");
- break;
-
- case EXPR_BAND:
- printf (" BOOL_AND");
- break;
-
- case EXPR_BOR:
- printf (" BOOL_OR");
- break;
-
- case EXPR_BXOR:
- printf (" BOOL_XOR");
- break;
-
- case EXPR_BNOT:
- printf (" BOOL_NOT");
- break;
-
- default:
- Internal ("Unknown Op type: %u", Expr->Op);
-
- }
-}
-
-
-
-void DumpExpr (ExprNode* Expr)
-/* Dump an expression tree to stdout */
-{
- InternalDumpExpr (Expr);
- printf ("\n");
-}
-
-
-
/*****************************************************************************/
/* Code */
/*****************************************************************************/
} else {
/* Skip any tokens */
int Braces = 0;
- while (Tok != TOK_SEP && Tok != TOK_EOF) {
+ while (!TokIsSep (Tok)) {
if (Tok == TOK_LPAREN) {
++Braces;
} else if (Tok == TOK_RPAREN) {
static int FuncDefined (void)
/* Handle the .DEFINED builtin function */
{
+ static const char* Keys[] = {
+ "ANY",
+ "GLOBAL",
+ "LOCAL",
+ };
+
+ char Name [sizeof (SVal)];
int Result = 0;
+ int Scope;
+ /* First argument is a symbol name */
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
if (Tok != TOK_RPAREN) {
NextTok ();
}
+ return 0;
+ }
+
+ /* Remember the name, then skip it */
+ strcpy (Name, SVal);
+ NextTok ();
+
+ /* Comma and scope spec may follow */
+ if (Tok == TOK_COMMA) {
+
+ /* Skip the comma */
+ NextTok ();
+
+ /* An identifier must follow */
+ if (Tok != TOK_IDENT) {
+ Error (ERR_IDENT_EXPECTED);
+ return 0;
+ }
+
+ /* Get the scope, then skip it */
+ Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
+ NextTok ();
+
+ /* Check if we got a valid keyword */
+ if (Scope < 0) {
+ Error (ERR_ILLEGAL_SCOPE);
+ return 0;
+ }
+
+ /* Map the scope */
+ switch (Scope) {
+ case 0: Scope = SCOPE_ANY; break;
+ case 1: Scope = SCOPE_GLOBAL; break;
+ case 2: Scope = SCOPE_LOCAL; break;
+ default: Internal ("Invalid scope: %d", Scope);
+ }
+
} else {
- Result = SymIsDef (SVal);
- NextTok ();
+
+ /* Any scope */
+ Scope = SCOPE_ANY;
+
}
+ /* Search for the symbol */
+ Result = SymIsDef (SVal, Scope);
+
/* Done */
return Result;
}
while (Tok != TOK_COMMA) {
/* We may not end-of-line of end-of-file here */
- if (Tok == TOK_SEP || Tok == TOK_EOF) {
+ if (TokIsSep (Tok)) {
Error (ERR_UNEXPECTED_EOL);
return 0;
}
while (Tok != TOK_RPAREN) {
/* We may not end-of-line of end-of-file here */
- if (Tok == TOK_SEP || Tok == TOK_EOF) {
+ if (TokIsSep (Tok)) {
Error (ERR_UNEXPECTED_EOL);
return 0;
}
NextTok ();
}
} else {
- Result = SymIsRef (SVal);
+ Result = SymIsRef (SVal, SCOPE_ANY);
NextTok ();
}
+static int FuncStrAt (void)
+/* Handle the .STRAT function */
+{
+ char Str [sizeof(SVal)];
+ long Index;
+
+ /* String constant expected */
+ if (Tok != TOK_STRCON) {
+ Error (ERR_STRCON_EXPECTED);
+ NextTok ();
+ return 0;
+
+ }
+
+ /* Remember the string and skip it */
+ strcpy (Str, SVal);
+ NextTok ();
+
+ /* Comma must follow */
+ ConsumeComma ();
+
+ /* Expression expected */
+ Index = ConstExpression ();
+
+ /* Must be a valid index */
+ if (Index >= (long) strlen (Str)) {
+ Error (ERR_RANGE);
+ return 0;
+ }
+
+ /* Return the char, handle as unsigned. Be sure to translate it into
+ * the target character set.
+ */
+ return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
+}
+
+
+
+static int FuncStrLen (void)
+/* Handle the .STRLEN function */
+{
+ /* String constant expected */
+ if (Tok != TOK_STRCON) {
+
+ Error (ERR_STRCON_EXPECTED);
+ /* Smart error recovery */
+ if (Tok != TOK_RPAREN) {
+ NextTok ();
+ }
+ return 0;
+
+ } else {
+
+ /* Get the length of the string */
+ int Len = strlen (SVal);
+
+ /* Skip the string */
+ NextTok ();
+
+ /* Return the length */
+ return Len;
+
+ }
+}
+
+
+
+static int FuncTCount (void)
+/* Handle the .TCOUNT function */
+{
+ /* We have a list of tokens that ends with the closing paren. Skip
+ * the tokens, handling nested braces and count them.
+ */
+ int Count = 0;
+ unsigned Parens = 0;
+ while (Parens != 0 || Tok != TOK_RPAREN) {
+
+ /* Check for end of line or end of input. Since the calling function
+ * will check for the closing paren, we don't need to print an error
+ * here, just bail out.
+ */
+ if (TokIsSep (Tok)) {
+ break;
+ }
+
+ /* One more token */
+ ++Count;
+
+ /* Keep track of the nesting level */
+ switch (Tok) {
+ case TOK_LPAREN: ++Parens; break;
+ case TOK_RPAREN: --Parens; break;
+ default: break;
+ }
+
+ /* Skip the token */
+ NextTok ();
+ }
+
+ /* Return the number of tokens */
+ return Count;
+}
+
+
+
static int FuncXMatch (void)
/* Handle the .XMATCH function */
{
if (Tok != TOK_LPAREN) {
Error (ERR_LPAREN_EXPECTED);
SkipUntilSep ();
- return LiteralExpr (0);
+ return GenLiteralExpr (0);
}
NextTok ();
/* Call the function itself */
- Result = (F () != 0);
+ Result = F ();
/* Closing brace must follow */
ConsumeRParen ();
/* Return an expression node with the boolean code */
- return LiteralExpr (Result);
+ return GenLiteralExpr (Result);
}
switch (Tok) {
case TOK_INTCON:
+ N = GenLiteralExpr (IVal);
+ NextTok ();
+ break;
+
case TOK_CHARCON:
- N = LiteralExpr (IVal);
+ N = GenLiteralExpr (TgtTranslateChar (IVal));
NextTok ();
break;
NextTok ();
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
- N = LiteralExpr (0); /* Dummy */
+ N = GenLiteralExpr (0); /* Dummy */
} else {
- S = SymRefGlobal (SVal);
+ S = SymRef (SVal, SCOPE_GLOBAL);
if (SymIsConst (S)) {
/* Use the literal value instead */
- N = LiteralExpr (GetSymVal (S));
+ N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
- N = NewExprNode ();
- N->Op = EXPR_SYMBOL;
- N->V.Sym = S;
+ N = GenSymExpr (S);
}
NextTok ();
}
break;
case TOK_IDENT:
- S = SymRef (SVal);
+ S = SymRef (SVal, SCOPE_LOCAL);
if (SymIsConst (S)) {
/* Use the literal value instead */
- N = LiteralExpr (GetSymVal (S));
+ N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
- N = NewExprNode ();
- N->Op = EXPR_SYMBOL;
- N->V.Sym = S;
+ N = GenSymExpr (S);
}
NextTok ();
break;
case TOK_MINUS:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_UNARY_MINUS);
N->Left = Factor ();
- N->Op = EXPR_UNARY_MINUS;
break;
case TOK_NOT:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_NOT);
N->Left = Factor ();
- N->Op = EXPR_NOT;
break;
case TOK_STAR:
case TOK_PC:
NextTok ();
- N = CurrentPC ();
+ N = GenCurrentPC ();
break;
case TOK_LT:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_BYTE0);
N->Left = Factor ();
- N->Op = EXPR_LOBYTE;
break;
case TOK_GT:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_BYTE1);
N->Left = Factor ();
- N->Op = EXPR_HIBYTE;
break;
case TOK_LPAREN:
break;
case TOK_CPU:
- N = LiteralExpr (GetCPU());
+ N = GenLiteralExpr (CPUIsets[CPU]);
NextTok ();
break;
N = Function (FuncReferenced);
break;
+ case TOK_STRAT:
+ N = Function (FuncStrAt);
+ break;
+
+ case TOK_STRLEN:
+ N = Function (FuncStrLen);
+ break;
+
+ case TOK_TCOUNT:
+ N = Function (FuncTCount);
+ break;
+
+ case TOK_TIME:
+ N = GenLiteralExpr (time (0));
+ NextTok ();
+ break;
+
+ case TOK_VERSION:
+ N = GenLiteralExpr (VERSION);
+ NextTok ();
+ break;
+
+
case TOK_XMATCH:
N = Function (FuncXMatch);
break;
default:
- N = LiteralExpr (0); /* Dummy */
- Error (ERR_SYNTAX);
+ if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
+ /* A character constant */
+ N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
+ } else {
+ N = GenLiteralExpr (0); /* Dummy */
+ Error (ERR_SYNTAX);
+ }
NextTok ();
break;
}
static ExprNode* Term (void)
{
- ExprNode* Root;
-
/* Read left hand side */
- Root = Factor ();
+ ExprNode* Root = Factor ();
/* Handle multiplicative operations */
while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
Tok == TOK_SHR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_MUL: Root->Op = EXPR_MUL; break;
- case TOK_DIV: Root->Op = EXPR_DIV; break;
- case TOK_MOD: Root->Op = EXPR_MOD; break;
- case TOK_AND: Root->Op = EXPR_AND; break;
- case TOK_XOR: Root->Op = EXPR_XOR; break;
- case TOK_SHL: Root->Op = EXPR_SHL; break;
- case TOK_SHR: Root->Op = EXPR_SHR; break;
+ case TOK_MUL: Root = NewExprNode (EXPR_MUL); break;
+ case TOK_DIV: Root = NewExprNode (EXPR_DIV); break;
+ case TOK_MOD: Root = NewExprNode (EXPR_MOD); break;
+ case TOK_AND: Root = NewExprNode (EXPR_AND); break;
+ case TOK_XOR: Root = NewExprNode (EXPR_XOR); break;
+ case TOK_SHL: Root = NewExprNode (EXPR_SHL); break;
+ case TOK_SHR: Root = NewExprNode (EXPR_SHR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
static ExprNode* SimpleExpr (void)
{
- ExprNode* Root;
-
/* Read left hand side */
- Root = Term ();
+ ExprNode* Root = Term ();
/* Handle additive operations */
while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_PLUS: Root->Op = EXPR_PLUS; break;
- case TOK_MINUS: Root->Op = EXPR_MINUS; break;
- case TOK_OR: Root->Op = EXPR_OR; break;
+ case TOK_PLUS: Root = NewExprNode (EXPR_PLUS); break;
+ case TOK_MINUS: Root = NewExprNode (EXPR_MINUS); break;
+ case TOK_OR: Root = NewExprNode (EXPR_OR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_EQ: Root->Op = EXPR_EQ; break;
- case TOK_NE: Root->Op = EXPR_NE; break;
- case TOK_LT: Root->Op = EXPR_LT; break;
- case TOK_GT: Root->Op = EXPR_GT; break;
- case TOK_LE: Root->Op = EXPR_LE; break;
- case TOK_GE: Root->Op = EXPR_GE; break;
+ case TOK_EQ: Root = NewExprNode (EXPR_EQ); break;
+ case TOK_NE: Root = NewExprNode (EXPR_NE); break;
+ case TOK_LT: Root = NewExprNode (EXPR_LT); break;
+ case TOK_GT: Root = NewExprNode (EXPR_GT); break;
+ case TOK_LE: Root = NewExprNode (EXPR_LE); break;
+ case TOK_GE: Root = NewExprNode (EXPR_GE); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
/* Handle booleans */
while (Tok == TOK_BAND || Tok == TOK_BXOR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_BAND: Root->Op = EXPR_BAND; break;
- case TOK_BXOR: Root->Op = EXPR_BXOR; break;
+ case TOK_BAND: Root = NewExprNode (EXPR_BAND); break;
+ case TOK_BXOR: Root = NewExprNode (EXPR_BXOR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
/* Handle booleans */
while (Tok == TOK_BOR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_BOR: Root->Op = EXPR_BOR; break;
+ case TOK_BOR: Root = NewExprNode (EXPR_BOR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
/* Handle booleans */
if (Tok == TOK_BNOT) {
- /* Create a new node */
- Root = NewExprNode ();
+ /* Create the new node */
+ Root = NewExprNode (EXPR_BNOT);
- /* Determine the operator token */
- switch (Tok) {
- case TOK_BNOT: Root->Op = EXPR_BNOT; break;
- default: Internal ("Invalid token");
- }
+ /* Skip the operator token */
NextTok ();
/* Parse the left hand side, allow more BNOTs */
/* Try to simplify the given expression tree */
{
if (Root) {
- SimplifyExpr (Root->Left);
- SimplifyExpr (Root->Right);
+ Root->Left = SimplifyExpr (Root->Left);
+ Root->Right = SimplifyExpr (Root->Right);
if (IsConstExpr (Root)) {
/* The complete expression is constant */
Root->V.Val = GetExprVal (Root);
* not constant.
*/
{
+ long Val;
+
/* Read the expression, and call finalize (exception here, since we
* expect a const).
*/
ExprNode* Expr = FinalizeExpr (Expression ());
- /* Return the value */
+ /* Get the value */
if (IsConstExpr (Expr)) {
- return GetExprVal (Expr);
+ Val = GetExprVal (Expr);
} else {
Error (ERR_CONSTEXPR_EXPECTED);
- return 0;
+ Val = 0;
}
+
+ /* Free the expression tree and return the value */
+ FreeExpr (Expr);
+ return Val;
}
-ExprNode* LiteralExpr (long Val)
+void FreeExpr (ExprNode* Root)
+/* Free the expression, Root is pointing to. */
+{
+ if (Root) {
+ FreeExpr (Root->Left);
+ FreeExpr (Root->Right);
+ if (Root->Op == EXPR_SYMBOL) {
+ /* Remove the symbol reference */
+ SymDelRef (Root->V.Sym, Root);
+ }
+ FreeExprNode (Root);
+ }
+}
+
+
+
+ExprNode* GenLiteralExpr (long Val)
/* Return an expression tree that encodes the given literal value */
{
- ExprNode* Expr = NewExprNode ();
- Expr->Op = EXPR_LITERAL;
+ ExprNode* Expr = NewExprNode (EXPR_LITERAL);
Expr->V.Val = Val;
return Expr;
}
-ExprNode* CurrentPC (void)
+ExprNode* GenSymExpr (SymEntry* Sym)
+/* Return an expression node that encodes the given symbol */
+{
+ ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
+ Expr->V.Sym = Sym;
+ SymAddRef (Sym, Expr);
+ return Expr;
+}
+
+
+
+static ExprNode* GenSectionExpr (unsigned SegNum)
+/* Return an expression node for the given section */
+{
+ ExprNode* Expr = NewExprNode (EXPR_SECTION);
+ Expr->V.SegNum = SegNum;
+ return Expr;
+}
+
+
+
+ExprNode* GenCurrentPC (void)
/* Return the current program counter as expression */
{
- ExprNode* Left;
ExprNode* Root;
if (RelocMode) {
/* Create SegmentBase + Offset */
- Left = NewExprNode ();
- Left->Op = EXPR_SEGMENT;
- Left->V.SegNum = GetSegNum ();
-
- Root = NewExprNode ();
- Root->Left = Left;
- Root->Right = LiteralExpr (GetPC ());
- Root->Op = EXPR_PLUS;
+ Root = NewExprNode (EXPR_PLUS);
+ Root->Left = GenSectionExpr (GetSegNum ());
+ Root->Right = GenLiteralExpr (GetPC ());
} else {
- /* Absolute mode, just return PC value */
- Root = LiteralExpr (GetPC ());
+ /* Absolute mode, just return PC value */
+ Root = GenLiteralExpr (GetPC ());
}
return Root;
-ExprNode* SwapExpr (ExprNode* Expr)
+ExprNode* GenSwapExpr (ExprNode* Expr)
/* Return an extended expression with lo and hi bytes swapped */
{
- ExprNode* N = NewExprNode ();
- N->Op = EXPR_SWAP;
+ ExprNode* N = NewExprNode (EXPR_SWAP);
N->Left = Expr;
return N;
}
-ExprNode* BranchExpr (unsigned Offs)
+ExprNode* GenBranchExpr (unsigned Offs)
/* Return an expression that encodes the difference between current PC plus
* offset and the target expression (that is, Expression() - (*+Offs) ).
*/
{
ExprNode* N;
ExprNode* Root;
- ExprNode* Left;
/* Create *+Offs */
if (RelocMode) {
- Left = NewExprNode ();
- Left->Op = EXPR_SEGMENT;
- Left->V.SegNum = GetSegNum ();
-
- N = NewExprNode ();
- N->Left = Left;
- N->Right = LiteralExpr (GetPC () + Offs);
- N->Op = EXPR_PLUS;
+ N = NewExprNode (EXPR_PLUS);
+ N->Left = GenSectionExpr (GetSegNum ());
+ N->Right = GenLiteralExpr (GetPC () + Offs);
} else {
- N = LiteralExpr (GetPC () + Offs);
+ N = GenLiteralExpr (GetPC () + Offs);
}
/* Create the root node */
- Root = NewExprNode ();
+ Root = NewExprNode (EXPR_MINUS);
Root->Left = Expression ();
Root->Right = N;
- Root->Op = EXPR_MINUS;
/* Return the result */
return SimplifyExpr (Root);
-ExprNode* ULabelExpr (unsigned Num)
+ExprNode* GenULabelExpr (unsigned Num)
/* Return an expression for an unnamed label with the given index */
{
- /* Get an expression node */
- ExprNode* Node = NewExprNode ();
-
- /* Set the values */
- Node->Op = EXPR_ULABEL;
+ ExprNode* Node = NewExprNode (EXPR_ULABEL);
Node->V.Val = Num;
/* Return the new node */
-void FreeExpr (ExprNode* Root)
-/* Free the expression, Root is pointing to. */
+ExprNode* GenByteExpr (ExprNode* Expr)
+/* Force the given expression into a byte and return the result */
{
- if (Root) {
- FreeExpr (Root->Left);
- FreeExpr (Root->Right);
- FreeExprNode (Root);
- }
+ /* Use the low byte operator to force the expression into byte size */
+ ExprNode* Root = NewExprNode (EXPR_BYTE0);
+ Root->Left = Expr;
+
+ /* Return the result */
+ return Root;
}
-ExprNode* ForceWordExpr (ExprNode* Expr)
+ExprNode* GenWordExpr (ExprNode* Expr)
/* Force the given expression into a word and return the result. */
{
- /* And the expression by $FFFF to force it into word size */
- ExprNode* Root = NewExprNode ();
+ /* AND the expression by $FFFF to force it into word size */
+ ExprNode* Root = NewExprNode (EXPR_AND);
Root->Left = Expr;
- Root->Op = EXPR_AND;
- Root->Right = LiteralExpr (0xFFFF);
+ Root->Right = GenLiteralExpr (0xFFFF);
+
+ /* Return the result */
+ return Root;
+}
+
+
+
+ExprNode* GenNE (ExprNode* Expr, long Val)
+/* Generate an expression that compares Expr and Val for inequality */
+{
+ /* Generate a compare node */
+ ExprNode* Root = NewExprNode (EXPR_NE);
+ Root->Left = Expr;
+ Root->Right = GenLiteralExpr (Val);
/* Return the result */
return Root;
case EXPR_SYMBOL:
Sym = Root->V.Sym;
if (SymHasUserMark (Sym)) {
- if (Verbose) {
+ if (Verbosity > 0) {
DumpExpr (Root);
}
PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
} else {
return IsConstExpr (Root->Right);
}
- } else {
+ } else {
/* lhs not const --> tree not const */
return 0;
}
case EXPR_LEAFNODE:
switch (N->Op) {
- case EXPR_SYMBOL:
- if (SymIsZP (N->V.Sym)) {
- *IsByte = 1;
- }
+ case EXPR_SYMBOL:
+ if (SymIsZP (N->V.Sym)) {
+ *IsByte = 1;
+ } else if (SymHasExpr (N->V.Sym)) {
+ /* Check if this expression is a byte expression */
+ *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
+ }
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
*IsByte = 1;
}
SimplifyExpr (Root);
}
return IsByteRange (GetExprVal (Root));
- } else if (Root->Op == EXPR_LOBYTE || Root->Op == EXPR_HIBYTE) {
+ } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
+ Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
/* Symbol forced to have byte range */
IsByte = 1;
} else {
case EXPR_NOT:
return ~GetExprVal (Expr->Left);
- case EXPR_LOBYTE:
+ case EXPR_BYTE0:
return GetExprVal (Expr->Left) & 0xFF;
- case EXPR_HIBYTE:
+ case EXPR_BYTE1:
return (GetExprVal (Expr->Left) >> 8) & 0xFF;
+ case EXPR_BYTE2:
+ return (GetExprVal (Expr->Left) >> 16) & 0xFF;
+
+ case EXPR_BYTE3:
+ return (GetExprVal (Expr->Left) >> 24) & 0xFF;
+
case EXPR_SWAP:
Left = GetExprVal (Expr->Left);
return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
case EXPR_SYMBOL:
if (SymHasExpr (Expr->V.Sym)) {
- /* The symbol has an expression tree */
- SymEntry* Sym = Expr->V.Sym;
- if (SymHasUserMark (Sym)) {
- /* Circular definition */
- if (Verbose) {
- DumpExpr (Expr);
- }
- PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
- return LiteralExpr (0); /* Return a dummy value */
- }
- SymMarkUser (Sym);
- Expr = RemoveSyms (GetSymExpr (Sym), 1);
- SymUnmarkUser (Sym);
- return Expr;
+ /* The symbol has an expression tree */
+ SymEntry* Sym = Expr->V.Sym;
+ if (SymHasUserMark (Sym)) {
+ /* Circular definition */
+ if (Verbosity) {
+ DumpExpr (Expr);
+ }
+ PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
+ return GenLiteralExpr (0); /* Return a dummy value */
+ }
+ SymMarkUser (Sym);
+ Expr = RemoveSyms (GetSymExpr (Sym), 1);
+ SymUnmarkUser (Sym);
+ return Expr;
} else if (SymIsConst (Expr->V.Sym)) {
- /* The symbol is a constant */
- return LiteralExpr (GetSymVal (Expr->V.Sym));
+ /* The symbol is a constant */
+ return GenLiteralExpr (GetSymVal (Expr->V.Sym));
}
break;
case EXPR_ULABEL:
if (ULabCanResolve ()) {
- ExprNode* NewExpr = ULabResolve (Expr->V.Val);
- FreeExpr (Expr);
- Expr = NewExpr;
+ ExprNode* NewExpr = ULabResolve (Expr->V.Val);
+ FreeExpr (Expr);
+ Expr = NewExpr;
}
break;
/* Clone the current node if needed */
if (MustClone) {
- /* Create a new node */
- ExprNode* Clone = NewExprNode ();
-
- /* Clone the operation */
- Clone->Op = Expr->Op;
+ ExprNode* Clone;
- /* Clone the attribute if needed */
+ /* Clone the expression tree */
switch (Expr->Op) {
case EXPR_LITERAL:
+ Clone = GenLiteralExpr (Expr->V.Val);
+ break;
+
case EXPR_ULABEL:
- Clone->V.Val = Expr->V.Val;
- break;
+ Clone = GenULabelExpr (Expr->V.Val);
+ break;
case EXPR_SYMBOL:
- Clone->V.Sym = Expr->V.Sym;
- break;
+ Clone = GenSymExpr (Expr->V.Sym);
+ break;
- case EXPR_SEGMENT:
- Clone->V.SegNum = Expr->V.SegNum;
- break;
+ case EXPR_SECTION:
+ Clone = GenSectionExpr (Expr->V.SegNum);
+ break;
- }
+ default:
+ Clone = NewExprNode (Expr->Op);
+ Clone->Left = RemoveSyms (Expr->Left, 1);
+ Clone->Right = RemoveSyms (Expr->Right, 1);
+ break;
- /* Clone the tree nodes */
- Clone->Left = RemoveSyms (Expr->Left, MustClone);
- Clone->Right = RemoveSyms (Expr->Right, MustClone);
+ }
/* Done */
return Clone;
} else {
/* Nothing to clone */
- Expr->Left = RemoveSyms (Expr->Left, MustClone);
- Expr->Right = RemoveSyms (Expr->Right, MustClone);
+ Expr->Left = RemoveSyms (Expr->Left, 0);
+ Expr->Right = RemoveSyms (Expr->Right, 0);
/* Done */
return Expr;
-
}
}
return Left;
} else {
/* Check for SEG - SEG which is now possible */
- if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
+ if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
Left->V.SegNum == Right->V.SegNum) {
/* SEG - SEG, remove it completely */
FreeExprNode (Left);
Expr = ConstExtract (Expr, &Val, 1);
if (Expr == 0) {
/* Reduced to a literal value */
- Expr = LiteralExpr (Val);
+ Expr = GenLiteralExpr (Val);
} else if (Val) {
/* Extracted a value */
- N = NewExprNode ();
- N->Op = EXPR_PLUS;
+ N = NewExprNode (EXPR_PLUS);
N->Left = Expr;
- N->Right = LiteralExpr (Val);
+ N->Right = GenLiteralExpr (Val);
Expr = N;
}
return Expr;
return 0;
}
- /* Get a new node */
- Clone = NewExprNode ();
-
- /* Clone the operation */
- Clone->Op = Expr->Op;
-
- /* Clone the attribute if needed */
+ /* Clone the node */
switch (Expr->Op) {
case EXPR_LITERAL:
+ Clone = GenLiteralExpr (Expr->V.Val);
+ break;
+
case EXPR_ULABEL:
- Clone->V.Val = Expr->V.Val;
+ Clone = GenULabelExpr (Expr->V.Val);
break;
case EXPR_SYMBOL:
- Clone->V.Sym = Expr->V.Sym;
+ Clone = GenSymExpr (Expr->V.Sym);
break;
- case EXPR_SEGMENT:
- Clone->V.SegNum = Expr->V.SegNum;
+ case EXPR_SECTION:
+ Clone = GenSectionExpr (Expr->V.SegNum);
break;
+ default:
+ /* Generate a new node */
+ Clone = NewExprNode (Expr->Op);
+ /* Clone the tree nodes */
+ Clone->Left = CloneExpr (Expr->Left);
+ Clone->Right = CloneExpr (Expr->Right);
+ break;
}
- /* Clone the tree nodes */
- Clone->Left = CloneExpr (Expr->Left);
- Clone->Right = CloneExpr (Expr->Right);
-
/* Done */
return Clone;
}
case EXPR_SYMBOL:
/* Maybe we should use a code here? */
CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
- ObjWrite16 (GetSymIndex (Expr->V.Sym));
+ ObjWriteVar (GetSymIndex (Expr->V.Sym));
break;
- case EXPR_SEGMENT:
+ case EXPR_SECTION:
ObjWrite8 (Expr->V.SegNum);
break;
+