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