]> git.sur5r.net Git - cc65/blobdiff - src/ca65/studyexpr.c
atari5200: name conio constructor 'initconio'
[cc65] / src / ca65 / studyexpr.c
index b21f3b28bbc375b43a2648b14ee987eb77096295..90d2d6e1826dc22277fac14a21b7344557c7bf29 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2003-2007 Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2003-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -37,7 +37,7 @@
 
 /* common */
 #include "check.h"
-#include "print.h"
+#include "debugflag.h"
 #include "shift.h"
 #include "xmalloc.h"
 
@@ -61,7 +61,7 @@ ExprDesc* ED_Init (ExprDesc* ED)
 {
     ED->Flags     = ED_OK;
     ED->AddrSize  = ADDR_SIZE_DEFAULT;
-    ED->Val      = 0;
+    ED->Val       = 0;
     ED->SymCount  = 0;
     ED->SymLimit  = 0;
     ED->SymRef    = 0;
@@ -106,11 +106,19 @@ int ED_IsConst (const ExprDesc* D)
 
 
 static int ED_IsValid (const ExprDesc* D)
-/* Return true if the expression is valid, that is, the TOO_COMPLEX flag is
- * not set
- */
+/* Return true if the expression is valid, that is, neither the ERROR nor the
+** TOO_COMPLEX flags are set.
+*/
 {
-    return ((D->Flags & ED_TOO_COMPLEX) == 0);
+    return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0);
+}
+
+
+
+static int ED_HasError (const ExprDesc* D)
+/* Return true if the expression has an error. */
+{
+    return ((D->Flags & ED_ERROR) != 0);
 }
 
 
@@ -123,6 +131,14 @@ static void ED_Invalidate (ExprDesc* D)
 
 
 
