1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
60 #include "studyexpr.h"
68 /*****************************************************************************/
70 /*****************************************************************************/
74 /* Since all expressions are first packed into expression trees, and each
75 ** expression tree node is allocated on the heap, we add some type of special
76 ** purpose memory allocation here: Instead of freeing the nodes, we save some
77 ** number of freed nodes for later and remember them in a single linked list
78 ** using the Left link.
80 #define MAX_FREE_NODES 64
81 static ExprNode* FreeExprNodes = 0;
82 static unsigned FreeNodeCount = 0;
86 /*****************************************************************************/
88 /*****************************************************************************/
92 static ExprNode* NewExprNode (unsigned Op)
93 /* Create a new expression node */
97 /* Do we have some nodes in the list already? */
99 /* Use first node from list */
101 FreeExprNodes = N->Left;
104 /* Allocate fresh memory */
105 N = xmalloc (sizeof (ExprNode));
108 N->Left = N->Right = 0;
116 static void FreeExprNode (ExprNode* E)
120 if (E->Op == EXPR_SYMBOL) {
121 /* Remove the symbol reference */
122 SymDelExprRef (E->V.Sym, E);
124 /* Place the symbol into the free nodes list if possible */
125 if (FreeNodeCount < MAX_FREE_NODES) {
126 /* Remember this node for later */
127 E->Left = FreeExprNodes;
131 /* Free the memory */
139 /*****************************************************************************/
141 /*****************************************************************************/
145 static ExprNode* Expr0 (void);
149 int IsByteRange (long Val)
150 /* Return true if this is a byte value */
152 return (Val & ~0xFFL) == 0;
157 int IsWordRange (long Val)
158 /* Return true if this is a word value */
160 return (Val & ~0xFFFFL) == 0;
165 int IsFarRange (long Val)
166 /* Return true if this is a far (24 bit) value */
168 return (Val & ~0xFFFFFFL) == 0;
173 int IsEasyConst (const ExprNode* E, long* Val)
174 /* Do some light checking if the given node is a constant. Don't care if E is
175 ** a complex expression. If E is a constant, return true and place its value
176 ** into Val, provided that Val is not NULL.
179 /* Resolve symbols, follow symbol chains */
180 while (E->Op == EXPR_SYMBOL) {
181 E = SymResolve (E->V.Sym);
183 /* Could not resolve */
188 /* Symbols resolved, check for a literal */
189 if (E->Op == EXPR_LITERAL) {
196 /* Not found to be a const according to our tests */
202 static ExprNode* LoByte (ExprNode* Operand)
203 /* Return the low byte of the given expression */
208 /* Special handling for const expressions */
209 if (IsEasyConst (Operand, &Val)) {
211 Expr = GenLiteralExpr (Val & 0xFF);
213 /* Extract byte #0 */
214 Expr = NewExprNode (EXPR_BYTE0);
215 Expr->Left = Operand;
222 static ExprNode* HiByte (ExprNode* Operand)
223 /* Return the high byte of the given expression */
228 /* Special handling for const expressions */
229 if (IsEasyConst (Operand, &Val)) {
231 Expr = GenLiteralExpr ((Val >> 8) & 0xFF);
233 /* Extract byte #1 */
234 Expr = NewExprNode (EXPR_BYTE1);
235 Expr->Left = Operand;
242 static ExprNode* Bank (ExprNode* Operand)
243 /* Return the bank of the given segmented expression */
245 /* Generate the bank expression */
246 ExprNode* Expr = NewExprNode (EXPR_BANK);
247 Expr->Left = Operand;
249 /* Return the result */
255 static ExprNode* BankByte (ExprNode* Operand)
256 /* Return the bank byte of the given expression */
261 /* Special handling for const expressions */
262 if (IsEasyConst (Operand, &Val)) {
264 Expr = GenLiteralExpr ((Val >> 16) & 0xFF);
266 /* Extract byte #2 */
267 Expr = NewExprNode (EXPR_BYTE2);
268 Expr->Left = Operand;
275 static ExprNode* LoWord (ExprNode* Operand)
276 /* Return the low word of the given expression */
281 /* Special handling for const expressions */
282 if (IsEasyConst (Operand, &Val)) {
284 Expr = GenLiteralExpr (Val & 0xFFFF);
286 /* Extract word #0 */
287 Expr = NewExprNode (EXPR_WORD0);
288 Expr->Left = Operand;
295 static ExprNode* HiWord (ExprNode* Operand)
296 /* Return the high word of the given expression */
301 /* Special handling for const expressions */
302 if (IsEasyConst (Operand, &Val)) {
304 Expr = GenLiteralExpr ((Val >> 16) & 0xFFFF);
306 /* Extract word #1 */
307 Expr = NewExprNode (EXPR_WORD1);
308 Expr->Left = Operand;
315 static ExprNode* Symbol (SymEntry* S)
316 /* Reference a symbol and return an expression for it */
319 /* Some weird error happened before */
320 return GenLiteralExpr (0);
322 /* Mark the symbol as referenced */
324 /* If the symbol is a variable, return just its value, otherwise
325 ** return a reference to the symbol.
328 return CloneExpr (GetSymExpr (S));
330 /* Create symbol node */
331 return GenSymExpr (S);
338 ExprNode* FuncBank (void)
339 /* Handle the .BANK builtin function */
341 return Bank (Expression ());
346 ExprNode* FuncBankByte (void)
347 /* Handle the .BANKBYTE builtin function */
349 return BankByte (Expression ());
354 static ExprNode* FuncBlank (void)
355 /* Handle the .BLANK builtin function */
357 /* We have a list of tokens that ends with the closing paren. Skip
358 ** the tokens, and count them. Allow optionally curly braces.
360 token_t Term = GetTokListTerm (TOK_RPAREN);
362 while (CurTok.Tok != Term) {
364 /* Check for end of line or end of input. Since the calling function
365 ** will check for the closing paren, we don't need to print an error
366 ** here, just bail out.
368 if (TokIsSep (CurTok.Tok)) {
379 /* If the list was enclosed in curly braces, skip the closing brace */
380 if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
384 /* Return true if the list was empty */
385 return GenLiteralExpr (Count == 0);
390 static ExprNode* FuncConst (void)
391 /* Handle the .CONST builtin function */
393 /* Read an expression */
394 ExprNode* Expr = Expression ();
396 /* Check the constness of the expression */
397 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
399 /* Free the expression */
408 static ExprNode* FuncDefined (void)
409 /* Handle the .DEFINED builtin function */
411 /* Parse the symbol name and search for the symbol */
412 SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
414 /* Check if the symbol is defined */
415 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
420 ExprNode* FuncHiByte (void)
421 /* Handle the .HIBYTE builtin function */
423 return HiByte (Expression ());
428 static ExprNode* FuncHiWord (void)
429 /* Handle the .HIWORD builtin function */
431 return HiWord (Expression ());
436 ExprNode* FuncLoByte (void)
437 /* Handle the .LOBYTE builtin function */
439 return LoByte (Expression ());
444 static ExprNode* FuncLoWord (void)
445 /* Handle the .LOWORD builtin function */
447 return LoWord (Expression ());
452 static ExprNode* DoMatch (enum TC EqualityLevel)
453 /* Handle the .MATCH and .XMATCH builtin functions */
460 /* A list of tokens follows. Read this list and remember it building a
461 ** single linked list of tokens including attributes. The list is
462 ** either enclosed in curly braces, or terminated by a comma.
464 token_t Term = GetTokListTerm (TOK_COMMA);
465 while (CurTok.Tok != Term) {
467 /* We may not end-of-line of end-of-file here */
468 if (TokIsSep (CurTok.Tok)) {
469 Error ("Unexpected end of line");
470 return GenLiteral0 ();
473 /* Get a node with this token */
474 Node = NewTokNode ();
476 /* Insert the node into the list */
488 /* Skip the terminator token*/
491 /* If the token list was enclosed in curly braces, we expect a comma */
492 if (Term == TOK_RCURLY) {
496 /* Read the second list which is optionally enclosed in curly braces and
497 ** terminated by the right parenthesis. Compare each token against the
498 ** one in the first list.
500 Term = GetTokListTerm (TOK_RPAREN);
503 while (CurTok.Tok != Term) {
505 /* We may not end-of-line of end-of-file here */
506 if (TokIsSep (CurTok.Tok)) {
507 Error ("Unexpected end of line");
508 return GenLiteral0 ();
511 /* Compare the tokens if the result is not already known */
514 /* The second list is larger than the first one */
516 } else if (TokCmp (Node) < EqualityLevel) {
517 /* Tokens do not match */
522 /* Next token in first list */
527 /* Next token in current list */
531 /* If the token list was enclosed in curly braces, eat the closing brace */
532 if (Term == TOK_RCURLY) {
536 /* Check if there are remaining tokens in the first list */
541 /* Free the token list */
548 /* Done, return the result */
549 return GenLiteralExpr (Result);
554 static ExprNode* FuncMatch (void)
555 /* Handle the .MATCH function */
557 return DoMatch (tcSameToken);
562 static ExprNode* FuncMax (void)
563 /* Handle the .MAX function */
568 long LeftVal, RightVal;
570 /* Two arguments to the pseudo function */
571 Left = Expression ();
573 Right = Expression ();
575 /* Check if we can evaluate the value immediately */
576 if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
579 Expr = GenLiteralExpr ((LeftVal > RightVal)? LeftVal : RightVal);
581 /* Make an expression node */
582 Expr = NewExprNode (EXPR_MAX);
591 static ExprNode* FuncMin (void)
592 /* Handle the .MIN function */
597 long LeftVal, RightVal;
599 /* Two arguments to the pseudo function */
600 Left = Expression ();
602 Right = Expression ();
604 /* Check if we can evaluate the value immediately */
605 if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
608 Expr = GenLiteralExpr ((LeftVal < RightVal)? LeftVal : RightVal);
610 /* Make an expression node */
611 Expr = NewExprNode (EXPR_MIN);
620 static ExprNode* FuncReferenced (void)
621 /* Handle the .REFERENCED builtin function */
623 /* Parse the symbol name and search for the symbol */
624 SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
626 /* Check if the symbol is referenced */
627 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
632 static ExprNode* FuncAddrSize (void)
633 /* Handle the .ADDRSIZE function */
635 StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
636 StrBuf Name = STATIC_STRBUF_INITIALIZER;
642 /* Assume we don't know the size */
645 /* Check for a cheap local which needs special handling */
646 if (CurTok.Tok == TOK_LOCAL_IDENT) {
648 /* Cheap local symbol */
649 Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
651 Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
653 AddrSize = Sym->AddrSize;
656 /* Remember and skip SVal, terminate ScopeName so it is empty */
657 SB_Copy (&Name, &CurTok.SVal);
659 SB_Terminate (&ScopeName);
663 /* Parse the scope and the name */
664 SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
666 /* Check if the parent scope is valid */
667 if (ParentScope == 0) {
669 SB_Done (&ScopeName);
671 return GenLiteral0 ();
674 /* If ScopeName is empty, no explicit scope was specified. We have to
675 ** search upper scope levels in this case.
677 NoScope = SB_IsEmpty (&ScopeName);
679 /* If we did find a scope with the name, read the symbol defining the
680 ** size, otherwise search for a symbol entry with the name and scope.
683 Sym = SymFindAny (ParentScope, &Name);
685 Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
687 /* If we found the symbol retrieve the size, otherwise complain */
689 AddrSize = Sym->AddrSize;
691 Error ("Unknown symbol or scope: `%m%p%m%p'",
698 Warning(1, "Unknown address size: `%m%p%m%p'",
702 /* Free the string buffers */
703 SB_Done (&ScopeName);
706 /* Return the size. */
708 return GenLiteralExpr (AddrSize);
713 static ExprNode* FuncSizeOf (void)
714 /* Handle the .SIZEOF function */
716 StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
717 StrBuf Name = STATIC_STRBUF_INITIALIZER;
725 /* Assume an error */
728 /* Check for a cheap local which needs special handling */
729 if (CurTok.Tok == TOK_LOCAL_IDENT) {
731 /* Cheap local symbol */
732 Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
734 Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
736 SizeSym = GetSizeOfSymbol (Sym);
739 /* Remember and skip SVal, terminate ScopeName so it is empty */
740 SB_Copy (&Name, &CurTok.SVal);
742 SB_Terminate (&ScopeName);
746 /* Parse the scope and the name */
747 SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
749 /* Check if the parent scope is valid */
750 if (ParentScope == 0) {
752 SB_Done (&ScopeName);
754 return GenLiteral0 ();
757 /* If ScopeName is empty, no explicit scope was specified. We have to
758 ** search upper scope levels in this case.
760 NoScope = SB_IsEmpty (&ScopeName);
762 /* First search for a scope with the given name */
764 Scope = SymFindAnyScope (ParentScope, &Name);
766 Scope = SymFindScope (ParentScope, &Name, SYM_FIND_EXISTING);
769 /* If we did find a scope with the name, read the symbol defining the
770 ** size, otherwise search for a symbol entry with the name and scope.
773 /* Yep, it's a scope */
774 SizeSym = GetSizeOfScope (Scope);
777 Sym = SymFindAny (ParentScope, &Name);
779 Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
782 /* If we found the symbol retrieve the size, otherwise complain */
784 SizeSym = GetSizeOfSymbol (Sym);
786 Error ("Unknown symbol or scope: `%m%p%m%p'",
792 /* Check if we have a size */
793 if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
794 Error ("Size of `%m%p%m%p' is unknown", &ScopeName, &Name);
798 /* Free the string buffers */
799 SB_Done (&ScopeName);
802 /* Return the size */
803 return GenLiteralExpr (Size);
808 static ExprNode* FuncStrAt (void)
809 /* Handle the .STRAT function */
811 StrBuf Str = STATIC_STRBUF_INITIALIZER;
815 /* String constant expected */
816 if (CurTok.Tok != TOK_STRCON) {
817 Error ("String constant expected");
822 /* Remember the string and skip it */
823 SB_Copy (&Str, &CurTok.SVal);
826 /* Comma must follow */
829 /* Expression expected */
830 Index = ConstExpression ();
832 /* Must be a valid index */
833 if (Index >= (long) SB_GetLen (&Str)) {
834 Error ("Range error");
838 /* Get the char, handle as unsigned. Be sure to translate it into
839 ** the target character set.
841 C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
844 /* Free string buffer memory */
847 /* Return the char expression */
848 return GenLiteralExpr (C);
853 static ExprNode* FuncStrLen (void)
854 /* Handle the .STRLEN function */
858 /* String constant expected */
859 if (CurTok.Tok != TOK_STRCON) {
861 Error ("String constant expected");
862 /* Smart error recovery */
863 if (CurTok.Tok != TOK_RPAREN) {
870 /* Get the length of the string */
871 Len = SB_GetLen (&CurTok.SVal);
873 /* Skip the string */
877 /* Return the length */
878 return GenLiteralExpr (Len);
883 static ExprNode* FuncTCount (void)
884 /* Handle the .TCOUNT function */
886 /* We have a list of tokens that ends with the closing paren. Skip
887 ** the tokens, and count them. Allow optionally curly braces.
889 token_t Term = GetTokListTerm (TOK_RPAREN);
891 while (CurTok.Tok != Term) {
893 /* Check for end of line or end of input. Since the calling function
894 ** will check for the closing paren, we don't need to print an error
895 ** here, just bail out.
897 if (TokIsSep (CurTok.Tok)) {
908 /* If the list was enclosed in curly braces, skip the closing brace */
909 if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
913 /* Return the number of tokens */
914 return GenLiteralExpr (Count);
919 static ExprNode* FuncXMatch (void)
920 /* Handle the .XMATCH function */
922 return DoMatch (tcIdentical);
927 static ExprNode* Function (ExprNode* (*F) (void))
928 /* Handle builtin functions */
932 /* Skip the keyword */
935 /* Expression must be enclosed in braces */
936 if (CurTok.Tok != TOK_LPAREN) {
937 Error ("'(' expected");
939 return GenLiteral0 ();
943 /* Call the function itself */
946 /* Closing brace must follow */
949 /* Return the result of the actual function */
955 static ExprNode* Factor (void)
961 switch (CurTok.Tok) {
964 N = GenLiteralExpr (CurTok.IVal);
969 N = GenLiteralExpr (TgtTranslateChar (CurTok.IVal));
975 case TOK_LOCAL_IDENT:
976 N = Symbol (ParseAnySymName (SYM_ALLOC_NEW));
980 N = ULabRef (CurTok.IVal);
992 if (IsEasyConst (L, &Val)) {
994 N = GenLiteralExpr (-Val);
996 N = NewExprNode (EXPR_UNARY_MINUS);
1004 if (IsEasyConst (L, &Val)) {
1006 N = GenLiteralExpr (~Val);
1008 N = NewExprNode (EXPR_NOT);
1016 N = GenCurrentPC ();
1021 N = LoByte (Factor ());
1026 N = HiByte (Factor ());
1030 /* ^ means the bank byte of an expression */
1032 N = BankByte (Factor ());
1042 N = Function (FuncBank);
1046 N = Function (FuncBankByte);
1050 N = Function (FuncAddrSize);
1054 N = Function (FuncBlank);
1058 N = Function (FuncConst);
1062 N = GenLiteralExpr (CPUIsets[CPU]);
1067 N = Function (FuncDefined);
1071 N = Function (FuncHiByte);
1075 N = Function (FuncHiWord);
1079 N = Function (FuncLoByte);
1083 N = Function (FuncLoWord);
1087 N = Function (FuncMatch);
1091 N = Function (FuncMax);
1095 N = Function (FuncMin);
1098 case TOK_REFERENCED:
1099 N = Function (FuncReferenced);
1103 N = Function (FuncSizeOf);
1107 N = Function (FuncStrAt);
1111 N = Function (FuncStrLen);
1115 N = Function (FuncTCount);
1119 N = GenLiteralExpr ((long) time (0));
1124 N = GenLiteralExpr (GetVersionAsNumber ());
1129 N = Function (FuncXMatch);
1133 if (LooseCharTerm && CurTok.Tok == TOK_STRCON &&
1134 SB_GetLen (&CurTok.SVal) == 1) {
1135 /* A character constant */
1136 N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0)));
1138 N = GenLiteral0 (); /* Dummy */
1139 Error ("Syntax error");
1149 static ExprNode* Term (void)
1151 /* Read left hand side */
1152 ExprNode* Root = Factor ();
1154 /* Handle multiplicative operations */
1155 while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV ||
1156 CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND ||
1157 CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL ||
1158 CurTok.Tok == TOK_SHR) {
1160 long LVal, RVal, Val;
1164 /* Remember the token and skip it */
1165 token_t T = CurTok.Tok;
1168 /* Move root to left side and read the right side */
1172 /* If both expressions are constant, we can evaluate the term */
1173 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1182 Error ("Division by zero");
1191 Error ("Modulo operation with zero");
1207 Val = shl_l (LVal, RVal);
1211 Val = shr_l (LVal, RVal);
1215 Internal ("Invalid token");
1218 /* Generate a literal expression and delete the old left and
1223 Root = GenLiteralExpr (Val);
1227 /* Generate an expression tree */
1230 case TOK_MUL: Op = EXPR_MUL; break;
1231 case TOK_DIV: Op = EXPR_DIV; break;
1232 case TOK_MOD: Op = EXPR_MOD; break;
1233 case TOK_AND: Op = EXPR_AND; break;
1234 case TOK_XOR: Op = EXPR_XOR; break;
1235 case TOK_SHL: Op = EXPR_SHL; break;
1236 case TOK_SHR: Op = EXPR_SHR; break;
1237 default: Internal ("Invalid token");
1239 Root = NewExprNode (Op);
1241 Root->Right = Right;
1247 /* Return the expression tree we've created */
1253 static ExprNode* SimpleExpr (void)
1255 /* Read left hand side */
1256 ExprNode* Root = Term ();
1258 /* Handle additive operations */
1259 while (CurTok.Tok == TOK_PLUS ||
1260 CurTok.Tok == TOK_MINUS ||
1261 CurTok.Tok == TOK_OR) {
1263 long LVal, RVal, Val;
1267 /* Remember the token and skip it */
1268 token_t T = CurTok.Tok;
1271 /* Move root to left side and read the right side */
1275 /* If both expressions are constant, we can evaluate the term */
1276 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1279 case TOK_PLUS: Val = LVal + RVal; break;
1280 case TOK_MINUS: Val = LVal - RVal; break;
1281 case TOK_OR: Val = LVal | RVal; break;
1282 default: Internal ("Invalid token");
1285 /* Generate a literal expression and delete the old left and
1290 Root = GenLiteralExpr (Val);
1294 /* Generate an expression tree */
1297 case TOK_PLUS: Op = EXPR_PLUS; break;
1298 case TOK_MINUS: Op = EXPR_MINUS; break;
1299 case TOK_OR: Op = EXPR_OR; break;
1300 default: Internal ("Invalid token");
1302 Root = NewExprNode (Op);
1304 Root->Right = Right;
1309 /* Return the expression tree we've created */
1315 static ExprNode* BoolExpr (void)
1316 /* Evaluate a boolean expression */
1318 /* Read left hand side */
1319 ExprNode* Root = SimpleExpr ();
1321 /* Handle booleans */
1322 while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE ||
1323 CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT ||
1324 CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) {
1326 long LVal, RVal, Val;
1330 /* Remember the token and skip it */
1331 token_t T = CurTok.Tok;
1334 /* Move root to left side and read the right side */
1336 Right = SimpleExpr ();
1338 /* If both expressions are constant, we can evaluate the term */
1339 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1342 case TOK_EQ: Val = (LVal == RVal); break;
1343 case TOK_NE: Val = (LVal != RVal); break;
1344 case TOK_LT: Val = (LVal < RVal); break;
1345 case TOK_GT: Val = (LVal > RVal); break;
1346 case TOK_LE: Val = (LVal <= RVal); break;
1347 case TOK_GE: Val = (LVal >= RVal); break;
1348 default: Internal ("Invalid token");
1351 /* Generate a literal expression and delete the old left and
1356 Root = GenLiteralExpr (Val);
1360 /* Generate an expression tree */
1363 case TOK_EQ: Op = EXPR_EQ; break;
1364 case TOK_NE: Op = EXPR_NE; break;
1365 case TOK_LT: Op = EXPR_LT; break;
1366 case TOK_GT: Op = EXPR_GT; break;
1367 case TOK_LE: Op = EXPR_LE; break;
1368 case TOK_GE: Op = EXPR_GE; break;
1369 default: Internal ("Invalid token");
1371 Root = NewExprNode (Op);
1373 Root->Right = Right;
1378 /* Return the expression tree we've created */
1384 static ExprNode* Expr2 (void)
1385 /* Boolean operators: AND and XOR */
1387 /* Read left hand side */
1388 ExprNode* Root = BoolExpr ();
1390 /* Handle booleans */
1391 while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) {
1393 long LVal, RVal, Val;
1397 /* Remember the token and skip it */
1398 token_t T = CurTok.Tok;
1401 /* Move root to left side and read the right side */
1403 Right = BoolExpr ();
1405 /* If both expressions are constant, we can evaluate the term */
1406 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1409 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
1410 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
1411 default: Internal ("Invalid token");
1414 /* Generate a literal expression and delete the old left and
1419 Root = GenLiteralExpr (Val);
1423 /* Generate an expression tree */
1426 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1427 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1428 default: Internal ("Invalid token");
1430 Root = NewExprNode (Op);
1432 Root->Right = Right;
1437 /* Return the expression tree we've created */
1443 static ExprNode* Expr1 (void)
1444 /* Boolean operators: OR */
1446 /* Read left hand side */
1447 ExprNode* Root = Expr2 ();
1449 /* Handle booleans */
1450 while (CurTok.Tok == TOK_BOOLOR) {
1452 long LVal, RVal, Val;
1456 /* Remember the token and skip it */
1457 token_t T = CurTok.Tok;
1460 /* Move root to left side and read the right side */
1464 /* If both expressions are constant, we can evaluate the term */
1465 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1468 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1469 default: Internal ("Invalid token");
1472 /* Generate a literal expression and delete the old left and
1477 Root = GenLiteralExpr (Val);
1481 /* Generate an expression tree */
1484 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1485 default: Internal ("Invalid token");
1487 Root = NewExprNode (Op);
1489 Root->Right = Right;
1494 /* Return the expression tree we've created */
1500 static ExprNode* Expr0 (void)
1501 /* Boolean operators: NOT */
1505 /* Handle booleans */
1506 if (CurTok.Tok == TOK_BOOLNOT) {
1511 /* Skip the operator token */
1514 /* Read the argument */
1517 /* If the argument is const, evaluate it directly */
1518 if (IsEasyConst (Left, &Val)) {
1520 Root = GenLiteralExpr (!Val);
1522 Root = NewExprNode (EXPR_BOOLNOT);
1528 /* Read left hand side */
1533 /* Return the expression tree we've created */
1539 ExprNode* Expression (void)
1540 /* Evaluate an expression, build the expression tree on the heap and return
1541 ** a pointer to the root of the tree.
1549 long ConstExpression (void)
1550 /* Parse an expression. Check if the expression is const, and print an error
1551 ** message if not. Return the value of the expression, or a dummy, if it is
1557 /* Read the expression */
1558 ExprNode* Expr = Expression ();
1560 /* Study the expression */
1563 StudyExpr (Expr, &D);
1565 /* Check if the expression is constant */
1566 if (ED_IsConst (&D)) {
1569 Error ("Constant expression expected");
1573 /* Free the expression tree and allocated memory for D */
1577 /* Return the value */
1583 void FreeExpr (ExprNode* Root)
1584 /* Free the expression, Root is pointing to. */
1587 FreeExpr (Root->Left);
1588 FreeExpr (Root->Right);
1589 FreeExprNode (Root);
1595 ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
1596 /* Try to simplify the given expression tree */
1598 if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
1599 /* No external references */
1601 Expr = GenLiteralExpr (D->Val);
1608 ExprNode* GenLiteralExpr (long Val)
1609 /* Return an expression tree that encodes the given literal value */
1611 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1618 ExprNode* GenLiteral0 (void)
1619 /* Return an expression tree that encodes the the number zero */
1621 return GenLiteralExpr (0);
1626 ExprNode* GenSymExpr (SymEntry* Sym)
1627 /* Return an expression node that encodes the given symbol */
1629 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1631 SymAddExprRef (Sym, Expr);
1637 static ExprNode* GenSectionExpr (unsigned SecNum)
1638 /* Return an expression node for the given section */
1640 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1641 Expr->V.SecNum = SecNum;
1647 static ExprNode* GenBankExpr (unsigned SecNum)
1648 /* Return an expression node for the given bank */
1650 ExprNode* Expr = NewExprNode (EXPR_BANK);
1651 Expr->V.SecNum = SecNum;
1657 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1658 /* Generate an addition from the two operands */
1661 if (IsEasyConst (Left, &Val) && Val == 0) {
1664 } else if (IsEasyConst (Right, &Val) && Val == 0) {
1668 ExprNode* Root = NewExprNode (EXPR_PLUS);
1670 Root->Right = Right;
1677 ExprNode* GenCurrentPC (void)
1678 /* Return the current program counter as expression */
1682 if (GetRelocMode ()) {
1683 /* Create SegmentBase + Offset */
1684 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1685 GenLiteralExpr (GetPC ()));
1687 /* Absolute mode, just return PC value */
1688 Root = GenLiteralExpr (GetPC ());
1696 ExprNode* GenSwapExpr (ExprNode* Expr)
1697 /* Return an extended expression with lo and hi bytes swapped */
1699 ExprNode* N = NewExprNode (EXPR_SWAP);
1706 ExprNode* GenBranchExpr (unsigned Offs)
1707 /* Return an expression that encodes the difference between current PC plus
1708 ** offset and the target expression (that is, Expression() - (*+Offs) ).
1715 /* Read Expression() */
1718 /* If the expression is a cheap constant, generate a simpler tree */
1719 if (IsEasyConst (N, &Val)) {
1721 /* Free the constant expression tree */
1724 /* Generate the final expression:
1726 ** Val - ((Seg + PC) + Offs)
1727 ** Val - Seg - PC - Offs
1728 ** (Val - PC - Offs) - Seg
1730 Root = GenLiteralExpr (Val - GetPC () - Offs);
1731 if (GetRelocMode ()) {
1733 Root = NewExprNode (EXPR_MINUS);
1735 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1740 /* Generate the expression:
1742 ** N - ((Seg + PC) + Offs)
1743 ** N - Seg - PC - Offs
1744 ** N - (PC + Offs) - Seg
1746 Root = NewExprNode (EXPR_MINUS);
1748 Root->Right = GenLiteralExpr (GetPC () + Offs);
1749 if (GetRelocMode ()) {
1751 Root = NewExprNode (EXPR_MINUS);
1753 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1757 /* Return the result */
1763 ExprNode* GenULabelExpr (unsigned Num)
1764 /* Return an expression for an unnamed label with the given index */
1766 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1769 /* Return the new node */
1775 ExprNode* GenByteExpr (ExprNode* Expr)
1776 /* Force the given expression into a byte and return the result */
1778 /* Use the low byte operator to force the expression into byte size */
1779 return LoByte (Expr);
1784 ExprNode* GenWordExpr (ExprNode* Expr)
1785 /* Force the given expression into a word and return the result. */
1787 /* Use the low byte operator to force the expression into word size */
1788 return LoWord (Expr);
1793 ExprNode* GenFarAddrExpr (ExprNode* Expr)
1794 /* Force the given expression into a far address and return the result. */
1798 /* Special handling for const expressions */
1799 if (IsEasyConst (Expr, &Val)) {
1801 Expr = GenLiteralExpr (Val & 0xFFFFFF);
1803 ExprNode* Operand = Expr;
1804 Expr = NewExprNode (EXPR_FARADDR);
1805 Expr->Left = Operand;
1812 ExprNode* GenDWordExpr (ExprNode* Expr)
1813 /* Force the given expression into a dword and return the result. */
1817 /* Special handling for const expressions */
1818 if (IsEasyConst (Expr, &Val)) {
1820 Expr = GenLiteralExpr (Val & 0xFFFFFFFF);
1822 ExprNode* Operand = Expr;
1823 Expr = NewExprNode (EXPR_DWORD);
1824 Expr->Left = Operand;
1831 ExprNode* GenNE (ExprNode* Expr, long Val)
1832 /* Generate an expression that compares Expr and Val for inequality */
1834 /* Generate a compare node */
1835 ExprNode* Root = NewExprNode (EXPR_NE);
1837 Root->Right = GenLiteralExpr (Val);
1839 /* Return the result */
1845 int IsConstExpr (ExprNode* Expr, long* Val)
1846 /* Return true if the given expression is a constant expression, that is, one
1847 ** with no references to external symbols. If Val is not NULL and the
1848 ** expression is constant, the constant value is stored here.
1853 /* Study the expression */
1856 StudyExpr (Expr, &D);
1858 /* Check if the expression is constant */
1859 IsConst = ED_IsConst (&D);
1860 if (IsConst && Val != 0) {
1864 /* Delete allocated memory and return the result */
1871 ExprNode* CloneExpr (ExprNode* Expr)
1872 /* Clone the given expression tree. The function will simply clone symbol
1873 ** nodes, it will not resolve them.
1878 /* Accept NULL pointers */
1883 /* Clone the node */
1887 Clone = GenLiteralExpr (Expr->V.IVal);
1891 Clone = GenULabelExpr (Expr->V.IVal);
1895 Clone = GenSymExpr (Expr->V.Sym);
1899 Clone = GenSectionExpr (Expr->V.SecNum);
1903 Clone = GenBankExpr (Expr->V.SecNum);
1907 /* Generate a new node */
1908 Clone = NewExprNode (Expr->Op);
1909 /* Clone the tree nodes */
1910 Clone->Left = CloneExpr (Expr->Left);
1911 Clone->Right = CloneExpr (Expr->Right);
1921 void WriteExpr (ExprNode* Expr)
1922 /* Write the given expression to the object file */
1924 /* Null expressions are encoded by a type byte of zero */
1926 ObjWrite8 (EXPR_NULL);
1930 /* If the is a leafnode, write the expression attribute, otherwise
1931 ** write the expression operands.
1936 ObjWrite8 (EXPR_LITERAL);
1937 ObjWrite32 (Expr->V.IVal);
1941 if (SymIsImport (Expr->V.Sym)) {
1942 ObjWrite8 (EXPR_SYMBOL);
1943 ObjWriteVar (GetSymImportId (Expr->V.Sym));
1945 WriteExpr (GetSymExpr (Expr->V.Sym));
1950 ObjWrite8 (EXPR_SECTION);
1951 ObjWriteVar (Expr->V.SecNum);
1955 WriteExpr (ULabResolve (Expr->V.IVal));
1959 /* Not a leaf node */
1960 ObjWrite8 (Expr->Op);
1961 WriteExpr (Expr->Left);
1962 WriteExpr (Expr->Right);
1970 void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
1971 /* Mark the address size of the given expression tree as guessed. The address
1972 ** size passed as argument is the one NOT used, because the actual address
1973 ** size wasn't known. Example: Zero page addressing was not used because symbol
1974 ** is undefined, and absolute addressing was available.
1975 ** This function will actually parse the expression tree for undefined symbols,
1976 ** and mark these symbols accordingly.
1979 /* Accept NULL expressions */
1984 /* Check the type code */
1985 switch (EXPR_NODETYPE (Expr->Op)) {
1988 if (Expr->Op == EXPR_SYMBOL) {
1989 if (!SymIsDef (Expr->V.Sym)) {
1990 /* Symbol is undefined, mark it */
1991 SymGuessedAddrSize (Expr->V.Sym, AddrSize);
1996 case EXPR_BINARYNODE:
1997 ExprGuessedAddrSize (Expr->Right, AddrSize);
2000 case EXPR_UNARYNODE:
2001 ExprGuessedAddrSize (Expr->Left, AddrSize);
2008 ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size)
2009 /* Force the given expression into a specific size of ForceRange is true */
2013 case 1: Expr = GenByteExpr (Expr); break;
2014 case 2: Expr = GenWordExpr (Expr); break;
2015 case 3: Expr = GenFarAddrExpr (Expr); break;
2016 case 4: Expr = GenDWordExpr (Expr); break;
2017 default: Internal ("Invalid size in BoundedExpr: %u", Size);
2025 ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
2026 /* Parse an expression and force it within a given size if ForceRange is true */
2028 return MakeBoundedExpr (ExprFunc (), Size);