]> git.sur5r.net Git - cc65/commitdiff
More work on expressions and address sizes
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 13 Nov 2003 00:21:31 +0000 (00:21 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 13 Nov 2003 00:21:31 +0000 (00:21 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2658 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/error.h
src/ca65/expr.c
src/ca65/main.c
src/ca65/pseudo.c
src/ca65/scanner.c
src/ca65/scanner.h
src/ca65/symentry.c
src/ca65/symentry.h
src/ca65/symtab.c
src/ca65/symtab.h

index 5eddd8949d4e7737096029f3784b51f8f7fa0629..2d7e2048babed9eaf4e3317939abe78b169a2e54 100644 (file)
@@ -7,7 +7,7 @@
 /*                                                                           */
 /*                                                                           */
 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -51,7 +51,7 @@
 
 
 /* Warning levels */
-extern unsigned                WarnLevel;
+extern unsigned WarnLevel;
 
 /* Statistics */
 extern unsigned ErrorCount;
@@ -73,7 +73,7 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) attr
 
 void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
 /* Print an error message */
-
+                
 void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
 /* Print an error message giving an explicit file and position. */
 
index 68baabb3f4b9934142ce587ec8a187bc09bc497c..9d44261912e783da92fd41e2cd0c572703c3ea45 100644 (file)
@@ -92,6 +92,17 @@ struct ExprDesc {
 
 
 
+/*****************************************************************************/
+/*                                 Forwards                                  */
+/*****************************************************************************/
+
+
+
+static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
+/* Study an expression tree and place the contents into D */
+
+
+
 /*****************************************************************************/
 /*                                 Helpers                                  */
 /*****************************************************************************/
@@ -559,8 +570,13 @@ static ExprNode* Factor (void)
            } else {
                /* Mark the symbol as referenced */
                SymRef (S);
-               /* Create symbol node */
-               N = GenSymExpr (S);
+                /* Remove the symbol if possible */
+                if (SymHasExpr (S)) {
+                    N = CloneExpr (GetSymExpr (S));
+                } else {
+                    /* Create symbol node */
+                    N = GenSymExpr (S);
+                }
            }
            break;
 
@@ -787,7 +803,7 @@ static ExprNode* Term (void)
 
             /* Generate an expression tree */
             unsigned char Op;
-            switch (T) {                           
+            switch (T) {
                 case TOK_MUL:   Op = EXPR_MUL; break;
                 case TOK_DIV:   Op = EXPR_DIV;  break;
                 case TOK_MOD:   Op = EXPR_MOD;  break;
@@ -819,22 +835,50 @@ static ExprNode* SimpleExpr (void)
     /* Handle additive operations */
     while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
 
-       /* Create the new node */
-       ExprNode* Left = Root;
-       switch (Tok) {
-                   case TOK_PLUS:      Root = NewExprNode (EXPR_PLUS);         break;
-                   case TOK_MINUS:     Root = NewExprNode (EXPR_MINUS);        break;
-                   case TOK_OR:        Root = NewExprNode (EXPR_OR);           break;
-           default:            Internal ("Invalid token");
-       }
-       Root->Left = Left;
+        long LVal, RVal, Val;
+        ExprNode* Left;
+        ExprNode* Right;
 
-        /* Skip the operator token */
-       NextTok ();
+        /* Remember the token and skip it */
+        enum Token T = Tok;
+        NextTok ();
 
-       /* Parse the right hand side */
-       Root->Right = Term ();
+        /* Move root to left side and read the right side */
+        Left  = Root;
+        Right = Term ();
+
+        /* If both expressions are constant, we can evaluate the term */
+        if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
 
+            switch (T) {
+                case TOK_PLUS:  Val = LVal + RVal;      break;
+                case TOK_MINUS: Val = LVal - RVal;      break;
+                case TOK_OR:    Val = LVal | RVal;      break;
+                default:        Internal ("Invalid token");
+            }
+
+            /* Generate a literal expression and delete the old left and
+             * right sides.
+             */
+            FreeExpr (Left);
+            FreeExpr (Right);
+            Root = GenLiteralExpr (Val);
+
+        } else {
+
+            /* Generate an expression tree */
+            unsigned char Op;
+            switch (T) {
+                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");
+            }
+            Root        = NewExprNode (Op);
+            Root->Left  = Left;
+            Root->Right = Right;
+
+        }
     }
 
     /* Return the expression tree we've created */
@@ -853,25 +897,56 @@ static ExprNode* BoolExpr (void)
     while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
           Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
 
-       /* Create the new node */
-       ExprNode* Left = Root;
-       switch (Tok) {
-                   case TOK_EQ:        Root = NewExprNode (EXPR_EQ);   break;
-                   case TOK_NE:        Root = NewExprNode (EXPR_NE);   break;
-                   case TOK_LT:        Root = NewExprNode (EXPR_LT);   break;
-                   case TOK_GT:        Root = NewExprNode (EXPR_GT);   break;
-                   case TOK_LE:        Root = NewExprNode (EXPR_LE);   break;
-                   case TOK_GE:        Root = NewExprNode (EXPR_GE);   break;
-           default:            Internal ("Invalid token");
-       }
-       Root->Left = Left;
+        long LVal, RVal, Val;
+        ExprNode* Left;
+        ExprNode* Right;
 
-        /* Skip the operator token */
-       NextTok ();
+        /* Remember the token and skip it */
+        enum Token T = Tok;
+        NextTok ();
+
+        /* Move root to left side and read the right side */
+        Left  = Root;
+        Right = SimpleExpr ();
+
+        /* If both expressions are constant, we can evaluate the term */
+        if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
 
-       /* Parse the right hand side */
-       Root->Right = SimpleExpr ();
+            switch (T) {
+                case TOK_EQ:    Val = (LVal == RVal);   break;
+                case TOK_NE:    Val = (LVal != RVal);   break;
+                case TOK_LT:    Val = (LVal < RVal);    break;
+                case TOK_GT:    Val = (LVal > RVal);    break;
+                case TOK_LE:    Val = (LVal <= RVal);   break;
+                case TOK_GE:    Val = (LVal >= RVal);   break;
+                default:        Internal ("Invalid token");
+            }
+
+            /* Generate a literal expression and delete the old left and
+             * right sides.
+             */
+            FreeExpr (Left);
+            FreeExpr (Right);
+            Root = GenLiteralExpr (Val);
+
+        } else {
 
+            /* Generate an expression tree */
+            unsigned char Op;
+            switch (T) {
+                case TOK_EQ:    Op = EXPR_EQ;   break;
+                case TOK_NE:    Op = EXPR_NE;   break;
+                case TOK_LT:    Op = EXPR_LT;   break;
+                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");
+            }
+            Root        = NewExprNode (Op);
+            Root->Left  = Left;
+            Root->Right = Right;
+
+        }
     }
 
     /* Return the expression tree we've created */