+static void ED_SetError (ExprDesc* D)
+/* Set the TOO_COMPLEX and ERROR flags for D */
+{
+    D->Flags |= (ED_ERROR | ED_TOO_COMPLEX);
+}
+
+
+
 static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
 /* Update the address size of the expression */
 {
@@ -148,22 +164,22 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
 {
     if (ED->AddrSize == ADDR_SIZE_DEFAULT) {
         /* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise
-         * it takes precedence over anything else.
-         */
+        ** it takes precedence over anything else.
+        */
         if (ED_IsValid (ED)) {
             ED->AddrSize = Right->AddrSize;
         }
     } else if (Right->AddrSize == ADDR_SIZE_DEFAULT) {
         /* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden,
-         * otherwise it takes precedence over anything else.
-         */
+        ** otherwise it takes precedence over anything else.
+        */
         if (!ED_IsValid (Right)) {
             ED->AddrSize = Right->AddrSize;
         }
     } else {
         /* Neither ED nor Right has a default address size, use the larger of
-         * the two.
-         */
+        ** the two.
+        */
         if (Right->AddrSize > ED->AddrSize) {
             ED->AddrSize = Right->AddrSize;
         }
@@ -174,8 +190,8 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
 
 static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
 /* Find a symbol reference and return it. Return NULL if the reference does
- * not exist.
- */
+** not exist.
+*/
 {
     unsigned I;
     ED_SymRef* SymRef;
@@ -191,8 +207,8 @@ static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
 
 static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
 /* Find a section reference and return it. Return NULL if the reference does
- * not exist.
- */
+** not exist.
+*/
 {
     unsigned I;
     ED_SecRef* SecRef;
@@ -208,8 +224,8 @@ static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
 
 static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
 /* Allocate a new symbol reference and return it. The count of the new
- * reference will be set to zero, and the reference itself to Sym.
- */
+** reference will be set to zero, and the reference itself to Sym.
+*/
 {
     ED_SymRef* SymRef;
 
@@ -235,8 +251,8 @@ static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
 
 static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
 /* Allocate a new section reference and return it. The count of the new
- * reference will be set to zero, and the reference itself to Sec.
- */
+** reference will be set to zero, and the reference itself to Sec.
+*/
 {
     ED_SecRef* SecRef;
 
@@ -262,8 +278,8 @@ static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
 
 static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
 /* Get a symbol reference and return it. If the symbol reference does not
- * exist, a new one is created and returned.
- */
+** exist, a new one is created and returned.
+*/
 {
     ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
     if (SymRef == 0) {
@@ -276,8 +292,8 @@ static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
 
 static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
 /* Get a section reference and return it. If the section reference does not
- * exist, a new one is created and returned.
- */
+** exist, a new one is created and returned.
+*/
 {
     ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
     if (SecRef == 0) {
@@ -400,8 +416,8 @@ static void ED_Neg (ExprDesc* D)
 
 static void ED_Move (ExprDesc* From, ExprDesc* To)
 /* Move the data from one ExprDesc to another. Old data is freed, and From
- * is prepared to that ED_Done may be called safely.
- */
+** is prepared to that ED_Done may be called safely.
+*/
 {
     /* Delete old data */
     ED_Done (To);
@@ -416,7 +432,7 @@ static void ED_Move (ExprDesc* From, ExprDesc* To)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -444,12 +460,12 @@ static unsigned char GetConstAddrSize (long Val)
 
 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
 /* Study a binary expression subtree. This is a helper function for StudyExpr
- * used for operations that succeed when both operands are known and constant.
- * It evaluates the two subtrees and checks if they are constant. If they
- * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
- * Otherwise the first value is returned in D->Val, the second one in D->Right,
- * so the actual operation can be done by the caller.
- */
+** used for operations that succeed when both operands are known and constant.
+** It evaluates the two subtrees and checks if they are constant. If they
+** aren't constant, it will set the TOO_COMPLEX flag, and merge references.
+** Otherwise the first value is returned in D->Val, the second one in D->Right,
+** so the actual operation can be done by the caller.
+*/
 {
     ExprDesc Right;
 
@@ -500,20 +516,17 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
     SymEntry* Sym = Expr->V.Sym;
 
     /* If the symbol is defined somewhere, it has an expression associated.
-     * In this case, just study the expression associated with the symbol,
-     * but mark the symbol so if we encounter it twice, we know that we have
-     * a circular reference.
-     */
+    ** In this case, just study the expression associated with the symbol,
+    ** but mark the symbol so if we encounter it twice, we know that we have
+    ** a circular reference.
+    */
     if (SymHasExpr (Sym)) {
 
         if (SymHasUserMark (Sym)) {
-            if (Verbosity > 0) {
-                DumpExpr (Expr, SymResolve);
-            }
             LIError (&Sym->DefLines,
-                     "Circular reference in definition of symbol `%m%p'",
+                     "Circular reference in definition of symbol '%m%p'",
                      GetSymName (Sym));
-            ED_Invalidate (D);
+            ED_SetError (D);
         } else {
 
             unsigned char AddrSize;
@@ -523,10 +536,15 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
             StudyExprInternal (GetSymExpr (Sym), D);
             SymUnmarkUser (Sym);
 
+            /* If requested and if the expression is valid, dump it */
+            if (Debug > 0 && !ED_HasError (D)) {
+                DumpExpr (Expr, SymResolve);
+            }
+
             /* If the symbol has an explicit address size, use it. This may
-             * lead to range errors later (maybe even in the linker stage), if
-             * the user lied about the address size, but for now we trust him.
-             */
+            ** lead to range errors later (maybe even in the linker stage), if
+            ** the user lied about the address size, but for now we trust him.
+            */
             AddrSize = GetSymAddrSize (Sym);
             if (AddrSize != ADDR_SIZE_DEFAULT) {
                 D->AddrSize = AddrSize;
@@ -536,8 +554,8 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
     } else if (SymIsImport (Sym)) {
 
         /* The symbol is an import. Track the symbols used and update the
-         * address size.
-         */
+        ** address size.
+        */
         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
         ++SymRef->Count;
         ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
@@ -548,17 +566,17 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
         SymTable* Parent;
 
         /* The symbol is undefined. Track symbol usage but set the "too
-         * complex" flag, since we cannot evaluate the final result.
-         */
+        ** complex" flag, since we cannot evaluate the final result.
+        */
         ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
         ++SymRef->Count;
         ED_Invalidate (D);
 
         /* Since the symbol may be a forward, and we may need a statement
-         * about the address size, check higher lexical levels for a symbol
-         * with the same name and use its address size if we find such a
-         * symbol which is defined.
-         */
+        ** about the address size, check higher lexical levels for a symbol
+        ** with the same name and use its address size if we find such a
+        ** symbol which is defined.
+        */
         AddrSize = GetSymAddrSize (Sym);
         Parent = GetSymParentScope (Sym);
         if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
@@ -594,8 +612,8 @@ static void StudyULabel (ExprNode* Expr, ExprDesc* D)
 /* Study an unnamed label expression node */
 {
     /* If we can resolve the label, study the expression associated with it,
-     * otherwise mark the expression as too complex to evaluate.
-     */
+    ** otherwise mark the expression as too complex to evaluate.
+    */
     if (ULabCanResolve ()) {
         /* We can resolve the label */
         StudyExprInternal (ULabResolve (Expr->V.IVal), D);
@@ -689,8 +707,8 @@ static void StudyMul (ExprNode* Expr, ExprDesc* D)
     StudyExprInternal (Expr->Right, &Right);
 
     /* We can handle the operation if at least one of both operands is const
-     * and the other one is valid.
-     */
+    ** and the other one is valid.
+    */
     if (ED_IsConst (D) && ED_IsValid (&Right)) {
 
         /* Multiplicate both, result goes into Right */
@@ -733,7 +751,7 @@ static void StudyDiv (ExprNode* Expr, ExprDesc* D)
     if (ED_IsValid (D)) {
         if (D->Right == 0) {
             Error ("Division by zero");
-            ED_Invalidate (D);
+            ED_SetError (D);
         } else {
             D->Val /= D->Right;
         }
@@ -752,7 +770,7 @@ static void StudyMod (ExprNode* Expr, ExprDesc* D)
     if (ED_IsValid (D)) {
         if (D->Right == 0) {
             Error ("Modulo operation with zero");
-            ED_Invalidate (D);
+            ED_SetError (D);
         } else {
             D->Val %= D->Right;
         }
@@ -1095,6 +1113,18 @@ static void StudyBoolNot (ExprNode* Expr, ExprDesc* D)
 
 
 
+static void StudyBank (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_BANK expression node */
+{
+    /* Study the expression extracting section references */
+    StudyExprInternal (Expr->Left, D);
+
+    /* The expression is always linker evaluated, so invalidate it */
+    ED_Invalidate (D);
+}
+
+
+
 static void StudyByte0 (ExprNode* Expr, ExprDesc* D)
 /* Study an EXPR_BYTE0 expression node */
 {
@@ -1179,7 +1209,7 @@ static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
 
     /* We can handle only const expressions */
     if (ED_IsConst (D)) {
-        D->Val = (D->Val & 0xFFFFL);
+        D->Val &= 0xFFFFL;
     } else {
         ED_Invalidate (D);
     }
@@ -1209,35 +1239,73 @@ static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
 
 
 
+static void StudyFarAddr (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_FARADDR expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val &= 0xFFFFFFL;
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is a far address */
+    D->AddrSize = ADDR_SIZE_FAR;
+}
+
+
+
+static void StudyDWord (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_DWORD expression node */
+{
+    /* Study the expression */
+    StudyExprInternal (Expr->Left, D);
+
+    /* We can handle only const expressions */
+    if (ED_IsConst (D)) {
+        D->Val &= 0xFFFFFFFFL;
+    } else {
+        ED_Invalidate (D);
+    }
+
+    /* In any case, the result is a long expression */
+    D->AddrSize = ADDR_SIZE_LONG;
+}
+
+
+
 static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
 /* Study an expression tree and place the contents into D */
 {
     /* Study this expression node */
     switch (Expr->Op) {
 
-       case EXPR_LITERAL:
+        case EXPR_LITERAL:
             StudyLiteral (Expr, D);
-           break;
+            break;
 
-       case EXPR_SYMBOL:
+        case EXPR_SYMBOL:
             StudySymbol (Expr, D);
             break;
 
-       case EXPR_SECTION:
+        case EXPR_SECTION:
             StudySection (Expr, D);
-           break;
+            break;
 
-       case EXPR_ULABEL:
+        case EXPR_ULABEL:
             StudyULabel (Expr, D);
             break;
 
-       case EXPR_PLUS:
+        case EXPR_PLUS:
             StudyPlus (Expr, D);
-           break;
+            break;
 
-       case EXPR_MINUS:
-                   StudyMinus (Expr, D);
-           break;
+        case EXPR_MINUS:
+            StudyMinus (Expr, D);
+            break;
 
         case EXPR_MUL:
             StudyMul (Expr, D);
@@ -1331,6 +1399,10 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
             StudyBoolNot (Expr, D);
             break;
 
+        case EXPR_BANK:
+            StudyBank (Expr, D);
+            break;
+
         case EXPR_BYTE0:
             StudyByte0 (Expr, D);
             break;
@@ -1355,9 +1427,17 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
             StudyWord1 (Expr, D);
             break;
 
+        case EXPR_FARADDR:
+            StudyFarAddr (Expr, D);
+            break;
+
+        case EXPR_DWORD:
+            StudyDWord (Expr, D);
+            break;
+
         default:
-           Internal ("Unknown Op type: %u", Expr->Op);
-           break;
+            Internal ("Unknown Op type: %u", Expr->Op);
+            break;
     }
 }
 
@@ -1400,24 +1480,24 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D)
     }
 
     /* If we don't have an address size, assign one if the expression is a
-     * constant.
-     */
+    ** constant.
+    */
     if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
         D->AddrSize = GetConstAddrSize (D->Val);
     }
 
     /* If the expression is valid, throw away the address size and recalculate
-     * it using the data we have. This is more exact than the on-the-fly
-     * calculation done when evaluating the tree, because symbols may have
-     * been removed from the expression, and the final numeric value is now
-     * known.
-     */
+    ** it using the data we have. This is more exact than the on-the-fly
+    ** calculation done when evaluating the tree, because symbols may have
+    ** been removed from the expression, and the final numeric value is now
+    ** known.
+    */
     if (ED_IsValid (D)) {
         unsigned char AddrSize;
 
         /* If there are symbols or sections, use the largest one. If the
-         * expression resolves to a const, use the address size of the value.
-         */
+        ** expression resolves to a const, use the address size of the value.
+        */
         if (D->SymCount > 0 || D->SecCount > 0) {
 
             D->AddrSize = ADDR_SIZE_DEFAULT;
@@ -1459,6 +1539,3 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D)
     printf ("%u sections:\n", D->SecCount);
 #endif
 }
-
-
-