1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 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 /*****************************************************************************/
62 /*****************************************************************************/
64 /*****************************************************************************/
68 /* Since all expressions are first packed into expression trees, and each
69 * expression tree node is allocated on the heap, we add some type of special
70 * purpose memory allocation here: Instead of freeing the nodes, we save some
71 * number of freed nodes for later and remember them in a single linked list
72 * using the Left link.
74 #define MAX_FREE_NODES 64
75 static ExprNode* FreeExprNodes = 0;
76 static unsigned FreeNodeCount = 0;
80 /*****************************************************************************/
82 /*****************************************************************************/
86 static ExprNode* NewExprNode (void)
87 /* Create a new expression node */
91 /* Do we have some nodes in the list already? */
93 /* Use first node from list */
95 FreeExprNodes = N->Left;
97 /* Allocate fresh memory */
98 N = xmalloc (sizeof (ExprNode));
101 N->Left = N->Right = 0;
109 static void FreeExprNode (ExprNode* E)
113 if (FreeNodeCount < MAX_FREE_NODES) {
114 /* Remember this node for later */
115 E->Left = FreeExprNodes;
118 /* Free the memory */
126 /*****************************************************************************/
128 /*****************************************************************************/
132 static ExprNode* Expr0 (void);
136 int IsByteRange (long Val)
137 /* Return true if this is a byte value */
139 return (Val & ~0xFFL) == 0;
144 int IsWordRange (long Val)
145 /* Return true if this is a word value */
147 return (Val & ~0xFFFF) == 0;
152 static int FuncBlank (void)
153 /* Handle the .BLANK builtin function */
155 /* Assume no tokens if the closing brace follows (this is not correct in
156 * all cases, since the token may be the closing brace, but this will
157 * give a syntax error anyway and may not be handled by .BLANK.
159 if (Tok == TOK_RPAREN) {
163 /* Skip any tokens */
165 while (!TokIsSep (Tok)) {
166 if (Tok == TOK_LPAREN) {
168 } else if (Tok == TOK_RPAREN) {
184 static int FuncConst (void)
185 /* Handle the .CONST builtin function */
187 /* Read an expression */
188 ExprNode* Expr = Expression ();
190 /* Check the constness of the expression */
191 int Result = IsConstExpr (Expr);
193 /* Free the expression */
202 static int FuncDefined (void)
203 /* Handle the .DEFINED builtin function */
205 static const char* Keys[] = {
211 char Name [sizeof (SVal)];
215 /* First argument is a symbol name */
216 if (Tok != TOK_IDENT) {
217 Error (ERR_IDENT_EXPECTED);
218 if (Tok != TOK_RPAREN) {
224 /* Remember the name, then skip it */
228 /* Comma and scope spec may follow */
229 if (Tok == TOK_COMMA) {
234 /* An identifier must follow */
235 if (Tok != TOK_IDENT) {
236 Error (ERR_IDENT_EXPECTED);
240 /* Get the scope, then skip it */
241 Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
244 /* Check if we got a valid keyword */
246 Error (ERR_ILLEGAL_SCOPE);
252 case 0: Scope = SCOPE_ANY; break;
253 case 1: Scope = SCOPE_GLOBAL; break;
254 case 2: Scope = SCOPE_LOCAL; break;
255 default: Internal ("Invalid scope: %d", Scope);
265 /* Search for the symbol */
266 Result = SymIsDef (SVal, Scope);
274 static int DoMatch (enum TC EqualityLevel)
275 /* Handle the .MATCH and .XMATCH builtin functions */
282 /* A list of tokens follows. Read this list and remember it building a
283 * single linked list of tokens including attributes. The list is
284 * terminated by a comma.
286 while (Tok != TOK_COMMA) {
288 /* We may not end-of-line of end-of-file here */
289 if (TokIsSep (Tok)) {
290 Error (ERR_UNEXPECTED_EOL);
294 /* Get a node with this token */
295 Node = NewTokNode ();
297 /* Insert the node into the list */
312 /* Read the second list which is terminated by the right parenthesis and
313 * compare each token against the one in the first list.
317 while (Tok != TOK_RPAREN) {
319 /* We may not end-of-line of end-of-file here */
320 if (TokIsSep (Tok)) {
321 Error (ERR_UNEXPECTED_EOL);
325 /* Compare the tokens if the result is not already known */
328 /* The second list is larger than the first one */
330 } else if (TokCmp (Node) < EqualityLevel) {
331 /* Tokens do not match */
336 /* Next token in first list */
341 /* Next token in current list */
345 /* Check if there are remaining tokens in the first list */
350 /* Free the token list */
357 /* Done, return the result */
363 static int FuncMatch (void)
364 /* Handle the .MATCH function */
366 return DoMatch (tcSameToken);
371 static int FuncReferenced (void)
372 /* Handle the .REFERENCED builtin function */
376 if (Tok != TOK_IDENT) {
377 Error (ERR_IDENT_EXPECTED);
378 if (Tok != TOK_RPAREN) {
382 Result = SymIsRef (SVal, SCOPE_ANY);
392 static int FuncStrAt (void)
393 /* Handle the .STRAT function */
395 char Str [sizeof(SVal)];
398 /* String constant expected */
399 if (Tok != TOK_STRCON) {
400 Error (ERR_STRCON_EXPECTED);
406 /* Remember the string and skip it */
410 /* Comma must follow */
413 /* Expression expected */
414 Index = ConstExpression ();
416 /* Must be a valid index */
417 if (Index >= (long) strlen (Str)) {
422 /* Return the char, handle as unsigned. Be sure to translate it into
423 * the target character set.
425 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
430 static int FuncStrLen (void)
431 /* Handle the .STRLEN function */
433 /* String constant expected */
434 if (Tok != TOK_STRCON) {
436 Error (ERR_STRCON_EXPECTED);
437 /* Smart error recovery */
438 if (Tok != TOK_RPAREN) {
445 /* Get the length of the string */
446 int Len = strlen (SVal);
448 /* Skip the string */
451 /* Return the length */
459 static int FuncTCount (void)
460 /* Handle the .TCOUNT function */
462 /* We have a list of tokens that ends with the closing paren. Skip
463 * the tokens, handling nested braces and count them.
467 while (Parens != 0 || Tok != TOK_RPAREN) {
469 /* Check for end of line or end of input. Since the calling function
470 * will check for the closing paren, we don't need to print an error
471 * here, just bail out.
473 if (TokIsSep (Tok)) {
480 /* Keep track of the nesting level */
482 case TOK_LPAREN: ++Parens; break;
483 case TOK_RPAREN: --Parens; break;
491 /* Return the number of tokens */
497 static int FuncXMatch (void)
498 /* Handle the .XMATCH function */
500 return DoMatch (tcIdentical);
505 static ExprNode* Function (int (*F) (void))
506 /* Handle builtin functions */
510 /* Skip the keyword */
513 /* Expression must be enclosed in braces */
514 if (Tok != TOK_LPAREN) {
515 Error (ERR_LPAREN_EXPECTED);
517 return GenLiteralExpr (0);
521 /* Call the function itself */
524 /* Closing brace must follow */
527 /* Return an expression node with the boolean code */
528 return GenLiteralExpr (Result);
533 static ExprNode* Factor (void)
541 N = GenLiteralExpr (IVal);
546 N = GenLiteralExpr (TgtTranslateChar (IVal));
552 if (Tok != TOK_IDENT) {
553 Error (ERR_IDENT_EXPECTED);
554 N = GenLiteralExpr (0); /* Dummy */
556 S = SymRef (SVal, SCOPE_GLOBAL);
557 if (SymIsConst (S)) {
558 /* Use the literal value instead */
559 N = GenLiteralExpr (GetSymVal (S));
561 /* Create symbol node */
571 S = SymRef (SVal, SCOPE_LOCAL);
572 if (SymIsConst (S)) {
573 /* Use the literal value instead */
574 N = GenLiteralExpr (GetSymVal (S));
576 /* Create symbol node */
593 N->Op = EXPR_UNARY_MINUS;
630 N = Function (FuncBlank);
634 N = Function (FuncConst);
638 N = GenLiteralExpr (CPUIsets[CPU]);
643 N = Function (FuncDefined);
647 N = Function (FuncMatch);
651 N = Function (FuncReferenced);
655 N = Function (FuncStrAt);
659 N = Function (FuncStrLen);
663 N = Function (FuncTCount);
667 N = GenLiteralExpr (time (0));
672 N = GenLiteralExpr (VERSION);
678 N = Function (FuncXMatch);
682 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
683 /* A character constant */
684 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
686 N = GenLiteralExpr (0); /* Dummy */
697 static ExprNode* Term (void)
701 /* Read left hand side */
704 /* Handle multiplicative operations */
705 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
706 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
709 /* Create a new node and insert the left expression */
710 ExprNode* Left = Root;
711 Root = NewExprNode ();
714 /* Determine the operator token */
716 case TOK_MUL: Root->Op = EXPR_MUL; break;
717 case TOK_DIV: Root->Op = EXPR_DIV; break;
718 case TOK_MOD: Root->Op = EXPR_MOD; break;
719 case TOK_AND: Root->Op = EXPR_AND; break;
720 case TOK_XOR: Root->Op = EXPR_XOR; break;
721 case TOK_SHL: Root->Op = EXPR_SHL; break;
722 case TOK_SHR: Root->Op = EXPR_SHR; break;
723 default: Internal ("Invalid token");
727 /* Parse the right hand side */
728 Root->Right = Factor ();
732 /* Return the expression tree we've created */
738 static ExprNode* SimpleExpr (void)
742 /* Read left hand side */
745 /* Handle additive operations */
746 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
748 /* Create a new node and insert the left expression */
749 ExprNode* Left = Root;
750 Root = NewExprNode ();
753 /* Determine the operator token */
755 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
756 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
757 case TOK_OR: Root->Op = EXPR_OR; break;
758 default: Internal ("Invalid token");
762 /* Parse the right hand side */
763 Root->Right = Term ();
767 /* Return the expression tree we've created */
773 static ExprNode* BoolExpr (void)
774 /* Evaluate a boolean expression */
776 /* Read left hand side */
777 ExprNode* Root = SimpleExpr ();
779 /* Handle booleans */
780 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
781 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
783 /* Create a new node and insert the left expression */
784 ExprNode* Left = Root;
785 Root = NewExprNode ();
788 /* Determine the operator token */
790 case TOK_EQ: Root->Op = EXPR_EQ; break;
791 case TOK_NE: Root->Op = EXPR_NE; break;
792 case TOK_LT: Root->Op = EXPR_LT; break;
793 case TOK_GT: Root->Op = EXPR_GT; break;
794 case TOK_LE: Root->Op = EXPR_LE; break;
795 case TOK_GE: Root->Op = EXPR_GE; break;
796 default: Internal ("Invalid token");
800 /* Parse the right hand side */
801 Root->Right = SimpleExpr ();
805 /* Return the expression tree we've created */
811 static ExprNode* Expr2 (void)
812 /* Boolean operators: AND and XOR */
814 /* Read left hand side */
815 ExprNode* Root = BoolExpr ();
817 /* Handle booleans */
818 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
820 /* Create a new node and insert the left expression */
821 ExprNode* Left = Root;
822 Root = NewExprNode ();
825 /* Determine the operator token */
827 case TOK_BAND: Root->Op = EXPR_BAND; break;
828 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
829 default: Internal ("Invalid token");
833 /* Parse the right hand side */
834 Root->Right = BoolExpr ();
838 /* Return the expression tree we've created */
844 static ExprNode* Expr1 (void)
845 /* Boolean operators: OR */
847 /* Read left hand side */
848 ExprNode* Root = Expr2 ();
850 /* Handle booleans */
851 while (Tok == TOK_BOR) {
853 /* Create a new node and insert the left expression */
854 ExprNode* Left = Root;
855 Root = NewExprNode ();
858 /* Determine the operator token */
860 case TOK_BOR: Root->Op = EXPR_BOR; break;
861 default: Internal ("Invalid token");
865 /* Parse the right hand side */
866 Root->Right = Expr2 ();
870 /* Return the expression tree we've created */
876 static ExprNode* Expr0 (void)
877 /* Boolean operators: NOT */
881 /* Handle booleans */
882 if (Tok == TOK_BNOT) {
884 /* Create a new node */
885 Root = NewExprNode ();
887 /* Determine the operator token */
889 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
890 default: Internal ("Invalid token");
894 /* Parse the left hand side, allow more BNOTs */
895 Root->Left = Expr0 ();
899 /* Read left hand side */
904 /* Return the expression tree we've created */
910 static ExprNode* SimplifyExpr (ExprNode* Root)
911 /* Try to simplify the given expression tree */
914 SimplifyExpr (Root->Left);
915 SimplifyExpr (Root->Right);
916 if (IsConstExpr (Root)) {
917 /* The complete expression is constant */
918 Root->V.Val = GetExprVal (Root);
919 Root->Op = EXPR_LITERAL;
920 FreeExpr (Root->Left);
921 FreeExpr (Root->Right);
922 Root->Left = Root->Right = 0;
930 ExprNode* Expression (void)
931 /* Evaluate an expression, build the expression tree on the heap and return
932 * a pointer to the root of the tree.
935 return SimplifyExpr (Expr0 ());
940 long ConstExpression (void)
941 /* Parse an expression. Check if the expression is const, and print an error
942 * message if not. Return the value of the expression, or a dummy, if it is
946 /* Read the expression, and call finalize (exception here, since we
949 ExprNode* Expr = FinalizeExpr (Expression ());
951 /* Return the value */
952 if (IsConstExpr (Expr)) {
953 return GetExprVal (Expr);
955 Error (ERR_CONSTEXPR_EXPECTED);
962 void FreeExpr (ExprNode* Root)
963 /* Free the expression, Root is pointing to. */
966 FreeExpr (Root->Left);
967 FreeExpr (Root->Right);
974 ExprNode* GenLiteralExpr (long Val)
975 /* Return an expression tree that encodes the given literal value */
977 ExprNode* Expr = NewExprNode ();
978 Expr->Op = EXPR_LITERAL;
985 ExprNode* GenCurrentPC (void)
986 /* Return the current program counter as expression */
992 /* Create SegmentBase + Offset */
993 Left = NewExprNode ();
994 Left->Op = EXPR_SECTION;
995 Left->V.SegNum = GetSegNum ();
997 Root = NewExprNode ();
999 Root->Right = GenLiteralExpr (GetPC ());
1000 Root->Op = EXPR_PLUS;
1002 /* Absolute mode, just return PC value */
1003 Root = GenLiteralExpr (GetPC ());
1011 ExprNode* GenSwapExpr (ExprNode* Expr)
1012 /* Return an extended expression with lo and hi bytes swapped */
1014 ExprNode* N = NewExprNode ();
1022 ExprNode* GenBranchExpr (unsigned Offs)
1023 /* Return an expression that encodes the difference between current PC plus
1024 * offset and the target expression (that is, Expression() - (*+Offs) ).
1033 Left = NewExprNode ();
1034 Left->Op = EXPR_SECTION;
1035 Left->V.SegNum = GetSegNum ();
1039 N->Right = GenLiteralExpr (GetPC () + Offs);
1042 N = GenLiteralExpr (GetPC () + Offs);
1045 /* Create the root node */
1046 Root = NewExprNode ();
1047 Root->Left = Expression ();
1049 Root->Op = EXPR_MINUS;
1051 /* Return the result */
1052 return SimplifyExpr (Root);
1057 ExprNode* GenULabelExpr (unsigned Num)
1058 /* Return an expression for an unnamed label with the given index */
1060 /* Get an expression node */
1061 ExprNode* Node = NewExprNode ();
1063 /* Set the values */
1064 Node->Op = EXPR_ULABEL;
1067 /* Return the new node */
1073 ExprNode* GenByteExpr (ExprNode* Expr)
1074 /* Force the given expression into a byte and return the result */
1076 /* Use the low byte operator to force the expression into byte size */
1077 ExprNode* Root = NewExprNode ();
1079 Root->Op = EXPR_BYTE0;
1081 /* Return the result */
1087 ExprNode* GenWordExpr (ExprNode* Expr)
1088 /* Force the given expression into a word and return the result. */
1090 /* AND the expression by $FFFF to force it into word size */
1091 ExprNode* Root = NewExprNode ();
1093 Root->Op = EXPR_AND;
1094 Root->Right = GenLiteralExpr (0xFFFF);
1096 /* Return the result */
1102 ExprNode* GenNE (ExprNode* Expr, long Val)
1103 /* Generate an expression that compares Expr and Val for inequality */
1105 /* Generate a compare node */
1106 ExprNode* Root = NewExprNode ();
1109 Root->Right = GenLiteralExpr (Val);
1111 /* Return the result */
1117 int IsConstExpr (ExprNode* Root)
1118 /* Return true if the given expression is a constant expression, that is, one
1119 * with no references to external symbols.
1125 if (EXPR_IS_LEAF (Root->Op)) {
1133 if (SymHasUserMark (Sym)) {
1134 if (Verbosity > 0) {
1137 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1141 Const = SymIsConst (Sym);
1142 SymUnmarkUser (Sym);
1150 } else if (EXPR_IS_UNARY (Root->Op)) {
1152 return IsConstExpr (Root->Left);
1156 /* We must handle shortcut boolean expressions here */
1160 if (IsConstExpr (Root->Left)) {
1161 /* lhs is const, if it is zero, don't eval right */
1162 if (GetExprVal (Root->Left) == 0) {
1165 return IsConstExpr (Root->Right);
1168 /* lhs not const --> tree not const */
1174 if (IsConstExpr (Root->Left)) {
1175 /* lhs is const, if it is not zero, don't eval right */
1176 if (GetExprVal (Root->Left) != 0) {
1179 return IsConstExpr (Root->Right);
1182 /* lhs not const --> tree not const */
1188 /* All others are handled normal */
1189 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1196 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1197 /* Internal routine that is recursively called to check if there is a zeropage
1198 * symbol in the expression tree.
1202 switch (N->Op & EXPR_TYPEMASK) {
1208 if (SymIsZP (N->V.Sym)) {
1210 } else if (SymHasExpr (N->V.Sym)) {
1211 /* Check if this expression is a byte expression */
1212 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1217 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1225 case EXPR_UNARYNODE:
1226 CheckByteExpr (N->Left, IsByte);
1229 case EXPR_BINARYNODE:
1230 CheckByteExpr (N->Left, IsByte);
1231 CheckByteExpr (N->Right, IsByte);
1235 Internal ("Unknown expression op: %02X", N->Op);
1242 int IsByteExpr (ExprNode* Root)
1243 /* Return true if this is a byte expression */
1247 if (IsConstExpr (Root)) {
1248 if (Root->Op != EXPR_LITERAL) {
1249 SimplifyExpr (Root);
1251 return IsByteRange (GetExprVal (Root));
1252 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1253 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1254 /* Symbol forced to have byte range */
1257 /* We have undefined symbols in the expression. Assume that the
1258 * expression is a byte expression if there is at least one symbol
1259 * declared as zeropage in it. Being wrong here is not a very big
1260 * problem since the linker knows about all symbols and detects
1261 * error like mixing absolute and zeropage labels.
1264 CheckByteExpr (Root, &IsByte);
1271 long GetExprVal (ExprNode* Expr)
1272 /* Get the value of a constant expression */
1282 return GetSymVal (Expr->V.Sym);
1285 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1288 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1291 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1294 Left = GetExprVal (Expr->Left);
1295 Right = GetExprVal (Expr->Right);
1297 Error (ERR_DIV_BY_ZERO);
1300 return Left / Right;
1303 Left = GetExprVal (Expr->Left);
1304 Right = GetExprVal (Expr->Right);
1306 Error (ERR_MOD_BY_ZERO);
1309 return Left % Right;
1312 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1315 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1318 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1321 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1324 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1327 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1330 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1333 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1336 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1339 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1342 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1344 case EXPR_UNARY_MINUS:
1345 return -GetExprVal (Expr->Left);
1348 return ~GetExprVal (Expr->Left);
1351 return GetExprVal (Expr->Left) & 0xFF;
1354 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1357 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1360 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1363 Left = GetExprVal (Expr->Left);
1364 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1367 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1370 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1373 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1376 return !GetExprVal (Expr->Left);
1379 Internal ("GetExprVal called for EXPR_ULABEL");
1384 Internal ("Unknown Op type: %u", Expr->Op);
1392 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1393 /* Remove resolved symbols from the tree by cloning symbol expressions */
1395 /* Accept NULL pointers */
1400 /* Special node handling */
1404 if (SymHasExpr (Expr->V.Sym)) {
1405 /* The symbol has an expression tree */
1406 SymEntry* Sym = Expr->V.Sym;
1407 if (SymHasUserMark (Sym)) {
1408 /* Circular definition */
1412 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1413 return GenLiteralExpr (0); /* Return a dummy value */
1416 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1417 SymUnmarkUser (Sym);
1419 } else if (SymIsConst (Expr->V.Sym)) {
1420 /* The symbol is a constant */
1421 return GenLiteralExpr (GetSymVal (Expr->V.Sym));
1426 if (ULabCanResolve ()) {
1427 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1435 /* Clone the current node if needed */
1438 /* Create a new node */
1439 ExprNode* Clone = NewExprNode ();
1441 /* Clone the operation */
1442 Clone->Op = Expr->Op;
1444 /* Clone the attribute if needed */
1449 Clone->V.Val = Expr->V.Val;
1453 Clone->V.Sym = Expr->V.Sym;
1457 Clone->V.SegNum = Expr->V.SegNum;
1462 /* Clone the tree nodes */
1463 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1464 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1471 /* Nothing to clone */
1472 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1473 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1483 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1484 /* Extract and evaluate all constant factors in an subtree that has only
1485 * additions and subtractions.
1488 if (Expr->Op == EXPR_LITERAL) {
1490 *Val -= Expr->V.Val;
1492 *Val += Expr->V.Val;
1494 FreeExprNode (Expr);
1498 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1501 Left = ConstExtract (Expr->Left, Val, Sign);
1502 if (Expr->Op == EXPR_MINUS) {
1505 Right = ConstExtract (Expr->Right, Val, Sign);
1506 if (Left == 0 && Right == 0) {
1507 FreeExprNode (Expr);
1509 } else if (Left == 0) {
1510 FreeExprNode (Expr);
1512 } else if (Right == 0) {
1513 FreeExprNode (Expr);
1516 /* Check for SEG - SEG which is now possible */
1517 if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
1518 Left->V.SegNum == Right->V.SegNum) {
1519 /* SEG - SEG, remove it completely */
1520 FreeExprNode (Left);
1521 FreeExprNode (Right);
1522 FreeExprNode (Expr);
1526 Expr->Right = Right;
1532 /* Some other sort of node, finalize the terms */
1534 Expr->Left = FinalizeExpr (Expr->Left);
1537 Expr->Right = FinalizeExpr (Expr->Right);
1545 ExprNode* FinalizeExpr (ExprNode* Expr)
1546 /* Resolve any symbols by cloning the symbol expression tree instead of the
1547 * symbol reference, then try to simplify the expression as much as possible.
1548 * This function must only be called if all symbols are resolved (no undefined
1555 Expr = RemoveSyms (Expr, 0);
1556 Expr = ConstExtract (Expr, &Val, 1);
1558 /* Reduced to a literal value */
1559 Expr = GenLiteralExpr (Val);
1561 /* Extracted a value */
1565 N->Right = GenLiteralExpr (Val);
1573 ExprNode* CloneExpr (ExprNode* Expr)
1574 /* Clone the given expression tree. The function will simply clone symbol
1575 * nodes, it will not resolve them.
1580 /* Accept NULL pointers */
1585 /* Get a new node */
1586 Clone = NewExprNode ();
1588 /* Clone the operation */
1589 Clone->Op = Expr->Op;
1591 /* Clone the attribute if needed */
1596 Clone->V.Val = Expr->V.Val;
1600 Clone->V.Sym = Expr->V.Sym;
1604 Clone->V.SegNum = Expr->V.SegNum;
1609 /* Clone the tree nodes */
1610 Clone->Left = CloneExpr (Expr->Left);
1611 Clone->Right = CloneExpr (Expr->Right);
1619 void WriteExpr (ExprNode* Expr)
1620 /* Write the given expression to the object file */
1622 /* Null expressions are encoded by a type byte of zero */
1628 /* Write the expression code */
1629 ObjWrite8 (Expr->Op);
1631 /* If the is a leafnode, write the expression attribute, otherwise
1632 * write the expression operands.
1637 ObjWrite32 (Expr->V.Val);
1641 /* Maybe we should use a code here? */
1642 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1643 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1647 ObjWrite8 (Expr->V.SegNum);
1651 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1655 /* Not a leaf node */
1656 WriteExpr (Expr->Left);
1657 WriteExpr (Expr->Right);