]> git.sur5r.net Git - cc65/blob - src/ca65/expr.c
Fixed _textcolor definition.
[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_ASIZE:
1103             if (GetCPU () != CPU_65816) {
1104                 N = GenLiteralExpr (8);
1105             } else {
1106                 N = GenLiteralExpr (ExtBytes[AM65I_IMM_ACCU] * 8);
1107             }
1108             NextTok ();
1109             break;
1110
1111         case TOK_BLANK:
1112             N = Function (FuncBlank);
1113             break;
1114
1115         case TOK_CONST:
1116             N = Function (FuncConst);
1117             break;
1118
1119         case TOK_CPU:
1120             N = GenLiteralExpr (CPUIsets[CPU]);
1121             NextTok ();
1122             break;
1123
1124         case TOK_DEFINED:
1125             N = Function (FuncDefined);
1126             break;
1127
1128         case TOK_DEFINEDMACRO:
1129             N = Function (FuncDefinedMacro);
1130             break;
1131
1132         case TOK_HIBYTE:
1133             N = Function (FuncHiByte);
1134             break;
1135
1136         case TOK_HIWORD:
1137             N = Function (FuncHiWord);
1138             break;
1139
1140         case TOK_ISMNEMONIC:
1141             N = Function (FuncIsMnemonic);
1142             break;
1143
1144         case TOK_ISIZE:
1145             if (GetCPU () != CPU_65816) {
1146                 N = GenLiteralExpr (8);
1147             } else {
1148                 N = GenLiteralExpr (ExtBytes[AM65I_IMM_INDEX] * 8);
1149             }
1150             NextTok ();
1151             break;
1152
1153         case TOK_LOBYTE:
1154             N = Function (FuncLoByte);
1155             break;
1156
1157         case TOK_LOWORD:
1158             N = Function (FuncLoWord);
1159             break;
1160
1161         case TOK_MATCH:
1162             N = Function (FuncMatch);
1163             break;
1164
1165         case TOK_MAX:
1166             N = Function (FuncMax);
1167             break;
1168
1169         case TOK_MIN:
1170             N = Function (FuncMin);
1171             break;
1172
1173         case TOK_REFERENCED:
1174             N = Function (FuncReferenced);
1175             break;
1176
1177         case TOK_SIZEOF:
1178             N = Function (FuncSizeOf);
1179             break;
1180
1181         case TOK_STRAT:
1182             N = Function (FuncStrAt);
1183             break;
1184
1185         case TOK_STRLEN:
1186             N = Function (FuncStrLen);
1187             break;
1188
1189         case TOK_TCOUNT:
1190             N = Function (FuncTCount);
1191             break;
1192
1193         case TOK_TIME:
1194             N = GenLiteralExpr ((long) time (0));
1195             NextTok ();
1196             break;
1197
1198         case TOK_VERSION:
1199             N = GenLiteralExpr (GetVersionAsNumber ());
1200             NextTok ();
1201             break;
1202
1203         case TOK_XMATCH:
1204             N = Function (FuncXMatch);
1205             break;
1206
1207         default:
1208             if (LooseCharTerm && CurTok.Tok == TOK_STRCON &&
1209                 SB_GetLen (&CurTok.SVal) == 1) {
1210                 /* A character constant */
1211                 N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0)));
1212             } else {
1213                 N = GenLiteral0 ();     /* Dummy */
1214                 Error ("Syntax error");
1215             }
1216             NextTok ();
1217             break;
1218     }
1219     return N;
1220 }
1221
1222
1223
1224 static ExprNode* Term (void)
1225 {
1226     /* Read left hand side */
1227     ExprNode* Root = Factor ();
1228
1229     /* Handle multiplicative operations */
1230     while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV ||
1231            CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND ||
1232            CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL ||
1233            CurTok.Tok == TOK_SHR) {
1234
1235         long LVal, RVal, Val;
1236         ExprNode* Left;
1237         ExprNode* Right;
1238
1239         /* Remember the token and skip it */
1240         token_t T = CurTok.Tok;
1241         NextTok ();
1242
1243         /* Move root to left side and read the right side */
1244         Left  = Root;
1245         Right = Factor ();
1246
1247         /* If both expressions are constant, we can evaluate the term */
1248         if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1249
1250             switch (T) {
1251                 case TOK_MUL:
1252                     Val = LVal * RVal;
1253                     break;
1254
1255                 case TOK_DIV:
1256                     if (RVal == 0) {
1257                         Error ("Division by zero");
1258                         Val = 1;
1259                     } else {
1260                         Val = LVal / RVal;
1261                     }
1262                     break;
1263
1264                 case TOK_MOD:
1265                     if (RVal == 0) {
1266                         Error ("Modulo operation with zero");
1267                         Val = 1;
1268                     } else {
1269                         Val = LVal % RVal;
1270                     }
1271                     break;
1272
1273                 case TOK_AND:
1274                     Val = LVal & RVal;
1275                     break;
1276
1277                 case TOK_XOR:
1278                     Val = LVal ^ RVal;
1279                     break;
1280
1281                 case TOK_SHL:
1282                     Val = shl_l (LVal, RVal);
1283                     break;
1284
1285                 case TOK_SHR:
1286                     Val = shr_l (LVal, RVal);
1287                     break;
1288
1289                 default:
1290                     Internal ("Invalid token");
1291             }
1292
1293             /* Generate a literal expression and delete the old left and
1294             ** right sides.
1295             */
1296             FreeExpr (Left);
1297             FreeExpr (Right);
1298             Root = GenLiteralExpr (Val);
1299
1300         } else {
1301
1302             /* Generate an expression tree */
1303             unsigned char Op;
1304             switch (T) {
1305                 case TOK_MUL:   Op = EXPR_MUL;  break;
1306                 case TOK_DIV:   Op = EXPR_DIV;  break;
1307                 case TOK_MOD:   Op = EXPR_MOD;  break;
1308                 case TOK_AND:   Op = EXPR_AND;  break;
1309                 case TOK_XOR:   Op = EXPR_XOR;  break;
1310                 case TOK_SHL:   Op = EXPR_SHL;  break;
1311                 case TOK_SHR:   Op = EXPR_SHR;  break;
1312                 default:        Internal ("Invalid token");
1313             }
1314             Root        = NewExprNode (Op);
1315             Root->Left  = Left;
1316             Root->Right = Right;
1317
1318         }
1319
1320     }
1321
1322     /* Return the expression tree we've created */
1323     return Root;
1324 }
1325
1326
1327
1328 static ExprNode* SimpleExpr (void)
1329 {
1330     /* Read left hand side */
1331     ExprNode* Root = Term ();
1332
1333     /* Handle additive operations */
1334     while (CurTok.Tok == TOK_PLUS  ||
1335            CurTok.Tok == TOK_MINUS ||
1336            CurTok.Tok == TOK_OR) {
1337
1338         long LVal, RVal, Val;
1339         ExprNode* Left;
1340         ExprNode* Right;
1341
1342         /* Remember the token and skip it */
1343         token_t T = CurTok.Tok;
1344         NextTok ();
1345
1346         /* Move root to left side and read the right side */
1347         Left  = Root;
1348         Right = Term ();
1349
1350         /* If both expressions are constant, we can evaluate the term */
1351         if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1352
1353             switch (T) {
1354                 case TOK_PLUS:  Val = LVal + RVal;      break;
1355                 case TOK_MINUS: Val = LVal - RVal;      break;
1356                 case TOK_OR:    Val = LVal | RVal;      break;
1357                 default:        Internal ("Invalid token");
1358             }
1359
1360             /* Generate a literal expression and delete the old left and
1361             ** right sides.
1362             */
1363             FreeExpr (Left);
1364             FreeExpr (Right);
1365             Root = GenLiteralExpr (Val);
1366
1367         } else {
1368
1369             /* Generate an expression tree */
1370             unsigned char Op;
1371             switch (T) {
1372                 case TOK_PLUS:  Op = EXPR_PLUS;  break;
1373                 case TOK_MINUS: Op = EXPR_MINUS; break;
1374                 case TOK_OR:    Op = EXPR_OR;    break;
1375                 default:        Internal ("Invalid token");
1376             }
1377             Root        = NewExprNode (Op);
1378             Root->Left  = Left;
1379             Root->Right = Right;
1380
1381         }
1382     }
1383
1384     /* Return the expression tree we've created */
1385     return Root;
1386 }
1387
1388
1389
1390 static ExprNode* BoolExpr (void)
1391 /* Evaluate a boolean expression */
1392 {
1393     /* Read left hand side */
1394     ExprNode* Root = SimpleExpr ();
1395
1396     /* Handle booleans */
1397     while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE ||
1398            CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT ||
1399            CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) {
1400
1401         long LVal, RVal, Val;
1402         ExprNode* Left;
1403         ExprNode* Right;
1404
1405         /* Remember the token and skip it */
1406         token_t T = CurTok.Tok;
1407         NextTok ();
1408
1409         /* Move root to left side and read the right side */
1410         Left  = Root;
1411         Right = SimpleExpr ();
1412
1413         /* If both expressions are constant, we can evaluate the term */
1414         if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1415
1416             switch (T) {
1417                 case TOK_EQ:    Val = (LVal == RVal);   break;
1418                 case TOK_NE:    Val = (LVal != RVal);   break;
1419                 case TOK_LT:    Val = (LVal < RVal);    break;
1420                 case TOK_GT:    Val = (LVal > RVal);    break;
1421                 case TOK_LE:    Val = (LVal <= RVal);   break;
1422                 case TOK_GE:    Val = (LVal >= RVal);   break;
1423                 default:        Internal ("Invalid token");
1424             }
1425
1426             /* Generate a literal expression and delete the old left and
1427             ** right sides.
1428             */
1429             FreeExpr (Left);
1430             FreeExpr (Right);
1431             Root = GenLiteralExpr (Val);
1432
1433         } else {
1434
1435             /* Generate an expression tree */
1436             unsigned char Op;
1437             switch (T) {
1438                 case TOK_EQ:    Op = EXPR_EQ;   break;
1439                 case TOK_NE:    Op = EXPR_NE;   break;
1440                 case TOK_LT:    Op = EXPR_LT;   break;
1441                 case TOK_GT:    Op = EXPR_GT;   break;
1442                 case TOK_LE:    Op = EXPR_LE;   break;
1443                 case TOK_GE:    Op = EXPR_GE;   break;
1444                 default:        Internal ("Invalid token");
1445             }
1446             Root        = NewExprNode (Op);
1447             Root->Left  = Left;
1448             Root->Right = Right;
1449
1450         }
1451     }
1452
1453     /* Return the expression tree we've created */
1454     return Root;
1455 }
1456
1457
1458
1459 static ExprNode* Expr2 (void)
1460 /* Boolean operators: AND and XOR */
1461 {
1462     /* Read left hand side */
1463     ExprNode* Root = BoolExpr ();
1464
1465     /* Handle booleans */
1466     while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) {
1467
1468         long LVal, RVal, Val;
1469         ExprNode* Left;
1470         ExprNode* Right;
1471
1472         /* Remember the token and skip it */
1473         token_t T = CurTok.Tok;
1474         NextTok ();
1475
1476         /* Move root to left side and read the right side */
1477         Left  = Root;
1478         Right = BoolExpr ();
1479
1480         /* If both expressions are constant, we can evaluate the term */
1481         if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1482
1483             switch (T) {
1484                 case TOK_BOOLAND:   Val = ((LVal != 0) && (RVal != 0)); break;
1485                 case TOK_BOOLXOR:   Val = ((LVal != 0) ^  (RVal != 0)); break;
1486                 default:        Internal ("Invalid token");
1487             }
1488
1489             /* Generate a literal expression and delete the old left and
1490             ** right sides.
1491             */
1492             FreeExpr (Left);
1493             FreeExpr (Right);
1494             Root = GenLiteralExpr (Val);
1495
1496         } else {
1497
1498             /* Generate an expression tree */
1499             unsigned char Op;
1500             switch (T) {
1501                 case TOK_BOOLAND:   Op = EXPR_BOOLAND; break;
1502                 case TOK_BOOLXOR:   Op = EXPR_BOOLXOR; break;
1503                 default:            Internal ("Invalid token");
1504             }
1505             Root        = NewExprNode (Op);
1506             Root->Left  = Left;
1507             Root->Right = Right;
1508
1509         }
1510     }
1511
1512     /* Return the expression tree we've created */
1513     return Root;
1514 }
1515
1516
1517
1518 static ExprNode* Expr1 (void)
1519 /* Boolean operators: OR */
1520 {
1521     /* Read left hand side */
1522     ExprNode* Root = Expr2 ();
1523
1524     /* Handle booleans */
1525     while (CurTok.Tok == TOK_BOOLOR) {
1526
1527         long LVal, RVal, Val;
1528         ExprNode* Left;
1529         ExprNode* Right;
1530
1531         /* Remember the token and skip it */
1532         token_t T = CurTok.Tok;
1533         NextTok ();
1534
1535         /* Move root to left side and read the right side */
1536         Left  = Root;
1537         Right = Expr2 ();
1538
1539         /* If both expressions are constant, we can evaluate the term */
1540         if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
1541
1542             switch (T) {
1543                 case TOK_BOOLOR:    Val = ((LVal != 0) || (RVal != 0)); break;
1544                 default:        Internal ("Invalid token");
1545             }
1546
1547             /* Generate a literal expression and delete the old left and
1548             ** right sides.
1549             */
1550             FreeExpr (Left);
1551             FreeExpr (Right);
1552             Root = GenLiteralExpr (Val);
1553
1554         } else {
1555
1556             /* Generate an expression tree */
1557             unsigned char Op;
1558             switch (T) {
1559                 case TOK_BOOLOR:    Op = EXPR_BOOLOR;  break;
1560                 default:            Internal ("Invalid token");
1561             }
1562             Root        = NewExprNode (Op);
1563             Root->Left  = Left;
1564             Root->Right = Right;
1565
1566         }
1567     }
1568
1569     /* Return the expression tree we've created */
1570     return Root;
1571 }
1572
1573
1574
1575 static ExprNode* Expr0 (void)
1576 /* Boolean operators: NOT */
1577 {
1578     ExprNode* Root;
1579
1580     /* Handle booleans */
1581     if (CurTok.Tok == TOK_BOOLNOT) {
1582
1583         long Val;
1584         ExprNode* Left;
1585
1586         /* Skip the operator token */
1587         NextTok ();
1588
1589         /* Read the argument */
1590         Left = Expr0 ();
1591
1592         /* If the argument is const, evaluate it directly */
1593         if (IsEasyConst (Left, &Val)) {
1594             FreeExpr (Left);
1595             Root = GenLiteralExpr (!Val);
1596         } else {
1597             Root = NewExprNode (EXPR_BOOLNOT);
1598             Root->Left = Left;
1599         }
1600
1601     } else {
1602
1603         /* Read left hand side */
1604         Root = Expr1 ();
1605
1606     }
1607
1608     /* Return the expression tree we've created */
1609     return Root;
1610 }
1611
1612
1613
1614 ExprNode* Expression (void)
1615 /* Evaluate an expression, build the expression tree on the heap and return
1616 ** a pointer to the root of the tree.
1617 */
1618 {
1619     return Expr0 ();
1620 }
1621
1622
1623
1624 long ConstExpression (void)
1625 /* Parse an expression. Check if the expression is const, and print an error
1626 ** message if not. Return the value of the expression, or a dummy, if it is
1627 ** not constant.
1628 */
1629 {
1630     long Val;
1631
1632     /* Read the expression */
1633     ExprNode* Expr = Expression ();
1634
1635     /* Study the expression */
1636     ExprDesc D;
1637     ED_Init (&D);
1638     StudyExpr (Expr, &D);
1639
1640     /* Check if the expression is constant */
1641     if (ED_IsConst (&D)) {
1642         Val = D.Val;
1643     } else {
1644         Error ("Constant expression expected");
1645         Val = 0;
1646     }
1647
1648     /* Free the expression tree and allocated memory for D */
1649     FreeExpr (Expr);
1650     ED_Done (&D);
1651
1652     /* Return the value */
1653     return Val;
1654 }
1655
1656
1657
1658 void FreeExpr (ExprNode* Root)
1659 /* Free the expression, Root is pointing to. */
1660 {
1661     if (Root) {
1662         FreeExpr (Root->Left);
1663         FreeExpr (Root->Right);
1664         FreeExprNode (Root);
1665     }
1666 }
1667
1668
1669
1670 ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D)
1671 /* Try to simplify the given expression tree */
1672 {
1673     if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) {
1674         /* No external references */
1675         FreeExpr (Expr);
1676         Expr = GenLiteralExpr (D->Val);
1677     }
1678     return Expr;
1679 }
1680
1681
1682
1683 ExprNode* GenLiteralExpr (long Val)
1684 /* Return an expression tree that encodes the given literal value */
1685 {
1686     ExprNode* Expr = NewExprNode (EXPR_LITERAL);
1687     Expr->V.IVal = Val;
1688     return Expr;
1689 }
1690
1691
1692
1693 ExprNode* GenLiteral0 (void)
1694 /* Return an expression tree that encodes the the number zero */
1695 {
1696     return GenLiteralExpr (0);
1697 }
1698
1699
1700
1701 ExprNode* GenSymExpr (SymEntry* Sym)
1702 /* Return an expression node that encodes the given symbol */
1703 {
1704     ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
1705     Expr->V.Sym = Sym;
1706     SymAddExprRef (Sym, Expr);
1707     return Expr;
1708 }
1709
1710
1711
1712 static ExprNode* GenSectionExpr (unsigned SecNum)
1713 /* Return an expression node for the given section */
1714 {
1715     ExprNode* Expr = NewExprNode (EXPR_SECTION);
1716     Expr->V.SecNum = SecNum;
1717     return Expr;
1718 }
1719
1720
1721
1722 static ExprNode* GenBankExpr (unsigned SecNum)
1723 /* Return an expression node for the given bank */
1724 {
1725     ExprNode* Expr = NewExprNode (EXPR_BANK);
1726     Expr->V.SecNum = SecNum;
1727     return Expr;
1728 }
1729
1730
1731
1732 ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right)
1733 /* Generate an addition from the two operands */
1734 {
1735     long Val;
1736     if (IsEasyConst (Left, &Val) && Val == 0) {
1737         FreeExpr (Left);
1738         return Right;
1739     } else if (IsEasyConst (Right, &Val) && Val == 0) {
1740         FreeExpr (Right);
1741         return Left;
1742     } else {
1743         ExprNode* Root = NewExprNode (EXPR_PLUS);
1744         Root->Left = Left;
1745         Root->Right = Right;
1746         return Root;
1747     }
1748 }
1749
1750
1751
1752 ExprNode* GenCurrentPC (void)
1753 /* Return the current program counter as expression */
1754 {
1755     ExprNode* Root;
1756
1757     if (GetRelocMode ()) {
1758         /* Create SegmentBase + Offset */
1759         Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
1760                            GenLiteralExpr (GetPC ()));
1761     } else {
1762         /* Absolute mode, just return PC value */
1763         Root = GenLiteralExpr (GetPC ());
1764     }
1765
1766     return Root;
1767 }
1768
1769
1770
1771 ExprNode* GenSwapExpr (ExprNode* Expr)
1772 /* Return an extended expression with lo and hi bytes swapped */
1773 {
1774     ExprNode* N = NewExprNode (EXPR_SWAP);
1775     N->Left = Expr;
1776     return N;
1777 }
1778
1779
1780
1781 ExprNode* GenBranchExpr (unsigned Offs)
1782 /* Return an expression that encodes the difference between current PC plus
1783 ** offset and the target expression (that is, Expression() - (*+Offs) ).
1784 */
1785 {
1786     ExprNode* N;
1787     ExprNode* Root;
1788     long      Val;
1789
1790     /* Read Expression() */
1791     N = Expression ();
1792
1793     /* If the expression is a cheap constant, generate a simpler tree */
1794     if (IsEasyConst (N, &Val)) {
1795
1796         /* Free the constant expression tree */
1797         FreeExpr (N);
1798
1799         /* Generate the final expression:
1800         ** Val - (* + Offs)
1801         ** Val - ((Seg + PC) + Offs)
1802         ** Val - Seg - PC - Offs
1803         ** (Val - PC - Offs) - Seg
1804         */
1805         Root = GenLiteralExpr (Val - 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     } else {
1814
1815         /* Generate the expression:
1816         ** N - (* + Offs)
1817         ** N - ((Seg + PC) + Offs)
1818         ** N - Seg - PC - Offs
1819         ** N - (PC + Offs) - Seg
1820         */
1821         Root = NewExprNode (EXPR_MINUS);
1822         Root->Left  = N;
1823         Root->Right = GenLiteralExpr (GetPC () + Offs);
1824         if (GetRelocMode ()) {
1825             N = Root;
1826             Root = NewExprNode (EXPR_MINUS);
1827             Root->Left  = N;
1828             Root->Right = GenSectionExpr (GetCurrentSegNum ());
1829         }
1830     }
1831
1832     /* Return the result */
1833     return Root;
1834 }
1835
1836
1837
1838 ExprNode* GenULabelExpr (unsigned Num)
1839 /* Return an expression for an unnamed label with the given index */
1840 {
1841     ExprNode* Node = NewExprNode (EXPR_ULABEL);
1842     Node->V.IVal        = Num;
1843
1844     /* Return the new node */
1845     return Node;
1846 }
1847
1848
1849
1850 ExprNode* GenByteExpr (ExprNode* Expr)
1851 /* Force the given expression into a byte and return the result */
1852 {
1853     /* Use the low byte operator to force the expression into byte size */
1854     return LoByte (Expr);
1855 }
1856
1857
1858
1859 ExprNode* GenWordExpr (ExprNode* Expr)
1860 /* Force the given expression into a word and return the result. */
1861 {
1862     /* Use the low byte operator to force the expression into word size */
1863     return LoWord (Expr);
1864 }
1865
1866
1867
1868 ExprNode* GenFarAddrExpr (ExprNode* Expr)
1869 /* Force the given expression into a far address and return the result. */
1870 {
1871     long      Val;
1872
1873     /* Special handling for const expressions */
1874     if (IsEasyConst (Expr, &Val)) {
1875         FreeExpr (Expr);
1876         Expr = GenLiteralExpr (Val & 0xFFFFFF);
1877     } else {
1878         ExprNode* Operand = Expr;
1879         Expr = NewExprNode (EXPR_FARADDR);
1880         Expr->Left = Operand;
1881     }
1882     return Expr;
1883 }
1884
1885
1886
1887 ExprNode* GenDWordExpr (ExprNode* Expr)
1888 /* Force the given expression into a dword and return the result. */
1889 {
1890     long      Val;
1891
1892     /* Special handling for const expressions */
1893     if (IsEasyConst (Expr, &Val)) {
1894         FreeExpr (Expr);
1895         Expr = GenLiteralExpr (Val & 0xFFFFFFFF);
1896     } else {
1897         ExprNode* Operand = Expr;
1898         Expr = NewExprNode (EXPR_DWORD);
1899         Expr->Left = Operand;
1900     }
1901     return Expr;
1902 }
1903
1904
1905
1906 ExprNode* GenNE (ExprNode* Expr, long Val)
1907 /* Generate an expression that compares Expr and Val for inequality */
1908 {
1909     /* Generate a compare node */
1910     ExprNode* Root = NewExprNode (EXPR_NE);
1911     Root->Left  = Expr;
1912     Root->Right = GenLiteralExpr (Val);
1913
1914     /* Return the result */
1915     return Root;
1916 }
1917
1918
1919
1920 int IsConstExpr (ExprNode* Expr, long* Val)
1921 /* Return true if the given expression is a constant expression, that is, one
1922 ** with no references to external symbols. If Val is not NULL and the
1923 ** expression is constant, the constant value is stored here.
1924 */
1925 {
1926     int IsConst;
1927
1928     /* Study the expression */
1929     ExprDesc D;
1930     ED_Init (&D);
1931     StudyExpr (Expr, &D);
1932
1933     /* Check if the expression is constant */
1934     IsConst = ED_IsConst (&D);
1935     if (IsConst && Val != 0) {
1936         *Val = D.Val;
1937     }
1938
1939     /* Delete allocated memory and return the result */
1940     ED_Done (&D);
1941     return IsConst;
1942 }
1943
1944
1945
1946 ExprNode* CloneExpr (ExprNode* Expr)
1947 /* Clone the given expression tree. The function will simply clone symbol
1948 ** nodes, it will not resolve them.
1949 */
1950 {
1951     ExprNode* Clone;
1952
1953     /* Accept NULL pointers */
1954     if (Expr == 0) {
1955         return 0;
1956     }
1957
1958     /* Clone the node */
1959     switch (Expr->Op) {
1960
1961         case EXPR_LITERAL:
1962             Clone = GenLiteralExpr (Expr->V.IVal);
1963             break;
1964
1965         case EXPR_ULABEL:
1966             Clone = GenULabelExpr (Expr->V.IVal);
1967             break;
1968
1969         case EXPR_SYMBOL:
1970             Clone = GenSymExpr (Expr->V.Sym);
1971             break;
1972
1973         case EXPR_SECTION:
1974             Clone = GenSectionExpr (Expr->V.SecNum);
1975             break;
1976
1977         case EXPR_BANK:
1978             Clone = GenBankExpr (Expr->V.SecNum);
1979             break;
1980
1981         default:
1982             /* Generate a new node */
1983             Clone = NewExprNode (Expr->Op);
1984             /* Clone the tree nodes */
1985             Clone->Left = CloneExpr (Expr->Left);
1986             Clone->Right = CloneExpr (Expr->Right);
1987             break;
1988     }
1989
1990     /* Done */
1991     return Clone;
1992 }
1993
1994
1995
1996 void WriteExpr (ExprNode* Expr)
1997 /* Write the given expression to the object file */
1998 {
1999     /* Null expressions are encoded by a type byte of zero */
2000     if (Expr == 0) {
2001         ObjWrite8 (EXPR_NULL);
2002         return;
2003     }
2004
2005     /* If the is a leafnode, write the expression attribute, otherwise
2006     ** write the expression operands.
2007     */
2008     switch (Expr->Op) {
2009
2010         case EXPR_LITERAL:
2011             ObjWrite8 (EXPR_LITERAL);
2012             ObjWrite32 (Expr->V.IVal);
2013             break;
2014
2015         case EXPR_SYMBOL:
2016             if (SymIsImport (Expr->V.Sym)) {
2017                 ObjWrite8 (EXPR_SYMBOL);
2018                 ObjWriteVar (GetSymImportId (Expr->V.Sym));
2019             } else {
2020                 WriteExpr (GetSymExpr (Expr->V.Sym));
2021             }
2022             break;
2023
2024         case EXPR_SECTION:
2025             ObjWrite8 (EXPR_SECTION);
2026             ObjWriteVar (Expr->V.SecNum);
2027             break;
2028
2029         case EXPR_ULABEL:
2030             WriteExpr (ULabResolve (Expr->V.IVal));
2031             break;
2032
2033         default:
2034             /* Not a leaf node */
2035             ObjWrite8 (Expr->Op);
2036             WriteExpr (Expr->Left);
2037             WriteExpr (Expr->Right);
2038             break;
2039
2040     }
2041 }
2042
2043
2044
2045 void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
2046 /* Mark the address size of the given expression tree as guessed. The address
2047 ** size passed as argument is the one NOT used, because the actual address
2048 ** size wasn't known. Example: Zero page addressing was not used because symbol
2049 ** is undefined, and absolute addressing was available.
2050 ** This function will actually parse the expression tree for undefined symbols,
2051 ** and mark these symbols accordingly.
2052 */
2053 {
2054     /* Accept NULL expressions */
2055     if (Expr == 0) {
2056         return;
2057     }
2058
2059     /* Check the type code */
2060     switch (EXPR_NODETYPE (Expr->Op)) {
2061
2062         case EXPR_LEAFNODE:
2063             if (Expr->Op == EXPR_SYMBOL) {
2064                 if (!SymIsDef (Expr->V.Sym)) {
2065                     /* Symbol is undefined, mark it */
2066                     SymGuessedAddrSize (Expr->V.Sym, AddrSize);
2067                 }
2068             }
2069             return;
2070
2071         case EXPR_BINARYNODE:
2072             ExprGuessedAddrSize (Expr->Right, AddrSize);
2073             /* FALLTHROUGH */
2074
2075         case EXPR_UNARYNODE:
2076             ExprGuessedAddrSize (Expr->Left, AddrSize);
2077             break;
2078     }
2079 }
2080
2081
2082
2083 ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size)
2084 /* Force the given expression into a specific size of ForceRange is true */
2085 {
2086     if (ForceRange) {
2087         switch (Size) {
2088             case 1:     Expr = GenByteExpr (Expr);      break;
2089             case 2:     Expr = GenWordExpr (Expr);      break;
2090             case 3:     Expr = GenFarAddrExpr (Expr);   break;
2091             case 4:     Expr = GenDWordExpr (Expr);     break;
2092             default:    Internal ("Invalid size in BoundedExpr: %u", Size);
2093         }
2094     }
2095     return Expr;
2096 }
2097
2098
2099
2100 ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
2101 /* Parse an expression and force it within a given size if ForceRange is true */
2102 {
2103     return MakeBoundedExpr (ExprFunc (), Size);
2104 }