@@ -889,21 +964,48 @@ static ExprNode* Expr2 (void)
     /* Handle booleans */
     while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
 
-       /* Create the new node */
-       ExprNode* Left = Root;
-       switch (Tok) {
-                   case TOK_BOOLAND:   Root = NewExprNode (EXPR_BOOLAND); break;
-                   case TOK_BOOLXOR:   Root = NewExprNode (EXPR_BOOLXOR); break;
-           default:            Internal ("Invalid token");
-       }
-       Root->Left = Left;
+        long LVal, RVal, Val;
+        ExprNode* Left;
+        ExprNode* Right;
 
-        /* Skip the operator token */
-       NextTok ();
+        /* Remember the token and skip it */
+        enum Token T = Tok;
+        NextTok ();
+
+        /* Move root to left side and read the right side */
+        Left  = Root;
+        Right = BoolExpr ();
+
+        /* If both expressions are constant, we can evaluate the term */
+        if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
+
+            switch (T) {
+                case TOK_BOOLAND:   Val = ((LVal != 0) && (RVal != 0)); break;
+                case TOK_BOOLXOR:   Val = ((LVal != 0) ^  (RVal != 0)); break;
+                default:        Internal ("Invalid token");
+            }
+
+            /* Generate a literal expression and delete the old left and
+             * right sides.
+             */
+            FreeExpr (Left);
+            FreeExpr (Right);
+            Root = GenLiteralExpr (Val);
 
-       /* Parse the right hand side */
-       Root->Right = BoolExpr ();
+        } else {
 
+            /* Generate an expression tree */
+            unsigned char Op;
+            switch (T) {
+                case TOK_BOOLAND:   Op = EXPR_BOOLAND; break;
+                case TOK_BOOLXOR:   Op = EXPR_BOOLXOR; break;
+                default:                   Internal ("Invalid token");
+            }
+            Root        = NewExprNode (Op);
+            Root->Left  = Left;
+            Root->Right = Right;
+
+        }
     }
 
     /* Return the expression tree we've created */
