]> git.sur5r.net Git - cc65/blobdiff - src/ca65/expr.c
Improved on funciton .ADDRSIZE. Conform to coding style.
[cc65] / src / ca65 / expr.c
index bb2aac50a09ef995ee9607c96fb8df31e1234dab..8fdc37421eb965a562779d258fe9268ede08a189 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                 expr.c                                   */
+/*                                  expr.c                                   */
 /*                                                                           */
-/*            Expression evaluation for the ca65 macroassembler             */
+/*             Expression evaluation for the ca65 macroassembler             */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2008 Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -42,6 +42,7 @@
 #include "exprdefs.h"
 #include "print.h"
 #include "shift.h"
+#include "segdefs.h"
 #include "strbuf.h"
 #include "tgttrans.h"
 #include "version.h"
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
 /* Since all expressions are first packed into expression trees, and each
- * expression tree node is allocated on the heap, we add some type of special
- * purpose memory allocation here: Instead of freeing the nodes, we save some
- * number of freed nodes for later and remember them in a single linked list
- * using the Left link.
- */
-#define        MAX_FREE_NODES  64
-static ExprNode*       FreeExprNodes = 0;
-static unsigned                FreeNodeCount = 0;
+** expression tree node is allocated on the heap, we add some type of special
+** purpose memory allocation here: Instead of freeing the nodes, we save some
+** number of freed nodes for later and remember them in a single linked list
+** using the Left link.
+*/
+#define MAX_FREE_NODES  64
+static ExprNode*        FreeExprNodes = 0;
+static unsigned         FreeNodeCount = 0;
 
 
 
 /*****************************************************************************/
-/*                                 Helpers                                  */
+/*                                  Helpers                                  */
 /*****************************************************************************/
 
 
@@ -94,12 +95,13 @@ static ExprNode* NewExprNode (unsigned Op)
     ExprNode* N;
 
     /* Do we have some nodes in the list already? */
-    if (FreeExprNodes) {
-       /* Use first node from list */
-       N = FreeExprNodes;
-       FreeExprNodes = N->Left;
+    if (FreeNodeCount) {
+        /* Use first node from list */
+        N = FreeExprNodes;
+        FreeExprNodes = N->Left;
+        --FreeNodeCount;
     } else {
-       /* Allocate fresh memory */
+        /* Allocate fresh memory */
         N = xmalloc (sizeof (ExprNode));
     }
     N->Op = Op;
@@ -120,21 +122,22 @@ static void FreeExprNode (ExprNode* E)
             SymDelExprRef (E->V.Sym, E);
         }
         /* Place the symbol into the free nodes list if possible */
-       if (FreeNodeCount < MAX_FREE_NODES) {
-           /* Remember this node for later */
-           E->Left = FreeExprNodes;
-           FreeExprNodes = E;
-       } else {
-           /* Free the memory */
-           xfree (E);
-       }
+        if (FreeNodeCount < MAX_FREE_NODES) {
+            /* Remember this node for later */
+            E->Left = FreeExprNodes;
+            FreeExprNodes = E;
+            ++FreeNodeCount;
+        } else {
+            /* Free the memory */
+            xfree (E);
+        }
     }
 }
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -167,11 +170,11 @@ int IsFarRange (long Val)
 
 
 
