]> git.sur5r.net Git - cc65/blob - src/ca65/expr.c
b5beb8e780c2203384c0a810e842274519ba2e74
[cc65] / src / ca65 / expr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  expr.c                                   */
4 /*                                                                           */
5 /*             Expression evaluation for the ca65 macroassembler             */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <time.h>
38
39 /* common */
40 #include "check.h"
41 #include "cpu.h"
42 #include "exprdefs.h"
43 #include "print.h"
44 #include "tgttrans.h"
45 #include "version.h"
46 #include "xmalloc.h"
47
48 /* ca65 */
49 #include "error.h"
50 #include "expr.h"
51 #include "global.h"
52 #include "instr.h"
53 #include "nexttok.h"
54 /* #include "objcode.h" */
55 #include "objfile.h"
56 #include "segment.h"
57 #include "symtab.h"
58 #include "toklist.h"
59 #include "ulabel.h"
60
61
62
63 /*****************************************************************************/
64 /*                                   Data                                    */
65 /*****************************************************************************/
66
67
68
69 /* Since all expressions are first packed into expression trees, and each
70  * expression tree node is allocated on the heap, we add some type of special
71  * purpose memory allocation here: Instead of freeing the nodes, we save some
72  * number of freed nodes for later and remember them in a single linked list
73  * using the Left link.
74  */
75 #define MAX_FREE_NODES  64
76 static ExprNode*        FreeExprNodes = 0;
77 static unsigned         FreeNodeCount = 0;
78
79
80
81 /*****************************************************************************/
82 /*                                  Helpers                                  */
83 /*****************************************************************************/
84
85
86
87 static ExprNode* NewExprNode (unsigned Op)
88 /* Create a new expression node */
89 {
90     ExprNode* N;
91
92     /* Do we have some nodes in the list already? */
93     if (FreeExprNodes) {
94         /* Use first node from list */
95         N = FreeExprNodes;
96         FreeExprNodes = N->Left;
97     } else {
98         /* Allocate fresh memory */
99         N = xmalloc (sizeof (ExprNode));
100     }
101     N->Op = Op;
102     N->Left = N->Right = 0;
103     N->Obj = 0;
104
105     return N;
106 }
107
108
109
110 static void FreeExprNode (ExprNode* E)
111 /* Free a node */
112 {
113     if (E) {
114         if (FreeNodeCount < MAX_FREE_NODES) {
115             /* Remember this node for later */
116             E->Left = FreeExprNodes;
117             FreeExprNodes = E;
118         } else {
119             /* Free the memory */
120             xfree (E);
121         }
122     }
123 }
124
125
126
127 /*****************************************************************************/
128 /*                                   Code                                    */
129 /*****************************************************************************/
130
131
132
133 static ExprNode* Expr0 (void);
134
135
136
137 int IsByteRange (long Val)
138 /* Return true if this is a byte value */
139 {
140     return (Val & ~0xFFL) == 0;
141 }
142
143
144
145 int IsWordRange (long Val)
146 /* Return true if this is a word value */
147 {
148     return (Val & ~0xFFFF) == 0;
149 }
150
151
152
153 static int FuncBlank (void)
154 /* Handle the .BLANK builtin function */
155 {
156     /* Assume no tokens if the closing brace follows (this is not correct in
157      * all cases, since the token may be the closing brace, but this will
158      * give a syntax error anyway and may not be handled by .BLANK.
159      */
160     if (Tok == TOK_RPAREN) {
161         /* No tokens */
162         return 1;
163     } else {
164         /* Skip any tokens */
165         int Braces = 0;
166         while (!TokIsSep (Tok)) {
167             if (Tok == TOK_LPAREN) {
168                 ++Braces;
169             } else if (Tok == TOK_RPAREN) {
170                 if (Braces == 0) {
171                     /* Done */
172                     break;
173                 } else {
174                     --Braces;
175                 }
176             }
177             NextTok ();
178         }
179         return 0;
180     }
181 }
182
183
184
185 static int FuncConst (void)
186 /* Handle the .CONST builtin function */
187 {
188     /* Read an expression */
189     ExprNode* Expr = Expression ();
190
191     /* Check the constness of the expression */
192     int Result = IsConstExpr (Expr);
193
194     /* Free the expression */
195     FreeExpr (Expr);
196
197     /* Done */
198     return Result;
199 }
200
201
202
203 static int FuncDefined (void)
204 /* Handle the .DEFINED builtin function */
205 {
206     static const char* Keys[] = {
207         "ANY",
208         "GLOBAL",
209         "LOCAL",
210     };
211
212     char Name [sizeof (SVal)];
213     int Result = 0;
214     int Scope;
215
216     /* First argument is a symbol name */
217     if (Tok != TOK_IDENT) {
218         Error (ERR_IDENT_EXPECTED);
219         if (Tok != TOK_RPAREN) {
220             NextTok ();
221         }
222         return 0;
223     }
224
225     /* Remember the name, then skip it */
226     strcpy (Name, SVal);
227     NextTok ();
228
229     /* Comma and scope spec may follow */
230     if (Tok == TOK_COMMA) {
231
232         /* Skip the comma */
233         NextTok ();
234
235         /* An identifier must follow */
236         if (Tok != TOK_IDENT) {
237             Error (ERR_IDENT_EXPECTED);
238             return 0;
239         }
240
241         /* Get the scope, then skip it */
242         Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
243         NextTok ();
244
245         /* Check if we got a valid keyword */
246         if (Scope < 0) {
247             Error (ERR_ILLEGAL_SCOPE);
248             return 0;
249         }
250
251         /* Map the scope */
252         switch (Scope) {
253             case 0:     Scope = SCOPE_ANY;    break;
254             case 1:     Scope = SCOPE_GLOBAL; break;
255             case 2:     Scope = SCOPE_LOCAL;  break;
256             default:    Internal ("Invalid scope: %d", Scope);
257         }
258
259     } else {
260
261         /* Any scope */
262         Scope = SCOPE_ANY;
263
264     }
265
266     /* Search for the symbol */
267     Result = SymIsDef (SVal, Scope);
268
269     /* Done */
270     return Result;
271 }
272
273
274
275 static int DoMatch (enum TC EqualityLevel)
276 /* Handle the .MATCH and .XMATCH builtin functions */
277 {
278     int Result;
279     TokNode* Root = 0;
280     TokNode* Last = 0;
281     TokNode* Node = 0;
282
283     /* A list of tokens follows. Read this list and remember it building a
284      * single linked list of tokens including attributes. The list is
285      * terminated by a comma.
286      */
287     while (Tok != TOK_COMMA) {
288
289         /* We may not end-of-line of end-of-file here */
290         if (TokIsSep (Tok)) {
291             Error (ERR_UNEXPECTED_EOL);
292             return 0;
293         }
294
295         /* Get a node with this token */
296         Node = NewTokNode ();
297
298         /* Insert the node into the list */
299         if (Last == 0) {
300             Root = Node;
301         } else {
302             Last->Next = Node;
303         }
304         Last = Node;
305
306         /* Skip the token */
307         NextTok ();
308     }
309
310     /* Skip the comma */
311     NextTok ();
312
313     /* Read the second list which is terminated by the right parenthesis and
314      * compare each token against the one in the first list.
315      */
316     Result = 1;
317     Node = Root;
318     while (Tok != TOK_RPAREN) {
319
320         /* We may not end-of-line of end-of-file here */
321         if (TokIsSep (Tok)) {
322             Error (ERR_UNEXPECTED_EOL);
323             return 0;
324         }
325
326         /* Compare the tokens if the result is not already known */
327         if (Result != 0) {
328             if (Node == 0) {
329                 /* The second list is larger than the first one */
330                 Result = 0;
331             } else if (TokCmp (Node) < EqualityLevel) {
332                 /* Tokens do not match */
333                 Result = 0;
334             }
335         }
336
337         /* Next token in first list */
338         if (Node) {
339             Node = Node->Next;
340         }
341
342         /* Next token in current list */
343         NextTok ();
344     }
345
346     /* Check if there are remaining tokens in the first list */
347     if (Node != 0) {
348         Result = 0;
349     }
350
351     /* Free the token list */
352     while (Root) {
353         Node = Root;
354         Root = Root->Next;
355         FreeTokNode (Node);
356     }
357
358     /* Done, return the result */
359     return Result;
360 }
361
362
363
364 static int FuncMatch (void)
365 /* Handle the .MATCH function */
366 {
367     return DoMatch (tcSameToken);
368 }
369
370
371
372 static int FuncReferenced (void)
373 /* Handle the .REFERENCED builtin function */
374 {
375     int Result = 0;
376
377     if (Tok != TOK_IDENT) {
378         Error (ERR_IDENT_EXPECTED);
379         if (Tok != TOK_RPAREN) {
380             NextTok ();
381         }
382     } else {
383         Result = SymIsRef (SVal, SCOPE_ANY);
384         NextTok ();
385     }
386
387     /* Done */
388     return Result;
389 }
390
391
392
393 static int FuncStrAt (void)
394 /* Handle the .STRAT function */
395 {
396     char Str [sizeof(SVal)];
397     long Index;
398
399     /* String constant expected */
400     if (Tok != TOK_STRCON) {
401         Error (ERR_STRCON_EXPECTED);
402         NextTok ();
403         return 0;
404
405     }
406
407     /* Remember the string and skip it */
408     strcpy (Str, SVal);
409     NextTok ();
410
411     /* Comma must follow */
412     ConsumeComma ();
413
414     /* Expression expected */
415     Index = ConstExpression ();
416
417     /* Must be a valid index */
418     if (Index >= (long) strlen (Str)) {
419         Error (ERR_RANGE);
420         return 0;
421     }
422
423     /* Return the char, handle as unsigned. Be sure to translate it into
424      * the target character set.
425      */
426     return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
427 }
428
429
430
431 static int FuncStrLen (void)
432 /* Handle the .STRLEN function */
433 {
434     /* String constant expected */
435     if (Tok != TOK_STRCON) {
436
437         Error (ERR_STRCON_EXPECTED);
438         /* Smart error recovery */
439         if (Tok != TOK_RPAREN) {
440             NextTok ();
441         }
442         return 0;
443
444     } else {
445
446         /* Get the length of the string */
447         int Len = strlen (SVal);
448
449         /* Skip the string */
450         NextTok ();
451
452         /* Return the length */
453         return Len;
454
455     }
456 }
457
458
459
460 static int FuncTCount (void)
461 /* Handle the .TCOUNT function */
462 {
463     /* We have a list of tokens that ends with the closing paren. Skip
464      * the tokens, handling nested braces and count them.
465      */
466     int      Count  = 0;
467     unsigned Parens = 0;
468     while (Parens != 0 || Tok != TOK_RPAREN) {
469
470         /* Check for end of line or end of input. Since the calling function
471          * will check for the closing paren, we don't need to print an error
472          * here, just bail out.
473          */
474         if (TokIsSep (Tok)) {
475             break;
476         }
477
478         /* One more token */
479         ++Count;
480
481         /* Keep track of the nesting level */
482         switch (Tok) {
483             case TOK_LPAREN:    ++Parens;       break;
484             case TOK_RPAREN:    --Parens;       break;
485             default:                            break;
486         }
487
488         /* Skip the token */
489         NextTok ();
490     }
491
492     /* Return the number of tokens */
493     return Count;
494 }
495
496
497
498 static int FuncXMatch (void)
499 /* Handle the .XMATCH function */
500 {
501     return DoMatch (tcIdentical);
502 }
503
504
505
506 static ExprNode* Function (int (*F) (void))
507 /* Handle builtin functions */
508 {
509     long Result;
510
511     /* Skip the keyword */
512     NextTok ();
513
514     /* Expression must be enclosed in braces */
515     if (Tok != TOK_LPAREN) {
516         Error (ERR_LPAREN_EXPECTED);
517         SkipUntilSep ();
518         return GenLiteralExpr (0);
519     }
520     NextTok ();
521
522     /* Call the function itself */
523     Result = F ();
524
525     /* Closing brace must follow */
526     ConsumeRParen ();
527
528     /* Return an expression node with the boolean code */
529     return GenLiteralExpr (Result);
530 }
531
532
533
534 static ExprNode* Factor (void)
535 {
536     ExprNode* N;
537     SymEntry* S;
538
539     switch (Tok) {
540
541         case TOK_INTCON:
542             N = GenLiteralExpr (IVal);
543             NextTok ();
544             break;
545
546         case TOK_CHARCON:
547             N = GenLiteralExpr (TgtTranslateChar (IVal));
548             NextTok ();
549             break;
550
551         case TOK_NAMESPACE:
552             NextTok ();
553             if (Tok != TOK_IDENT) {
554                 Error (ERR_IDENT_EXPECTED);
555                 N = GenLiteralExpr (0); /* Dummy */
556             } else {
557                 S = SymRef (SVal, SCOPE_GLOBAL);
558                 if (SymIsConst (S)) {
559                     /* Use the literal value instead */
560                     N = GenLiteralExpr (GetSymVal (S));
561                 } else {
562                     /* Create symbol node */
563                     N = GenSymExpr (S);
564                 }
565                 NextTok ();
566             }
567             break;
568
569         case TOK_IDENT:
570             S = SymRef (SVal, SCOPE_LOCAL);
571             if (SymIsConst (S)) {
572                 /* Use the literal value instead */
573                 N = GenLiteralExpr (GetSymVal (S));
574             } else {
575                 /* Create symbol node */
576                 N = GenSymExpr (S);
577             }
578             NextTok ();
579             break;
580
581         case TOK_ULABEL:
582             N = ULabRef (IVal);
583             NextTok ();
584             break;
585
586         case TOK_MINUS:
587             NextTok ();
588             N = NewExprNode (EXPR_UNARY_MINUS);
589             N->Left = Factor ();
590             break;
591
592         case TOK_NOT:
593             NextTok ();
594             N = NewExprNode (EXPR_NOT);
595             N->Left = Factor ();
596             break;
597
598         case TOK_STAR:
599         case TOK_PC:
600             NextTok ();
601             N = GenCurrentPC ();
602             break;
603
604         case TOK_LT:
605             NextTok ();
606             N = NewExprNode (EXPR_BYTE0);
607             N->Left = Factor ();
608             break;
609
610         case TOK_GT:
611             NextTok ();
612             N = NewExprNode (EXPR_BYTE1);
613             N->Left = Factor ();
614             break;
615
616         case TOK_LPAREN:
617             NextTok ();
618             N = Expr0 ();
619             ConsumeRParen ();
620             break;
621
622         case TOK_BLANK:
623             N = Function (FuncBlank);
624             break;
625
626         case TOK_CONST:
627             N = Function (FuncConst);
628             break;
629
630         case TOK_CPU:
631             N = GenLiteralExpr (CPUIsets[CPU]);
632             NextTok ();
633             break;
634
635         case TOK_DEFINED:
636             N = Function (FuncDefined);
637             break;
638
639         case TOK_MATCH:
640             N = Function (FuncMatch);
641             break;
642
643         case TOK_REFERENCED:
644             N = Function (FuncReferenced);
645             break;
646
647         case TOK_STRAT:
648             N = Function (FuncStrAt);
649             break;
650
651         case TOK_STRLEN:
652             N = Function (FuncStrLen);
653             break;
654
655         case TOK_TCOUNT:
656             N = Function (FuncTCount);
657             break;
658
659         case TOK_TIME:
660             N = GenLiteralExpr (time (0));
661             NextTok ();
662             break;
663
664         case TOK_VERSION:
665             N = GenLiteralExpr (VERSION);
666             NextTok ();
667             break;
668
669
670         case TOK_XMATCH:
671             N = Function (FuncXMatch);
672             break;
673
674         default:
675             if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
676                 /* A character constant */
677                 N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
678             } else {
679                 N = GenLiteralExpr (0); /* Dummy */
680                 Error (ERR_SYNTAX);
681             }
682             NextTok ();
683             break;
684     }
685     return N;
686 }
687
688
689
690 static ExprNode* Term (void)
691 {
692     /* Read left hand side */
693     ExprNode* Root = Factor ();
694
695     /* Handle multiplicative operations */
696     while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
697            Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
698            Tok == TOK_SHR) {
699
700         /* Create the new node */
701         ExprNode* Left = Root;
702         switch (Tok) {
703             case TOK_MUL:       Root = NewExprNode (EXPR_MUL);  break;
704             case TOK_DIV:       Root = NewExprNode (EXPR_DIV);  break;
705             case TOK_MOD:       Root = NewExprNode (EXPR_MOD);  break;
706             case TOK_AND:       Root = NewExprNode (EXPR_AND);  break;
707             case TOK_XOR:       Root = NewExprNode (EXPR_XOR);  break;
708             case TOK_SHL:       Root = NewExprNode (EXPR_SHL);  break;
709             case TOK_SHR:       Root = NewExprNode (EXPR_SHR);  break;
710             default:            Internal ("Invalid token");
711         }
712         Root->Left = Left;
713
714         /* Skip the operator token */
715         NextTok ();
716
717         /* Parse the right hand side */
718         Root->Right = Factor ();
719
720     }
721
722     /* Return the expression tree we've created */
723     return Root;
724 }
725
726
727
728 static ExprNode* SimpleExpr (void)
729 {
730     /* Read left hand side */
731     ExprNode* Root = Term ();
732
733     /* Handle additive operations */
734     while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
735
736         /* Create the new node */
737         ExprNode* Left = Root;
738         switch (Tok) {
739             case TOK_PLUS:      Root = NewExprNode (EXPR_PLUS);         break;
740             case TOK_MINUS:     Root = NewExprNode (EXPR_MINUS);        break;
741             case TOK_OR:        Root = NewExprNode (EXPR_OR);           break;
742             default:            Internal ("Invalid token");
743         }
744         Root->Left = Left;
745
746         /* Skip the operator token */
747         NextTok ();
748
749         /* Parse the right hand side */
750         Root->Right = Term ();
751
752     }
753
754     /* Return the expression tree we've created */
755     return Root;
756 }
757
758
759
760 static ExprNode* BoolExpr (void)
761 /* Evaluate a boolean expression */
762 {
763     /* Read left hand side */
764     ExprNode* Root = SimpleExpr ();
765
766     /* Handle booleans */
767     while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
768            Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
769
770         /* Create the new node */
771         ExprNode* Left = Root;
772         switch (Tok) {
773             case TOK_EQ:        Root = NewExprNode (EXPR_EQ);   break;
774             case TOK_NE:        Root = NewExprNode (EXPR_NE);   break;
775             case TOK_LT:        Root = NewExprNode (EXPR_LT);   break;
776             case TOK_GT:        Root = NewExprNode (EXPR_GT);   break;
777             case TOK_LE:        Root = NewExprNode (EXPR_LE);   break;
778             case TOK_GE:        Root = NewExprNode (EXPR_GE);   break;
779             default:            Internal ("Invalid token");
780         }
781         Root->Left = Left;
782
783         /* Skip the operator token */
784         NextTok ();
785
786         /* Parse the right hand side */
787         Root->Right = SimpleExpr ();
788
789     }
790
791     /* Return the expression tree we've created */
792     return Root;
793 }
794
795
796
797 static ExprNode* Expr2 (void)
798 /* Boolean operators: AND and XOR */
799 {
800     /* Read left hand side */
801     ExprNode* Root = BoolExpr ();
802
803     /* Handle booleans */
804     while (Tok == TOK_BAND || Tok == TOK_BXOR) {
805
806         /* Create the new node */
807         ExprNode* Left = Root;
808         switch (Tok) {
809             case TOK_BAND:      Root = NewExprNode (EXPR_BAND); break;
810             case TOK_BXOR:      Root = NewExprNode (EXPR_BXOR); break;
811             default:            Internal ("Invalid token");
812         }
813         Root->Left = Left;
814
815         /* Skip the operator token */
816         NextTok ();
817
818         /* Parse the right hand side */
819         Root->Right = BoolExpr ();
820
821     }
822
823     /* Return the expression tree we've created */
824     return Root;
825 }
826
827
828
829 static ExprNode* Expr1 (void)
830 /* Boolean operators: OR */
831 {
832     /* Read left hand side */
833     ExprNode* Root = Expr2 ();
834
835     /* Handle booleans */
836     while (Tok == TOK_BOR) {
837
838         /* Create the new node */
839         ExprNode* Left = Root;
840         switch (Tok) {
841             case TOK_BOR:       Root = NewExprNode (EXPR_BOR);  break;
842             default:            Internal ("Invalid token");
843         }
844         Root->Left = Left;
845
846         /* Skip the operator token */
847         NextTok ();
848
849         /* Parse the right hand side */
850         Root->Right = Expr2 ();
851
852     }
853
854     /* Return the expression tree we've created */
855     return Root;
856 }
857
858
859
860 static ExprNode* Expr0 (void)
861 /* Boolean operators: NOT */
862 {
863     ExprNode* Root;
864
865     /* Handle booleans */
866     if (Tok == TOK_BNOT) {
867
868         /* Create the new node */
869         Root = NewExprNode (EXPR_BNOT);
870
871         /* Skip the operator token */
872         NextTok ();
873
874         /* Parse the left hand side, allow more BNOTs */
875         Root->Left = Expr0 ();
876
877     } else {
878
879         /* Read left hand side */
880         Root = Expr1 ();
881
882     }
883
884     /* Return the expression tree we've created */
885     return Root;
886 }
887
888
889
890 static ExprNode* SimplifyExpr (ExprNode* Root)
891 /* Try to simplify the given expression tree */
892 {
893     if (Root) {
894         Root->Left  = SimplifyExpr (Root->Left);
895         Root->Right = SimplifyExpr (Root->Right);
896         if (IsConstExpr (Root)) {
897             /* The complete expression is constant */
898             Root->V.Val = GetExprVal (Root);
899             Root->Op = EXPR_LITERAL;
900             FreeExpr (Root->Left);
901             FreeExpr (Root->Right);
902             Root->Left = Root->Right = 0;
903         }
904     }
905     return Root;
906 }
907
908
909
910 ExprNode* Expression (void)
911 /* Evaluate an expression, build the expression tree on the heap and return
912  * a pointer to the root of the tree.
913  */
914 {
915     return SimplifyExpr (Expr0 ());
916 }
917
918
919
920 long ConstExpression (void)
921 /* Parse an expression. Check if the expression is const, and print an error
922  * message if not. Return the value of the expression, or a dummy, if it is
923  * not constant.
924  */
925 {
926     long Val;
927
928     /* Read the expression, and call finalize (exception here, since we
929      * expect a const).
930      */
931     ExprNode* Expr = FinalizeExpr (Expression ());
932
933     /* Get the value */
934     if (IsConstExpr (Expr)) {
935         Val = GetExprVal (Expr);
936     } else {
937         Error (ERR_CONSTEXPR_EXPECTED);
938         Val = 0;
939     }
940
941     /* Free the expression tree and return the value */
942     FreeExpr (Expr);
943     return Val;
944 }
945
946
947
948 void FreeExpr (ExprNode* Root)
949 /* Free the expression, Root is pointing to. */
950 {
951     if (Root) {
952         FreeExpr (Root->Left);
953         FreeExpr (Root->Right);
954         if (Root->Op == EXPR_SYMBOL) {
955             /* Remove the symbol reference */
956             SymDelRef (Root->V.Sym, Root);
957         }
958         FreeExprNode (Root);
959     }
960 }
961
962
963
964 ExprNode* GenLiteralExpr (long Val)
965 /* Return an expression tree that encodes the given literal value */
966 {
967     ExprNode* Expr = NewExprNode (EXPR_LITERAL);
968     Expr->V.Val = Val;
969     return Expr;
970 }
971
972
973
974 ExprNode* GenSymExpr (SymEntry* Sym)
975 /* Return an expression node that encodes the given symbol */
976 {
977     ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
978     Expr->V.Sym = Sym;
979     SymAddRef (Sym, Expr);
980     return Expr;
981 }
982
983
984
985 static ExprNode* GenSectionExpr (unsigned SegNum)
986 /* Return an expression node for the given section */
987 {
988     ExprNode* Expr = NewExprNode (EXPR_SECTION);
989     Expr->V.SegNum = SegNum;
990     return Expr;
991 }
992
993
994
995 ExprNode* GenCurrentPC (void)
996 /* Return the current program counter as expression */
997 {
998     ExprNode* Root;
999
1000     if (RelocMode) {
1001         /* Create SegmentBase + Offset */
1002         Root = NewExprNode (EXPR_PLUS);
1003         Root->Left  = GenSectionExpr (GetSegNum ());
1004         Root->Right = GenLiteralExpr (GetPC ());
1005     } else {
1006         /* Absolute mode, just return PC value */
1007         Root = GenLiteralExpr (GetPC ());
1008     }
1009
1010     return Root;
1011 }
1012
1013
1014
1015 ExprNode* GenSwapExpr (ExprNode* Expr)
1016 /* Return an extended expression with lo and hi bytes swapped */
1017 {
1018     ExprNode* N = NewExprNode (EXPR_SWAP);
1019     N->Left = Expr;
1020     return N;
1021 }
1022
1023
1024
1025 ExprNode* GenBranchExpr (unsigned Offs)
1026 /* Return an expression that encodes the difference between current PC plus
1027  * offset and the target expression (that is, Expression() - (*+Offs) ).
1028  */
1029 {
1030     ExprNode* N;
1031     ExprNode* Root;
1032
1033     /* Create *+Offs */
1034     if (RelocMode) {
1035         N = NewExprNode (EXPR_PLUS);
1036         N->Left  = GenSectionExpr (GetSegNum ());
1037         N->Right = GenLiteralExpr (GetPC () + Offs);
1038     } else {
1039         N = GenLiteralExpr (GetPC () + Offs);
1040     }
1041
1042     /* Create the root node */
1043     Root = NewExprNode (EXPR_MINUS);
1044     Root->Left = Expression ();
1045     Root->Right = N;
1046
1047     /* Return the result */
1048     return SimplifyExpr (Root);
1049 }
1050
1051
1052
1053 ExprNode* GenULabelExpr (unsigned Num)
1054 /* Return an expression for an unnamed label with the given index */
1055 {
1056     ExprNode* Node = NewExprNode (EXPR_ULABEL);
1057     Node->V.Val = Num;
1058
1059     /* Return the new node */
1060     return Node;
1061 }
1062
1063
1064
1065 ExprNode* GenByteExpr (ExprNode* Expr)
1066 /* Force the given expression into a byte and return the result */
1067 {
1068     /* Use the low byte operator to force the expression into byte size */
1069     ExprNode* Root = NewExprNode (EXPR_BYTE0);
1070     Root->Left  = Expr;
1071
1072     /* Return the result */
1073     return Root;
1074 }
1075
1076
1077
1078 ExprNode* GenWordExpr (ExprNode* Expr)
1079 /* Force the given expression into a word and return the result. */
1080 {
1081     /* AND the expression by $FFFF to force it into word size */
1082     ExprNode* Root = NewExprNode (EXPR_AND);
1083     Root->Left  = Expr;
1084     Root->Right = GenLiteralExpr (0xFFFF);
1085
1086     /* Return the result */
1087     return Root;
1088 }
1089
1090
1091
1092 ExprNode* GenNE (ExprNode* Expr, long Val)
1093 /* Generate an expression that compares Expr and Val for inequality */
1094 {
1095     /* Generate a compare node */
1096     ExprNode* Root = NewExprNode (EXPR_NE);
1097     Root->Left  = Expr;
1098     Root->Right = GenLiteralExpr (Val);
1099
1100     /* Return the result */
1101     return Root;
1102 }
1103
1104
1105
1106 int IsConstExpr (ExprNode* Root)
1107 /* Return true if the given expression is a constant expression, that is, one
1108  * with no references to external symbols.
1109  */
1110 {
1111     int Const;
1112     SymEntry* Sym;
1113
1114     if (EXPR_IS_LEAF (Root->Op)) {
1115         switch (Root->Op) {
1116
1117             case EXPR_LITERAL:
1118                 return 1;
1119
1120             case EXPR_SYMBOL:
1121                 Sym = Root->V.Sym;
1122                 if (SymHasUserMark (Sym)) {
1123                     if (Verbosity > 0) {
1124                         DumpExpr (Root);
1125                     }
1126                     PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1127                     Const = 0;
1128                 } else {
1129                     SymMarkUser (Sym);
1130                     Const = SymIsConst (Sym);
1131                     SymUnmarkUser (Sym);
1132                 }
1133                 return Const;
1134
1135             default:
1136                 return 0;
1137
1138         }
1139     } else if (EXPR_IS_UNARY (Root->Op)) {
1140
1141         return IsConstExpr (Root->Left);
1142
1143     } else {
1144
1145         /* We must handle shortcut boolean expressions here */
1146         switch (Root->Op) {
1147
1148             case EXPR_BAND:
1149                 if (IsConstExpr (Root->Left)) {
1150                     /* lhs is const, if it is zero, don't eval right */
1151                     if (GetExprVal (Root->Left) == 0) {
1152                         return 1;
1153                     } else {
1154                         return IsConstExpr (Root->Right);
1155                     }
1156                 } else {
1157                     /* lhs not const --> tree not const */
1158                     return 0;
1159                 }
1160                 break;
1161
1162             case EXPR_BOR:
1163                 if (IsConstExpr (Root->Left)) {
1164                     /* lhs is const, if it is not zero, don't eval right */
1165                     if (GetExprVal (Root->Left) != 0) {
1166                         return 1;
1167                     } else {
1168                         return IsConstExpr (Root->Right);
1169                     }
1170                 } else {
1171                     /* lhs not const --> tree not const */
1172                     return 0;
1173                 }
1174                 break;
1175
1176             default:
1177                 /* All others are handled normal */
1178                 return IsConstExpr (Root->Left) && IsConstExpr (Root->Right);
1179         }
1180     }
1181 }
1182
1183
1184
1185 static void CheckByteExpr (const ExprNode* N, int* IsByte)
1186 /* Internal routine that is recursively called to check if there is a zeropage
1187  * symbol in the expression tree.
1188  */
1189 {
1190     if (N) {
1191         switch (N->Op & EXPR_TYPEMASK) {
1192
1193             case EXPR_LEAFNODE:
1194                 switch (N->Op) {
1195
1196                     case EXPR_SYMBOL:
1197                         if (SymIsZP (N->V.Sym)) {
1198                             *IsByte = 1;
1199                         } else if (SymHasExpr (N->V.Sym)) {
1200                             /* Check if this expression is a byte expression */
1201                             *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
1202                         }
1203                         break;
1204
1205                     case EXPR_SECTION:
1206                         if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
1207                             *IsByte = 1;
1208                         }
1209                         break;
1210
1211                 }
1212                 break;
1213
1214             case EXPR_UNARYNODE:
1215                 CheckByteExpr (N->Left, IsByte);
1216                 break;
1217
1218             case EXPR_BINARYNODE:
1219                 CheckByteExpr (N->Left, IsByte);
1220                 CheckByteExpr (N->Right, IsByte);
1221                 break;
1222
1223             default:
1224                 Internal ("Unknown expression op: %02X", N->Op);
1225         }
1226     }
1227 }
1228
1229
1230
1231 int IsByteExpr (ExprNode* Root)
1232 /* Return true if this is a byte expression */
1233 {
1234     int IsByte;
1235
1236     if (IsConstExpr (Root)) {
1237         if (Root->Op != EXPR_LITERAL) {
1238             SimplifyExpr (Root);
1239         }
1240         return IsByteRange (GetExprVal (Root));
1241     } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
1242                Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
1243         /* Symbol forced to have byte range */
1244         IsByte = 1;
1245     } else {
1246         /* We have undefined symbols in the expression. Assume that the
1247          * expression is a byte expression if there is at least one symbol
1248          * declared as zeropage in it. Being wrong here is not a very big
1249          * problem since the linker knows about all symbols and detects
1250          * error like mixing absolute and zeropage labels.
1251          */
1252         IsByte = 0;
1253         CheckByteExpr (Root, &IsByte);
1254     }
1255     return IsByte;
1256 }
1257
1258
1259
1260 long GetExprVal (ExprNode* Expr)
1261 /* Get the value of a constant expression */
1262 {
1263     long Right, Left;
1264
1265     switch (Expr->Op) {
1266
1267         case EXPR_LITERAL:
1268             return Expr->V.Val;
1269
1270         case EXPR_SYMBOL:
1271             return GetSymVal (Expr->V.Sym);
1272
1273         case EXPR_PLUS:
1274             return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
1275
1276         case EXPR_MINUS:
1277             return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
1278
1279         case EXPR_MUL:
1280             return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
1281
1282         case EXPR_DIV:
1283             Left  = GetExprVal (Expr->Left);
1284             Right = GetExprVal (Expr->Right);
1285             if (Right == 0) {
1286                 Error (ERR_DIV_BY_ZERO);
1287                 return 0;
1288             }
1289             return Left / Right;
1290
1291         case EXPR_MOD:
1292             Left  = GetExprVal (Expr->Left);
1293             Right = GetExprVal (Expr->Right);
1294             if (Right == 0) {
1295                 Error (ERR_MOD_BY_ZERO);
1296                 return 0;
1297             }
1298             return Left % Right;
1299
1300         case EXPR_OR:
1301             return GetExprVal (Expr->Left) | GetExprVal (Expr->Right);
1302
1303         case EXPR_XOR:
1304             return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right);
1305
1306         case EXPR_AND:
1307             return GetExprVal (Expr->Left) & GetExprVal (Expr->Right);
1308
1309         case EXPR_SHL:
1310             return GetExprVal (Expr->Left) << GetExprVal (Expr->Right);
1311
1312         case EXPR_SHR:
1313             return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right);
1314
1315         case EXPR_EQ:
1316             return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right));
1317
1318         case EXPR_NE:
1319             return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right));
1320
1321         case EXPR_LT:
1322             return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right));
1323
1324         case EXPR_GT:
1325             return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right));
1326
1327         case EXPR_LE:
1328             return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right));
1329
1330         case EXPR_GE:
1331             return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right));
1332
1333         case EXPR_UNARY_MINUS:
1334             return -GetExprVal (Expr->Left);
1335
1336         case EXPR_NOT:
1337             return ~GetExprVal (Expr->Left);
1338
1339         case EXPR_BYTE0:
1340             return GetExprVal (Expr->Left) & 0xFF;
1341
1342         case EXPR_BYTE1:
1343             return (GetExprVal (Expr->Left) >> 8) & 0xFF;
1344
1345         case EXPR_BYTE2:
1346             return (GetExprVal (Expr->Left) >> 16) & 0xFF;
1347
1348         case EXPR_BYTE3:
1349             return (GetExprVal (Expr->Left) >> 24) & 0xFF;
1350
1351         case EXPR_SWAP:
1352             Left = GetExprVal (Expr->Left);
1353             return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
1354
1355         case EXPR_BAND:
1356             return GetExprVal (Expr->Left) && GetExprVal (Expr->Right);
1357
1358         case EXPR_BOR:
1359             return GetExprVal (Expr->Left) || GetExprVal (Expr->Right);
1360
1361         case EXPR_BXOR:
1362             return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0);
1363
1364         case EXPR_BNOT:
1365             return !GetExprVal (Expr->Left);
1366
1367         case EXPR_ULABEL:
1368             Internal ("GetExprVal called for EXPR_ULABEL");
1369             /* NOTREACHED */
1370             return 0;
1371
1372         default:
1373             Internal ("Unknown Op type: %u", Expr->Op);
1374             /* NOTREACHED */
1375             return 0;
1376     }
1377 }
1378
1379
1380
1381 static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
1382 /* Remove resolved symbols from the tree by cloning symbol expressions */
1383 {
1384     /* Accept NULL pointers */
1385     if (Expr == 0) {
1386         return 0;
1387     }
1388
1389     /* Special node handling */
1390     switch (Expr->Op) {
1391
1392         case EXPR_SYMBOL:
1393             if (SymHasExpr (Expr->V.Sym)) {
1394                 /* The symbol has an expression tree */
1395                 SymEntry* Sym = Expr->V.Sym;
1396                 if (SymHasUserMark (Sym)) {
1397                     /* Circular definition */
1398                     if (Verbosity) {
1399                         DumpExpr (Expr);
1400                     }
1401                     PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
1402                     return GenLiteralExpr (0);          /* Return a dummy value */
1403                 }
1404                 SymMarkUser (Sym);
1405                 Expr = RemoveSyms (GetSymExpr (Sym), 1);
1406                 SymUnmarkUser (Sym);
1407                 return Expr;
1408             } else if (SymIsConst (Expr->V.Sym)) {
1409                 /* The symbol is a constant */
1410                 return GenLiteralExpr (GetSymVal (Expr->V.Sym));
1411             }
1412             break;
1413
1414         case EXPR_ULABEL:
1415             if (ULabCanResolve ()) {
1416                 ExprNode* NewExpr = ULabResolve (Expr->V.Val);
1417                 FreeExpr (Expr);
1418                 Expr = NewExpr;
1419             }
1420             break;
1421
1422     }
1423
1424     /* Clone the current node if needed */
1425     if (MustClone) {
1426
1427         ExprNode* Clone;
1428
1429         /* Clone the expression tree */
1430         switch (Expr->Op) {
1431
1432             case EXPR_LITERAL:
1433                 Clone = GenLiteralExpr (Expr->V.Val);
1434                 break;
1435
1436             case EXPR_ULABEL:
1437                 Clone = GenULabelExpr (Expr->V.Val);
1438                 break;
1439
1440             case EXPR_SYMBOL:
1441                 Clone = GenSymExpr (Expr->V.Sym);
1442                 break;
1443
1444             case EXPR_SECTION:
1445                 Clone = GenSectionExpr (Expr->V.SegNum);
1446                 break;
1447
1448             default:
1449                 Clone = NewExprNode (Expr->Op);
1450                 Clone->Left  = RemoveSyms (Expr->Left, 1);
1451                 Clone->Right = RemoveSyms (Expr->Right, 1);
1452                 break;
1453
1454         }
1455
1456         /* Done */
1457         return Clone;
1458
1459     } else {
1460
1461         /* Nothing to clone */
1462         Expr->Left  = RemoveSyms (Expr->Left, 0);
1463         Expr->Right = RemoveSyms (Expr->Right, 0);
1464
1465         /* Done */
1466         return Expr;
1467     }
1468 }
1469
1470
1471
1472 static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
1473 /* Extract and evaluate all constant factors in an subtree that has only
1474  * additions and subtractions.
1475  */
1476 {
1477     if (Expr->Op == EXPR_LITERAL) {
1478         if (Sign < 0) {
1479             *Val -= Expr->V.Val;
1480         } else {
1481             *Val += Expr->V.Val;
1482         }
1483         FreeExprNode (Expr);
1484         return 0;
1485     }
1486
1487     if (Expr->Op == EXPR_PLUS || Expr->Op == EXPR_MINUS) {
1488         ExprNode* Left;
1489         ExprNode* Right;
1490         Left = ConstExtract (Expr->Left, Val, Sign);
1491         if (Expr->Op == EXPR_MINUS) {
1492             Sign = -Sign;
1493         }
1494         Right = ConstExtract (Expr->Right, Val, Sign);
1495         if (Left == 0 && Right == 0) {
1496             FreeExprNode (Expr);
1497             return 0;
1498         } else if (Left == 0) {
1499             FreeExprNode (Expr);
1500             return Right;
1501         } else if (Right == 0) {
1502             FreeExprNode (Expr);
1503             return Left;
1504         } else {
1505             /* Check for SEG - SEG which is now possible */
1506             if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
1507                 Left->V.SegNum == Right->V.SegNum) {
1508                 /* SEG - SEG, remove it completely */
1509                 FreeExprNode (Left);
1510                 FreeExprNode (Right);
1511                 FreeExprNode (Expr);
1512                 return 0;
1513             } else {
1514                 Expr->Left  = Left;
1515                 Expr->Right = Right;
1516                 return Expr;
1517             }
1518         }
1519     }
1520
1521     /* Some other sort of node, finalize the terms */
1522     if (Expr->Left) {
1523         Expr->Left = FinalizeExpr (Expr->Left);
1524     }
1525     if (Expr->Right) {
1526         Expr->Right = FinalizeExpr (Expr->Right);
1527     }
1528
1529     return Expr;
1530 }
1531
1532
1533
1534 ExprNode* FinalizeExpr (ExprNode* Expr)
1535 /* Resolve any symbols by cloning the symbol expression tree instead of the
1536  * symbol reference, then try to simplify the expression as much as possible.
1537  * This function must only be called if all symbols are resolved (no undefined
1538  * symbol errors).
1539  */
1540 {
1541     long Val = 0;
1542     ExprNode* N;
1543
1544     Expr = RemoveSyms (Expr, 0);
1545     Expr = ConstExtract (Expr, &Val, 1);
1546     if (Expr == 0) {
1547         /* Reduced to a literal value */
1548         Expr = GenLiteralExpr (Val);
1549     } else if (Val) {
1550         /* Extracted a value */
1551         N = NewExprNode (EXPR_PLUS);
1552         N->Left = Expr;
1553         N->Right = GenLiteralExpr (Val);
1554         Expr = N;
1555     }
1556     return Expr;
1557 }
1558
1559
1560
1561 ExprNode* CloneExpr (ExprNode* Expr)
1562 /* Clone the given expression tree. The function will simply clone symbol
1563  * nodes, it will not resolve them.
1564  */
1565 {
1566     ExprNode* Clone;
1567
1568     /* Accept NULL pointers */
1569     if (Expr == 0) {
1570         return 0;
1571     }
1572
1573     /* Clone the node */
1574     switch (Expr->Op) {
1575
1576         case EXPR_LITERAL:
1577             Clone = GenLiteralExpr (Expr->V.Val);
1578             break;
1579
1580         case EXPR_ULABEL:
1581             Clone = GenULabelExpr (Expr->V.Val);
1582             break;
1583
1584         case EXPR_SYMBOL:
1585             Clone = GenSymExpr (Expr->V.Sym);
1586             break;
1587
1588         case EXPR_SECTION:
1589             Clone = GenSectionExpr (Expr->V.SegNum);
1590             break;
1591
1592         default:
1593             /* Generate a new node */
1594             Clone = NewExprNode (Expr->Op);
1595             /* Clone the tree nodes */
1596             Clone->Left = CloneExpr (Expr->Left);
1597             Clone->Right = CloneExpr (Expr->Right);
1598             break;
1599     }
1600
1601     /* Done */
1602     return Clone;
1603 }
1604
1605
1606
1607 void WriteExpr (ExprNode* Expr)
1608 /* Write the given expression to the object file */
1609 {
1610     /* Null expressions are encoded by a type byte of zero */
1611     if (Expr == 0) {
1612         ObjWrite8 (0);
1613         return;
1614     }
1615
1616     /* Write the expression code */
1617     ObjWrite8 (Expr->Op);
1618
1619     /* If the is a leafnode, write the expression attribute, otherwise
1620      * write the expression operands.
1621      */
1622     switch (Expr->Op) {
1623
1624         case EXPR_LITERAL:
1625             ObjWrite32 (Expr->V.Val);
1626             break;
1627
1628         case EXPR_SYMBOL:
1629             /* Maybe we should use a code here? */
1630             CHECK (SymIsImport (Expr->V.Sym));  /* Safety */
1631             ObjWriteVar (GetSymIndex (Expr->V.Sym));
1632             break;
1633
1634         case EXPR_SECTION:
1635             ObjWrite8 (Expr->V.SegNum);
1636             break;
1637
1638         case EXPR_ULABEL:
1639             Internal ("WriteExpr: Cannot write EXPR_ULABEL nodes");
1640             break;
1641
1642         default:
1643             /* Not a leaf node */
1644             WriteExpr (Expr->Left);
1645             WriteExpr (Expr->Right);
1646             break;
1647
1648     }
1649 }
1650
1651
1652
1653