1 /*****************************************************************************/
5 /* Expression evaluation for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
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 /*****************************************************************************/
58 #include "studyexpr.h"
66 /*****************************************************************************/
68 /*****************************************************************************/
72 /* Since all expressions are first packed into expression trees, and each
73 * expression tree node is allocated on the heap, we add some type of special
74 * purpose memory allocation here: Instead of freeing the nodes, we save some
75 * number of freed nodes for later and remember them in a single linked list
76 * using the Left link.
78 #define MAX_FREE_NODES 64
79 static ExprNode* FreeExprNodes = 0;
80 static unsigned FreeNodeCount = 0;
84 /*****************************************************************************/
86 /*****************************************************************************/
90 static ExprNode* NewExprNode (unsigned Op)
91 /* Create a new expression node */
95 /* Do we have some nodes in the list already? */
97 /* Use first node from list */
99 FreeExprNodes = N->Left;
101 /* Allocate fresh memory */
102 N = xmalloc (sizeof (ExprNode));
105 N->Left = N->Right = 0;
113 static void FreeExprNode (ExprNode* E)
117 if (E->Op == EXPR_SYMBOL) {
118 /* Remove the symbol reference */
119 SymDelExprRef (E->V.Sym, E);
121 /* Place the symbol into the free nodes list if possible */
122 if (FreeNodeCount < MAX_FREE_NODES) {
123 /* Remember this node for later */
124 E->Left = FreeExprNodes;
127 /* Free the memory */
135 /*****************************************************************************/
137 /*****************************************************************************/
141 static ExprNode* Expr0 (void);
145 int IsByteRange (long Val)
146 /* Return true if this is a byte value */
148 return (Val & ~0xFFL) == 0;
153 int IsWordRange (long Val)
154 /* Return true if this is a word value */
156 return (Val & ~0xFFFFL) == 0;
161 int IsFarRange (long Val)
162 /* Return true if this is a far (24 bit) value */
164 return (Val & ~0xFFFFFFL) == 0;
169 static int IsEasyConst (const ExprNode* E, long* Val)
170 /* Do some light checking if the given node is a constant. Don't care if E is
171 * a complex expression. If E is a constant, return true and place its value
172 * into Val, provided that Val is not NULL.
175 /* Resolve symbols, follow symbol chains */
176 while (E->Op == EXPR_SYMBOL) {
177 E = SymResolve (E->V.Sym);
179 /* Could not resolve */
184 /* Symbols resolved, check for a literal */
185 if (E->Op == EXPR_LITERAL) {
192 /* Not found to be a const according to our tests */
198 static ExprNode* FuncBlank (void)
199 /* Handle the .BLANK builtin function */
203 /* Assume no tokens if the closing brace follows (this is not correct in
204 * all cases, since the token may be the closing brace, but this will
205 * give a syntax error anyway and may not be handled by .BLANK.
207 if (Tok != TOK_RPAREN) {
208 /* Skip any tokens */
210 while (!TokIsSep (Tok)) {
211 if (Tok == TOK_LPAREN) {
213 } else if (Tok == TOK_RPAREN) {
225 return GenLiteralExpr (Result);
230 static ExprNode* FuncConst (void)
231 /* Handle the .CONST builtin function */
233 /* Read an expression */
234 ExprNode* Expr = Expression ();
236 /* Check the constness of the expression */
237 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
239 /* Free the expression */
248 static ExprNode* FuncDefined (void)
249 /* Handle the .DEFINED builtin function */
251 /* Parse the symbol name and search for the symbol */
252 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
254 /* Check if the symbol is defined */
255 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
260 static ExprNode* DoMatch (enum TC EqualityLevel)
261 /* Handle the .MATCH and .XMATCH builtin functions */
268 /* A list of tokens follows. Read this list and remember it building a
269 * single linked list of tokens including attributes. The list is
270 * terminated by a comma.
272 while (Tok != TOK_COMMA) {
274 /* We may not end-of-line of end-of-file here */
275 if (TokIsSep (Tok)) {
276 Error ("Unexpected end of line");
280 /* Get a node with this token */
281 Node = NewTokNode ();
283 /* Insert the node into the list */
298 /* Read the second list which is terminated by the right parenthesis and
299 * compare each token against the one in the first list.
303 while (Tok != TOK_RPAREN) {
305 /* We may not end-of-line of end-of-file here */
306 if (TokIsSep (Tok)) {
307 Error ("Unexpected end of line");
311 /* Compare the tokens if the result is not already known */
314 /* The second list is larger than the first one */
316 } else if (TokCmp (Node) < EqualityLevel) {
317 /* Tokens do not match */
322 /* Next token in first list */
327 /* Next token in current list */
331 /* Check if there are remaining tokens in the first list */
336 /* Free the token list */
343 /* Done, return the result */
344 return GenLiteralExpr (Result);
349 static ExprNode* FuncMatch (void)
350 /* Handle the .MATCH function */
352 return DoMatch (tcSameToken);
357 static ExprNode* FuncReferenced (void)
358 /* Handle the .REFERENCED builtin function */
360 /* Parse the symbol name and search for the symbol */
361 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
363 /* Check if the symbol is referenced */
364 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
369 static ExprNode* FuncSizeOf (void)
370 /* Handle the .SIZEOF function */
374 /* Get the struct for the scoped struct name */
375 SymTable* Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
377 /* Check if the given symbol is really a struct */
378 if (GetSymTabType (Struct) != ST_STRUCT) {
379 Error ("Argument to .SIZEOF is not a struct");
382 Size = GetStructSize (Struct);
385 /* Return the size */
386 return GenLiteralExpr (Size);
391 static ExprNode* FuncStrAt (void)
392 /* Handle the .STRAT function */
394 char Str [sizeof(SVal)];
398 /* String constant expected */
399 if (Tok != TOK_STRCON) {
400 Error ("String constant 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)) {
418 Error ("Range error");
422 /* Get the char, handle as unsigned. Be sure to translate it into
423 * the target character set.
425 C = TgtTranslateChar (Str [(size_t)Index]);
427 /* Return the char expression */
428 return GenLiteralExpr (C);
433 static ExprNode* FuncStrLen (void)
434 /* Handle the .STRLEN function */
438 /* String constant expected */
439 if (Tok != TOK_STRCON) {
441 Error ("String constant expected");
442 /* Smart error recovery */
443 if (Tok != TOK_RPAREN) {
450 /* Get the length of the string */
453 /* Skip the string */
457 /* Return the length */
458 return GenLiteralExpr (Len);
463 static ExprNode* FuncTCount (void)
464 /* Handle the .TCOUNT function */
466 /* We have a list of tokens that ends with the closing paren. Skip
467 * the tokens, handling nested braces and count them.
471 while (Parens != 0 || Tok != TOK_RPAREN) {
473 /* Check for end of line or end of input. Since the calling function
474 * will check for the closing paren, we don't need to print an error
475 * here, just bail out.
477 if (TokIsSep (Tok)) {
484 /* Keep track of the nesting level */
486 case TOK_LPAREN: ++Parens; break;
487 case TOK_RPAREN: --Parens; break;
495 /* Return the number of tokens */
496 return GenLiteralExpr (Count);
501 static ExprNode* FuncXMatch (void)
502 /* Handle the .XMATCH function */
504 return DoMatch (tcIdentical);
509 static ExprNode* Function (ExprNode* (*F) (void))
510 /* Handle builtin functions */
514 /* Skip the keyword */
517 /* Expression must be enclosed in braces */
518 if (Tok != TOK_LPAREN) {
519 Error ("'(' expected");
521 return GenLiteralExpr (0);
525 /* Call the function itself */
528 /* Closing brace must follow */
531 /* Return the result of the actual function */
537 static ExprNode* Factor (void)
547 N = GenLiteralExpr (IVal);
552 N = GenLiteralExpr (TgtTranslateChar (IVal));
558 /* Search for the symbol */
559 S = ParseScopedSymName (SYM_ALLOC_NEW);
561 /* Some weird error happened before */
562 N = GenLiteralExpr (0);
564 /* Mark the symbol as referenced */
566 /* Remove the symbol if possible */
567 if (SymHasExpr (S)) {
568 N = CloneExpr (GetSymExpr (S));
570 /* Create symbol node */
584 if (IsEasyConst (L, &Val)) {
586 N = GenLiteralExpr (-Val);
588 N = NewExprNode (EXPR_UNARY_MINUS);
596 if (IsEasyConst (L, &Val)) {
598 N = GenLiteralExpr (~Val);
600 N = NewExprNode (EXPR_NOT);
614 if (IsEasyConst (L, &Val)) {
616 N = GenLiteralExpr (Val & 0xFF);
618 N = NewExprNode (EXPR_BYTE0);
626 if (IsEasyConst (L, &Val)) {
628 N = GenLiteralExpr ((Val >> 8) & 0xFF);
630 N = NewExprNode (EXPR_BYTE1);
638 if (IsEasyConst (L, &Val)) {
640 N = GenLiteralExpr ((Val >> 16) & 0xFF);
642 N = NewExprNode (EXPR_BYTE2);
654 N = Function (FuncBlank);
658 N = Function (FuncConst);
662 N = GenLiteralExpr (CPUIsets[CPU]);
667 N = Function (FuncDefined);
671 N = Function (FuncMatch);
675 N = Function (FuncReferenced);
679 N = Function (FuncSizeOf);
683 N = Function (FuncStrAt);
687 N = Function (FuncStrLen);
691 N = Function (FuncTCount);
695 N = GenLiteralExpr (time (0));
700 N = GenLiteralExpr (VERSION);
705 N = Function (FuncXMatch);
709 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
710 /* A character constant */
711 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
713 N = GenLiteralExpr (0); /* Dummy */
714 Error ("Syntax error");
724 static ExprNode* Term (void)
726 /* Read left hand side */
727 ExprNode* Root = Factor ();
729 /* Handle multiplicative operations */
730 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
731 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
734 long LVal, RVal, Val;
738 /* Remember the token and skip it */
742 /* Move root to left side and read the right side */
746 /* If both expressions are constant, we can evaluate the term */
747 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
756 Error ("Division by zero");
765 Error ("Modulo operation with zero");
781 Val = shl_l (LVal, RVal);
785 Val = shr_l (LVal, RVal);
789 Internal ("Invalid token");
792 /* Generate a literal expression and delete the old left and
797 Root = GenLiteralExpr (Val);
801 /* Generate an expression tree */
804 case TOK_MUL: Op = EXPR_MUL; break;
805 case TOK_DIV: Op = EXPR_DIV; break;
806 case TOK_MOD: Op = EXPR_MOD; break;
807 case TOK_AND: Op = EXPR_AND; break;
808 case TOK_XOR: Op = EXPR_XOR; break;
809 case TOK_SHL: Op = EXPR_SHL; break;
810 case TOK_SHR: Op = EXPR_SHR; break;
811 default: Internal ("Invalid token");
813 Root = NewExprNode (Op);
821 /* Return the expression tree we've created */
827 static ExprNode* SimpleExpr (void)
829 /* Read left hand side */
830 ExprNode* Root = Term ();
832 /* Handle additive operations */
833 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
835 long LVal, RVal, Val;
839 /* Remember the token and skip it */
843 /* Move root to left side and read the right side */
847 /* If both expressions are constant, we can evaluate the term */
848 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
851 case TOK_PLUS: Val = LVal + RVal; break;
852 case TOK_MINUS: Val = LVal - RVal; break;
853 case TOK_OR: Val = LVal | RVal; break;
854 default: Internal ("Invalid token");
857 /* Generate a literal expression and delete the old left and
862 Root = GenLiteralExpr (Val);
866 /* Generate an expression tree */
869 case TOK_PLUS: Op = EXPR_PLUS; break;
870 case TOK_MINUS: Op = EXPR_MINUS; break;
871 case TOK_OR: Op = EXPR_OR; break;
872 default: Internal ("Invalid token");
874 Root = NewExprNode (Op);
881 /* Return the expression tree we've created */
887 static ExprNode* BoolExpr (void)
888 /* Evaluate a boolean expression */
890 /* Read left hand side */
891 ExprNode* Root = SimpleExpr ();
893 /* Handle booleans */
894 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
895 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
897 long LVal, RVal, Val;
901 /* Remember the token and skip it */
905 /* Move root to left side and read the right side */
907 Right = SimpleExpr ();
909 /* If both expressions are constant, we can evaluate the term */
910 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
913 case TOK_EQ: Val = (LVal == RVal); break;
914 case TOK_NE: Val = (LVal != RVal); break;
915 case TOK_LT: Val = (LVal < RVal); break;
916 case TOK_GT: Val = (LVal > RVal); break;
917 case TOK_LE: Val = (LVal <= RVal); break;
918 case TOK_GE: Val = (LVal >= RVal); break;
919 default: Internal ("Invalid token");
922 /* Generate a literal expression and delete the old left and
927 Root = GenLiteralExpr (Val);
931 /* Generate an expression tree */
934 case TOK_EQ: Op = EXPR_EQ; break;
935 case TOK_NE: Op = EXPR_NE; break;
936 case TOK_LT: Op = EXPR_LT; break;
937 case TOK_GT: Op = EXPR_GT; break;
938 case TOK_LE: Op = EXPR_LE; break;
939 case TOK_GE: Op = EXPR_GE; break;
940 default: Internal ("Invalid token");
942 Root = NewExprNode (Op);
949 /* Return the expression tree we've created */
955 static ExprNode* Expr2 (void)
956 /* Boolean operators: AND and XOR */
958 /* Read left hand side */
959 ExprNode* Root = BoolExpr ();
961 /* Handle booleans */
962 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
964 long LVal, RVal, Val;
968 /* Remember the token and skip it */
972 /* Move root to left side and read the right side */
976 /* If both expressions are constant, we can evaluate the term */
977 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
980 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
981 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
982 default: Internal ("Invalid token");
985 /* Generate a literal expression and delete the old left and
990 Root = GenLiteralExpr (Val);
994 /* Generate an expression tree */
997 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
998 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
999 default: Internal ("Invalid token");
1001 Root = NewExprNode (Op);
1003 Root->Right = Right;
1008 /* Return the expression tree we've created */
1014 static ExprNode* Expr1 (void)
1015 /* Boolean operators: OR */
1017 /* Read left hand side */
1018 ExprNode* Root = Expr2 ();
1020 /* Handle booleans */
1021 while (Tok == TOK_BOOLOR) {
1023 long LVal, RVal, Val;
1027 /* Remember the token and skip it */
1031 /* Move root to left side and read the right side */
1035 /* If both expressions are constant, we can evaluate the term */
1036 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1039 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1040 default: Internal ("Invalid token");
1043 /* Generate a literal expression and delete the old left and
1048 Root = GenLiteralExpr (Val);
1052 /* Generate an expression tree */
1055 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1056 default: Internal ("Invalid token");
1058 Root = NewExprNode (Op);
1060 Root->Right = Right;
1065 /* Return the expression tree we've created */
1071 static ExprNode* Expr0 (void)
1072 /* Boolean operators: NOT */
1076 /* Handle booleans */
1077 if (Tok == TOK_BOOLNOT) {
1082 /* Skip the operator token */
1085 /* Read the argument */
1088 /* If the argument is const, evaluate it directly */
1089 if (IsEasyConst (Left, &Val)) {
1091 Root = GenLiteralExpr (!Val);
1093 Root = NewExprNode (EXPR_BOOLNOT);
1099 /* Read left hand side */
1104 /* Return the expression tree we've created */
1110 ExprNode* Expression (void)
1111 /* Evaluate an expression, build the expression tree on the heap and return
1112 * a pointer to the root of the tree.
1116 return SimplifyExpr (Expr0 ());
1119 ExprNode* Expr = Expr0 ();
1120 printf ("Before: "); DumpExpr (Expr, SymResolve);
1121 Expr = SimplifyExpr (Expr);
1122 printf ("After: "); DumpExpr (Expr, SymResolve);
1129 long ConstExpression (void)
1130 /* Parse an expression. Check if the expression is const, and print an error
1131 * message if not. Return the value of the expression, or a dummy, if it is
1138 /* Read the expression */
1139 ExprNode* Expr = Expr0 ();
1142 ExprNode* Expr = Expression ();
1145 /* Study the expression */
1148 StudyExpr (Expr, &D);
1150 /* Check if the expression is constant */
1151 if (ED_IsConst (&D)) {
1154 Error ("Constant expression expected");
1158 /* Free the expression tree and allocated memory for D */
1162 /* Return the value */
1168 void FreeExpr (ExprNode* Root)
1169 /* Free the expression, Root is pointing to. */
1172 FreeExpr (Root->Left);
1173 FreeExpr (Root->Right);
1174 FreeExprNode (Root);
1180 ExprNode* SimplifyExpr (ExprNode* Expr)
1181 /* Try to simplify the given expression tree */
1183 if (Expr && Expr->Op != EXPR_LITERAL) {
1185 /* Create an expression description and initialize it */
1189 /* Study the expression */
1190 StudyExpr (Expr, &D);
1192 /* Now check if we can generate a literal value */
1193 if (ED_IsConst (&D)) {
1194 /* No external references */
1196 Expr = GenLiteralExpr (D.Val);
1199 /* Free allocated memory */
1207 ExprNode* GenLiteralExpr (long Val)
1208 /* Return an expression tree that encodes the given literal value */
1210 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1217 ExprNode* GenSymExpr (SymEntry* Sym)
1218 /* Return an expression node that encodes the given symbol */
1220 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1222 SymAddExprRef (Sym, Expr);
1228 static ExprNode* GenSectionExpr (unsigned SegNum)
1229 /* Return an expression node for the given section */
1231 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1232 Expr->V.SegNum = SegNum;
1238 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1239 /* Generate an addition from the two operands */
1241 ExprNode* Root = NewExprNode (EXPR_PLUS);
1243 Root->Right = Right;
1249 ExprNode* GenCurrentPC (void)
1250 /* Return the current program counter as expression */
1255 /* Create SegmentBase + Offset */
1256 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1257 GenLiteralExpr (GetPC ()));
1259 /* Absolute mode, just return PC value */
1260 Root = GenLiteralExpr (GetPC ());
1268 ExprNode* GenSwapExpr (ExprNode* Expr)
1269 /* Return an extended expression with lo and hi bytes swapped */
1271 ExprNode* N = NewExprNode (EXPR_SWAP);
1278 ExprNode* GenBranchExpr (unsigned Offs)
1279 /* Return an expression that encodes the difference between current PC plus
1280 * offset and the target expression (that is, Expression() - (*+Offs) ).
1287 /* Read Expression() */
1290 /* If the expression is a cheap constant, generate a simpler tree */
1291 if (IsEasyConst (N, &Val)) {
1293 /* Free the constant expression tree */
1296 /* Generate the final expression:
1298 * Val - ((Seg + PC) + Offs)
1299 * Val - Seg - PC - Offs
1300 * (Val - PC - Offs) - Seg
1302 Root = GenLiteralExpr (Val - GetPC () - Offs);
1305 Root = NewExprNode (EXPR_MINUS);
1307 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1312 /* Generate the expression:
1314 * N - ((Seg + PC) + Offs)
1315 * N - Seg - PC - Offs
1316 * N - (PC + Offs) - Seg
1318 Root = NewExprNode (EXPR_MINUS);
1320 Root->Right = GenLiteralExpr (GetPC () + Offs);
1323 Root = NewExprNode (EXPR_MINUS);
1325 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1329 /* Return the result */
1335 ExprNode* GenULabelExpr (unsigned Num)
1336 /* Return an expression for an unnamed label with the given index */
1338 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1341 /* Return the new node */
1347 ExprNode* GenByteExpr (ExprNode* Expr)
1348 /* Force the given expression into a byte and return the result */
1350 /* Use the low byte operator to force the expression into byte size */
1351 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1354 /* Return the result */
1360 ExprNode* GenWordExpr (ExprNode* Expr)
1361 /* Force the given expression into a word and return the result. */
1363 /* AND the expression by $FFFF to force it into word size */
1364 ExprNode* Root = NewExprNode (EXPR_AND);
1366 Root->Right = GenLiteralExpr (0xFFFF);
1368 /* Return the result */
1374 ExprNode* GenNE (ExprNode* Expr, long Val)
1375 /* Generate an expression that compares Expr and Val for inequality */
1377 /* Generate a compare node */
1378 ExprNode* Root = NewExprNode (EXPR_NE);
1380 Root->Right = GenLiteralExpr (Val);
1382 /* Return the result */
1388 int IsConstExpr (ExprNode* Expr, long* Val)
1389 /* Return true if the given expression is a constant expression, that is, one
1390 * with no references to external symbols. If Val is not NULL and the
1391 * expression is constant, the constant value is stored here.
1396 /* Study the expression */
1399 StudyExpr (Expr, &D);
1401 /* Check if the expression is constant */
1402 IsConst = ED_IsConst (&D);
1403 if (IsConst && Val != 0) {
1407 /* Delete allocated memory and return the result */
1414 static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
1415 /* Internal routine that is recursively called to check for the address size
1416 * of the expression tree.
1420 unsigned char Left, Right;
1423 switch (N->Op & EXPR_TYPEMASK) {
1429 if (SymIsZP (N->V.Sym)) {
1430 if (*AddrSize < ADDR_SIZE_ZP) {
1431 *AddrSize = ADDR_SIZE_ZP;
1433 } else if (SymHasExpr (N->V.Sym)) {
1434 /* Check if this expression is a byte expression */
1435 CheckAddrSize (GetSymExpr (N->V.Sym), AddrSize);
1437 /* Undefined symbol, use absolute */
1438 if (*AddrSize < ADDR_SIZE_ABS) {
1439 *AddrSize = ADDR_SIZE_ABS;
1445 A = GetSegAddrSize (N->V.SegNum);
1446 if (A > *AddrSize) {
1454 case EXPR_UNARYNODE:
1461 /* No need to look at the expression */
1462 *AddrSize = ADDR_SIZE_ZP;
1467 /* No need to look at the expression */
1468 *AddrSize = ADDR_SIZE_ABS;
1472 CheckAddrSize (N->Left, AddrSize);
1477 case EXPR_BINARYNODE:
1478 Left = Right = ADDR_SIZE_DEFAULT;
1479 CheckAddrSize (N->Left, &Left);
1480 CheckAddrSize (N->Right, &Right);
1481 A = (Left > Right)? Left : Right;
1482 if (A > *AddrSize) {
1488 Internal ("Unknown expression op: %02X", N->Op);
1495 int IsByteExpr (ExprNode* Root)
1496 /* Return true if this is a byte expression */
1500 if (IsConstExpr (Root, &Val)) {
1501 return IsByteRange (Val);
1503 unsigned char AddrSize = ADDR_SIZE_DEFAULT;
1504 CheckAddrSize (Root, &AddrSize);
1505 return (AddrSize == ADDR_SIZE_ZP);
1511 ExprNode* CloneExpr (ExprNode* Expr)
1512 /* Clone the given expression tree. The function will simply clone symbol
1513 * nodes, it will not resolve them.
1518 /* Accept NULL pointers */
1523 /* Clone the node */
1527 Clone = GenLiteralExpr (Expr->V.Val);
1531 Clone = GenULabelExpr (Expr->V.Val);
1535 Clone = GenSymExpr (Expr->V.Sym);
1539 Clone = GenSectionExpr (Expr->V.SegNum);
1543 /* Generate a new node */
1544 Clone = NewExprNode (Expr->Op);
1545 /* Clone the tree nodes */
1546 Clone->Left = CloneExpr (Expr->Left);
1547 Clone->Right = CloneExpr (Expr->Right);
1557 void WriteExpr (ExprNode* Expr)
1558 /* Write the given expression to the object file */
1560 /* Null expressions are encoded by a type byte of zero */
1562 ObjWrite8 (EXPR_NULL);
1566 /* If the is a leafnode, write the expression attribute, otherwise
1567 * write the expression operands.
1572 ObjWrite8 (EXPR_LITERAL);
1573 ObjWrite32 (Expr->V.Val);
1577 if (SymIsImport (Expr->V.Sym)) {
1578 ObjWrite8 (EXPR_SYMBOL);
1579 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1581 WriteExpr (GetSymExpr (Expr->V.Sym));
1586 ObjWrite8 (EXPR_SECTION);
1587 ObjWrite8 (Expr->V.SegNum);
1591 WriteExpr (ULabResolve (Expr->V.Val));
1595 /* Not a leaf node */
1596 ObjWrite8 (Expr->Op);
1597 WriteExpr (Expr->Left);
1598 WriteExpr (Expr->Right);