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 /*****************************************************************************/
36 #include "../common/exprdefs.h"
37 #include "../common/xmalloc.h"
52 /*****************************************************************************/
54 /*****************************************************************************/
58 /* Since all expressions are first packed into expression trees, and each
59 * expression tree node is allocated on the heap, we add some type of special
60 * purpose memory allocation here: Instead of freeing the nodes, we save some
61 * number of freed nodes for later and remember them in a single linked list
62 * using the Left link.
64 #define MAX_FREE_NODES 64
65 static ExprNode* FreeExprNodes = 0;
66 static unsigned FreeNodeCount = 0;
70 /*****************************************************************************/
72 /*****************************************************************************/
76 static ExprNode* NewExprNode (void)
77 /* Create a new expression node */
81 /* Do we have some nodes in the list already? */
83 /* Use first node from list */
85 FreeExprNodes = N->Left;
87 /* Allocate fresh memory */
88 N = xmalloc (sizeof (ExprNode));
91 N->Left = N->Right = 0;
99 static void FreeExprNode (ExprNode* E)
103 if (FreeNodeCount < MAX_FREE_NODES) {
104 /* Remember this node for later */
105 E->Left = FreeExprNodes;
108 /* Free the memory */
116 /*****************************************************************************/
117 /* Dump an expression tree on stdout for debugging */
118 /*****************************************************************************/
122 static void InternalDumpExpr (ExprNode* Expr)
123 /* Dump an expression in UPN */
128 InternalDumpExpr (Expr->Left);
129 InternalDumpExpr (Expr->Right);
135 printf (" $%04lX", Expr->V.Val & 0xFFFF);
139 printf (" %s", GetSymName (Expr->V.Sym));
202 case EXPR_UNARY_MINUS:
223 printf (" BOOL_AND");
231 printf (" BOOL_XOR");
235 printf (" BOOL_NOT");
239 Internal ("Unknown Op type: %u", Expr->Op);
246 void DumpExpr (ExprNode* Expr)
247 /* Dump an expression tree to stdout */
249 InternalDumpExpr (Expr);
255 /*****************************************************************************/
257 /*****************************************************************************/
261 static ExprNode* Expr0 (void);
265 int IsByteRange (long Val)
266 /* Return true if this is a byte value */
268 return (Val & ~0xFFL) == 0;
273 int IsWordRange (long Val)
274 /* Return true if this is a word value */
276 return (Val & ~0xFFFF) == 0;
281 static int FuncBlank (void)
282 /* Handle the .BLANK builtin function */
284 /* Assume no tokens if the closing brace follows (this is not correct in
285 * all cases, since the token may be the closing brace, but this will
286 * give a syntax error anyway and may not be handled by .BLANK.
288 if (Tok == TOK_RPAREN) {
292 /* Skip any tokens */
294 while (Tok != TOK_SEP && Tok != TOK_EOF) {
295 if (Tok == TOK_LPAREN) {
297 } else if (Tok == TOK_RPAREN) {
313 static int FuncConst (void)
314 /* Handle the .CONST builtin function */
316 /* Read an expression */
317 ExprNode* Expr = Expression ();
319 /* Check the constness of the expression */
320 int Result = IsConstExpr (Expr);
322 /* Free the expression */
331 static int FuncDefined (void)
332 /* Handle the .DEFINED builtin function */
336 if (Tok != TOK_IDENT) {
337 Error (ERR_IDENT_EXPECTED);
338 if (Tok != TOK_RPAREN) {
342 Result = SymIsDef (SVal);
352 static int DoMatch (enum TC EqualityLevel)
353 /* Handle the .MATCH and .XMATCH builtin functions */
360 /* A list of tokens follows. Read this list and remember it building a
361 * single linked list of tokens including attributes. The list is
362 * terminated by a comma.
364 while (Tok != TOK_COMMA) {
366 /* We may not end-of-line of end-of-file here */
367 if (Tok == TOK_SEP || Tok == TOK_EOF) {
368 Error (ERR_UNEXPECTED_EOL);
372 /* Get a node with this token */
373 Node = NewTokNode ();
375 /* Insert the node into the list */
390 /* Read the second list which is terminated by the right parenthesis and
391 * compare each token against the one in the first list.
395 while (Tok != TOK_RPAREN) {
397 /* We may not end-of-line of end-of-file here */
398 if (Tok == TOK_SEP || Tok == TOK_EOF) {
399 Error (ERR_UNEXPECTED_EOL);
403 /* Compare the tokens if the result is not already known */
406 /* The second list is larger than the first one */
408 } else if (TokCmp (Node) < EqualityLevel) {
409 /* Tokens do not match */
414 /* Next token in first list */
419 /* Next token in current list */
423 /* Check if there are remaining tokens in the first list */
428 /* Free the token list */
435 /* Done, return the result */
441 static int FuncMatch (void)
442 /* Handle the .MATCH function */
444 return DoMatch (tcSameToken);
449 static int FuncReferenced (void)
450 /* Handle the .REFERENCED builtin function */
454 if (Tok != TOK_IDENT) {
455 Error (ERR_IDENT_EXPECTED);
456 if (Tok != TOK_RPAREN) {
460 Result = SymIsRef (SVal);
470 static int FuncStrAt (void)
471 /* Handle the .STRAT function */
473 char Str [sizeof(SVal)];
476 /* String constant expected */
477 if (Tok != TOK_STRCON) {
478 Error (ERR_STRCON_EXPECTED);
484 /* Remember the string and skip it */
488 /* Comma must follow */
491 /* Expression expected */
492 Index = ConstExpression ();
494 /* Must be a valid index */
495 if (Index >= strlen (Str)) {
500 /* Return the char, handle as unsigned */
501 return (unsigned char) Str[(size_t)Index];
506 static int FuncStrLen (void)
507 /* Handle the .STRLEN function */
509 /* String constant expected */
510 if (Tok != TOK_STRCON) {
512 Error (ERR_STRCON_EXPECTED);
513 /* Smart error recovery */
514 if (Tok != TOK_RPAREN) {
521 /* Get the length of the string */
522 int Len = strlen (SVal);
524 /* Skip the string */
527 /* Return the length */
535 static int FuncTCount (void)
536 /* Handle the .TCOUNT function */
538 /* We have a list of tokens that ends with the closing paren. Skip
539 * the tokens, handling nested braces and count them.
543 while (Parens != 0 || Tok != TOK_RPAREN) {
545 /* Check for end of line or end of input. Since the calling function
546 * will check for the closing paren, we don't need to print an error
547 * here, just bail out.
549 if (Tok == TOK_SEP || Tok == TOK_EOF) {
556 /* Keep track of the nesting level */
558 case TOK_LPAREN: ++Parens; break;
559 case TOK_RPAREN: --Parens; break;
567 /* Return the number of tokens */
573 static int FuncXMatch (void)
574 /* Handle the .XMATCH function */
576 return DoMatch (tcIdentical);
581 static ExprNode* Function (int (*F) (void))
582 /* Handle builtin functions */
586 /* Skip the keyword */
589 /* Expression must be enclosed in braces */
590 if (Tok != TOK_LPAREN) {
591 Error (ERR_LPAREN_EXPECTED);
593 return LiteralExpr (0);
597 /* Call the function itself */
600 /* Closing brace must follow */
603 /* Return an expression node with the boolean code */
604 return LiteralExpr (Result);
609 static ExprNode* Factor (void)
618 N = LiteralExpr (IVal);
624 if (Tok != TOK_IDENT) {
625 Error (ERR_IDENT_EXPECTED);
626 N = LiteralExpr (0); /* Dummy */
628 S = SymRefGlobal (SVal);
629 if (SymIsConst (S)) {
630 /* Use the literal value instead */
631 N = LiteralExpr (GetSymVal (S));
633 /* Create symbol node */
644 if (SymIsConst (S)) {
645 /* Use the literal value instead */
646 N = LiteralExpr (GetSymVal (S));
648 /* Create symbol node */
665 N->Op = EXPR_UNARY_MINUS;
702 N = Function (FuncBlank);
706 N = Function (FuncConst);
710 N = LiteralExpr (GetCPU());
715 N = Function (FuncDefined);
719 N = Function (FuncMatch);
723 N = Function (FuncReferenced);
727 N = Function (FuncStrAt);
731 N = Function (FuncStrLen);
735 N = Function (FuncTCount);
739 N = Function (FuncXMatch);
743 N = LiteralExpr (0); /* Dummy */
753 static ExprNode* Term (void)
757 /* Read left hand side */
760 /* Handle multiplicative operations */
761 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
762 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
765 /* Create a new node and insert the left expression */
766 ExprNode* Left = Root;
767 Root = NewExprNode ();
770 /* Determine the operator token */
772 case TOK_MUL: Root->Op = EXPR_MUL; break;
773 case TOK_DIV: Root->Op = EXPR_DIV; break;
774 case TOK_MOD: Root->Op = EXPR_MOD; break;
775 case TOK_AND: Root->Op = EXPR_AND; break;
776 case TOK_XOR: Root->Op = EXPR_XOR; break;
777 case TOK_SHL: Root->Op = EXPR_SHL; break;
778 case TOK_SHR: Root->Op = EXPR_SHR; break;
779 default: Internal ("Invalid token");
783 /* Parse the right hand side */
784 Root->Right = Factor ();
788 /* Return the expression tree we've created */
794 static ExprNode* SimpleExpr (void)
798 /* Read left hand side */
801 /* Handle additive operations */
802 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
804 /* Create a new node and insert the left expression */
805 ExprNode* Left = Root;
806 Root = NewExprNode ();
809 /* Determine the operator token */
811 case TOK_PLUS: Root->Op = EXPR_PLUS; break;
812 case TOK_MINUS: Root->Op = EXPR_MINUS; break;
813 case TOK_OR: Root->Op = EXPR_OR; break;
814 default: Internal ("Invalid token");
818 /* Parse the right hand side */
819 Root->Right = Term ();
823 /* Return the expression tree we've created */
829 static ExprNode* BoolExpr (void)
830 /* Evaluate a boolean expression */
832 /* Read left hand side */
833 ExprNode* Root = SimpleExpr ();
835 /* Handle booleans */
836 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
837 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
839 /* Create a new node and insert the left expression */
840 ExprNode* Left = Root;
841 Root = NewExprNode ();
844 /* Determine the operator token */
846 case TOK_EQ: Root->Op = EXPR_EQ; break;
847 case TOK_NE: Root->Op = EXPR_NE; break;
848 case TOK_LT: Root->Op = EXPR_LT; break;
849 case TOK_GT: Root->Op = EXPR_GT; break;
850 case TOK_LE: Root->Op = EXPR_LE; break;
851 case TOK_GE: Root->Op = EXPR_GE; break;
852 default: Internal ("Invalid token");
856 /* Parse the right hand side */
857 Root->Right = SimpleExpr ();
861 /* Return the expression tree we've created */
867 static ExprNode* Expr2 (void)
868 /* Boolean operators: AND and XOR */
870 /* Read left hand side */
871 ExprNode* Root = BoolExpr ();
873 /* Handle booleans */
874 while (Tok == TOK_BAND || Tok == TOK_BXOR) {
876 /* Create a new node and insert the left expression */
877 ExprNode* Left = Root;
878 Root = NewExprNode ();
881 /* Determine the operator token */
883 case TOK_BAND: Root->Op = EXPR_BAND; break;
884 case TOK_BXOR: Root->Op = EXPR_BXOR; break;
885 default: Internal ("Invalid token");
889 /* Parse the right hand side */
890 Root->Right = BoolExpr ();
894 /* Return the expression tree we've created */
900 static ExprNode* Expr1 (void)
901 /* Boolean operators: OR */
903 /* Read left hand side */
904 ExprNode* Root = Expr2 ();
906 /* Handle booleans */
907 while (Tok == TOK_BOR) {
909 /* Create a new node and insert the left expression */
910 ExprNode* Left = Root;
911 Root = NewExprNode ();
914 /* Determine the operator token */
916 case TOK_BOR: Root->Op = EXPR_BOR; break;
917 default: Internal ("Invalid token");
921 /* Parse the right hand side */
922 Root->Right = Expr2 ();
926 /* Return the expression tree we've created */
932 static ExprNode* Expr0 (void)
933 /* Boolean operators: NOT */
937 /* Handle booleans */
938 if (Tok == TOK_BNOT) {
940 /* Create a new node */
941 Root = NewExprNode ();
943 /* Determine the operator token */
945 case TOK_BNOT: Root->Op = EXPR_BNOT; break;
946 default: Internal ("Invalid token");
950 /* Parse the left hand side, allow more BNOTs */
951 Root->Left = Expr0 ();
955 /* Read left hand side */
960 /* Return the expression tree we've created */
966 static ExprNode* SimplifyExpr (ExprNode* Root)
967 /* Try to simplify the given expression tree */
970 SimplifyExpr (Root->Left);
971 SimplifyExpr (Root->Right);
972 if (IsConstExpr (Root)) {
973 /* The complete expression is constant */
974 Root->V.Val = GetExprVal (Root);
975 Root->Op = EXPR_LITERAL;
976 FreeExpr (Root->Left);
977 FreeExpr (Root->Right);
978 Root->Left = Root->Right = 0;
986 ExprNode* Expression (void)
987 /* Evaluate an expression, build the expression tree on the heap and return
988 * a pointer to the root of the tree.
991 return SimplifyExpr (Expr0 ());
996 long ConstExpression (void)
997 /* Parse an expression. Check if the expression is const, and print an error
998 * message if not. Return the value of the expression, or a dummy, if it is
1002 /* Read the expression, and call finalize (exception here, since we
1005 ExprNode* Expr = FinalizeExpr (Expression ());
1007 /* Return the value */
1008 if (IsConstExpr (Expr)) {
1009 return GetExprVal (Expr);
1011 Error (ERR_CONSTEXPR_EXPECTED);
1018 ExprNode* LiteralExpr (long Val)
1019 /* Return an expression tree that encodes the given literal value */
1021 ExprNode* Expr = NewExprNode ();
1022 Expr->Op = EXPR_LITERAL;
1029 ExprNode* CurrentPC (void)
1030 /* Return the current program counter as expression */
1036 /* Create SegmentBase + Offset */
1037 Left = NewExprNode ();
1038 Left->Op = EXPR_SEGMENT;
1039 Left->V.SegNum = GetSegNum ();
1041 Root = NewExprNode ();
1043 Root->Right = LiteralExpr (GetPC ());
1044 Root->Op = EXPR_PLUS;
1046 /* Absolute mode, just return PC value */
1047 Root = LiteralExpr (GetPC ());
1055 ExprNode* SwapExpr (ExprNode* Expr)
1056 /* Return an extended expression with lo and hi bytes swapped */
1058 ExprNode* N = NewExprNode ();
1066 ExprNode* BranchExpr (unsigned Offs)
1067 /* Return an expression that encodes the difference between current PC plus
1068 * offset and the target expression (that is, Expression() - (*+Offs) ).
1077 Left = NewExprNode ();
1078 Left->Op = EXPR_SEGMENT;
1079 Left->V.SegNum = GetSegNum ();
1083 N->Right = LiteralExpr (GetPC () + Offs);
1086 N = LiteralExpr (GetPC () + Offs);
1089 /* Create the root node */
1090 Root = NewExprNode ();
1091 Root->Left = Expression ();
1093 Root->Op = EXPR_MINUS;
1095 /* Return the result */
1096 return SimplifyExpr (Root);
1101 ExprNode* ULabelExpr (unsigned Num)
1102 /* Return an expression for an unnamed label with the given index */
1104 /* Get an expression node */
1105 ExprNode* Node = NewExprNode ();
1107 /* Set the values */
1108 Node->Op = EXPR_ULABEL;
1111 /* Return the new node */
1117 void FreeExpr (ExprNode* Root)
1118 /* Free the expression, Root is pointing to. */
1121 FreeExpr (Root->Left);
1122 FreeExpr (Root->Right);
1123 FreeExprNode (Root);
1129 ExprNode* ForceWordExpr (ExprNode* Expr)
1130 /* Force the given expression into a word and return the result. */
1132 /* And the expression by $FFFF to force it into word size */
1133 ExprNode* Root = NewExprNode ();
1135 Root->Op = EXPR_AND;
1136 Root->Right = LiteralExpr (0xFFFF);
1138 /* Return the result */
1144 int IsConstExpr (ExprNode* Root)
1145 /* Return true if the given expression is a constant expression, that is, one
1146 * with no references to external symbols.
1152 if (EXPR_IS_LEAF (Root->Op)) {
1160 if (SymHasUserMark (Sym)) {
1164 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1168 Const = SymIsConst (Sym);
1169 SymUnmarkUser (Sym);
1177 } else if (EXPR_IS_UNARY (Root->Op)) {
1179 return IsConstExpr (Root->Left);
1183 /* We must handle shortcut boolean expressions here */
1187 if (IsConstExpr (Root->Left)) {
1188 /* lhs is const, if it is zero, don't eval right */
1189 if (GetExprVal (Root->Left) == 0) {
1192 return IsConstExpr (Root->Right);
1195 /* lhs not const --> tree not const */
1201 if (IsConstExpr (Root->Left)) {
1202 /* lhs is const, if it is not zero, don't eval right */
1203 if (GetExprVal (Root->Left) != 0) {
1206 return IsConstExpr (Root->Right);
1209 /* lhs not const --> tree not const */
1215 /* All others are handled normal */
1216 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1223 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1224 /* Internal routine that is recursively called to check if there is a zeropage
1225 * symbol in the expression tree.
1229 switch (N->Op & EXPR_TYPEMASK) {
1235 if (SymIsZP (N->V.Sym)) {
1241 if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1249 case EXPR_UNARYNODE:
1250 CheckByteExpr (N->Left, IsByte);
1253 case EXPR_BINARYNODE:
1254 CheckByteExpr (N->Left, IsByte);
1255 CheckByteExpr (N->Right, IsByte);
1259 Internal ("Unknown expression op: %02X", N->Op);
1266 int IsByteExpr (ExprNode* Root)
1267 /* Return true if this is a byte expression */
1271 if (IsConstExpr (Root)) {
1272 if (Root->Op != EXPR_LITERAL) {
1273 SimplifyExpr (Root);
1275 return IsByteRange (GetExprVal (Root));
1276 } else if (Root->Op == EXPR_LOBYTE || Root->Op == EXPR_HIBYTE) {
1277 /* Symbol forced to have byte range */
1280 /* We have undefined symbols in the expression. Assume that the
1281 * expression is a byte expression if there is at least one symbol
1282 * declared as zeropage in it. Being wrong here is not a very big
1283 * problem since the linker knows about all symbols and detects
1284 * error like mixing absolute and zeropage labels.
1287 CheckByteExpr (Root, &IsByte);
1294 long GetExprVal (ExprNode* Expr)
1295 /* Get the value of a constant expression */
1305 return GetSymVal (Expr->V.Sym);
1308 return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1311 return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1314 return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1317 Left = GetExprVal (Expr->Left);
1318 Right = GetExprVal (Expr->Right);
1320 Error (ERR_DIV_BY_ZERO);
1323 return Left / Right;
1326 Left = GetExprVal (Expr->Left);
1327 Right = GetExprVal (Expr->Right);
1329 Error (ERR_MOD_BY_ZERO);
1332 return Left % Right;
1335 return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1338 return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1341 return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1344 return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1347 return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1350 return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1353 return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1356 return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1359 return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1362 return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1365 return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1367 case EXPR_UNARY_MINUS:
1368 return -GetExprVal (Expr->Left);
1371 return ~GetExprVal (Expr->Left);
1374 return GetExprVal (Expr->Left) & 0xFF;
1377 return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1380 Left = GetExprVal (Expr->Left);
1381 return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1384 return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1387 return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1390 return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1393 return !GetExprVal (Expr->Left);
1396 Internal ("GetExprVal called for EXPR_ULABEL");
1401 Internal ("Unknown Op type: %u", Expr->Op);
1409 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1410 /* Remove resolved symbols from the tree by cloning symbol expressions */
1412 /* Accept NULL pointers */
1417 /* Special node handling */
1421 if (SymHasExpr (Expr->V.Sym)) {
1422 /* The symbol has an expression tree */
1423 SymEntry* Sym = Expr->V.Sym;
1424 if (SymHasUserMark (Sym)) {
1425 /* Circular definition */
1429 PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1430 return LiteralExpr (0); /* Return a dummy value */
1433 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1434 SymUnmarkUser (Sym);
1436 } else if (SymIsConst (Expr->V.Sym)) {
1437 /* The symbol is a constant */
1438 return LiteralExpr (GetSymVal (Expr->V.Sym));
1443 if (ULabCanResolve ()) {
1444 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1452 /* Clone the current node if needed */
1455 /* Create a new node */
1456 ExprNode* Clone = NewExprNode ();
1458 /* Clone the operation */
1459 Clone->Op = Expr->Op;
1461 /* Clone the attribute if needed */
1466 Clone->V.Val = Expr->V.Val;
1470 Clone->V.Sym = Expr->V.Sym;
1474 Clone->V.SegNum = Expr->V.SegNum;
1479 /* Clone the tree nodes */
1480 Clone->Left = RemoveSyms (Expr->Left, MustClone);
1481 Clone->Right = RemoveSyms (Expr->Right, MustClone);
1488 /* Nothing to clone */
1489 Expr->Left = RemoveSyms (Expr->Left, MustClone);
1490 Expr->Right = RemoveSyms (Expr->Right, MustClone);
1500 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1501 /* Extract and evaluate all constant factors in an subtree that has only
1502 * additions and subtractions.
1505 if (Expr->Op == EXPR_LITERAL) {
1507 *Val -= Expr->V.Val;
1509 *Val += Expr->V.Val;
1511 FreeExprNode (Expr);
1515 if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1518 Left = ConstExtract (Expr->Left, Val, Sign);
1519 if (Expr->Op == EXPR_MINUS) {
1522 Right = ConstExtract (Expr->Right, Val, Sign);
1523 if (Left == 0 && Right == 0) {
1524 FreeExprNode (Expr);
1526 } else if (Left == 0) {
1527 FreeExprNode (Expr);
1529 } else if (Right == 0) {
1530 FreeExprNode (Expr);
1533 /* Check for SEG - SEG which is now possible */
1534 if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
1535 Left->V.SegNum == Right->V.SegNum) {
1536 /* SEG - SEG, remove it completely */
1537 FreeExprNode (Left);
1538 FreeExprNode (Right);
1539 FreeExprNode (Expr);
1543 Expr->Right = Right;
1549 /* Some other sort of node, finalize the terms */
1551 Expr->Left = FinalizeExpr (Expr->Left);
1554 Expr->Right = FinalizeExpr (Expr->Right);
1562 ExprNode* FinalizeExpr (ExprNode* Expr)
1563 /* Resolve any symbols by cloning the symbol expression tree instead of the
1564 * symbol reference, then try to simplify the expression as much as possible.
1565 * This function must only be called if all symbols are resolved (no undefined
1572 Expr = RemoveSyms (Expr, 0);
1573 Expr = ConstExtract (Expr, &Val, 1);
1575 /* Reduced to a literal value */
1576 Expr = LiteralExpr (Val);
1578 /* Extracted a value */
1582 N->Right = LiteralExpr (Val);
1590 ExprNode* CloneExpr (ExprNode* Expr)
1591 /* Clone the given expression tree. The function will simply clone symbol
1592 * nodes, it will not resolve them.
1597 /* Accept NULL pointers */
1602 /* Get a new node */
1603 Clone = NewExprNode ();
1605 /* Clone the operation */
1606 Clone->Op = Expr->Op;
1608 /* Clone the attribute if needed */
1613 Clone->V.Val = Expr->V.Val;
1617 Clone->V.Sym = Expr->V.Sym;
1621 Clone->V.SegNum = Expr->V.SegNum;
1626 /* Clone the tree nodes */
1627 Clone->Left = CloneExpr (Expr->Left);
1628 Clone->Right = CloneExpr (Expr->Right);
1636 void WriteExpr (ExprNode* Expr)
1637 /* Write the given expression to the object file */
1639 /* Null expressions are encoded by a type byte of zero */
1645 /* Write the expression code */
1646 ObjWrite8 (Expr->Op);
1648 /* If the is a leafnode, write the expression attribute, otherwise
1649 * write the expression operands.
1654 ObjWrite32 (Expr->V.Val);
1658 /* Maybe we should use a code here? */
1659 CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
1660 ObjWrite16 (GetSymIndex (Expr->V.Sym));
1664 ObjWrite8 (Expr->V.SegNum);
1668 Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1672 /* Not a leaf node */
1673 WriteExpr (Expr->Left);
1674 WriteExpr (Expr->Right);