1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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 /*****************************************************************************/
58 /*****************************************************************************/
60 /*****************************************************************************/
64 /* Since all expressions are first packed into expression trees, and each
65 * expression tree node is allocated on the heap, we add some type of special
66 * purpose memory allocation here: Instead of freeing the nodes, we save some
67 * number of freed nodes for later and remember them in a single linked list
68 * using the Left link.
70 #define MAX_FREE_NODES 64
71 static ExprNode* FreeExprNodes = 0;
72 static unsigned FreeNodeCount = 0;
76 /*****************************************************************************/
78 /*****************************************************************************/
82 static ExprNode* NewExprNode (void)
83 /* Create a new expression node */
87 /* Do we have some nodes in the list already? */
89 /* Use first node from list */
91 FreeExprNodes = N->Left;
93 /* Allocate fresh memory */
94 N = xmalloc (sizeof (ExprNode));
97 N->Left = N->Right = 0;
105 static void FreeExprNode (ExprNode* E)
109 if (FreeNodeCount < MAX_FREE_NODES) {
110 /* Remember this node for later */
111 E->Left = FreeExprNodes;
114 /* Free the memory */
122 /*****************************************************************************/
124 /*****************************************************************************/
128 static ExprNode* Expr0 (void);
132 int IsByteRange (long Val)
133 /* Return true if this is a byte value */
135 return (Val & ~0xFFL) == 0;
140 int IsWordRange (long Val)
141 /* Return true if this is a word value */
143 return (Val & ~0xFFFF) == 0;
148 static int FuncBlank (void)
149 /* Handle the .BLANK builtin function */
151 /* Assume no tokens if the closing brace follows (this is not correct in
152 * all cases, since the token may be the closing brace, but this will
153 * give a syntax error anyway and may not be handled by .BLANK.
155 if (Tok == TOK_RPAREN) {
159 /* Skip any tokens */
161 while (Tok != TOK_SEP && Tok != TOK_EOF) {
162 if (Tok == TOK_LPAREN) {
164 } else if (Tok == TOK_RPAREN) {
180 static int FuncConst (void)
181 /* Handle the .CONST builtin function */
183 /* Read an expression */
184 ExprNode* Expr = Expression ();
186 /* Check the constness of the expression */
187 int Result = IsConstExpr (Expr);
189 /* Free the expression */
198 static int FuncDefined (void)
199 /* Handle the .DEFINED builtin function */
203 if (Tok != TOK_IDENT) {
204 Error (ERR_IDENT_EXPECTED);
205 if (Tok != TOK_RPAREN) {
209 Result = SymIsDef (SVal);
219 static int DoMatch (enum TC EqualityLevel)
220 /* Handle the .MATCH and .XMATCH builtin functions */
227 /* A list of tokens follows. Read this list and remember it building a
228 * single linked list of tokens including attributes. The list is
229 * terminated by a comma.
231 while (Tok != TOK_COMMA) {
233 /* We may not end-of-line of end-of-file here */
234 if (Tok == TOK_SEP || Tok == TOK_EOF) {
235 Error (ERR_UNEXPECTED_EOL);
239 /* Get a node with this token */
240 Node = NewTokNode ();
242 /* Insert the node into the list */
257 /* Read the second list which is terminated by the right parenthesis and
258 * compare each token against the one in the first list.
262 while (Tok != TOK_RPAREN) {
264 /* We may not end-of-line of end-of-file here */
265 if (Tok == TOK_SEP || Tok == TOK_EOF) {
266 Error (ERR_UNEXPECTED_EOL);
270 /* Compare the tokens if the result is not already known */
273 /* The second list is larger than the first one */
275 } else if (TokCmp (Node) < EqualityLevel) {
276 /* Tokens do not match */
281 /* Next token in first list */
286 /* Next token in current list */
290 /* Check if there are remaining tokens in the first list */
295 /* Free the token list */
302 /* Done, return the result */
308 static int FuncMatch (void)
309 /* Handle the .MATCH function */
311 return DoMatch (tcSameToken);
316 static int FuncReferenced (void)
317 /* Handle the .REFERENCED builtin function */
321 if (Tok != TOK_IDENT) {
322 Error (ERR_IDENT_EXPECTED);
323 if (Tok != TOK_RPAREN) {
327 Result = SymIsRef (SVal);
337 static int FuncStrAt (void)
338 /* Handle the .STRAT function */
340 char Str [sizeof(SVal)];
343 /* String constant expected */
344 if (Tok != TOK_STRCON) {
345 Error (ERR_STRCON_EXPECTED);
351 /* Remember the string and skip it */
355 /* Comma must follow */
358 /* Expression expected */
359 Index = ConstExpression ();
361 /* Must be a valid index */
362 if (Index >= strlen (Str)) {
367 /* Return the char, handle as unsigned. Be sure to translate it into
368 * the target character set.
370 return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
375 static int FuncStrLen (void)
376 /* Handle the .STRLEN function */
378 /* String constant expected */
379 if (Tok != TOK_STRCON) {
381 Error (ERR_STRCON_EXPECTED);
382 /* Smart error recovery */
383 if (Tok != TOK_RPAREN) {
390 /* Get the length of the string */
391 int Len = strlen (SVal);
393 /* Skip the string */
396 /* Return the length */
404 static int FuncTCount (void)
405 /* Handle the .TCOUNT function */
407 /* We have a list of tokens that ends with the closing paren. Skip
408 * the tokens, handling nested braces and count them.
412 while (Parens != 0 || Tok != TOK_RPAREN) {
414 /* Check for end of line or end of input. Since the calling function
415 * will check for the closing paren, we don't need to print an error
416 * here, just bail out.
418 if (Tok == TOK_SEP || Tok == TOK_EOF) {
425 /* Keep track of the nesting level */
427 case TOK_LPAREN: ++Parens; break;
428 case TOK_RPAREN: --Parens; break;
436 /* Return the number of tokens */
442 static int FuncXMatch (void)
443 /* Handle the .XMATCH function */
445 return DoMatch (tcIdentical);
450 static ExprNode* Function (int (*F) (void))
451 /* Handle builtin functions */
455 /* Skip the keyword */
458 /* Expression must be enclosed in braces */
459 if (Tok != TOK_LPAREN) {
460 Error (ERR_LPAREN_EXPECTED);
462 return LiteralExpr (0);
466 /* Call the function itself */
469 /* Closing brace must follow */
472 /* Return an expression node with the boolean code */
473 return LiteralExpr (Result);
478 static ExprNode* Factor (void)
486 N = LiteralExpr (IVal);
491 N = LiteralExpr (TgtTranslateChar (IVal));
497 if (Tok != TOK_IDENT) {
498 Error (ERR_IDENT_EXPECTED);
499 N = LiteralExpr (0); /* Dummy */
501 S = SymRefGlobal (SVal);
502 if (SymIsConst (S)) {
503 /* Use the literal value instead */
504 N = LiteralExpr (GetSymVal (S));
506 /* Create symbol node */
517 if (SymIsConst (S)) {
518 /* Use the literal value instead */
519 N = LiteralExpr (GetSymVal (S));
521 /* Create symbol node */
538 N->Op = EXPR_UNARY_MINUS;
575 N = Function (FuncBlank);
579 N = Function (FuncConst);
583 N = LiteralExpr (GetCPU());
588 N = Function (FuncDefined);
592 N = Function (FuncMatch);
596 N = Function (FuncReferenced);
600 N = Function (FuncStrAt);
604 N = Function (FuncStrLen);
608 N = Function (FuncTCount);
612 N = Function (FuncXMatch);
616 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
617 /* A character constant */
618 N = LiteralExpr (TgtTranslateChar (SVal[0]));
620 N = LiteralExpr (0); /* Dummy */
631 static ExprNode* Term (void)
635 /* Read left hand side */
638 /* Handle multiplicative operations */
639 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
640 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
643 /* Create a new node and insert the left expression */
644 ExprNode* Left = Root;
645 Root = NewExprNode ();
648 /* Determine the operator token */
650 case TOK_MUL: Root->Op = EXPR_MUL; break;
651 case TOK_DIV: Root->Op = EXPR_DIV; break;
652 case TOK_MOD: Root->Op = EXPR_MOD; break;
653 case TOK_AND: Root->Op = EXPR_AND; break;
654 case TOK_XOR: Root->Op = EXPR_XOR; break;
655 case TOK_SHL: Root->Op = EXPR_SHL; break;
656 case TOK_SHR: Root->Op = EXPR_SHR; break;
657 default: Internal ("Invalid token");
661 /* Parse the right hand side */
662 Root->Right = Factor ();
666 /* Return the expression tree we've created */
672 static ExprNode* SimpleExpr (void)
676 /* Read left hand side */
679 /* Handle additive operations */
680 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
682 /* Create a new node and insert the left expression */
683 ExprNode* Left = Root;
684 Root = NewExprNode ();
687 /* Determine the operator token */
689 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
690 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
691 case TOK_OR: Root->Op = EXPR_OR; break;
692 default: Internal ("Invalid token");
696 /* Parse the right hand side */
697 Root->Right = Term ();
701 /* Return the expression tree we've created */
707 static ExprNode* BoolExpr (void)
708 /* Evaluate a boolean expression */
710 /* Read left hand side */
711 ExprNode* Root = SimpleExpr ();
713 /* Handle booleans */
714 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
715 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
717 /* Create a new node and insert the left expression */
718 ExprNode* Left = Root;
719 Root = NewExprNode ();
722 /* Determine the operator token */
724 case TOK_EQ: Root->Op = EXPR_EQ; break;
725 case TOK_NE: Root->Op = EXPR_NE; break;
726 case TOK_LT: Root->Op = EXPR_LT; break;
727 case TOK_GT: Root->Op = EXPR_GT; break;
728 case TOK_LE: Root->Op = EXPR_LE; break;
729 case TOK_GE: Root->Op = EXPR_GE; break;
730 default: Internal ("Invalid token");
734 /* Parse the right hand side */
735 Root->Right = SimpleExpr ();
739 /* Return the expression tree we've created */
745 static ExprNode* Expr2 (void)
746 /* Boolean operators: AND and XOR */
748 /* Read left hand side */
749 ExprNode* Root = BoolExpr ();
751 /* Handle booleans */
752 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
754 /* Create a new node and insert the left expression */
755 ExprNode* Left = Root;
756 Root = NewExprNode ();
759 /* Determine the operator token */
761 case TOK_BAND: Root->Op = EXPR_BAND; break;
762 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
763 default: Internal ("Invalid token");
767 /* Parse the right hand side */
768 Root->Right = BoolExpr ();
772 /* Return the expression tree we've created */
778 static ExprNode* Expr1 (void)
779 /* Boolean operators: OR */
781 /* Read left hand side */
782 ExprNode* Root = Expr2 ();
784 /* Handle booleans */
785 while (Tok == TOK_BOR) {
787 /* Create a new node and insert the left expression */
788 ExprNode* Left = Root;
789 Root = NewExprNode ();
792 /* Determine the operator token */
794 case TOK_BOR: Root->Op = EXPR_BOR; break;
795 default: Internal ("Invalid token");
799 /* Parse the right hand side */
800 Root->Right = Expr2 ();
804 /* Return the expression tree we've created */
810 static ExprNode* Expr0 (void)
811 /* Boolean operators: NOT */
815 /* Handle booleans */
816 if (Tok == TOK_BNOT) {
818 /* Create a new node */
819 Root = NewExprNode ();
821 /* Determine the operator token */
823 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
824 default: Internal ("Invalid token");
828 /* Parse the left hand side, allow more BNOTs */
829 Root->Left = Expr0 ();
833 /* Read left hand side */
838 /* Return the expression tree we've created */
844 static ExprNode* SimplifyExpr (ExprNode* Root)
845 /* Try to simplify the given expression tree */
848 SimplifyExpr (Root->Left);
849 SimplifyExpr (Root->Right);
850 if (IsConstExpr (Root)) {
851 /* The complete expression is constant */
852 Root->V.Val = GetExprVal (Root);
853 Root->Op = EXPR_LITERAL;
854 FreeExpr (Root->Left);
855 FreeExpr (Root->Right);
856 Root->Left = Root->Right = 0;
864 ExprNode* Expression (void)
865 /* Evaluate an expression, build the expression tree on the heap and return
866 * a pointer to the root of the tree.
869 return SimplifyExpr (Expr0 ());
874 long ConstExpression (void)
875 /* Parse an expression. Check if the expression is const, and print an error
876 * message if not. Return the value of the expression, or a dummy, if it is
880 /* Read the expression, and call finalize (exception here, since we
883 ExprNode* Expr = FinalizeExpr (Expression ());
885 /* Return the value */
886 if (IsConstExpr (Expr)) {
887 return GetExprVal (Expr);
889 Error (ERR_CONSTEXPR_EXPECTED);
896 ExprNode* LiteralExpr (long Val)
897 /* Return an expression tree that encodes the given literal value */
899 ExprNode* Expr = NewExprNode ();
900 Expr->Op = EXPR_LITERAL;
907 ExprNode* CurrentPC (void)
908 /* Return the current program counter as expression */
914 /* Create SegmentBase + Offset */
915 Left = NewExprNode ();
916 Left->Op = EXPR_SEGMENT;
917 Left->V.SegNum = GetSegNum ();
919 Root = NewExprNode ();
921 Root->Right = LiteralExpr (GetPC ());
922 Root->Op = EXPR_PLUS;
924 /* Absolute mode, just return PC value */
925 Root = LiteralExpr (GetPC ());
933 ExprNode* SwapExpr (ExprNode* Expr)
934 /* Return an extended expression with lo and hi bytes swapped */
936 ExprNode* N = NewExprNode ();
944 ExprNode* BranchExpr (unsigned Offs)
945 /* Return an expression that encodes the difference between current PC plus
946 * offset and the target expression (that is, Expression() - (*+Offs) ).
955 Left = NewExprNode ();
956 Left->Op = EXPR_SEGMENT;
957 Left->V.SegNum = GetSegNum ();
961 N->Right = LiteralExpr (GetPC () + Offs);
964 N = LiteralExpr (GetPC () + Offs);
967 /* Create the root node */
968 Root = NewExprNode ();
969 Root->Left = Expression ();
971 Root->Op = EXPR_MINUS;
973 /* Return the result */
974 return SimplifyExpr (Root);
979 ExprNode* ULabelExpr (unsigned Num)
980 /* Return an expression for an unnamed label with the given index */
982 /* Get an expression node */
983 ExprNode* Node = NewExprNode ();
986 Node->Op = EXPR_ULABEL;
989 /* Return the new node */
995 void FreeExpr (ExprNode* Root)
996 /* Free the expression, Root is pointing to. */
999 FreeExpr (Root->Left);
1000 FreeExpr (Root->Right);
1001 FreeExprNode (Root);
1007 ExprNode* ForceWordExpr (ExprNode* Expr)
1008 /* Force the given expression into a word and return the result. */
1010 /* And the expression by $FFFF to force it into word size */
1011 ExprNode* Root = NewExprNode ();
1013 Root->Op = EXPR_AND;
1014 Root->Right = LiteralExpr (0xFFFF);
1016 /* Return the result */
1022 int IsConstExpr (ExprNode* Root)
1023 /* Return true if the given expression is a constant expression, that is, one
1024 * with no references to external symbols.
1030 if (EXPR_IS_LEAF (Root->Op)) {
1038 if (SymHasUserMark (Sym)) {
1042 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1046 Const = SymIsConst (Sym);
1047 SymUnmarkUser (Sym);
1055 } else if (EXPR_IS_UNARY (Root->Op)) {
1057 return IsConstExpr (Root->Left);
1061 /* We must handle shortcut boolean expressions here */
1065 if (IsConstExpr (Root->Left)) {
1066 /* lhs is const, if it is zero, don't eval right */
1067 if (GetExprVal (Root->Left) == 0) {
1070 return IsConstExpr (Root->Right);
1073 /* lhs not const --> tree not const */
1079 if (IsConstExpr (Root->Left)) {
1080 /* lhs is const, if it is not zero, don't eval right */
1081 if (GetExprVal (Root->Left) != 0) {
1084 return IsConstExpr (Root->Right);
1087 /* lhs not const --> tree not const */
1093 /* All others are handled normal */
1094 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1101 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1102 /* Internal routine that is recursively called to check if there is a zeropage
1103 * symbol in the expression tree.
1107 switch (N->Op & EXPR_TYPEMASK) {
1113 if (SymIsZP (N->V.Sym)) {
1115 } else if (SymHasExpr (N->V.Sym)) {
1116 /* Check if this expression is a byte expression */
1117 *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1122 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1130 case EXPR_UNARYNODE:
1131 CheckByteExpr (N->Left, IsByte);
1134 case EXPR_BINARYNODE:
1135 CheckByteExpr (N->Left, IsByte);
1136 CheckByteExpr (N->Right, IsByte);
1140 Internal ("Unknown expression op: %02X", N->Op);
1147 int IsByteExpr (ExprNode* Root)
1148 /* Return true if this is a byte expression */
1152 if (IsConstExpr (Root)) {
1153 if (Root->Op != EXPR_LITERAL) {
1154 SimplifyExpr (Root);
1156 return IsByteRange (GetExprVal (Root));
1157 } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1158 Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1159 /* Symbol forced to have byte range */
1162 /* We have undefined symbols in the expression. Assume that the
1163 * expression is a byte expression if there is at least one symbol
1164 * declared as zeropage in it. Being wrong here is not a very big
1165 * problem since the linker knows about all symbols and detects
1166 * error like mixing absolute and zeropage labels.
1169 CheckByteExpr (Root, &IsByte);
1176 long GetExprVal (ExprNode* Expr)
1177 /* Get the value of a constant expression */
1187 return GetSymVal (Expr->V.Sym);
1190 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1193 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1196 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1199 Left = GetExprVal (Expr->Left);
1200 Right = GetExprVal (Expr->Right);
1202 Error (ERR_DIV_BY_ZERO);
1205 return Left / Right;
1208 Left = GetExprVal (Expr->Left);
1209 Right = GetExprVal (Expr->Right);
1211 Error (ERR_MOD_BY_ZERO);
1214 return Left % Right;
1217 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1220 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1223 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1226 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1229 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1232 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1235 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1238 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1241 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1244 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1247 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1249 case EXPR_UNARY_MINUS:
1250 return -GetExprVal (Expr->Left);
1253 return ~GetExprVal (Expr->Left);
1256 return GetExprVal (Expr->Left) & 0xFF;
1259 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1262 return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1265 return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1268 Left = GetExprVal (Expr->Left);
1269 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1272 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1275 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1278 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1281 return !GetExprVal (Expr->Left);
1284 Internal ("GetExprVal called for EXPR_ULABEL");
1289 Internal ("Unknown Op type: %u", Expr->Op);
1297 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1298 /* Remove resolved symbols from the tree by cloning symbol expressions */
1300 /* Accept NULL pointers */
1305 /* Special node handling */
1309 if (SymHasExpr (Expr->V.Sym)) {
1310 /* The symbol has an expression tree */
1311 SymEntry* Sym = Expr->V.Sym;
1312 if (SymHasUserMark (Sym)) {
1313 /* Circular definition */
1317 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1318 return LiteralExpr (0); /* Return a dummy value */
1321 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1322 SymUnmarkUser (Sym);
1324 } else if (SymIsConst (Expr->V.Sym)) {
1325 /* The symbol is a constant */
1326 return LiteralExpr (GetSymVal (Expr->V.Sym));
1331 if (ULabCanResolve ()) {
1332 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1340 /* Clone the current node if needed */
1343 /* Create a new node */
1344 ExprNode* Clone = NewExprNode ();
1346 /* Clone the operation */
1347 Clone->Op = Expr->Op;
1349 /* Clone the attribute if needed */
1354 Clone->V.Val = Expr->V.Val;
1358 Clone->V.Sym = Expr->V.Sym;
1362 Clone->V.SegNum = Expr->V.SegNum;
1367 /* Clone the tree nodes */
1368 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1369 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1376 /* Nothing to clone */
1377 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1378 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1388 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1389 /* Extract and evaluate all constant factors in an subtree that has only
1390 * additions and subtractions.
1393 if (Expr->Op == EXPR_LITERAL) {
1395 *Val -= Expr->V.Val;
1397 *Val += Expr->V.Val;
1399 FreeExprNode (Expr);
1403 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1406 Left = ConstExtract (Expr->Left, Val, Sign);
1407 if (Expr->Op == EXPR_MINUS) {
1410 Right = ConstExtract (Expr->Right, Val, Sign);
1411 if (Left == 0 && Right == 0) {
1412 FreeExprNode (Expr);
1414 } else if (Left == 0) {
1415 FreeExprNode (Expr);
1417 } else if (Right == 0) {
1418 FreeExprNode (Expr);
1421 /* Check for SEG - SEG which is now possible */
1422 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1423 Left->V.SegNum == Right->V.SegNum) {
1424 /* SEG - SEG, remove it completely */
1425 FreeExprNode (Left);
1426 FreeExprNode (Right);
1427 FreeExprNode (Expr);
1431 Expr->Right = Right;
1437 /* Some other sort of node, finalize the terms */
1439 Expr->Left = FinalizeExpr (Expr->Left);
1442 Expr->Right = FinalizeExpr (Expr->Right);
1450 ExprNode* FinalizeExpr (ExprNode* Expr)
1451 /* Resolve any symbols by cloning the symbol expression tree instead of the
1452 * symbol reference, then try to simplify the expression as much as possible.
1453 * This function must only be called if all symbols are resolved (no undefined
1460 Expr = RemoveSyms (Expr, 0);
1461 Expr = ConstExtract (Expr, &Val, 1);
1463 /* Reduced to a literal value */
1464 Expr = LiteralExpr (Val);
1466 /* Extracted a value */
1470 N->Right = LiteralExpr (Val);
1478 ExprNode* CloneExpr (ExprNode* Expr)
1479 /* Clone the given expression tree. The function will simply clone symbol
1480 * nodes, it will not resolve them.
1485 /* Accept NULL pointers */
1490 /* Get a new node */
1491 Clone = NewExprNode ();
1493 /* Clone the operation */
1494 Clone->Op = Expr->Op;
1496 /* Clone the attribute if needed */
1501 Clone->V.Val = Expr->V.Val;
1505 Clone->V.Sym = Expr->V.Sym;
1509 Clone->V.SegNum = Expr->V.SegNum;
1514 /* Clone the tree nodes */
1515 Clone->Left = CloneExpr (Expr->Left);
1516 Clone->Right = CloneExpr (Expr->Right);
1524 void WriteExpr (ExprNode* Expr)
1525 /* Write the given expression to the object file */
1527 /* Null expressions are encoded by a type byte of zero */
1533 /* Write the expression code */
1534 ObjWrite8 (Expr->Op);
1536 /* If the is a leafnode, write the expression attribute, otherwise
1537 * write the expression operands.
1542 ObjWrite32 (Expr->V.Val);
1546 /* Maybe we should use a code here? */
1547 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1548 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1552 ObjWrite8 (Expr->V.SegNum);
1556 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1560 /* Not a leaf node */
1561 WriteExpr (Expr->Left);
1562 WriteExpr (Expr->Right);