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