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