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