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