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 /* Remove the symbol if possible */
208 if (SymHasExpr (S)) {
209 return CloneExpr (GetSymExpr (S));
211 /* Create symbol node */
212 return GenSymExpr (S);
219 static ExprNode* FuncBlank (void)
220 /* Handle the .BLANK builtin function */
224 /* Assume no tokens if the closing brace follows (this is not correct in
225 * all cases, since the token may be the closing brace, but this will
226 * give a syntax error anyway and may not be handled by .BLANK.
228 if (Tok != TOK_RPAREN) {
229 /* Skip any tokens */
231 while (!TokIsSep (Tok)) {
232 if (Tok == TOK_LPAREN) {
234 } else if (Tok == TOK_RPAREN) {
246 return GenLiteralExpr (Result);
251 static ExprNode* FuncConst (void)
252 /* Handle the .CONST builtin function */
254 /* Read an expression */
255 ExprNode* Expr = Expression ();
257 /* Check the constness of the expression */
258 ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0));
260 /* Free the expression */
269 static ExprNode* FuncDefined (void)
270 /* Handle the .DEFINED builtin function */
272 /* Parse the symbol name and search for the symbol */
273 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
275 /* Check if the symbol is defined */
276 return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
281 static ExprNode* DoMatch (enum TC EqualityLevel)
282 /* Handle the .MATCH and .XMATCH builtin functions */
289 /* A list of tokens follows. Read this list and remember it building a
290 * single linked list of tokens including attributes. The list is
291 * terminated by a comma.
293 while (Tok != TOK_COMMA) {
295 /* We may not end-of-line of end-of-file here */
296 if (TokIsSep (Tok)) {
297 Error ("Unexpected end of line");
301 /* Get a node with this token */
302 Node = NewTokNode ();
304 /* Insert the node into the list */
319 /* Read the second list which is terminated by the right parenthesis and
320 * compare each token against the one in the first list.
324 while (Tok != TOK_RPAREN) {
326 /* We may not end-of-line of end-of-file here */
327 if (TokIsSep (Tok)) {
328 Error ("Unexpected end of line");
332 /* Compare the tokens if the result is not already known */
335 /* The second list is larger than the first one */
337 } else if (TokCmp (Node) < EqualityLevel) {
338 /* Tokens do not match */
343 /* Next token in first list */
348 /* Next token in current list */
352 /* Check if there are remaining tokens in the first list */
357 /* Free the token list */
364 /* Done, return the result */
365 return GenLiteralExpr (Result);
370 static ExprNode* FuncMatch (void)
371 /* Handle the .MATCH function */
373 return DoMatch (tcSameToken);
378 static ExprNode* FuncReferenced (void)
379 /* Handle the .REFERENCED builtin function */
381 /* Parse the symbol name and search for the symbol */
382 SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
384 /* Check if the symbol is referenced */
385 return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
390 static ExprNode* FuncSizeOf (void)
391 /* Handle the .SIZEOF function */
393 /* Get the struct for the scoped struct name */
394 SymTable* Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
396 /* Check if the given symbol is really a struct */
397 if (GetSymTabType (Struct) != ST_STRUCT) {
398 Error ("Argument to .SIZEOF is not a struct");
399 return GenLiteralExpr (0);
401 return Symbol (GetSizeOfScope (Struct));
407 static ExprNode* FuncStrAt (void)
408 /* Handle the .STRAT function */
410 char Str [sizeof(SVal)];
414 /* String constant expected */
415 if (Tok != TOK_STRCON) {
416 Error ("String constant expected");
422 /* Remember the string and skip it */
426 /* Comma must follow */
429 /* Expression expected */
430 Index = ConstExpression ();
432 /* Must be a valid index */
433 if (Index >= (long) strlen (Str)) {
434 Error ("Range error");
438 /* Get the char, handle as unsigned. Be sure to translate it into
439 * the target character set.
441 C = TgtTranslateChar (Str [(size_t)Index]);
443 /* Return the char expression */
444 return GenLiteralExpr (C);
449 static ExprNode* FuncStrLen (void)
450 /* Handle the .STRLEN function */
454 /* String constant expected */
455 if (Tok != TOK_STRCON) {
457 Error ("String constant expected");
458 /* Smart error recovery */
459 if (Tok != TOK_RPAREN) {
466 /* Get the length of the string */
469 /* Skip the string */
473 /* Return the length */
474 return GenLiteralExpr (Len);
479 static ExprNode* FuncTCount (void)
480 /* Handle the .TCOUNT function */
482 /* We have a list of tokens that ends with the closing paren. Skip
483 * the tokens, handling nested braces and count them.
487 while (Parens != 0 || Tok != TOK_RPAREN) {
489 /* Check for end of line or end of input. Since the calling function
490 * will check for the closing paren, we don't need to print an error
491 * here, just bail out.
493 if (TokIsSep (Tok)) {
500 /* Keep track of the nesting level */
502 case TOK_LPAREN: ++Parens; break;
503 case TOK_RPAREN: --Parens; break;
511 /* Return the number of tokens */
512 return GenLiteralExpr (Count);
517 static ExprNode* FuncXMatch (void)
518 /* Handle the .XMATCH function */
520 return DoMatch (tcIdentical);
525 static ExprNode* Function (ExprNode* (*F) (void))
526 /* Handle builtin functions */
530 /* Skip the keyword */
533 /* Expression must be enclosed in braces */
534 if (Tok != TOK_LPAREN) {
535 Error ("'(' expected");
537 return GenLiteralExpr (0);
541 /* Call the function itself */
544 /* Closing brace must follow */
547 /* Return the result of the actual function */
553 static ExprNode* Factor (void)
562 N = GenLiteralExpr (IVal);
567 N = GenLiteralExpr (TgtTranslateChar (IVal));
573 N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
576 case TOK_LOCAL_IDENT:
577 N = Symbol (SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW));
589 if (IsEasyConst (L, &Val)) {
591 N = GenLiteralExpr (-Val);
593 N = NewExprNode (EXPR_UNARY_MINUS);
601 if (IsEasyConst (L, &Val)) {
603 N = GenLiteralExpr (~Val);
605 N = NewExprNode (EXPR_NOT);
619 if (IsEasyConst (L, &Val)) {
621 N = GenLiteralExpr (Val & 0xFF);
623 N = NewExprNode (EXPR_BYTE0);
631 if (IsEasyConst (L, &Val)) {
633 N = GenLiteralExpr ((Val >> 8) & 0xFF);
635 N = NewExprNode (EXPR_BYTE1);
643 if (IsEasyConst (L, &Val)) {
645 N = GenLiteralExpr ((Val >> 16) & 0xFF);
647 N = NewExprNode (EXPR_BYTE2);
659 N = Function (FuncBlank);
663 N = Function (FuncConst);
667 N = GenLiteralExpr (CPUIsets[CPU]);
672 N = Function (FuncDefined);
676 N = Function (FuncMatch);
680 N = Function (FuncReferenced);
684 N = Function (FuncSizeOf);
688 N = Function (FuncStrAt);
692 N = Function (FuncStrLen);
696 N = Function (FuncTCount);
700 N = GenLiteralExpr (time (0));
705 N = GenLiteralExpr (VERSION);
710 N = Function (FuncXMatch);
714 if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
715 /* A character constant */
716 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
718 N = GenLiteralExpr (0); /* Dummy */
719 Error ("Syntax error");
729 static ExprNode* Term (void)
731 /* Read left hand side */
732 ExprNode* Root = Factor ();
734 /* Handle multiplicative operations */
735 while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
736 Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
739 long LVal, RVal, Val;
743 /* Remember the token and skip it */
747 /* Move root to left side and read the right side */
751 /* If both expressions are constant, we can evaluate the term */
752 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
761 Error ("Division by zero");
770 Error ("Modulo operation with zero");
786 Val = shl_l (LVal, RVal);
790 Val = shr_l (LVal, RVal);
794 Internal ("Invalid token");
797 /* Generate a literal expression and delete the old left and
802 Root = GenLiteralExpr (Val);
806 /* Generate an expression tree */
809 case TOK_MUL: Op = EXPR_MUL; break;
810 case TOK_DIV: Op = EXPR_DIV; break;
811 case TOK_MOD: Op = EXPR_MOD; break;
812 case TOK_AND: Op = EXPR_AND; break;
813 case TOK_XOR: Op = EXPR_XOR; break;
814 case TOK_SHL: Op = EXPR_SHL; break;
815 case TOK_SHR: Op = EXPR_SHR; break;
816 default: Internal ("Invalid token");
818 Root = NewExprNode (Op);
826 /* Return the expression tree we've created */
832 static ExprNode* SimpleExpr (void)
834 /* Read left hand side */
835 ExprNode* Root = Term ();
837 /* Handle additive operations */
838 while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
840 long LVal, RVal, Val;
844 /* Remember the token and skip it */
848 /* Move root to left side and read the right side */
852 /* If both expressions are constant, we can evaluate the term */
853 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
856 case TOK_PLUS: Val = LVal + RVal; break;
857 case TOK_MINUS: Val = LVal - RVal; break;
858 case TOK_OR: Val = LVal | RVal; break;
859 default: Internal ("Invalid token");
862 /* Generate a literal expression and delete the old left and
867 Root = GenLiteralExpr (Val);
871 /* Generate an expression tree */
874 case TOK_PLUS: Op = EXPR_PLUS; break;
875 case TOK_MINUS: Op = EXPR_MINUS; break;
876 case TOK_OR: Op = EXPR_OR; break;
877 default: Internal ("Invalid token");
879 Root = NewExprNode (Op);
886 /* Return the expression tree we've created */
892 static ExprNode* BoolExpr (void)
893 /* Evaluate a boolean expression */
895 /* Read left hand side */
896 ExprNode* Root = SimpleExpr ();
898 /* Handle booleans */
899 while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
900 Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
902 long LVal, RVal, Val;
906 /* Remember the token and skip it */
910 /* Move root to left side and read the right side */
912 Right = SimpleExpr ();
914 /* If both expressions are constant, we can evaluate the term */
915 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
918 case TOK_EQ: Val = (LVal == RVal); break;
919 case TOK_NE: Val = (LVal != RVal); break;
920 case TOK_LT: Val = (LVal < RVal); break;
921 case TOK_GT: Val = (LVal > RVal); break;
922 case TOK_LE: Val = (LVal <= RVal); break;
923 case TOK_GE: Val = (LVal >= RVal); break;
924 default: Internal ("Invalid token");
927 /* Generate a literal expression and delete the old left and
932 Root = GenLiteralExpr (Val);
936 /* Generate an expression tree */
939 case TOK_EQ: Op = EXPR_EQ; break;
940 case TOK_NE: Op = EXPR_NE; break;
941 case TOK_LT: Op = EXPR_LT; break;
942 case TOK_GT: Op = EXPR_GT; break;
943 case TOK_LE: Op = EXPR_LE; break;
944 case TOK_GE: Op = EXPR_GE; break;
945 default: Internal ("Invalid token");
947 Root = NewExprNode (Op);
954 /* Return the expression tree we've created */
960 static ExprNode* Expr2 (void)
961 /* Boolean operators: AND and XOR */
963 /* Read left hand side */
964 ExprNode* Root = BoolExpr ();
966 /* Handle booleans */
967 while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
969 long LVal, RVal, Val;
973 /* Remember the token and skip it */
977 /* Move root to left side and read the right side */
981 /* If both expressions are constant, we can evaluate the term */
982 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
985 case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
986 case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
987 default: Internal ("Invalid token");
990 /* Generate a literal expression and delete the old left and
995 Root = GenLiteralExpr (Val);
999 /* Generate an expression tree */
1002 case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
1003 case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
1004 default: Internal ("Invalid token");
1006 Root = NewExprNode (Op);
1008 Root->Right = Right;
1013 /* Return the expression tree we've created */
1019 static ExprNode* Expr1 (void)
1020 /* Boolean operators: OR */
1022 /* Read left hand side */
1023 ExprNode* Root = Expr2 ();
1025 /* Handle booleans */
1026 while (Tok == TOK_BOOLOR) {
1028 long LVal, RVal, Val;
1032 /* Remember the token and skip it */
1036 /* Move root to left side and read the right side */
1040 /* If both expressions are constant, we can evaluate the term */
1041 if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1044 case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
1045 default: Internal ("Invalid token");
1048 /* Generate a literal expression and delete the old left and
1053 Root = GenLiteralExpr (Val);
1057 /* Generate an expression tree */
1060 case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
1061 default: Internal ("Invalid token");
1063 Root = NewExprNode (Op);
1065 Root->Right = Right;
1070 /* Return the expression tree we've created */
1076 static ExprNode* Expr0 (void)
1077 /* Boolean operators: NOT */
1081 /* Handle booleans */
1082 if (Tok == TOK_BOOLNOT) {
1087 /* Skip the operator token */
1090 /* Read the argument */
1093 /* If the argument is const, evaluate it directly */
1094 if (IsEasyConst (Left, &Val)) {
1096 Root = GenLiteralExpr (!Val);
1098 Root = NewExprNode (EXPR_BOOLNOT);
1104 /* Read left hand side */
1109 /* Return the expression tree we've created */
1115 ExprNode* Expression (void)
1116 /* Evaluate an expression, build the expression tree on the heap and return
1117 * a pointer to the root of the tree.
1121 return SimplifyExpr (Expr0 ());
1124 ExprNode* Expr = Expr0 ();
1125 printf ("Before: "); DumpExpr (Expr, SymResolve);
1126 Expr = SimplifyExpr (Expr);
1127 printf ("After: "); DumpExpr (Expr, SymResolve);
1134 long ConstExpression (void)
1135 /* Parse an expression. Check if the expression is const, and print an error
1136 * message if not. Return the value of the expression, or a dummy, if it is
1143 /* Read the expression */
1144 ExprNode* Expr = Expr0 ();
1147 ExprNode* Expr = Expression ();
1150 /* Study the expression */
1153 StudyExpr (Expr, &D);
1155 /* Check if the expression is constant */
1156 if (ED_IsConst (&D)) {
1159 Error ("Constant expression expected");
1163 /* Free the expression tree and allocated memory for D */
1167 /* Return the value */
1173 void FreeExpr (ExprNode* Root)
1174 /* Free the expression, Root is pointing to. */
1177 FreeExpr (Root->Left);
1178 FreeExpr (Root->Right);
1179 FreeExprNode (Root);
1185 ExprNode* SimplifyExpr (ExprNode* Expr)
1186 /* Try to simplify the given expression tree */
1188 if (Expr && Expr->Op != EXPR_LITERAL) {
1190 /* Create an expression description and initialize it */
1194 /* Study the expression */
1195 StudyExpr (Expr, &D);
1197 /* Now check if we can generate a literal value */
1198 if (ED_IsConst (&D)) {
1199 /* No external references */
1201 Expr = GenLiteralExpr (D.Val);
1204 /* Free allocated memory */
1212 ExprNode* GenLiteralExpr (long Val)
1213 /* Return an expression tree that encodes the given literal value */
1215 ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1222 ExprNode* GenSymExpr (SymEntry* Sym)
1223 /* Return an expression node that encodes the given symbol */
1225 ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1227 SymAddExprRef (Sym, Expr);
1233 static ExprNode* GenSectionExpr (unsigned SegNum)
1234 /* Return an expression node for the given section */
1236 ExprNode* Expr = NewExprNode (EXPR_SECTION);
1237 Expr->V.SegNum = SegNum;
1243 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1244 /* Generate an addition from the two operands */
1246 ExprNode* Root = NewExprNode (EXPR_PLUS);
1248 Root->Right = Right;
1254 ExprNode* GenCurrentPC (void)
1255 /* Return the current program counter as expression */
1260 /* Create SegmentBase + Offset */
1261 Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1262 GenLiteralExpr (GetPC ()));
1264 /* Absolute mode, just return PC value */
1265 Root = GenLiteralExpr (GetPC ());
1273 ExprNode* GenSwapExpr (ExprNode* Expr)
1274 /* Return an extended expression with lo and hi bytes swapped */
1276 ExprNode* N = NewExprNode (EXPR_SWAP);
1283 ExprNode* GenBranchExpr (unsigned Offs)
1284 /* Return an expression that encodes the difference between current PC plus
1285 * offset and the target expression (that is, Expression() - (*+Offs) ).
1292 /* Read Expression() */
1295 /* If the expression is a cheap constant, generate a simpler tree */
1296 if (IsEasyConst (N, &Val)) {
1298 /* Free the constant expression tree */
1301 /* Generate the final expression:
1303 * Val - ((Seg + PC) + Offs)
1304 * Val - Seg - PC - Offs
1305 * (Val - PC - Offs) - Seg
1307 Root = GenLiteralExpr (Val - GetPC () - Offs);
1310 Root = NewExprNode (EXPR_MINUS);
1312 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1317 /* Generate the expression:
1319 * N - ((Seg + PC) + Offs)
1320 * N - Seg - PC - Offs
1321 * N - (PC + Offs) - Seg
1323 Root = NewExprNode (EXPR_MINUS);
1325 Root->Right = GenLiteralExpr (GetPC () + Offs);
1328 Root = NewExprNode (EXPR_MINUS);
1330 Root->Right = GenSectionExpr (GetCurrentSegNum ());
1334 /* Return the result */
1340 ExprNode* GenULabelExpr (unsigned Num)
1341 /* Return an expression for an unnamed label with the given index */
1343 ExprNode* Node = NewExprNode (EXPR_ULABEL);
1346 /* Return the new node */
1352 ExprNode* GenByteExpr (ExprNode* Expr)
1353 /* Force the given expression into a byte and return the result */
1355 /* Use the low byte operator to force the expression into byte size */
1356 ExprNode* Root = NewExprNode (EXPR_BYTE0);
1359 /* Return the result */
1365 ExprNode* GenWordExpr (ExprNode* Expr)
1366 /* Force the given expression into a word and return the result. */
1368 /* AND the expression by $FFFF to force it into word size */
1369 ExprNode* Root = NewExprNode (EXPR_AND);
1371 Root->Right = GenLiteralExpr (0xFFFF);
1373 /* Return the result */
1379 ExprNode* GenNE (ExprNode* Expr, long Val)
1380 /* Generate an expression that compares Expr and Val for inequality */
1382 /* Generate a compare node */
1383 ExprNode* Root = NewExprNode (EXPR_NE);
1385 Root->Right = GenLiteralExpr (Val);
1387 /* Return the result */
1393 int IsConstExpr (ExprNode* Expr, long* Val)
1394 /* Return true if the given expression is a constant expression, that is, one
1395 * with no references to external symbols. If Val is not NULL and the
1396 * expression is constant, the constant value is stored here.
1401 /* Study the expression */
1404 StudyExpr (Expr, &D);
1406 /* Check if the expression is constant */
1407 IsConst = ED_IsConst (&D);
1408 if (IsConst && Val != 0) {
1412 /* Delete allocated memory and return the result */
1419 static void CheckAddrSize (const ExprNode* N, unsigned char* AddrSize)
1420 /* Internal routine that is recursively called to check for the address size
1421 * of the expression tree.
1425 unsigned char Left, Right;
1428 switch (N->Op & EXPR_TYPEMASK) {
1434 if (SymIsZP (N->V.Sym)) {
1435 if (*AddrSize < ADDR_SIZE_ZP) {
1436 *AddrSize = ADDR_SIZE_ZP;
1438 } else if (SymHasExpr (N->V.Sym)) {
1439 /* Check if this expression is a byte expression */
1440 CheckAddrSize (GetSymExpr (N->V.Sym), AddrSize);
1442 /* Undefined symbol, use absolute */
1443 if (*AddrSize < ADDR_SIZE_ABS) {
1444 *AddrSize = ADDR_SIZE_ABS;
1450 A = GetSegAddrSize (N->V.SegNum);
1451 if (A > *AddrSize) {
1459 case EXPR_UNARYNODE:
1466 /* No need to look at the expression */
1467 *AddrSize = ADDR_SIZE_ZP;
1472 /* No need to look at the expression */
1473 *AddrSize = ADDR_SIZE_ABS;
1477 CheckAddrSize (N->Left, AddrSize);
1482 case EXPR_BINARYNODE:
1483 Left = Right = ADDR_SIZE_DEFAULT;
1484 CheckAddrSize (N->Left, &Left);
1485 CheckAddrSize (N->Right, &Right);
1486 A = (Left > Right)? Left : Right;
1487 if (A > *AddrSize) {
1493 Internal ("Unknown expression op: %02X", N->Op);
1500 int IsByteExpr (ExprNode* Root)
1501 /* Return true if this is a byte expression */
1505 if (IsConstExpr (Root, &Val)) {
1506 return IsByteRange (Val);
1508 unsigned char AddrSize = ADDR_SIZE_DEFAULT;
1509 CheckAddrSize (Root, &AddrSize);
1510 return (AddrSize == ADDR_SIZE_ZP);
1516 ExprNode* CloneExpr (ExprNode* Expr)
1517 /* Clone the given expression tree. The function will simply clone symbol
1518 * nodes, it will not resolve them.
1523 /* Accept NULL pointers */
1528 /* Clone the node */
1532 Clone = GenLiteralExpr (Expr->V.Val);
1536 Clone = GenULabelExpr (Expr->V.Val);
1540 Clone = GenSymExpr (Expr->V.Sym);
1544 Clone = GenSectionExpr (Expr->V.SegNum);
1548 /* Generate a new node */
1549 Clone = NewExprNode (Expr->Op);
1550 /* Clone the tree nodes */
1551 Clone->Left = CloneExpr (Expr->Left);
1552 Clone->Right = CloneExpr (Expr->Right);
1562 void WriteExpr (ExprNode* Expr)
1563 /* Write the given expression to the object file */
1565 /* Null expressions are encoded by a type byte of zero */
1567 ObjWrite8 (EXPR_NULL);
1571 /* If the is a leafnode, write the expression attribute, otherwise
1572 * write the expression operands.
1577 ObjWrite8 (EXPR_LITERAL);
1578 ObjWrite32 (Expr->V.Val);
1582 if (SymIsImport (Expr->V.Sym)) {
1583 ObjWrite8 (EXPR_SYMBOL);
1584 ObjWriteVar (GetSymIndex (Expr->V.Sym));
1586 WriteExpr (GetSymExpr (Expr->V.Sym));
1591 ObjWrite8 (EXPR_SECTION);
1592 ObjWrite8 (Expr->V.SegNum);
1596 WriteExpr (ULabResolve (Expr->V.Val));
1600 /* Not a leaf node */
1601 ObjWrite8 (Expr->Op);
1602 WriteExpr (Expr->Left);
1603 WriteExpr (Expr->Right);