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