-static int IsEasyConst (const ExprNode* E, long* Val)
+int IsEasyConst (const ExprNode* E, long* Val)
 /* Do some light checking if the given node is a constant. Don't care if E is
- * a complex expression. If E is a constant, return true and place its value
- * into Val, provided that Val is not NULL.
- */
+** a complex expression. If E is a constant, return true and place its value
+** into Val, provided that Val is not NULL.
+*/
 {
     /* Resolve symbols, follow symbol chains */
     while (E->Op == EXPR_SYMBOL) {
@@ -236,6 +239,19 @@ static ExprNode* HiByte (ExprNode* Operand)
 
 
 
+static ExprNode* Bank (ExprNode* Operand)
+/* Return the bank of the given segmented expression */
+{
+    /* Generate the bank expression */
+    ExprNode* Expr = NewExprNode (EXPR_BANK);
+    Expr->Left = Operand;
+
+    /* Return the result */
+    return Expr;
+}
+
+
+
 static ExprNode* BankByte (ExprNode* Operand)
 /* Return the bank byte of the given expression */
 {
@@ -306,8 +322,8 @@ static ExprNode* Symbol (SymEntry* S)
         /* Mark the symbol as referenced */
         SymRef (S);
         /* If the symbol is a variable, return just its value, otherwise
-         * return a reference to the symbol.
-         */
+        ** return a reference to the symbol.
+        */
         if (SymIsVar (S)) {
             return CloneExpr (GetSymExpr (S));
         } else {
@@ -319,6 +335,14 @@ static ExprNode* Symbol (SymEntry* S)
 
 
 
+ExprNode* FuncBank (void)
+/* Handle the .BANK builtin function */
+{
+    return Bank (Expression ());
+}
+
+
+
 ExprNode* FuncBankByte (void)
 /* Handle the .BANKBYTE builtin function */
 {
@@ -331,29 +355,29 @@ static ExprNode* FuncBlank (void)
 /* Handle the .BLANK builtin function */
 {
     /* We have a list of tokens that ends with the closing paren. Skip
-     * the tokens, and count them. Allow optionally curly braces.
-     */
-    Token Term = GetTokListTerm (TOK_RPAREN);
+    ** the tokens, and count them. Allow optionally curly braces.
+    */
+    token_t Term = GetTokListTerm (TOK_RPAREN);
     unsigned Count = 0;
-    while (Tok != Term) {
+    while (CurTok.Tok != Term) {
 
-       /* Check for end of line or end of input. Since the calling function
-        * will check for the closing paren, we don't need to print an error
-        * here, just bail out.
-        */
-       if (TokIsSep (Tok)) {
-           break;
-       }
+        /* Check for end of line or end of input. Since the calling function
+        ** will check for the closing paren, we don't need to print an error
+        ** here, just bail out.
+        */
+        if (TokIsSep (CurTok.Tok)) {
+            break;
+        }
 
-       /* One more token */
-       ++Count;
+        /* One more token */
+        ++Count;
 
-       /* Skip the token */
-       NextTok ();
+        /* Skip the token */
+        NextTok ();
     }
 
     /* If the list was enclosed in curly braces, skip the closing brace */
-    if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+    if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
         NextTok ();
     }
 
@@ -385,7 +409,7 @@ static ExprNode* FuncDefined (void)
 /* Handle the .DEFINED builtin function */
 {
     /* Parse the symbol name and search for the symbol */
-    SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
 
     /* Check if the symbol is defined */
     return GenLiteralExpr (Sym != 0 && SymIsDef (Sym));
@@ -434,31 +458,31 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
     TokNode* Node;
 
     /* A list of tokens follows. Read this list and remember it building a
-     * single linked list of tokens including attributes. The list is
-     * either enclosed in curly braces, or terminated by a comma.
-     */
-    Token Term = GetTokListTerm (TOK_COMMA);
-    while (Tok != Term) {
-
-       /* We may not end-of-line of end-of-file here */
-       if (TokIsSep (Tok)) {
-           Error ("Unexpected end of line");
-           return GenLiteral0 ();
-       }
-
-       /* Get a node with this token */
-       Node = NewTokNode ();
-
-       /* Insert the node into the list */
-       if (Last == 0) {
-                   Root = Node;
-       } else {
-           Last->Next = Node;
-       }
-       Last = Node;
-
-       /* Skip the token */
-       NextTok ();
+    ** single linked list of tokens including attributes. The list is
+    ** either enclosed in curly braces, or terminated by a comma.
+    */
+    token_t Term = GetTokListTerm (TOK_COMMA);
+    while (CurTok.Tok != Term) {
+
+        /* We may not end-of-line of end-of-file here */
+        if (TokIsSep (CurTok.Tok)) {
+            Error ("Unexpected end of line");
+            return GenLiteral0 ();
+        }
+
+        /* Get a node with this token */
+        Node = NewTokNode ();
+
+        /* Insert the node into the list */
+        if (Last == 0) {
+            Root = Node;
+        } else {
+            Last->Next = Node;
+        }
+        Last = Node;
+
+        /* Skip the token */
+        NextTok ();
     }
 
     /* Skip the terminator token*/
@@ -470,38 +494,38 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
     }
 
     /* Read the second list which is optionally enclosed in curly braces and
-     * terminated by the right parenthesis. Compare each token against the
-     * one in the first list.
-     */
+    ** terminated by the right parenthesis. Compare each token against the
+    ** one in the first list.
+    */
     Term = GetTokListTerm (TOK_RPAREN);
     Result = 1;
     Node = Root;
-    while (Tok != Term) {
-
-       /* We may not end-of-line of end-of-file here */
-       if (TokIsSep (Tok)) {
-           Error ("Unexpected end of line");
-           return GenLiteral0 ();
-       }
-
-               /* Compare the tokens if the result is not already known */
-       if (Result != 0) {
-           if (Node == 0) {
-               /* The second list is larger than the first one */
-               Result = 0;
-           } else if (TokCmp (Node) < EqualityLevel) {
-               /* Tokens do not match */
-               Result = 0;
-           }
-       }
-
-       /* Next token in first list */
-       if (Node) {
-           Node = Node->Next;
-       }
-
-               /* Next token in current list */
-       NextTok ();
+    while (CurTok.Tok != Term) {
+
+        /* We may not end-of-line of end-of-file here */
+        if (TokIsSep (CurTok.Tok)) {
+            Error ("Unexpected end of line");
+            return GenLiteral0 ();
+        }
+
+        /* Compare the tokens if the result is not already known */
+        if (Result != 0) {
+            if (Node == 0) {
+                /* The second list is larger than the first one */
+                Result = 0;
+            } else if (TokCmp (Node) < EqualityLevel) {
+                /* Tokens do not match */
+                Result = 0;
+            }
+        }
+
+        /* Next token in first list */
+        if (Node) {
+            Node = Node->Next;
+        }
+
+        /* Next token in current list */
+        NextTok ();
     }
 
     /* If the token list was enclosed in curly braces, eat the closing brace */
@@ -511,14 +535,14 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
 
     /* Check if there are remaining tokens in the first list */
     if (Node != 0) {
-       Result = 0;
+        Result = 0;
     }
 
     /* Free the token list */
     while (Root) {
-       Node = Root;
-       Root = Root->Next;
-       FreeTokNode (Node);
+        Node = Root;
+        Root = Root->Next;
+        FreeTokNode (Node);
     }
 
     /* Done, return the result */
@@ -535,11 +559,69 @@ static ExprNode* FuncMatch (void)
 
 
 
+static ExprNode* FuncMax (void)
+/* Handle the .MAX function */
+{
+    ExprNode* Left;
+    ExprNode* Right;
+    ExprNode* Expr;
+    long LeftVal, RightVal;
+
+    /* Two arguments to the pseudo function */
+    Left = Expression ();
+    ConsumeComma ();
+    Right = Expression ();
+
+    /* Check if we can evaluate the value immediately */
+    if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
+        FreeExpr (Left);
+        FreeExpr (Right);
+        Expr = GenLiteralExpr ((LeftVal > RightVal)? LeftVal : RightVal);
+    } else {
+        /* Make an expression node */
+        Expr = NewExprNode (EXPR_MAX);
+        Expr->Left = Left;
+        Expr->Right = Right;
+    }
+    return Expr;
+}
+
+
+
+static ExprNode* FuncMin (void)
+/* Handle the .MIN function */
+{
+    ExprNode* Left;
+    ExprNode* Right;
+    ExprNode* Expr;
+    long LeftVal, RightVal;
+
+    /* Two arguments to the pseudo function */
+    Left = Expression ();
+    ConsumeComma ();
+    Right = Expression ();
+
+    /* Check if we can evaluate the value immediately */
+    if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) {
+        FreeExpr (Left);
+        FreeExpr (Right);
+        Expr = GenLiteralExpr ((LeftVal < RightVal)? LeftVal : RightVal);
+    } else {
+        /* Make an expression node */
+        Expr = NewExprNode (EXPR_MIN);
+        Expr->Left = Left;
+        Expr->Right = Right;
+    }
+    return Expr;
+}
+
+
+
 static ExprNode* FuncReferenced (void)
 /* Handle the .REFERENCED builtin function */
 {
     /* Parse the symbol name and search for the symbol */
-    SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
+    SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING);
 
     /* Check if the symbol is referenced */
     return GenLiteralExpr (Sym != 0 && SymIsRef (Sym));
@@ -547,6 +629,87 @@ static ExprNode* FuncReferenced (void)
 
 
 
+static ExprNode* FuncAddrSize (void)
+/* Handle the .ADDRSIZE function */
+{
+    StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
+    StrBuf    Name = STATIC_STRBUF_INITIALIZER;
+    SymEntry* Sym;
+    int       AddrSize;
+    int       NoScope;
+
+
+    /* Assume we don't know the size */
+    AddrSize = 0;
+
+    /* Check for a cheap local which needs special handling */
+    if (CurTok.Tok == TOK_LOCAL_IDENT) {
+
+        /* Cheap local symbol */
+        Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
+        if (Sym == 0) {
+            Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
+        } else {
+            AddrSize = Sym->AddrSize;
+        }
+
+        /* Remember and skip SVal, terminate ScopeName so it is empty */
+        SB_Copy (&Name, &CurTok.SVal);
+        NextTok ();
+        SB_Terminate (&ScopeName);
+
+    } else {
+
+        /* Parse the scope and the name */
+        SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
+
+        /* Check if the parent scope is valid */
+        if (ParentScope == 0) {
+            /* No such scope */
+            SB_Done (&ScopeName);
+            SB_Done (&Name);
+            return GenLiteral0 ();
+        }
+
+        /* If ScopeName is empty, no explicit scope was specified. We have to
+        ** search upper scope levels in this case.
+        */
+        NoScope = SB_IsEmpty (&ScopeName);
+
+        /* If we did find a scope with the name, read the symbol defining the
+        ** size, otherwise search for a symbol entry with the name and scope.
+        */
+        if (NoScope) {
+            Sym = SymFindAny (ParentScope, &Name);
+        } else {
+            Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
+        }
+        /* If we found the symbol retrieve the size, otherwise complain */
+        if (Sym) {
+            AddrSize = Sym->AddrSize;
+        } else {
+            Error ("Unknown symbol or scope: `%m%p%m%p'",
+                &ScopeName, &Name);
+        }
+
+    }
+
+    if (AddrSize == 0) {
+        Warning(1, "Unknown address size: `%m%p%m%p'",
+            &ScopeName, &Name);
+    }
+
+    /* Free the string buffers */
+    SB_Done (&ScopeName);
+    SB_Done (&Name);
+
+    /* Return the size. */
+
+    return GenLiteralExpr (AddrSize);
+}
+
+
+
 static ExprNode* FuncSizeOf (void)
 /* Handle the .SIZEOF function */
 {
@@ -563,18 +726,18 @@ static ExprNode* FuncSizeOf (void)
     SizeSym = 0;
 
     /* Check for a cheap local which needs special handling */
-    if (Tok == TOK_LOCAL_IDENT) {
+    if (CurTok.Tok == TOK_LOCAL_IDENT) {
 
         /* Cheap local symbol */
-        Sym = SymFindLocal (SymLast, &SVal, SYM_FIND_EXISTING);
+        Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
         if (Sym == 0) {
-            Error ("Unknown symbol or scope: `%m%p'", &SVal);
+            Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
         } else {
             SizeSym = GetSizeOfSymbol (Sym);
         }
 
         /* Remember and skip SVal, terminate ScopeName so it is empty */
-        SB_Copy (&Name, &SVal);
+        SB_Copy (&Name, &CurTok.SVal);
         NextTok ();
         SB_Terminate (&ScopeName);
 
@@ -592,8 +755,8 @@ static ExprNode* FuncSizeOf (void)
         }
 
         /* If ScopeName is empty, no explicit scope was specified. We have to
-         * search upper scope levels in this case.
-         */
+        ** search upper scope levels in this case.
+        */
         NoScope = SB_IsEmpty (&ScopeName);
 
         /* First search for a scope with the given name */
@@ -604,8 +767,8 @@ static ExprNode* FuncSizeOf (void)
         }
 
         /* If we did find a scope with the name, read the symbol defining the
-         * size, otherwise search for a symbol entry with the name and scope.
-         */
+        ** size, otherwise search for a symbol entry with the name and scope.
+        */
         if (Scope) {
             /* Yep, it's a scope */
             SizeSym = GetSizeOfScope (Scope);
@@ -650,14 +813,14 @@ static ExprNode* FuncStrAt (void)
     unsigned char C = 0;
 
     /* String constant expected */
-    if (Tok != TOK_STRCON) {
-       Error ("String constant expected");
-       NextTok ();
-               goto ExitPoint;
+    if (CurTok.Tok != TOK_STRCON) {
+        Error ("String constant expected");
+        NextTok ();
+        goto ExitPoint;
     }
 
     /* Remember the string and skip it */
-    SB_Copy (&Str, &SVal);
+    SB_Copy (&Str, &CurTok.SVal);
     NextTok ();
 
     /* Comma must follow */
@@ -668,13 +831,13 @@ static ExprNode* FuncStrAt (void)
 
     /* Must be a valid index */
     if (Index >= (long) SB_GetLen (&Str)) {
-       Error ("Range error");
+        Error ("Range error");
         goto ExitPoint;
     }
 
     /* Get the char, handle as unsigned. Be sure to translate it into
-     * the target character set.
-     */
+    ** the target character set.
+    */
     C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
 
 ExitPoint:
@@ -693,22 +856,22 @@ static ExprNode* FuncStrLen (void)
     int Len;
 
     /* String constant expected */
-    if (Tok != TOK_STRCON) {
+    if (CurTok.Tok != TOK_STRCON) {
 
-       Error ("String constant expected");
-       /* Smart error recovery */
-       if (Tok != TOK_RPAREN) {
-           NextTok ();
-       }
-               Len = 0;
+        Error ("String constant expected");
+        /* Smart error recovery */
+        if (CurTok.Tok != TOK_RPAREN) {
+            NextTok ();
+        }
+        Len = 0;
 
     } else {
 
         /* Get the length of the string */
-               Len = SB_GetLen (&SVal);
+        Len = SB_GetLen (&CurTok.SVal);
 
-       /* Skip the string */
-       NextTok ();
+        /* Skip the string */
+        NextTok ();
     }
 
     /* Return the length */
@@ -721,29 +884,29 @@ static ExprNode* FuncTCount (void)
 /* Handle the .TCOUNT function */
 {
     /* We have a list of tokens that ends with the closing paren. Skip
-     * the tokens, and count them. Allow optionally curly braces.
-     */
-    Token Term = GetTokListTerm (TOK_RPAREN);
+    ** the tokens, and count them. Allow optionally curly braces.
+    */
+    token_t Term = GetTokListTerm (TOK_RPAREN);
     int Count = 0;
-    while (Tok != Term) {
+    while (CurTok.Tok != Term) {
 
-       /* Check for end of line or end of input. Since the calling function
-        * will check for the closing paren, we don't need to print an error
-        * here, just bail out.
-        */
-       if (TokIsSep (Tok)) {
-           break;
-       }
+        /* Check for end of line or end of input. Since the calling function
+        ** will check for the closing paren, we don't need to print an error
+        ** here, just bail out.
+        */
+        if (TokIsSep (CurTok.Tok)) {
+            break;
+        }
 
-       /* One more token */
-       ++Count;
+        /* One more token */
+        ++Count;
 
-       /* Skip the token */
-       NextTok ();
+        /* Skip the token */
+        NextTok ();
     }
 
     /* If the list was enclosed in curly braces, skip the closing brace */
-    if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+    if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) {
         NextTok ();
     }
 
@@ -770,10 +933,10 @@ static ExprNode* Function (ExprNode* (*F) (void))
     NextTok ();
 
     /* Expression must be enclosed in braces */
-    if (Tok != TOK_LPAREN) {
-       Error ("'(' expected");
-       SkipUntilSep ();
-       return GenLiteral0 ();
+    if (CurTok.Tok != TOK_LPAREN) {
+        Error ("'(' expected");
+        SkipUntilSep ();
+        return GenLiteral0 ();
     }
     NextTok ();
 
@@ -795,52 +958,48 @@ static ExprNode* Factor (void)
     ExprNode* N;
     long      Val;
 
-    switch (Tok) {
+    switch (CurTok.Tok) {
 
-       case TOK_INTCON:
-           N = GenLiteralExpr (IVal);
-                   NextTok ();
-           break;
-
-       case TOK_CHARCON:
-           N = GenLiteralExpr (TgtTranslateChar (IVal));
-                   NextTok ();
-           break;
+        case TOK_INTCON:
+            N = GenLiteralExpr (CurTok.IVal);
+            NextTok ();
+            break;
 
-       case TOK_NAMESPACE:
-       case TOK_IDENT:
-            N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
-           break;
+        case TOK_CHARCON:
+            N = GenLiteralExpr (TgtTranslateChar (CurTok.IVal));
+            NextTok ();
+            break;
 
+        case TOK_NAMESPACE:
+        case TOK_IDENT:
         case TOK_LOCAL_IDENT:
-            N = Symbol (SymFindLocal (SymLast, &SVal, SYM_ALLOC_NEW));
-            NextTok ();
+            N = Symbol (ParseAnySymName (SYM_ALLOC_NEW));
             break;
 
-       case TOK_ULABEL:
-           N = ULabRef (IVal);
-           NextTok ();
-           break;
+        case TOK_ULABEL:
+            N = ULabRef (CurTok.IVal);
+            NextTok ();
+            break;
 
         case TOK_PLUS:
             NextTok ();
             N = Factor ();
             break;
 
-       case TOK_MINUS:
-           NextTok ();
+        case TOK_MINUS:
+            NextTok ();
             L = Factor ();
             if (IsEasyConst (L, &Val)) {
                 FreeExpr (L);
                 N = GenLiteralExpr (-Val);
             } else {
                 N = NewExprNode (EXPR_UNARY_MINUS);
-                       N->Left = L;
+                N->Left = L;
             }
-           break;
+            break;
 
-       case TOK_NOT:
-           NextTok ();
+        case TOK_NOT:
+            NextTok ();
             L = Factor ();
             if (IsEasyConst (L, &Val)) {
                 FreeExpr (L);
@@ -849,55 +1008,64 @@ static ExprNode* Factor (void)
                 N = NewExprNode (EXPR_NOT);
                 N->Left = L;
             }
-           break;
+            break;
 
-       case TOK_STAR:
-       case TOK_PC:
-           NextTok ();
-                   N = GenCurrentPC ();
-           break;
+        case TOK_STAR:
+        case TOK_PC:
+            NextTok ();
+            N = GenCurrentPC ();
+            break;
 
-       case TOK_LT:
-           NextTok ();
+        case TOK_LT:
+            NextTok ();
             N = LoByte (Factor ());
-           break;
+            break;
 
-       case TOK_GT:
-           NextTok ();
+        case TOK_GT:
+            NextTok ();
             N = HiByte (Factor ());
-           break;
+            break;
 
-        case TOK_BANK:
+        case TOK_XOR:
+            /* ^ means the bank byte of an expression */
             NextTok ();
             N = BankByte (Factor ());
             break;
 
-       case TOK_LPAREN:
-           NextTok ();
-           N = Expr0 ();
-                   ConsumeRParen ();
-           break;
+        case TOK_LPAREN:
+            NextTok ();
+            N = Expr0 ();
+            ConsumeRParen ();
+            break;
+
+        case TOK_BANK:
+            N = Function (FuncBank);
+            break;
 
         case TOK_BANKBYTE:
             N = Function (FuncBankByte);
             break;
 
+        case TOK_ADDRSIZE:
+            N = Function (FuncAddrSize);
+            break;
+
         case TOK_BLANK:
-           N = Function (FuncBlank);
-           break;
+            N = Function (FuncBlank);
+            break;
 
-       case TOK_CONST:
-           N = Function (FuncConst);
-           break;
+        case TOK_CONST:
+            N = Function (FuncConst);
+            break;
 
-       case TOK_CPU:
-           N = GenLiteralExpr (CPUIsets[CPU]);
-           NextTok ();
-           break;
+        case TOK_CPU:
+            N = GenLiteralExpr (CPUIsets[CPU]);
+            NextTok ();
+            break;
 
         case TOK_DEFINED:
-           N = Function (FuncDefined);
-           break;
+            N = Function (FuncDefined);
+            break;
 
         case TOK_HIBYTE:
             N = Function (FuncHiByte);
@@ -915,54 +1083,63 @@ static ExprNode* Factor (void)
             N = Function (FuncLoWord);
             break;
 
-       case TOK_MATCH:
-           N = Function (FuncMatch);
-           break;
+        case TOK_MATCH:
+            N = Function (FuncMatch);
+            break;
+
+        case TOK_MAX:
+            N = Function (FuncMax);
+            break;
+
+        case TOK_MIN:
+            N = Function (FuncMin);
+            break;
 
         case TOK_REFERENCED:
-           N = Function (FuncReferenced);
-           break;
+            N = Function (FuncReferenced);
+            break;
 
         case TOK_SIZEOF:
             N = Function (FuncSizeOf);
             break;
 
-       case TOK_STRAT:
-           N = Function (FuncStrAt);
-           break;
+        case TOK_STRAT:
+            N = Function (FuncStrAt);
+            break;
 
-       case TOK_STRLEN:
-           N = Function (FuncStrLen);
-           break;
+        case TOK_STRLEN:
+            N = Function (FuncStrLen);
+            break;
 
-       case TOK_TCOUNT:
-           N = Function (FuncTCount);
-           break;
+        case TOK_TCOUNT:
+            N = Function (FuncTCount);
+            break;
 
-       case TOK_TIME:
-           N = GenLiteralExpr (time (0));
-           NextTok ();
-           break;
+        case TOK_TIME:
+            N = GenLiteralExpr ((long) time (0));
+            NextTok ();
+            break;
 
         case TOK_VERSION:
-            N = GenLiteralExpr (VERSION);
+            N = GenLiteralExpr (GetVersionAsNumber ());
             NextTok ();
             break;
 
-       case TOK_XMATCH:
-           N = Function (FuncXMatch);
-           break;
-
-       default:
-           if (LooseCharTerm && Tok == TOK_STRCON && SB_GetLen (&SVal) == 1) {
-               /* A character constant */
-               N = GenLiteralExpr (TgtTranslateChar (SB_At (&SVal, 0)));
-           } else {
-               N = GenLiteral0 ();     /* Dummy */
-               Error ("Syntax error");
-           }
-           NextTok ();
-           break;
+        case TOK_XMATCH:
+            N = Function (FuncXMatch);
+            break;
+
+        default:
+            if (LooseCharTerm && CurTok.Tok == TOK_STRCON &&
+                SB_GetLen (&CurTok.SVal) == 1) {
+                /* A character constant */
+                N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0)));
+            } else {
+                N = GenLiteral0 ();     /* Dummy */
+                Error ("Syntax error");
+            }
+            NextTok ();
+            break;
     }
     return N;
 }
@@ -975,16 +1152,17 @@ static ExprNode* Term (void)
     ExprNode* Root = Factor ();
 
     /* Handle multiplicative operations */
-    while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
-          Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
-          Tok == TOK_SHR) {
+    while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV ||
+           CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND ||
+           CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL ||
+           CurTok.Tok == TOK_SHR) {
 
         long LVal, RVal, Val;
         ExprNode* Left;
         ExprNode* Right;
 
         /* Remember the token and skip it */
-        Token T = Tok;
+        token_t T = CurTok.Tok;
         NextTok ();
 
         /* Move root to left side and read the right side */
@@ -1038,8 +1216,8 @@ static ExprNode* Term (void)
             }
 
             /* Generate a literal expression and delete the old left and
-             * right sides.
-             */
+            ** right sides.
+            */
             FreeExpr (Left);
             FreeExpr (Right);
             Root = GenLiteralExpr (Val);
@@ -1049,14 +1227,14 @@ static ExprNode* Term (void)
             /* Generate an expression tree */
             unsigned char Op;
             switch (T) {
-                case TOK_MUL:   Op = EXPR_MUL; break;
+                case TOK_MUL:   Op = EXPR_MUL;  break;
                 case TOK_DIV:   Op = EXPR_DIV;  break;
                 case TOK_MOD:   Op = EXPR_MOD;  break;
                 case TOK_AND:   Op = EXPR_AND;  break;
                 case TOK_XOR:   Op = EXPR_XOR;  break;
                 case TOK_SHL:   Op = EXPR_SHL;  break;
                 case TOK_SHR:   Op = EXPR_SHR;  break;
-                default:               Internal ("Invalid token");
+                default:        Internal ("Invalid token");
             }
             Root        = NewExprNode (Op);
             Root->Left  = Left;
@@ -1078,14 +1256,16 @@ static ExprNode* SimpleExpr (void)
     ExprNode* Root = Term ();
 
     /* Handle additive operations */
-    while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
+    while (CurTok.Tok == TOK_PLUS  ||
+           CurTok.Tok == TOK_MINUS ||
+           CurTok.Tok == TOK_OR) {
 
         long LVal, RVal, Val;
         ExprNode* Left;
         ExprNode* Right;
 
         /* Remember the token and skip it */
-        Token T = Tok;
+        token_t T = CurTok.Tok;
         NextTok ();
 
         /* Move root to left side and read the right side */
@@ -1103,8 +1283,8 @@ static ExprNode* SimpleExpr (void)
             }
 
             /* Generate a literal expression and delete the old left and
-             * right sides.
-             */
+            ** right sides.
+            */
             FreeExpr (Left);
             FreeExpr (Right);
             Root = GenLiteralExpr (Val);
@@ -1117,7 +1297,7 @@ static ExprNode* SimpleExpr (void)
                 case TOK_PLUS:  Op = EXPR_PLUS;  break;
                 case TOK_MINUS: Op = EXPR_MINUS; break;
                 case TOK_OR:    Op = EXPR_OR;    break;
-                default:               Internal ("Invalid token");
+                default:        Internal ("Invalid token");
             }
             Root        = NewExprNode (Op);
             Root->Left  = Left;
@@ -1139,15 +1319,16 @@ static ExprNode* BoolExpr (void)
     ExprNode* Root = SimpleExpr ();
 
     /* Handle booleans */
-    while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
-          Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
+    while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE ||
+           CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT ||
+           CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) {
 
         long LVal, RVal, Val;
         ExprNode* Left;
         ExprNode* Right;
 
         /* Remember the token and skip it */
-        Token T = Tok;
+        token_t T = CurTok.Tok;
         NextTok ();
 
         /* Move root to left side and read the right side */
@@ -1168,8 +1349,8 @@ static ExprNode* BoolExpr (void)
             }
 
             /* Generate a literal expression and delete the old left and
-             * right sides.
-             */
+            ** right sides.
+            */
             FreeExpr (Left);
             FreeExpr (Right);
             Root = GenLiteralExpr (Val);
@@ -1185,7 +1366,7 @@ static ExprNode* BoolExpr (void)
                 case TOK_GT:    Op = EXPR_GT;   break;
                 case TOK_LE:    Op = EXPR_LE;   break;
                 case TOK_GE:    Op = EXPR_GE;   break;
-                default:               Internal ("Invalid token");
+                default:        Internal ("Invalid token");
             }
             Root        = NewExprNode (Op);
             Root->Left  = Left;
@@ -1207,14 +1388,14 @@ static ExprNode* Expr2 (void)
     ExprNode* Root = BoolExpr ();
 
     /* Handle booleans */
-    while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
+    while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) {
 
         long LVal, RVal, Val;
         ExprNode* Left;
         ExprNode* Right;
 
         /* Remember the token and skip it */
-        Token T = Tok;
+        token_t T = CurTok.Tok;
         NextTok ();
 
         /* Move root to left side and read the right side */
@@ -1231,8 +1412,8 @@ static ExprNode* Expr2 (void)
             }
 
             /* Generate a literal expression and delete the old left and
-             * right sides.
-             */
+            ** right sides.
+            */
             FreeExpr (Left);
             FreeExpr (Right);
             Root = GenLiteralExpr (Val);
@@ -1244,7 +1425,7 @@ static ExprNode* Expr2 (void)
             switch (T) {
                 case TOK_BOOLAND:   Op = EXPR_BOOLAND; break;
                 case TOK_BOOLXOR:   Op = EXPR_BOOLXOR; break;
-                default:                   Internal ("Invalid token");
+                default:            Internal ("Invalid token");
             }
             Root        = NewExprNode (Op);
             Root->Left  = Left;
@@ -1266,14 +1447,14 @@ static ExprNode* Expr1 (void)
     ExprNode* Root = Expr2 ();
 
     /* Handle booleans */
-    while (Tok == TOK_BOOLOR) {
+    while (CurTok.Tok == TOK_BOOLOR) {
 
         long LVal, RVal, Val;
         ExprNode* Left;
         ExprNode* Right;
 
         /* Remember the token and skip it */
-        Token T = Tok;
+        token_t T = CurTok.Tok;
         NextTok ();
 
         /* Move root to left side and read the right side */
@@ -1289,8 +1470,8 @@ static ExprNode* Expr1 (void)
             }
 
             /* Generate a literal expression and delete the old left and
-             * right sides.
-             */
+            ** right sides.
+            */
             FreeExpr (Left);
             FreeExpr (Right);
             Root = GenLiteralExpr (Val);
@@ -1301,7 +1482,7 @@ static ExprNode* Expr1 (void)
             unsigned char Op;
             switch (T) {
                 case TOK_BOOLOR:    Op = EXPR_BOOLOR;  break;
-                default:                   Internal ("Invalid token");
+                default:            Internal ("Invalid token");
             }
             Root        = NewExprNode (Op);
             Root->Left  = Left;
@@ -1322,13 +1503,13 @@ static ExprNode* Expr0 (void)
     ExprNode* Root;
 
     /* Handle booleans */
-    if (Tok == TOK_BOOLNOT) {
+    if (CurTok.Tok == TOK_BOOLNOT) {
 
         long Val;
         ExprNode* Left;
 
         /* Skip the operator token */
-       NextTok ();
+        NextTok ();
 
         /* Read the argument */
         Left = Expr0 ();
@@ -1344,8 +1525,8 @@ static ExprNode* Expr0 (void)
 
     } else {
 
-       /* Read left hand side */
-       Root = Expr1 ();
+        /* Read left hand side */
+        Root = Expr1 ();
 
     }
 
@@ -1357,8 +1538,8 @@ static ExprNode* Expr0 (void)
 
 ExprNode* Expression (void)
 /* Evaluate an expression, build the expression tree on the heap and return
- * a pointer to the root of the tree.
- */
+** a pointer to the root of the tree.
+*/
 {
     return Expr0 ();
 }
@@ -1367,9 +1548,9 @@ ExprNode* Expression (void)
 
 long ConstExpression (void)
 /* Parse an expression. Check if the expression is const, and print an error
- * message if not. Return the value of the expression, or a dummy, if it is
- * not constant.
- */
+** message if not. Return the value of the expression, or a dummy, if it is
+** not constant.
+*/
 {
     long Val;
 
@@ -1385,8 +1566,8 @@ long ConstExpression (void)
     if (ED_IsConst (&D)) {
         Val = D.Val;
     } else {
-       Error ("Constant expression expected");
-       Val = 0;
+        Error ("Constant expression expected");
+        Val = 0;
     }
 
     /* Free the expression tree and allocated memory for D */
@@ -1403,9 +1584,9 @@ void FreeExpr (ExprNode* Root)
 /* Free the expression, Root is pointing to. */
 {
     if (Root) {
-       FreeExpr (Root->Left);
-       FreeExpr (Root->Right);
-       FreeExprNode (Root);
+        FreeExpr (Root->Left);
+        FreeExpr (Root->Right);
+        FreeExprNode (Root);
     }
 }
 
@@ -1453,11 +1634,21 @@ ExprNode* GenSymExpr (SymEntry* Sym)
 
 
 
-static ExprNode* GenSectionExpr (unsigned SegNum)
+static ExprNode* GenSectionExpr (unsigned SecNum)
 /* Return an expression node for the given section */
 {
     ExprNode* Expr = NewExprNode (EXPR_SECTION);
-    Expr->V.SegNum = SegNum;
+    Expr->V.SecNum = SecNum;
+    return Expr;
+}
+
+
+
+static ExprNode* GenBankExpr (unsigned SecNum)
+/* Return an expression node for the given bank */
+{
+    ExprNode* Expr = NewExprNode (EXPR_BANK);
+    Expr->V.SecNum = SecNum;
     return Expr;
 }
 
@@ -1489,12 +1680,12 @@ ExprNode* GenCurrentPC (void)
     ExprNode* Root;
 
     if (GetRelocMode ()) {
-       /* Create SegmentBase + Offset */
-               Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
+        /* Create SegmentBase + Offset */
+        Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
                            GenLiteralExpr (GetPC ()));
     } else {
-       /* Absolute mode, just return PC value */
-       Root = GenLiteralExpr (GetPC ());
+        /* Absolute mode, just return PC value */
+        Root = GenLiteralExpr (GetPC ());
     }
 
     return Root;
@@ -1514,8 +1705,8 @@ ExprNode* GenSwapExpr (ExprNode* Expr)
 
 ExprNode* GenBranchExpr (unsigned Offs)
 /* Return an expression that encodes the difference between current PC plus
- * offset and the target expression (that is, Expression() - (*+Offs) ).
- */
+** offset and the target expression (that is, Expression() - (*+Offs) ).
+*/
 {
     ExprNode* N;
     ExprNode* Root;
@@ -1531,11 +1722,11 @@ ExprNode* GenBranchExpr (unsigned Offs)
         FreeExpr (N);
 
         /* Generate the final expression:
-         * Val - (* + Offs)
-         * Val - ((Seg + PC) + Offs)
-         * Val - Seg - PC - Offs
-         * (Val - PC - Offs) - Seg
-         */
+        ** Val - (* + Offs)
+        ** Val - ((Seg + PC) + Offs)
+        ** Val - Seg - PC - Offs
+        ** (Val - PC - Offs) - Seg
+        */
         Root = GenLiteralExpr (Val - GetPC () - Offs);
         if (GetRelocMode ()) {
             N = Root;
@@ -1547,11 +1738,11 @@ ExprNode* GenBranchExpr (unsigned Offs)
     } else {
 
         /* Generate the expression:
-         * N - (* + Offs)
-         * N - ((Seg + PC) + Offs)
-         * N - Seg - PC - Offs
-         * N - (PC + Offs) - Seg
-         */
+        ** N - (* + Offs)
+        ** N - ((Seg + PC) + Offs)
+        ** N - Seg - PC - Offs
+        ** N - (PC + Offs) - Seg
+        */
         Root = NewExprNode (EXPR_MINUS);
         Root->Left  = N;
         Root->Right = GenLiteralExpr (GetPC () + Offs);
@@ -1573,7 +1764,7 @@ ExprNode* GenULabelExpr (unsigned Num)
 /* Return an expression for an unnamed label with the given index */
 {
     ExprNode* Node = NewExprNode (EXPR_ULABEL);
-    Node->V.IVal       = Num;
+    Node->V.IVal        = Num;
 
     /* Return the new node */
     return Node;
@@ -1599,13 +1790,51 @@ ExprNode* GenWordExpr (ExprNode* Expr)
 
 
 
+ExprNode* GenFarAddrExpr (ExprNode* Expr)
+/* Force the given expression into a far address and return the result. */
+{
+    long      Val;
+
+    /* Special handling for const expressions */
+    if (IsEasyConst (Expr, &Val)) {
+        FreeExpr (Expr);
+        Expr = GenLiteralExpr (Val & 0xFFFFFF);
+    } else {
+        ExprNode* Operand = Expr;
+        Expr = NewExprNode (EXPR_FARADDR);
+        Expr->Left = Operand;
+    }
+    return Expr;
+}
+
+
+
+ExprNode* GenDWordExpr (ExprNode* Expr)
+/* Force the given expression into a dword and return the result. */
+{
+    long      Val;
+
+    /* Special handling for const expressions */
+    if (IsEasyConst (Expr, &Val)) {
+        FreeExpr (Expr);
+        Expr = GenLiteralExpr (Val & 0xFFFFFFFF);
+    } else {
+        ExprNode* Operand = Expr;
+        Expr = NewExprNode (EXPR_DWORD);
+        Expr->Left = Operand;
+    }
+    return Expr;
+}
+
+
+
 ExprNode* GenNE (ExprNode* Expr, long Val)
 /* Generate an expression that compares Expr and Val for inequality */
 {
     /* Generate a compare node */
     ExprNode* Root = NewExprNode (EXPR_NE);
     Root->Left  = Expr;
-    Root->Right        = GenLiteralExpr (Val);
+    Root->Right = GenLiteralExpr (Val);
 
     /* Return the result */
     return Root;
@@ -1615,9 +1844,9 @@ ExprNode* GenNE (ExprNode* Expr, long Val)
 
 int IsConstExpr (ExprNode* Expr, long* Val)
 /* Return true if the given expression is a constant expression, that is, one
- * with no references to external symbols. If Val is not NULL and the
- * expression is constant, the constant value is stored here.
- */
+** with no references to external symbols. If Val is not NULL and the
+** expression is constant, the constant value is stored here.
+*/
 {
     int IsConst;
 
@@ -1641,8 +1870,8 @@ int IsConstExpr (ExprNode* Expr, long* Val)
 
 ExprNode* CloneExpr (ExprNode* Expr)
 /* Clone the given expression tree. The function will simply clone symbol
- * nodes, it will not resolve them.
- */
+** nodes, it will not resolve them.
+*/
 {
     ExprNode* Clone;
 
@@ -1654,21 +1883,25 @@ ExprNode* CloneExpr (ExprNode* Expr)
     /* Clone the node */
     switch (Expr->Op) {
 
-       case EXPR_LITERAL:
+        case EXPR_LITERAL:
             Clone = GenLiteralExpr (Expr->V.IVal);
             break;
 
-       case EXPR_ULABEL:
-           Clone = GenULabelExpr (Expr->V.IVal);
-           break;
+        case EXPR_ULABEL:
+            Clone = GenULabelExpr (Expr->V.IVal);
+            break;
 
-       case EXPR_SYMBOL:
-           Clone = GenSymExpr (Expr->V.Sym);
-           break;
+        case EXPR_SYMBOL:
+            Clone = GenSymExpr (Expr->V.Sym);
+            break;
 
-       case EXPR_SECTION:
-           Clone = GenSectionExpr (Expr->V.SegNum);
-           break;
+        case EXPR_SECTION:
+            Clone = GenSectionExpr (Expr->V.SecNum);
+            break;
+
+        case EXPR_BANK:
+            Clone = GenBankExpr (Expr->V.SecNum);
+            break;
 
         default:
             /* Generate a new node */
@@ -1690,44 +1923,44 @@ void WriteExpr (ExprNode* Expr)
 {
     /* Null expressions are encoded by a type byte of zero */
     if (Expr == 0) {
-       ObjWrite8 (EXPR_NULL);
-       return;
+        ObjWrite8 (EXPR_NULL);
+        return;
     }
 
     /* If the is a leafnode, write the expression attribute, otherwise
-     * write the expression operands.
-     */
+    ** write the expression operands.
+    */
     switch (Expr->Op) {
 
         case EXPR_LITERAL:
             ObjWrite8 (EXPR_LITERAL);
-           ObjWrite32 (Expr->V.IVal);
-           break;
+            ObjWrite32 (Expr->V.IVal);
+            break;
 
         case EXPR_SYMBOL:
-           if (SymIsImport (Expr->V.Sym)) {
+            if (SymIsImport (Expr->V.Sym)) {
                 ObjWrite8 (EXPR_SYMBOL);
-                ObjWriteVar (GetSymIndex (Expr->V.Sym));
+                ObjWriteVar (GetSymImportId (Expr->V.Sym));
             } else {
                 WriteExpr (GetSymExpr (Expr->V.Sym));
             }
-           break;
+            break;
 
         case EXPR_SECTION:
             ObjWrite8 (EXPR_SECTION);
-           ObjWrite8 (Expr->V.SegNum);
-           break;
+            ObjWriteVar (Expr->V.SecNum);
+            break;
 
-       case EXPR_ULABEL:
+        case EXPR_ULABEL:
             WriteExpr (ULabResolve (Expr->V.IVal));
-           break;
+            break;
 
         default:
-           /* Not a leaf node */
+            /* Not a leaf node */
             ObjWrite8 (Expr->Op);
-           WriteExpr (Expr->Left);
-           WriteExpr (Expr->Right);
-           break;
+            WriteExpr (Expr->Left);
+            WriteExpr (Expr->Right);
+            break;
 
     }
 }
@@ -1736,12 +1969,12 @@ void WriteExpr (ExprNode* Expr)
 
 void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
 /* Mark the address size of the given expression tree as guessed. The address
- * size passed as argument is the one NOT used, because the actual address
- * size wasn't known. Example: Zero page addressing was not used because symbol
- * is undefined, and absolute addressing was available.
- * This function will actually parse the expression tree for undefined symbols,
- * and mark these symbols accordingly.
- */
+** size passed as argument is the one NOT used, because the actual address
+** size wasn't known. Example: Zero page addressing was not used because symbol
+** is undefined, and absolute addressing was available.
+** This function will actually parse the expression tree for undefined symbols,
+** and mark these symbols accordingly.
+*/
 {
     /* Accept NULL expressions */
     if (Expr == 0) {
@@ -1749,7 +1982,7 @@ void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
     }
 
     /* Check the type code */
-    switch (Expr->Op & EXPR_TYPEMASK) {
+    switch (EXPR_NODETYPE (Expr->Op)) {
 
         case EXPR_LEAFNODE:
             if (Expr->Op == EXPR_SYMBOL) {
@@ -1772,3 +2005,25 @@ void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
 
 
 
+ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size)
+/* Force the given expression into a specific size of ForceRange is true */
+{
+    if (ForceRange) {
+        switch (Size) {
+            case 1:     Expr = GenByteExpr (Expr);      break;
+            case 2:     Expr = GenWordExpr (Expr);      break;
+            case 3:     Expr = GenFarAddrExpr (Expr);   break;
+            case 4:     Expr = GenDWordExpr (Expr);     break;
+            default:    Internal ("Invalid size in BoundedExpr: %u", Size);
+        }
+    }
+    return Expr;
+}
+
+
+
+ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
+/* Parse an expression and force it within a given size if ForceRange is true */
+{
+    return MakeBoundedExpr (ExprFunc (), Size);
+}