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