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