@@ -921,20 +1023,46 @@ static ExprNode* Expr1 (void)
     /* Handle booleans */
     while (Tok == TOK_BOOLOR) {
 
-       /* Create the new node */
-       ExprNode* Left = Root;
-       switch (Tok) {
-                   case TOK_BOOLOR:    Root = NewExprNode (EXPR_BOOLOR);  break;
-           default:            Internal ("Invalid token");
-       }
-       Root->Left = Left;
+        long LVal, RVal, Val;
+        ExprNode* Left;
+        ExprNode* Right;
 
-        /* Skip the operator token */
-       NextTok ();
+        /* Remember the token and skip it */
+        enum Token T = Tok;
+        NextTok ();
+
+        /* Move root to left side and read the right side */
+        Left  = Root;
+        Right = Expr2 ();
+
+        /* If both expressions are constant, we can evaluate the term */
+        if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
+
+            switch (T) {
+                case TOK_BOOLOR:    Val = ((LVal != 0) || (RVal != 0)); break;
+                default:        Internal ("Invalid token");
+            }
 
-       /* Parse the right hand side */
-       Root->Right = Expr2 ();
+            /* Generate a literal expression and delete the old left and
+             * right sides.
+             */
+            FreeExpr (Left);
+            FreeExpr (Right);
+            Root = GenLiteralExpr (Val);
+
+        } else {
+
+            /* Generate an expression tree */
+            unsigned char Op;
+            switch (T) {
+                case TOK_BOOLOR:    Op = EXPR_BOOLOR;  break;
+                default:                   Internal ("Invalid token");
+            }
+            Root        = NewExprNode (Op);
+            Root->Left  = Left;
+            Root->Right = Right;
 
+        }
     }
 
     /* Return the expression tree we've created */
