/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "exprdefs.h"
#include "print.h"
#include "shift.h"
+#include "strbuf.h"
#include "tgttrans.h"
#include "version.h"
#include "xmalloc.h"
#include "nexttok.h"
#include "objfile.h"
#include "segment.h"
-#include "struct.h"
+#include "sizeof.h"
#include "studyexpr.h"
#include "symbol.h"
#include "symtab.h"
/* Symbols resolved, check for a literal */
if (E->Op == EXPR_LITERAL) {
if (Val) {
- *Val = E->V.Val;
+ *Val = E->V.IVal;
}
return 1;
}
+static ExprNode* LoByte (ExprNode* Operand)
+/* Return the low byte of the given expression */
+{
+ ExprNode* Expr;
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Operand, &Val)) {
+ FreeExpr (Operand);
+ Expr = GenLiteralExpr (Val & 0xFF);
+ } else {
+ /* Extract byte #0 */
+ Expr = NewExprNode (EXPR_BYTE0);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+static ExprNode* HiByte (ExprNode* Operand)
+/* Return the high byte of the given expression */
+{
+ ExprNode* Expr;
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Operand, &Val)) {
+ FreeExpr (Operand);
+ Expr = GenLiteralExpr ((Val >> 8) & 0xFF);
+ } else {
+ /* Extract byte #1 */
+ Expr = NewExprNode (EXPR_BYTE1);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+static ExprNode* BankByte (ExprNode* Operand)
+/* Return the bank byte of the given expression */
+{
+ ExprNode* Expr;
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Operand, &Val)) {
+ FreeExpr (Operand);
+ Expr = GenLiteralExpr ((Val >> 16) & 0xFF);
+ } else {
+ /* Extract byte #2 */
+ Expr = NewExprNode (EXPR_BYTE2);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+static ExprNode* LoWord (ExprNode* Operand)
+/* Return the low word of the given expression */
+{
+ ExprNode* Expr;
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Operand, &Val)) {
+ FreeExpr (Operand);
+ Expr = GenLiteralExpr (Val & 0xFFFF);
+ } else {
+ /* Extract word #0 */
+ Expr = NewExprNode (EXPR_WORD0);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+static ExprNode* HiWord (ExprNode* Operand)
+/* Return the high word of the given expression */
+{
+ ExprNode* Expr;
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Operand, &Val)) {
+ FreeExpr (Operand);
+ Expr = GenLiteralExpr ((Val >> 16) & 0xFFFF);
+ } else {
+ /* Extract word #1 */
+ Expr = NewExprNode (EXPR_WORD1);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+static ExprNode* Symbol (SymEntry* S)
+/* Reference a symbol and return an expression for it */
+{
+ if (S == 0) {
+ /* Some weird error happened before */
+ return GenLiteralExpr (0);
+ } else {
+ /* Mark the symbol as referenced */
+ SymRef (S);
+ /* If the symbol is a variable, return just its value, otherwise
+ * return a reference to the symbol.
+ */
+ if (SymIsVar (S)) {
+ return CloneExpr (GetSymExpr (S));
+ } else {
+ /* Create symbol node */
+ return GenSymExpr (S);
+ }
+ }
+}
+
+
+
+ExprNode* FuncBankByte (void)
+/* Handle the .BANKBYTE builtin function */
+{
+ return BankByte (Expression ());
+}
+
+
+
static ExprNode* FuncBlank (void)
/* Handle the .BLANK builtin function */
{
- int Result = 1;
-
- /* Assume no tokens if the closing brace follows (this is not correct in
- * all cases, since the token may be the closing brace, but this will
- * give a syntax error anyway and may not be handled by .BLANK.
+ /* We have a list of tokens that ends with the closing paren. Skip
+ * the tokens, and count them. Allow optionally curly braces.
*/
- if (Tok != TOK_RPAREN) {
- /* Skip any tokens */
- int Braces = 0;
- while (!TokIsSep (Tok)) {
- if (Tok == TOK_LPAREN) {
- ++Braces;
- } else if (Tok == TOK_RPAREN) {
- if (Braces == 0) {
- /* Done */
- break;
- } else {
- --Braces;
- }
- }
- NextTok ();
+ token_t Term = GetTokListTerm (TOK_RPAREN);
+ unsigned Count = 0;
+ while (CurTok.Tok != Term) {
+
+ /* 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 (CurTok.Tok)) {
+ break;
}
- return 0;
+
+ /* One more token */
+ ++Count;
+
+ /* Skip the token */
+ NextTok ();
}
- return GenLiteralExpr (Result);
+
+ /* If the list was enclosed in curly braces, skip the closing brace */
+ if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
+ NextTok ();
+ }
+
+ /* Return true if the list was empty */
+ return GenLiteralExpr (Count == 0);
}
/* Handle the .DEFINED builtin function */
{
/* Parse the symbol name and search for the symbol */
- SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
/* Check if the symbol is defined */
return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
+ExprNode* FuncHiByte (void)
+/* Handle the .HIBYTE builtin function */
+{
+ return HiByte (Expression ());
+}
+
+
+
+static ExprNode* FuncHiWord (void)
+/* Handle the .HIWORD builtin function */
+{
+ return HiWord (Expression ());
+}
+
+
+
+ExprNode* FuncLoByte (void)
+/* Handle the .LOBYTE builtin function */
+{
+ return LoByte (Expression ());
+}
+
+
+
+static ExprNode* FuncLoWord (void)
+/* Handle the .LOWORD builtin function */
+{
+ return LoWord (Expression ());
+}
+
+
+
static ExprNode* DoMatch (enum TC EqualityLevel)
/* Handle the .MATCH and .XMATCH builtin functions */
{
int Result;
TokNode* Root = 0;
TokNode* Last = 0;
- TokNode* Node = 0;
+ TokNode* Node;
/* A list of tokens follows. Read this list and remember it building a
* single linked list of tokens including attributes. The list is
- * terminated by a comma.
+ * either enclosed in curly braces, or terminated by a comma.
*/
- while (Tok != TOK_COMMA) {
+ token_t Term = GetTokListTerm (TOK_COMMA);
+ while (CurTok.Tok != Term) {
/* We may not end-of-line of end-of-file here */
- if (TokIsSep (Tok)) {
+ if (TokIsSep (CurTok.Tok)) {
Error ("Unexpected end of line");
- return 0;
+ return GenLiteral0 ();
}
/* Get a node with this token */
NextTok ();
}
- /* Skip the comma */
+ /* Skip the terminator token*/
NextTok ();
- /* Read the second list which is terminated by the right parenthesis and
- * compare each token against the one in the first list.
+ /* If the token list was enclosed in curly braces, we expect a comma */
+ if (Term == TOK_RCURLY) {
+ ConsumeComma ();
+ }
+
+ /* Read the second list which is optionally enclosed in curly braces and
+ * terminated by the right parenthesis. Compare each token against the
+ * one in the first list.
*/
+ Term = GetTokListTerm (TOK_RPAREN);
Result = 1;
Node = Root;
- while (Tok != TOK_RPAREN) {
+ while (CurTok.Tok != Term) {
/* We may not end-of-line of end-of-file here */
- if (TokIsSep (Tok)) {
+ if (TokIsSep (CurTok.Tok)) {
Error ("Unexpected end of line");
- return 0;
+ return GenLiteral0 ();
}
/* Compare the tokens if the result is not already known */
NextTok ();
}
+ /* If the token list was enclosed in curly braces, eat the closing brace */
+ if (Term == TOK_RCURLY) {
+ NextTok ();
+ }
+
/* Check if there are remaining tokens in the first list */
if (Node != 0) {
Result = 0;
+static ExprNode* FuncMax (void)
+/* Handle the .MAX function */
+{
+ ExprNode* Left;
+ ExprNode* Right;
+ ExprNode* Expr;
+ long LeftVal, RightVal;
+
+ /* Two arguments to the pseudo function */
+ Left = Expression ();
+ ConsumeComma ();
+ Right = Expression ();
+
+ /* Check if we can evaluate the value immediately */
+ if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
+ FreeExpr (Left);
+ FreeExpr (Right);
+ Expr = GenLiteralExpr ((LeftVal > RightVal)? LeftVal : RightVal);
+ } else {
+ /* Make an expression node */
+ Expr = NewExprNode (EXPR_MAX);
+ Expr->Left = Left;
+ Expr->Right = Right;
+ }
+ return Expr;
+}
+
+
+
+static ExprNode* FuncMin (void)
+/* Handle the .MIN function */
+{
+ ExprNode* Left;
+ ExprNode* Right;
+ ExprNode* Expr;
+ long LeftVal, RightVal;
+
+ /* Two arguments to the pseudo function */
+ Left = Expression ();
+ ConsumeComma ();
+ Right = Expression ();
+
+ /* Check if we can evaluate the value immediately */
+ if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
+ FreeExpr (Left);
+ FreeExpr (Right);
+ Expr = GenLiteralExpr ((LeftVal < RightVal)? LeftVal : RightVal);
+ } else {
+ /* Make an expression node */
+ Expr = NewExprNode (EXPR_MIN);
+ Expr->Left = Left;
+ Expr->Right = Right;
+ }
+ return Expr;
+}
+
+
+
static ExprNode* FuncReferenced (void)
/* Handle the .REFERENCED builtin function */
{
/* Parse the symbol name and search for the symbol */
- SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+ SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
/* Check if the symbol is referenced */
return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
static ExprNode* FuncSizeOf (void)
/* Handle the .SIZEOF function */
{
- long Size;
+ StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
+ StrBuf Name = STATIC_STRBUF_INITIALIZER;
+ SymTable* Scope;
+ SymEntry* Sym;
+ SymEntry* SizeSym;
+ long Size;
+ int NoScope;
+
+
+ /* Assume an error */
+ SizeSym = 0;
- /* Get the struct for the scoped struct name */
- SymTable* Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
+ /* Check for a cheap local which needs special handling */
+ if (CurTok.Tok == TOK_LOCAL_IDENT) {
+
+ /* Cheap local symbol */
+ Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
+ if (Sym == 0) {
+ Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
+ } else {
+ SizeSym = GetSizeOfSymbol (Sym);
+ }
+
+ /* Remember and skip SVal, terminate ScopeName so it is empty */
+ SB_Copy (&Name, &CurTok.SVal);
+ NextTok ();
+ SB_Terminate (&ScopeName);
- /* Check if the given symbol is really a struct */
- if (GetSymTabType (Struct) != ST_STRUCT) {
- Error ("Argument to .SIZEOF is not a struct");
- Size = 1;
} else {
- Size = GetStructSize (Struct);
+
+ /* Parse the scope and the name */
+ SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
+
+ /* Check if the parent scope is valid */
+ if (ParentScope == 0) {
+ /* No such scope */
+ SB_Done (&ScopeName);
+ SB_Done (&Name);
+ return GenLiteral0 ();
+ }
+
+ /* If ScopeName is empty, no explicit scope was specified. We have to
+ * search upper scope levels in this case.
+ */
+ NoScope = SB_IsEmpty (&ScopeName);
+
+ /* First search for a scope with the given name */
+ if (NoScope) {
+ Scope = SymFindAnyScope (ParentScope, &Name);
+ } else {
+ Scope = SymFindScope (ParentScope, &Name, SYM_FIND_EXISTING);
+ }
+
+ /* If we did find a scope with the name, read the symbol defining the
+ * size, otherwise search for a symbol entry with the name and scope.
+ */
+ if (Scope) {
+ /* Yep, it's a scope */
+ SizeSym = GetSizeOfScope (Scope);
+ } else {
+ if (NoScope) {
+ Sym = SymFindAny (ParentScope, &Name);
+ } else {
+ Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
+ }
+
+ /* If we found the symbol retrieve the size, otherwise complain */
+ if (Sym) {
+ SizeSym = GetSizeOfSymbol (Sym);
+ } else {
+ Error ("Unknown symbol or scope: `%m%p%m%p'",
+ &ScopeName, &Name);
+ }
+ }
}
+ /* Check if we have a size */
+ if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
+ Error ("Size of `%m%p%m%p' is unknown", &ScopeName, &Name);
+ Size = 0;
+ }
+
+ /* Free the string buffers */
+ SB_Done (&ScopeName);
+ SB_Done (&Name);
+
/* Return the size */
return GenLiteralExpr (Size);
}
static ExprNode* FuncStrAt (void)
/* Handle the .STRAT function */
{
- char Str [sizeof(SVal)];
+ StrBuf Str = STATIC_STRBUF_INITIALIZER;
long Index;
- unsigned char C;
+ unsigned char C = 0;
/* String constant expected */
- if (Tok != TOK_STRCON) {
+ if (CurTok.Tok != TOK_STRCON) {
Error ("String constant expected");
NextTok ();
- return 0;
-
+ goto ExitPoint;
}
/* Remember the string and skip it */
- strcpy (Str, SVal);
+ SB_Copy (&Str, &CurTok.SVal);
NextTok ();
/* Comma must follow */
Index = ConstExpression ();
/* Must be a valid index */
- if (Index >= (long) strlen (Str)) {
+ if (Index >= (long) SB_GetLen (&Str)) {
Error ("Range error");
- return 0;
+ goto ExitPoint;
}
/* Get the char, handle as unsigned. Be sure to translate it into
* the target character set.
*/
- C = TgtTranslateChar (Str [(size_t)Index]);
+ C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
+
+ExitPoint:
+ /* Free string buffer memory */
+ SB_Done (&Str);
/* Return the char expression */
return GenLiteralExpr (C);
int Len;
/* String constant expected */
- if (Tok != TOK_STRCON) {
+ if (CurTok.Tok != TOK_STRCON) {
Error ("String constant expected");
/* Smart error recovery */
- if (Tok != TOK_RPAREN) {
+ if (CurTok.Tok != TOK_RPAREN) {
NextTok ();
}
Len = 0;
} else {
/* Get the length of the string */
- Len = strlen (SVal);
+ Len = SB_GetLen (&CurTok.SVal);
/* Skip the string */
NextTok ();
/* 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.
+ * the tokens, and count them. Allow optionally curly braces.
*/
- int Count = 0;
- unsigned Parens = 0;
- while (Parens != 0 || Tok != TOK_RPAREN) {
+ token_t Term = GetTokListTerm (TOK_RPAREN);
+ int Count = 0;
+ while (CurTok.Tok != Term) {
/* 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)) {
+ if (TokIsSep (CurTok.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 ();
}
+ /* If the list was enclosed in curly braces, skip the closing brace */
+ if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
+ NextTok ();
+ }
+
/* Return the number of tokens */
return GenLiteralExpr (Count);
}
NextTok ();
/* Expression must be enclosed in braces */
- if (Tok != TOK_LPAREN) {
+ if (CurTok.Tok != TOK_LPAREN) {
Error ("'(' expected");
SkipUntilSep ();
- return GenLiteralExpr (0);
+ return GenLiteral0 ();
}
NextTok ();
{
ExprNode* L;
ExprNode* N;
- SymEntry* S;
long Val;
- switch (Tok) {
+ switch (CurTok.Tok) {
case TOK_INTCON:
- N = GenLiteralExpr (IVal);
+ N = GenLiteralExpr (CurTok.IVal);
NextTok ();
break;
case TOK_CHARCON:
- N = GenLiteralExpr (TgtTranslateChar (IVal));
+ N = GenLiteralExpr (TgtTranslateChar (CurTok.IVal));
NextTok ();
break;
case TOK_NAMESPACE:
case TOK_IDENT:
- /* Search for the symbol */
- S = ParseScopedSymName (SYM_ALLOC_NEW);
- if (S == 0) {
- /* Some weird error happened before */
- N = GenLiteralExpr (0);
- } else {
- /* Mark the symbol as referenced */
- SymRef (S);
- /* Remove the symbol if possible */
- if (SymHasExpr (S)) {
- N = CloneExpr (GetSymExpr (S));
- } else {
- /* Create symbol node */
- N = GenSymExpr (S);
- }
- }
+ case TOK_LOCAL_IDENT:
+ N = Symbol (ParseAnySymName (SYM_ALLOC_NEW));
break;
case TOK_ULABEL:
- N = ULabRef (IVal);
+ N = ULabRef (CurTok.IVal);
NextTok ();
break;
+ case TOK_PLUS:
+ NextTok ();
+ N = Factor ();
+ break;
+
case TOK_MINUS:
NextTok ();
L = Factor ();
case TOK_LT:
NextTok ();
- L = Factor ();
- if (IsEasyConst (L, &Val)) {
- FreeExpr (L);
- N = GenLiteralExpr (Val & 0xFF);
- } else {
- N = NewExprNode (EXPR_BYTE0);
- N->Left = L;
- }
+ N = LoByte (Factor ());
break;
case TOK_GT:
NextTok ();
- L = Factor ();
- if (IsEasyConst (L, &Val)) {
- FreeExpr (L);
- N = GenLiteralExpr ((Val >> 8) & 0xFF);
- } else {
- N = NewExprNode (EXPR_BYTE1);
- N->Left = L;
- }
+ N = HiByte (Factor ());
break;
case TOK_BANK:
NextTok ();
- L = Factor ();
- if (IsEasyConst (L, &Val)) {
- FreeExpr (L);
- N = GenLiteralExpr ((Val >> 16) & 0xFF);
- } else {
- N = NewExprNode (EXPR_BYTE2);
- N->Left = L;
- }
+ N = BankByte (Factor ());
break;
case TOK_LPAREN:
ConsumeRParen ();
break;
+ case TOK_BANKBYTE:
+ N = Function (FuncBankByte);
+ break;
+
case TOK_BLANK:
N = Function (FuncBlank);
break;
N = Function (FuncDefined);
break;
+ case TOK_HIBYTE:
+ N = Function (FuncHiByte);
+ break;
+
+ case TOK_HIWORD:
+ N = Function (FuncHiWord);
+ break;
+
+ case TOK_LOBYTE:
+ N = Function (FuncLoByte);
+ break;
+
+ case TOK_LOWORD:
+ N = Function (FuncLoWord);
+ break;
+
case TOK_MATCH:
N = Function (FuncMatch);
break;
+ case TOK_MAX:
+ N = Function (FuncMax);
+ break;
+
+ case TOK_MIN:
+ N = Function (FuncMin);
+ break;
+
case TOK_REFERENCED:
N = Function (FuncReferenced);
break;
break;
case TOK_VERSION:
- N = GenLiteralExpr (VERSION);
+ N = GenLiteralExpr (GetVersionAsNumber ());
NextTok ();
break;
break;
default:
- if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
+ if (LooseCharTerm && CurTok.Tok == TOK_STRCON &&
+ SB_GetLen (&CurTok.SVal) == 1) {
/* A character constant */
- N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
+ N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0)));
} else {
- N = GenLiteralExpr (0); /* Dummy */
+ N = GenLiteral0 (); /* Dummy */
Error ("Syntax error");
}
NextTok ();
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) {
+ while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV ||
+ CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND ||
+ CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL ||
+ CurTok.Tok == TOK_SHR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- enum Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
ExprNode* Root = Term ();
/* Handle additive operations */
- while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
+ while (CurTok.Tok == TOK_PLUS ||
+ CurTok.Tok == TOK_MINUS ||
+ CurTok.Tok == TOK_OR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- enum Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
ExprNode* Root = SimpleExpr ();
/* Handle booleans */
- while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
- Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
+ while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE ||
+ CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT ||
+ CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- enum Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
ExprNode* Root = BoolExpr ();
/* Handle booleans */
- while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
+ while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- enum Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
ExprNode* Root = Expr2 ();
/* Handle booleans */
- while (Tok == TOK_BOOLOR) {
+ while (CurTok.Tok == TOK_BOOLOR) {
long LVal, RVal, Val;
ExprNode* Left;
ExprNode* Right;
/* Remember the token and skip it */
- enum Token T = Tok;
+ token_t T = CurTok.Tok;
NextTok ();
/* Move root to left side and read the right side */
ExprNode* Root;
/* Handle booleans */
- if (Tok == TOK_BOOLNOT) {
+ if (CurTok.Tok == TOK_BOOLNOT) {
long Val;
ExprNode* Left;
* a pointer to the root of the tree.
*/
{
-#if 1
- return SimplifyExpr (Expr0 ());
-#else
- /* Test code */
- ExprNode* Expr = Expr0 ();
- printf ("Before: "); DumpExpr (Expr, SymResolve);
- Expr = SimplifyExpr (Expr);
- printf ("After: "); DumpExpr (Expr, SymResolve);
- return Expr;
-#endif
+ return Expr0 ();
}
{
long Val;
-#if 1
/* Read the expression */
- ExprNode* Expr = Expr0 ();
-#else
- /* Test code */
ExprNode* Expr = Expression ();
-#endif
/* Study the expression */
ExprDesc D;
-ExprNode* SimplifyExpr (ExprNode* Expr)
+ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
/* Try to simplify the given expression tree */
{
- if (Expr && Expr->Op != EXPR_LITERAL) {
-
- /* Create an expression description and initialize it */
- ExprDesc D;
- ED_Init (&D);
-
- /* Study the expression */
- StudyExpr (Expr, &D);
-
- /* Now check if we can generate a literal value */
- if (ED_IsConst (&D)) {
- /* No external references */
- FreeExpr (Expr);
- Expr = GenLiteralExpr (D.Val);
- }
-
- /* Free allocated memory */
- ED_Done (&D);
+ if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
+ /* No external references */
+ FreeExpr (Expr);
+ Expr = GenLiteralExpr (D->Val);
}
return Expr;
}
/* Return an expression tree that encodes the given literal value */
{
ExprNode* Expr = NewExprNode (EXPR_LITERAL);
- Expr->V.Val = Val;
+ Expr->V.IVal = Val;
return Expr;
}
+ExprNode* GenLiteral0 (void)
+/* Return an expression tree that encodes the the number zero */
+{
+ return GenLiteralExpr (0);
+}
+
+
+
ExprNode* GenSymExpr (SymEntry* Sym)
/* Return an expression node that encodes the given symbol */
{
-static ExprNode* GenSectionExpr (unsigned SegNum)
+static ExprNode* GenSectionExpr (unsigned SecNum)
/* Return an expression node for the given section */
{
ExprNode* Expr = NewExprNode (EXPR_SECTION);
- Expr->V.SegNum = SegNum;
+ Expr->V.SecNum = SecNum;
return Expr;
}
ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
/* Generate an addition from the two operands */
{
- ExprNode* Root = NewExprNode (EXPR_PLUS);
- Root->Left = Left;
- Root->Right = Right;
- return Root;
+ long Val;
+ if (IsEasyConst (Left, &Val) && Val == 0) {
+ FreeExpr (Left);
+ return Right;
+ } else if (IsEasyConst (Right, &Val) && Val == 0) {
+ FreeExpr (Right);
+ return Left;
+ } else {
+ ExprNode* Root = NewExprNode (EXPR_PLUS);
+ Root->Left = Left;
+ Root->Right = Right;
+ return Root;
+ }
}
{
ExprNode* Root;
- if (RelocMode) {
+ if (GetRelocMode ()) {
/* Create SegmentBase + Offset */
Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
GenLiteralExpr (GetPC ()));
* (Val - PC - Offs) - Seg
*/
Root = GenLiteralExpr (Val - GetPC () - Offs);
- if (RelocMode) {
+ if (GetRelocMode ()) {
N = Root;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root->Right = GenLiteralExpr (GetPC () + Offs);
- if (RelocMode) {
+ if (GetRelocMode ()) {
N = Root;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
/* Return an expression for an unnamed label with the given index */
{
ExprNode* Node = NewExprNode (EXPR_ULABEL);
- Node->V.Val = Num;
+ Node->V.IVal = Num;
/* Return the new node */
return Node;
/* Force the given expression into a byte and return the result */
{
/* 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;
+ return LoByte (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 (EXPR_AND);
- Root->Left = Expr;
- Root->Right = GenLiteralExpr (0xFFFF);
-
- /* Return the result */
- return Root;
+ /* Use the low byte operator to force the expression into word size */
+ return LoWord (Expr);
}
-static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
-/* Internal routine that is recursively called to check for the address size
- * of the expression tree.
- */
-{
- unsigned char A;
- unsigned char Left, Right;
-
- if (N) {
- switch (N->Op & EXPR_TYPEMASK) {
-
- case EXPR_LEAFNODE:
- switch (N->Op) {
-
- case EXPR_SYMBOL:
- if (SymIsZP (N->V.Sym)) {
- if (*AddrSize < ADDR_SIZE_ZP) {
- *AddrSize = ADDR_SIZE_ZP;
- }
- } else if (SymHasExpr (N->V.Sym)) {
- /* Check if this expression is a byte expression */
- CheckAddrSize (GetSymExpr (N->V.Sym), AddrSize);
- } else {
- /* Undefined symbol, use absolute */
- if (*AddrSize < ADDR_SIZE_ABS) {
- *AddrSize = ADDR_SIZE_ABS;
- }
- }
- break;
-
- case EXPR_SECTION:
- A = GetSegAddrSize (N->V.SegNum);
- if (A > *AddrSize) {
- *AddrSize = A;
- }
- break;
-
- }
- break;
-
- case EXPR_UNARYNODE:
- switch (N->Op) {
-
- case EXPR_BYTE0:
- case EXPR_BYTE1:
- case EXPR_BYTE2:
- case EXPR_BYTE3:
- /* No need to look at the expression */
- *AddrSize = ADDR_SIZE_ZP;
- break;
-
- case EXPR_WORD0:
- case EXPR_WORD1:
- /* No need to look at the expression */
- *AddrSize = ADDR_SIZE_ABS;
- break;
-
- default:
- CheckAddrSize (N->Left, AddrSize);
- break;
- }
- break;
-
- case EXPR_BINARYNODE:
- Left = Right = ADDR_SIZE_DEFAULT;
- CheckAddrSize (N->Left, &Left);
- CheckAddrSize (N->Right, &Right);
- A = (Left > Right)? Left : Right;
- if (A > *AddrSize) {
- *AddrSize = A;
- }
- break;
-
- default:
- Internal ("Unknown expression op: %02X", N->Op);
- }
- }
-}
-
-
-
-int IsByteExpr (ExprNode* Root)
-/* Return true if this is a byte expression */
-{
- long Val;
-
- if (IsConstExpr (Root, &Val)) {
- return IsByteRange (Val);
- } else {
- unsigned char AddrSize = ADDR_SIZE_DEFAULT;
- CheckAddrSize (Root, &AddrSize);
- return (AddrSize == ADDR_SIZE_ZP);
- }
-}
-
-
-
ExprNode* CloneExpr (ExprNode* Expr)
/* Clone the given expression tree. The function will simply clone symbol
* nodes, it will not resolve them.
switch (Expr->Op) {
case EXPR_LITERAL:
- Clone = GenLiteralExpr (Expr->V.Val);
+ Clone = GenLiteralExpr (Expr->V.IVal);
break;
case EXPR_ULABEL:
- Clone = GenULabelExpr (Expr->V.Val);
+ Clone = GenULabelExpr (Expr->V.IVal);
break;
case EXPR_SYMBOL:
break;
case EXPR_SECTION:
- Clone = GenSectionExpr (Expr->V.SegNum);
+ Clone = GenSectionExpr (Expr->V.SecNum);
break;
default:
case EXPR_LITERAL:
ObjWrite8 (EXPR_LITERAL);
- ObjWrite32 (Expr->V.Val);
- break;
+ ObjWrite32 (Expr->V.IVal);
+ break;
case EXPR_SYMBOL:
- if (SymIsImport (Expr->V.Sym)) {
+ if (SymIsImport (Expr->V.Sym)) {
ObjWrite8 (EXPR_SYMBOL);
- ObjWriteVar (GetSymIndex (Expr->V.Sym));
+ ObjWriteVar (GetSymImportId (Expr->V.Sym));
} else {
WriteExpr (GetSymExpr (Expr->V.Sym));
}
case EXPR_SECTION:
ObjWrite8 (EXPR_SECTION);
- ObjWrite8 (Expr->V.SegNum);
+ ObjWrite8 (Expr->V.SecNum);
break;
case EXPR_ULABEL:
- WriteExpr (ULabResolve (Expr->V.Val));
+ WriteExpr (ULabResolve (Expr->V.IVal));
break;
default:
+void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
+/* Mark the address size of the given expression tree as guessed. The address
+ * size passed as argument is the one NOT used, because the actual address
+ * size wasn't known. Example: Zero page addressing was not used because symbol
+ * is undefined, and absolute addressing was available.
+ * This function will actually parse the expression tree for undefined symbols,
+ * and mark these symbols accordingly.
+ */
+{
+ /* Accept NULL expressions */
+ if (Expr == 0) {
+ return;
+ }
+
+ /* Check the type code */
+ switch (Expr->Op & EXPR_TYPEMASK) {
+
+ case EXPR_LEAFNODE:
+ if (Expr->Op == EXPR_SYMBOL) {
+ if (!SymIsDef (Expr->V.Sym)) {
+ /* Symbol is undefined, mark it */
+ SymGuessedAddrSize (Expr->V.Sym, AddrSize);
+ }
+ }
+ return;
+
+ case EXPR_BINARYNODE:
+ ExprGuessedAddrSize (Expr->Right, AddrSize);
+ /* FALLTHROUGH */
+
+ case EXPR_UNARYNODE:
+ ExprGuessedAddrSize (Expr->Left, AddrSize);
+ break;
+ }
+}
+
+