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