@@ -951,14 +1079,23 @@ static ExprNode* Expr0 (void)
     /* Handle booleans */
     if (Tok == TOK_BOOLNOT) {
 
-       /* Create the new node */
-        Root = NewExprNode (EXPR_BOOLNOT);
+        long Val;
+        ExprNode* Left;
 
         /* Skip the operator token */
        NextTok ();
 
-       /* Parse the left hand side, allow more BNOTs */
-       Root->Left = Expr0 ();
+        /* Read the argument */
+        Left = Expr0 ();
+
+        /* If the argument is const, evaluate it directly */
+        if (IsEasyConst (Left, &Val)) {
+            FreeExpr (Left);
+            Root = GenLiteralExpr (!Val);
+        } else {
+            Root = NewExprNode (EXPR_BOOLNOT);
+            Root->Left = Left;
+        }
 
     } else {
 
@@ -973,9 +1110,8 @@ static ExprNode* Expr0 (void)
 
 
 
-static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
-/* Study a binary expression subtree */
+/* Study a binary expression subtree. Helper function for StudyExpr. */
 {
     StudyExpr (Expr->Left, D, 1);
     if (ExprDescIsConst (D)) {
@@ -1542,23 +1678,52 @@ ExprNode* GenBranchExpr (unsigned Offs)
 {
     ExprNode* N;
     ExprNode* Root;
+    long      Val;
+
+    /* Read Expression() */
+    N = Expression ();
+
+    /* If the expression is a cheap constant, generate a simpler tree */
+    if (IsEasyConst (N, &Val)) {
+
+        /* Free the constant expression tree */
+        FreeExpr (N);
+
+        /* Generate the final expression:
+         * Val - (* + Offs)
+         * Val - ((Seg + PC) + Offs)
+         * Val - Seg - PC - Offs
+         * (Val - PC - Offs) - Seg
+         */
+        Root = GenLiteralExpr (Val - GetPC () - Offs);
+        if (RelocMode) {
+            N = Root;
+            Root = NewExprNode (EXPR_MINUS);
+            Root->Left  = N;
+            Root->Right = GenSectionExpr (GetCurrentSegNum ());
+        }
 
-    /* Create *+Offs */
-    if (RelocMode) {
-       N = NewExprNode (EXPR_PLUS);
-       N->Left  = GenSectionExpr (GetCurrentSegNum ());
-       N->Right = GenLiteralExpr (GetPC () + Offs);
     } else {
-       N = GenLiteralExpr (GetPC () + Offs);
-    }
 
-    /* Create the root node */
-    Root = NewExprNode (EXPR_MINUS);
-    Root->Left = Expression ();
-    Root->Right = N;
+        /* Generate the expression:
+         * 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);
+        if (RelocMode) {
+            N = Root;
+            Root = NewExprNode (EXPR_MINUS);
+            Root->Left  = N;
+            Root->Right = GenSectionExpr (GetCurrentSegNum ());
+        }
+    }
 
     /* Return the result */
-    return SimplifyExpr (Root);
+    return Root;
 }
 
 
index 413492e3202266e693bf84efd04c4f3662eacd7a..6223bfe9254b0bf464b68ca84a7f39d90099b800 100644 (file)
@@ -524,7 +524,7 @@ int main (int argc, char* argv [])
     /* Enter the base lexical level. We must do that here, since we may
      * define symbols using -D.
      */
-    SymEnterLevel ("", ADDR_SIZE_DEFAULT);
+    SymEnterLevel ("", ST_GLOBAL, ADDR_SIZE_DEFAULT);
 
     /* Check the parameters */
     I = 1;
index 42674285af706a3ac98c457bc59f2f56cd7fc507..4d6d945cb7be0868d0e1d7b5609252b1891a0f49 100644 (file)
@@ -7,7 +7,7 @@
 /*                                                                           */
 /*                                                                           */
 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -114,7 +114,7 @@ static void DoInvalid (void);
 
 
 
-static unsigned OptionalAddrSize (void)
+static unsigned char OptionalAddrSize (void)
 /* If a colon follows, parse an optional address size spec and return it.
  * Otherwise return ADDR_SIZE_DEFAULT.
  */
@@ -161,12 +161,12 @@ static void SetBoolOption (unsigned char* Flag)
 
 
 
-static void ExportImport (void (*Func) (SymEntry*, unsigned, unsigned),
-                          unsigned DefAddrSize, unsigned Flags)
+static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
+                          unsigned char DefAddrSize, unsigned Flags)
 /* Export or import symbols */
 {
     SymEntry* Sym;
-    unsigned  AddrSize;
+    unsigned char AddrSize;
 
     while (1) {
 
@@ -227,6 +227,10 @@ static void ConDes (const char* Name, unsigned Type)
 {
     long Prio;
 
+
+    /* Find the symbol table entry, allocate a new one if necessary */
+    SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
+
     /* Optional constructor priority */
     if (Tok == TOK_COMMA) {
        /* Priority value follows */
@@ -243,7 +247,7 @@ static void ConDes (const char* Name, unsigned Type)
     }
 
     /* Define the symbol */
-    SymConDes (Name, Type, (unsigned) Prio);
+    SymConDes (Sym, ADDR_SIZE_DEFAULT, Type, (unsigned) Prio);
 }
 
 
@@ -700,11 +704,11 @@ static void DoEnd (void)
 static void DoEndProc (void)
 /* Leave a lexical level */
 {
-    if (CurrentScope != RootScope) {
-        SymLeaveLevel ();
-    } else {
+    if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_PROC) {
         /* No local scope */
-        ErrorSkip ("No open lexical level");
+        ErrorSkip ("No open .PROC");
+    } else {
+        SymLeaveLevel ();
     }
 }
 
@@ -713,11 +717,11 @@ static void DoEndProc (void)
 static void DoEndScope (void)
 /* Leave a lexical level */
 {
-    if (CurrentScope != RootScope) {
-        SymLeaveLevel ();
-    } else {
+    if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_SCOPE) {
         /* No local scope */
-        ErrorSkip ("No open lexical level");
+        ErrorSkip ("No open .SCOPE");
+    } else {
+        SymLeaveLevel ();
     }
 }
 
@@ -1294,12 +1298,12 @@ static void DoPopSeg (void)
 static void DoProc (void)
 /* Start a new lexical scope */
 {
-    if (Tok == TOK_IDENT) {
+    char Name[sizeof(SVal)];
+    unsigned char AddrSize;
 
-        unsigned AddrSize;
+    if (Tok == TOK_IDENT) {
 
        /* The new scope has a name. Remember it. */
-        char Name[sizeof(SVal)];
         strcpy (Name, SVal);
 
         /* Search for the symbol, generate a new one if needed */
@@ -1314,17 +1318,17 @@ static void DoProc (void)
         /* Mark the symbol as defined */
        SymDef (Sym, GenCurrentPC (), AddrSize, SF_LABEL);
 
-        /* Enter a new scope with the given name */
-        SymEnterLevel (Name, AddrSize);
-
     } else {
 
         /* A .PROC statement without a name */
-        char Buf[sizeof (SVal)];
-        SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"), ADDR_SIZE_DEFAULT);
         Warning (1, "Unnamed .PROCs are deprecated, please use .SCOPE");
+        AnonName (Name, sizeof (Name), "PROC");
+        AddrSize = ADDR_SIZE_DEFAULT;
 
     }
+
+    /* Enter a new scope */
+    SymEnterLevel (Name, ST_PROC, AddrSize);
 }
 
 
@@ -1413,27 +1417,28 @@ static void DoScope (void)
 /* Start a local scope */
 {
     char Name[sizeof (SVal)];
+    unsigned char AddrSize;
 
-    if (Tok == TOK_IDENT) {
 
-        unsigned AddrSize;
+    if (Tok == TOK_IDENT) {
 
-       /* The new scope has a name. Remember and skip it. */
+       /* The new scope has a name. Remember and skip it. */
         strcpy (Name, SVal);
         NextTok ();
 
-        /* Read an optional address size specifier */
-        AddrSize = OptionalAddrSize ();
-
-        /* Enter a new scope with the given name */
-        SymEnterLevel (Name, AddrSize);
-
     } else {
 
         /* An unnamed scope */
-        SymEnterLevel (AnonName (Name, sizeof (Name), "Scope"), ADDR_SIZE_DEFAULT);
+        AnonName (Name, sizeof (Name), "SCOPE");
 
     }
+
+    /* Read an optional address size specifier */
+    AddrSize = OptionalAddrSize ();
+
+    /* Enter the new scope */
+    SymEnterLevel (Name, ST_SCOPE, AddrSize);
+
 }
 
 
@@ -1671,7 +1676,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoRepeat        },
     { ccNone,          DoRes           },
     { ccNone,          DoInvalid       },      /* .RIGHT */
-    { ccNone,          DoROData        },   
+    { ccNone,          DoROData        },
     { ccNone,           DoScope         },
     { ccNone,          DoSegment       },
     { ccNone,                  DoSetCPU        },
index b1a3b522d2fe2952df45dcf125b951bbccbff3a2..594584da593505473833f737d44352856c508aff 100644 (file)
@@ -1138,7 +1138,7 @@ int GetSubKey (const char** Keys, unsigned Count)
 
 
 
-unsigned ParseAddrSize (void)
+unsigned char ParseAddrSize (void)
 /* Check if the next token is a keyword that denotes an address size specifier.
  * If so, return the corresponding address size constant, otherwise output an
  * error message and return ADDR_SIZE_DEFAULT.
index 38a2b2d95c50a2ff6935658c0a42e681e28010b5..ed5d2614de08b9ecfebb7da3dd7744ad836de807 100644 (file)
@@ -7,7 +7,7 @@
 /*                                                                           */
 /*                                                                           */
 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -294,7 +294,7 @@ int GetSubKey (const char** Keys, unsigned Count);
  * or -1 if the keyword was not found.
  */
 
-unsigned ParseAddrSize (void);
+unsigned char ParseAddrSize (void);
 /* Check if the next token is a keyword that denotes an address size specifier.
  * If so, return the corresponding address size constant, otherwise output an
  * error message and return ADDR_SIZE_DEFAULT.
index 35e60b5efad61779d737a1bed820c9257535fc17..f716e3288852ab7e8272c61dade5922079b9f980 100644 (file)
@@ -44,6 +44,7 @@
 #include "expr.h"
 #include "global.h"
 #include "scanner.h"
+#include "segment.h"
 #include "spool.h"
 #include "symentry.h"
 #include "symtab.h"
@@ -94,8 +95,8 @@ static unsigned SymAddrSize (const SymEntry* S)
         return ADDR_SIZE_ABS;
     }
 
-    /* Return the address size of the enclosing scope */
-    return S->SymTab->AddrSize;
+    /* Return the address size of the segment */
+    return GetCurrentSegAddrSize ();
 }
 
 
@@ -139,7 +140,7 @@ void SymRef (SymEntry* S)
 
 
 
-void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
+void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
 /* Define a new symbol */
 {
     if (S->Flags & SF_IMPORT) {
@@ -160,7 +161,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
     }
 
     /* Set the symbol value */
-    S->V.Expr  = Expr;
+    S->V.Expr = Expr;
 
     /* If the symbol is marked as global, export it */
     if (S->Flags & SF_GLOBAL) {
@@ -178,7 +179,9 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
             /* Use the real size of the symbol */
             S->ExportSize = S->AddrSize;
         } else if (S->AddrSize > S->ExportSize) {
-            Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
+            PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported as %s",
+                      GetSymName (S), AddrSizeToStr (S->AddrSize),
+                      AddrSizeToStr (S->ExportSize));
         }
     }
 
@@ -198,7 +201,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
 
 
 
-void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
+void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
 /* Mark the given symbol as an imported symbol */
 {
     /* Don't accept local symbols */
@@ -226,11 +229,18 @@ void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
     /* If the symbol is marked as import or global, check the symbol flags,
      * then do silently remove the global flag
      */
-    if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
-       if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
-            AddrSize != S->AddrSize) {
+    if (S->Flags & SF_IMPORT) {
+       if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
                    Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
        }
+        if (AddrSize != S->AddrSize) {
+            Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+        }
+    }
+    if (S->Flags & SF_GLOBAL) {
+        if (S->AddrSize != ADDR_SIZE_DEFAULT && S->AddrSize != AddrSize) {
+            Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+       }
         S->Flags &= ~SF_GLOBAL;
     }
 
@@ -241,7 +251,7 @@ void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
 
 
 
-void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
+void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
 /* Mark the given symbol as an exported symbol */
 {
     /* Don't accept local symbols */
@@ -257,15 +267,25 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
        return;
     }
 
-    /* If the symbol was already marked as an export or global, check if
-     * this was done specifiying the same address size. In case of a global
-     * declaration, silently remove the global flag.
+    /* If the symbol was marked as global before, make it an export */
+    if (S->Flags & SF_GLOBAL) {
+        S->ExportSize = S->AddrSize;
+        S->Flags &= ~SF_GLOBAL;
+    }
+
+    /* If the symbol was already marked as an export, check if this was done
+     * specifiying the same address size. If the old spec had no explicit
+     * address size, use the new one.
      */
-    if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
-        if (S->ExportSize != AddrSize) {
+    if (S->Flags & SF_EXPORT) {
+        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+            S->ExportSize = AddrSize;
+        } else if (AddrSize == ADDR_SIZE_DEFAULT) {
+            AddrSize = S->ExportSize;
+        }
+        if (S->ExportSize != ADDR_SIZE_DEFAULT && S->ExportSize != AddrSize) {
             Error ("Address size mismatch for symbol `%s'", GetSymName (S));
         }
-        S->Flags &= ~SF_GLOBAL;
     }
     S->ExportSize = AddrSize;
 
@@ -274,10 +294,12 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
      */
     if (S->Flags & SF_DEFINED) {
         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
-            /* Use the real size of the symbol */
+            /* No export size given, use the real size of the symbol */
             S->ExportSize = S->AddrSize;
         } else if (S->AddrSize > S->ExportSize) {
-            Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
+            Warning (1, "Symbol `%s' is %s but exported as %s",
+                     GetSymName (S), AddrSizeToStr (S->AddrSize),
+                     AddrSizeToStr (S->ExportSize));
         }
     }
 
@@ -287,7 +309,7 @@ void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
 
 
 
-void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
+void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
 /* Mark the given symbol as a global symbol, that is, as a symbol that is
  * either imported or exported.
  */
@@ -298,21 +320,22 @@ void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
        return;
     }
 
-    /* Map a default address size to a real value */
-    if (AddrSize == ADDR_SIZE_DEFAULT) {
-        AddrSize = SymAddrSize (S);
-    }
-
     /* If the symbol is already marked as import or export, check the
      * size of the definition, then bail out.
      */
     if (S->Flags & SF_IMPORT) {
-        if (AddrSize != S->AddrSize) {
+        if (AddrSize != ADDR_SIZE_DEFAULT && AddrSize != S->AddrSize) {
             Error ("Address size mismatch for symbol `%s'", GetSymName (S));
         }
         return;
     }
     if (S->Flags & SF_EXPORT) {
+        /* If the old symbol had no explicit address size spec, use the
+         * new one.
+         */
+        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+            S->ExportSize = AddrSize;
+        }
         if (AddrSize != S->ExportSize) {
             Error ("Address size mismatch for symbol `%s'", GetSymName (S));
         }
@@ -324,8 +347,14 @@ void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
      */
     if (S->Flags & SF_DEFINED) {
         /* The symbol is defined, export it */
-        if (S->ExportSize != AddrSize) {
-            Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+        S->ExportSize = AddrSize;
+        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+            /* No export size given, use the real size of the symbol */
+            S->ExportSize = S->AddrSize;
+        } else if (S->AddrSize > S->ExportSize) {
+            Warning (1, "Symbol `%s' is %s but exported as %s",
+                     GetSymName (S), AddrSizeToStr (S->AddrSize),
+                     AddrSizeToStr (S->ExportSize));
         }
         S->Flags |= (SF_EXPORT | Flags);
         S->ExportSize = AddrSize;
@@ -337,6 +366,72 @@ void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
 
 
 
+void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
+/* Mark the given symbol as a module constructor/destructor. This will also
+ * mark the symbol as an export. Initializers may never be zero page symbols.
+ */
+{
+    /* Check the parameters */
+#if (CD_TYPE_MIN != 0)
+    CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
+#else
+    CHECK (Type <= CD_TYPE_MAX);
+#endif
+    CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
+
+    /* Don't accept local symbols */
+    if (IsLocalNameId (S->Name)) {
+               Error ("Illegal use of a local symbol");
+               return;
+    }
+
+    /* Check for errors */
+    if (S->Flags & SF_IMPORT) {
+               /* The symbol is already marked as imported external symbol */
+               Error ("Symbol `%s' is already an import", GetSymName (S));
+               return;
+    }
+
+    /* If the symbol was already marked as an export or global, check if
+     * this was done specifiying the same address size. In case of a global
+     * declaration, silently remove the global flag.
+     */
+    if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
+        if (S->ExportSize != AddrSize) {
+            Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+        }
+        S->Flags &= ~SF_GLOBAL;
+    }
+    S->ExportSize = AddrSize;
+
+    /* If the symbol is already defined, check symbol size against the
+     * exported size.
+     */
+    if (S->Flags & SF_DEFINED) {
+        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+            /* Use the real size of the symbol */
+            S->ExportSize = S->AddrSize;
+        } else if (S->AddrSize != S->ExportSize) {
+            Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+        }
+    }
+
+    /* If the symbol was already declared as a condes, check if the new
+     * priority value is the same as the old one.
+     */
+    if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
+       if (S->ConDesPrio[Type] != Prio) {
+           Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
+       }
+    }
+    S->ConDesPrio[Type] = Prio;
+
+    /* Set the symbol data */
+    S->Flags |= (SF_EXPORT | SF_REFERENCED);
+}
+
+
+
 int SymIsDef (const SymEntry* S)
 /* Return true if the given symbol is already defined */
 {
index 940278bab8dd0d9dbf4a26dfc47b8ad8c30d8648..46dba46faef884453b323a8b0f69249f6e26932c 100644 (file)
@@ -136,23 +136,28 @@ INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
 #define SymDelExprRef(Sym,Expr)     CollDeleteItem (&(Sym)->ExprRefs, Expr)
 #endif
 
-void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned AddrSize, unsigned Flags);
+void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned char AddrSize, unsigned Flags);
 /* Mark a symbol as defined */
 
 void SymRef (SymEntry* Sym);
 /* Mark the given symbol as referenced */
 
