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