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* Symbol (SymEntry* S)
199 /* Reference a symbol and return an expression for it */
202 /* Some weird error happened before */
203 return GenLiteralExpr (0);
205 /* Mark the symbol as referenced */
207 /* Create symbol node */
208 return GenSymExpr (S);
214 static ExprNode* FuncBlank (void)
215 /* Handle the .BLANK builtin function */
219 /* Assume no tokens if the closing brace follows (this is not correct in
220 * all cases, since the token may be the closing brace, but this will
221 * give a syntax error anyway and may not be handled by .BLANK.
223 if (Tok != TOK_RPAREN) {
224 /* Skip any tokens */
226 while (!TokIsSep (Tok)) {
227 if (Tok == TOK_LPAREN) {
229 } else if (Tok == TOK_RPAREN) {
241 return GenLiteralExpr (Result);
246 static ExprNode* FuncConst (void)
247 /* Handle the .CONST builtin function */
249 /* Read an expression */
250 ExprNode* Expr = Expression ();
252 /* Check the constness of the expression */
253 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
255 /* Free the expression */
264 static ExprNode* FuncDefined (void)
265 /* Handle the .DEFINED builtin function */
267 /* Parse the symbol name and search for the symbol */
268 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
270 /* Check if the symbol is defined */
271 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
276 static ExprNode* DoMatch (enum TC EqualityLevel)
277 /* Handle the .MATCH and .XMATCH builtin functions */
284 /* A list of tokens follows. Read this list and remember it building a
285 * single linked list of tokens including attributes. The list is
286 * terminated by a comma.
288 while (Tok != TOK_COMMA) {
290 /* We may not end-of-line of end-of-file here */
291 if (TokIsSep (Tok)) {
292 Error ("Unexpected end of line");
296 /* Get a node with this token */
297 Node = NewTokNode ();
299 /* Insert the node into the list */
314 /* Read the second list which is terminated by the right parenthesis and
315 * compare each token against the one in the first list.
319 while (Tok != TOK_RPAREN) {
321 /* We may not end-of-line of end-of-file here */
322 if (TokIsSep (Tok)) {
323 Error ("Unexpected end of line");
327 /* Compare the tokens if the result is not already known */
330 /* The second list is larger than the first one */
332 } else if (TokCmp (Node) < EqualityLevel) {
333 /* Tokens do not match */
338 /* Next token in first list */
343 /* Next token in current list */
347 /* Check if there are remaining tokens in the first list */
352 /* Free the token list */
359 /* Done, return the result */
360 return GenLiteralExpr (Result);
365 static ExprNode* FuncMatch (void)
366 /* Handle the .MATCH function */
368 return DoMatch (tcSameToken);
373 static ExprNode* FuncReferenced (void)
374 /* Handle the .REFERENCED builtin function */
376 /* Parse the symbol name and search for the symbol */
377 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
379 /* Check if the symbol is referenced */
380 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
385 static ExprNode* FuncSizeOf (void)
386 /* Handle the .SIZEOF function */
388 /* Get the struct for the scoped struct name */
389 SymTable* Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
391 /* Check if the given symbol is really a struct */
392 if (GetSymTabType (Struct) != ST_STRUCT) {
393 Error ("Argument to .SIZEOF is not a struct");
394 return GenLiteralExpr (0);
396 return Symbol (GetSizeOfScope (Struct));
402 static ExprNode* FuncStrAt (void)
403 /* Handle the .STRAT function */
405 char Str [sizeof(SVal)];
409 /* String constant expected */
410 if (Tok != TOK_STRCON) {
411 Error ("String constant expected");
417 /* Remember the string and skip it */
421 /* Comma must follow */
424 /* Expression expected */
425 Index = ConstExpression ();
427 /* Must be a valid index */
428 if (Index >= (long) strlen (Str)) {
429 Error ("Range error");
433 /* Get the char, handle as unsigned. Be sure to translate it into
434 * the target character set.
436 C = TgtTranslateChar (Str [(size_t)Index]);
438 /* Return the char expression */
439 return GenLiteralExpr (C);
444 static ExprNode* FuncStrLen (void)
445 /* Handle the .STRLEN function */
449 /* String constant expected */
450 if (Tok != TOK_STRCON) {
452 Error ("String constant expected");
453 /* Smart error recovery */
454 if (Tok != TOK_RPAREN) {
461 /* Get the length of the string */
464 /* Skip the string */
468 /* Return the length */
469 return GenLiteralExpr (Len);
474 static ExprNode* FuncTCount (void)
475 /* Handle the .TCOUNT function */
477 /* We have a list of tokens that ends with the closing paren. Skip
478 * the tokens, handling nested braces and count them.
482 while (Parens != 0 || Tok != TOK_RPAREN) {
484 /* Check for end of line or end of input. Since the calling function
485 * will check for the closing paren, we don't need to print an error
486 * here, just bail out.
488 if (TokIsSep (Tok)) {
495 /* Keep track of the nesting level */
497 case TOK_LPAREN: ++Parens; break;
498 case TOK_RPAREN: --Parens; break;
506 /* Return the number of tokens */
507 return GenLiteralExpr (Count);
512 static ExprNode* FuncXMatch (void)
513 /* Handle the .XMATCH function */
515 return DoMatch (tcIdentical);
520 static ExprNode* Function (ExprNode* (*F) (void))
521 /* Handle builtin functions */
525 /* Skip the keyword */
528 /* Expression must be enclosed in braces */
529 if (Tok != TOK_LPAREN) {
530 Error ("'(' expected");
532 return GenLiteralExpr (0);
536 /* Call the function itself */
539 /* Closing brace must follow */
542 /* Return the result of the actual function */
548 static ExprNode* Factor (void)
557 N = GenLiteralExpr (IVal);
562 N = GenLiteralExpr (TgtTranslateChar (IVal));
568 N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
571 case TOK_LOCAL_IDENT:
572 N = Symbol (SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW));
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.
1120 long ConstExpression (void)
1121 /* Parse an expression. Check if the expression is const, and print an error
1122 * message if not. Return the value of the expression, or a dummy, if it is
1128 /* Read the expression */
1129 ExprNode* Expr = Expression ();
1131 /* Study the expression */
1134 StudyExpr (Expr, &D);
1136 /* Check if the expression is constant */
1137 if (ED_IsConst (&D)) {
1140 Error ("Constant expression expected");
1144 /* Free the expression tree and allocated memory for D */
1148 /* Return the value */
1154 void FreeExpr (ExprNode* Root)
1155 /* Free the expression, Root is pointing to. */
1158 FreeExpr (Root->Left);
1159 FreeExpr (Root->Right);
1160 FreeExprNode (Root);
1166 ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
1167 /* Try to simplify the given expression tree */
1169 if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
1170 /* No external references */
1172 Expr = GenLiteralExpr (D->Val);
1179 ExprNode* GenLiteralExpr (long Val)
1180 /* Return an expression tree that encodes the given literal value */
1182 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1189 ExprNode* GenSymExpr (SymEntry* Sym)
1190 /* Return an expression node that encodes the given symbol */
1192 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1194 SymAddExprRef (Sym, Expr);
1200 static ExprNode* GenSectionExpr (unsigned SegNum)
1201 /* Return an expression node for the given section */
1203 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1204 Expr->V.SegNum = SegNum;
1210 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1211 /* Generate an addition from the two operands */
1214 if (IsEasyConst (Left, &Val) && Val == 0) {
1217 } else if (IsEasyConst (Right, &Val) && Val == 0) {
1221 ExprNode* Root = NewExprNode (EXPR_PLUS);
1223 Root->Right = Right;
1230 ExprNode* GenCurrentPC (void)
1231 /* Return the current program counter as expression */
1236 /* Create SegmentBase + Offset */
1237 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1238 GenLiteralExpr (GetPC ()));
1240 /* Absolute mode, just return PC value */
1241 Root = GenLiteralExpr (GetPC ());
1249 ExprNode* GenSwapExpr (ExprNode* Expr)
1250 /* Return an extended expression with lo and hi bytes swapped */
1252 ExprNode* N = NewExprNode (EXPR_SWAP);
1259 ExprNode* GenBranchExpr (unsigned Offs)
1260 /* Return an expression that encodes the difference between current PC plus
1261 * offset and the target expression (that is, Expression() - (*+Offs) ).
1268 /* Read Expression() */
1271 /* If the expression is a cheap constant, generate a simpler tree */
1272 if (IsEasyConst (N, &Val)) {
1274 /* Free the constant expression tree */
1277 /* Generate the final expression:
1279 * Val - ((Seg + PC) + Offs)
1280 * Val - Seg - PC - Offs
1281 * (Val - PC - Offs) - Seg
1283 Root = GenLiteralExpr (Val - GetPC () - Offs);
1286 Root = NewExprNode (EXPR_MINUS);
1288 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1293 /* Generate the expression:
1295 * N - ((Seg + PC) + Offs)
1296 * N - Seg - PC - Offs
1297 * N - (PC + Offs) - Seg
1299 Root = NewExprNode (EXPR_MINUS);
1301 Root->Right = GenLiteralExpr (GetPC () + Offs);
1304 Root = NewExprNode (EXPR_MINUS);
1306 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1310 /* Return the result */
1316 ExprNode* GenULabelExpr (unsigned Num)
1317 /* Return an expression for an unnamed label with the given index */
1319 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1322 /* Return the new node */
1328 ExprNode* GenByteExpr (ExprNode* Expr)
1329 /* Force the given expression into a byte and return the result */
1331 /* Use the low byte operator to force the expression into byte size */
1332 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1335 /* Return the result */
1341 ExprNode* GenWordExpr (ExprNode* Expr)
1342 /* Force the given expression into a word and return the result. */
1344 /* AND the expression by $FFFF to force it into word size */
1345 ExprNode* Root = NewExprNode (EXPR_AND);
1347 Root->Right = GenLiteralExpr (0xFFFF);
1349 /* Return the result */
1355 ExprNode* GenNE (ExprNode* Expr, long Val)
1356 /* Generate an expression that compares Expr and Val for inequality */
1358 /* Generate a compare node */
1359 ExprNode* Root = NewExprNode (EXPR_NE);
1361 Root->Right = GenLiteralExpr (Val);
1363 /* Return the result */
1369 int IsConstExpr (ExprNode* Expr, long* Val)
1370 /* Return true if the given expression is a constant expression, that is, one
1371 * with no references to external symbols. If Val is not NULL and the
1372 * expression is constant, the constant value is stored here.
1377 /* Study the expression */
1380 StudyExpr (Expr, &D);
1382 /* Check if the expression is constant */
1383 IsConst = ED_IsConst (&D);
1384 if (IsConst && Val != 0) {
1388 /* Delete allocated memory and return the result */
1395 static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
1396 /* Internal routine that is recursively called to check for the address size
1397 * of the expression tree.
1401 unsigned char Left, Right;
1404 switch (N->Op & EXPR_TYPEMASK) {
1410 if (SymIsZP (N->V.Sym)) {
1411 if (*AddrSize < ADDR_SIZE_ZP) {
1412 *AddrSize = ADDR_SIZE_ZP;
1414 } else if (SymHasExpr (N->V.Sym)) {
1415 /* Check if this expression is a byte expression */
1416 CheckAddrSize (GetSymExpr (N->V.Sym), AddrSize);
1418 /* Undefined symbol, use absolute */
1419 if (*AddrSize < ADDR_SIZE_ABS) {
1420 *AddrSize = ADDR_SIZE_ABS;
1426 A = GetSegAddrSize (N->V.SegNum);
1427 if (A > *AddrSize) {
1435 case EXPR_UNARYNODE:
1442 /* No need to look at the expression */
1443 *AddrSize = ADDR_SIZE_ZP;
1448 /* No need to look at the expression */
1449 *AddrSize = ADDR_SIZE_ABS;
1453 CheckAddrSize (N->Left, AddrSize);
1458 case EXPR_BINARYNODE:
1459 Left = Right = ADDR_SIZE_DEFAULT;
1460 CheckAddrSize (N->Left, &Left);
1461 CheckAddrSize (N->Right, &Right);
1462 A = (Left > Right)? Left : Right;
1463 if (A > *AddrSize) {
1469 Internal ("Unknown expression op: %02X", N->Op);
1476 int IsByteExpr (ExprNode* Root)
1477 /* Return true if this is a byte expression */
1481 if (IsConstExpr (Root, &Val)) {
1482 return IsByteRange (Val);
1484 unsigned char AddrSize = ADDR_SIZE_DEFAULT;
1485 CheckAddrSize (Root, &AddrSize);
1486 return (AddrSize == ADDR_SIZE_ZP);
1492 ExprNode* CloneExpr (ExprNode* Expr)
1493 /* Clone the given expression tree. The function will simply clone symbol
1494 * nodes, it will not resolve them.
1499 /* Accept NULL pointers */
1504 /* Clone the node */
1508 Clone = GenLiteralExpr (Expr->V.Val);
1512 Clone = GenULabelExpr (Expr->V.Val);
1516 Clone = GenSymExpr (Expr->V.Sym);
1520 Clone = GenSectionExpr (Expr->V.SegNum);
1524 /* Generate a new node */
1525 Clone = NewExprNode (Expr->Op);
1526 /* Clone the tree nodes */
1527 Clone->Left = CloneExpr (Expr->Left);
1528 Clone->Right = CloneExpr (Expr->Right);
1538 void WriteExpr (ExprNode* Expr)
1539 /* Write the given expression to the object file */
1541 /* Null expressions are encoded by a type byte of zero */
1543 ObjWrite8 (EXPR_NULL);
1547 /* If the is a leafnode, write the expression attribute, otherwise
1548 * write the expression operands.
1553 ObjWrite8 (EXPR_LITERAL);
1554 ObjWrite32 (Expr->V.Val);
1558 if (SymIsImport (Expr->V.Sym)) {
1559 ObjWrite8 (EXPR_SYMBOL);
1560 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1562 WriteExpr (GetSymExpr (Expr->V.Sym));
1567 ObjWrite8 (EXPR_SECTION);
1568 ObjWrite8 (Expr->V.SegNum);
1572 WriteExpr (ULabResolve (Expr->V.Val));
1576 /* Not a leaf node */
1577 ObjWrite8 (Expr->Op);
1578 WriteExpr (Expr->Left);
1579 WriteExpr (Expr->Right);