-void SymImport (SymEntry* Sym, unsigned AddrSize, unsigned Flags);
+void SymImport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
 /* Mark the given symbol as an imported symbol */
 
-void SymExport (SymEntry* Sym, unsigned AddrSize, unsigned Flags);
+void SymExport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
 /* Mark the given symbol as an exported symbol */
 
-void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags);
+void SymGlobal (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
 /* Mark the given symbol as a global symbol, that is, as a symbol that is
  * either imported or exported.
  */
 
+void SymConDes (SymEntry* Sym, unsigned char AddrSize, unsigned Type, unsigned Prio);
+/* Mark the given symbol as a module constructor/destructor. This will also
+ * mark the symbol as an export. Initializers may never be zero page symbols.
+ */
+
 int SymIsDef (const SymEntry* Sym);
 /* Return true if the given symbol is already defined */
 
index 6af89a97eece65ed8f8c97ed7d79ebdb09d50d67..d21d0e1eb73f5833d326b7b677a72a98a3ca77ea 100644 (file)
@@ -112,7 +112,7 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
     S->Childs       = 0;
     S->Flags        = ST_NONE;
     S->AddrSize     = ADDR_SIZE_DEFAULT;
-    S->Type         = 0;
+    S->Type         = ST_UNDEF;
     S->Level        = Level;
     S->TableSlots   = Slots;
     S->TableEntries = 0;
@@ -203,7 +203,7 @@ static int SearchSymTree (SymEntry* T, const char* Name, SymEntry** E)
 
 
 
-void SymEnterLevel (const char* ScopeName, unsigned AddrSize)
+void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize)
 /* Enter a new lexical level */
 {
     /* Map a default address size to something real */
@@ -216,18 +216,23 @@ void SymEnterLevel (const char* ScopeName, unsigned AddrSize)
      * new one if it doesn't exist. If this is the root scope, just create it.
      */
     if (CurrentScope) {
+
+        /* Search for the scope, create a new one */
         CurrentScope = SymFindScope (CurrentScope, ScopeName, SYM_ALLOC_NEW);
 
         /* Check if the scope has been defined before */
         if (CurrentScope->Flags & ST_DEFINED) {
             Error ("Duplicate scope `%s'", ScopeName);
         }
+
     } else {
         CurrentScope = RootScope = NewSymTable (0, ScopeName);
     }
 
-    /* Mark the scope as defined */
-    CurrentScope->Flags |= ST_DEFINED;
+    /* Mark the scope as defined and set type and address size */
+    CurrentScope->Flags    |= ST_DEFINED;
+    CurrentScope->AddrSize = AddrSize;
+    CurrentScope->Type     = Type;
 }
 
 
@@ -364,7 +369,7 @@ static SymEntry* SymFindAny (SymTable* Scope, const char* Name)
     do {
        /* Search in the current table */
        Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
-       if (Sym) {
+               if (Sym) {
            /* Found, return it */
            return Sym;
        } else {
@@ -379,61 +384,6 @@ static SymEntry* SymFindAny (SymTable* Scope, const char* Name)
 
 
 
-void SymConDes (const char* Name, unsigned Type, unsigned Prio)
-/* Mark the given symbol as a module constructor/destructor. This will also
- * mark the symbol as an export. Initializers may never be zero page symbols.
- */
-{
-    SymEntry* S;
-
-    /* Check the parameters */
-#if (CD_TYPE_MIN != 0)
-    CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
-#else
-    CHECK (Type <= CD_TYPE_MAX);
-#endif
-    CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
-
-    /* Don't accept local symbols */
-    if (IsLocalName (Name)) {
-       Error ("Illegal use of a local symbol");
-       return;
-    }
-
-    /* Do we have such a symbol? */
-    S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
-    if (S->Flags & SF_IMPORT) {
-       /* The symbol is already marked as imported external symbol */
-       Error ("Symbol `%s' is already an import", Name);
-       return;
-    }
-
-    /* If the symbol is marked as global, silently remove the global flag */
-    if (S->Flags & SF_GLOBAL) {
-        S->Flags &= ~SF_GLOBAL;
-    }
-
-    /* Check if the symbol was not already defined as ZP symbol */
-    if (S->AddrSize == ADDR_SIZE_ZP) {
-       Error ("Redeclaration mismatch for symbol `%s'", Name);
-    }
-
-    /* If the symbol was already declared as a condes, check if the new
-     * priority value is the same as the old one.
-     */
-    if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
-       if (S->ConDesPrio[Type] != Prio) {
-           Error ("Redeclaration mismatch for symbol `%s'", Name);
-       }
-    }
-    S->ConDesPrio[Type] = Prio;
-
-    /* Set the symbol data */
-    S->Flags |= SF_EXPORT | SF_REFERENCED;
-}
-
-
-
 int SymIsZP (SymEntry* S)
 /* Return true if the symbol is explicitly marked as zeropage symbol */
 {
@@ -464,6 +414,15 @@ int SymIsZP (SymEntry* S)
 
 
 
+unsigned char GetCurrentSymTabType ()
+/* Return the type of the current symbol table */
+{
+    CHECK (CurrentScope != 0);
+    return CurrentScope->Type;
+}
+
+
+
 static void SymCheckUndefined (SymEntry* S)
 /* Handle an undefined symbol */
 {
@@ -821,4 +780,4 @@ void WriteDbgSyms (void)
 
 
 
-                                 
+
index fc28def444fb176b7737d7efbe67adb7831addd8..86d0aa4caa8c40fe5405983968c16df48d9cd959 100644 (file)
 #define ST_NONE         0x00            /* No flags */
 #define ST_DEFINED      0x01            /* Scope has been defined */
 
+/* Symbol table types */
+#define ST_GLOBAL       0x00            /* Root level */
+#define ST_PROC         0x01            /* .PROC */
+#define ST_SCOPE        0x02            /* .SCOPE */
+#define ST_STUCT        0x03            /* .STRUCT */
+#define ST_UNDEF        0xFF
+
 /* A symbol table */
 typedef struct SymTable SymTable;
 struct SymTable {
@@ -87,7 +94,7 @@ SymTable*     RootScope;      /* Root symbol table */
 
 
 
-void SymEnterLevel (const char* ScopeName, unsigned AddrSize);
+void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize);
 /* Enter a new lexical level */
 
 void SymLeaveLevel (void);
@@ -102,14 +109,12 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
  * new entry created, or - in case AllocNew is zero - return 0.
  */
 
-void SymConDes (const char* Name, unsigned Type, unsigned Prio);
-/* Mark the given symbol as a module constructor/destructor. This will also
- * mark the symbol as an export. Initializers may never be zero page symbols.
- */
-
 int SymIsZP (SymEntry* Sym);
 /* Return true if the symbol is explicitly marked as zeropage symbol */
 
+unsigned char GetCurrentSymTabType ();
+/* Return the type of the current symbol table */
+
 void SymCheck (void);
 /* Run through all symbols and check for anomalies and errors */