]> git.sur5r.net Git - cc65/blobdiff - src/ca65/symtab.c
The line counter got confused for lines with more than 256 chars. Removed the
[cc65] / src / ca65 / symtab.c
index ec853248c276ffdce85e1148177b3498c4e9d23a..356f7386d45ad3fff7ecb252230905d548dad223 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2004 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 #define SF_DBGINFOVAL  (SF_DEFINED)
 
 /* Symbol tables */
-SymTable*              CurrentScope = 0;       /* Pointer to current symbol table */
-SymTable*      RootScope    = 0;       /* Root symbol table */
+SymTable*                  CurrentScope = 0;   /* Pointer to current symbol table */
+SymTable*          RootScope    = 0;   /* Root symbol table */
+static SymTable*    LastScope    = 0;   /* Pointer to last scope in list */
 
 /* Symbol table variables */
-static unsigned ImportCount = 0;        /* Counter for import symbols */
-static unsigned ExportCount = 0;        /* Counter for export symbols */
+static unsigned     ImportCount = 0;    /* Counter for import symbols */
+static unsigned     ExportCount = 0;    /* Counter for export symbols */
 
 
 
@@ -97,7 +98,7 @@ static unsigned ScopeTableSize (unsigned Level)
 
 
 
-static SymTable* NewSymTable (SymTable* Parent, const char* Name)
+static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
 /* Allocate a symbol table on the heap and return it */
 {
     /* Determine the lexical level and the number of table slots */
@@ -111,6 +112,7 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
     S->Left         = 0;
     S->Right        = 0;
     S->Childs       = 0;
+    S->OwnerSym     = 0;
     S->SegRanges    = AUTO_COLLECTION_INITIALIZER;
     S->Flags        = ST_NONE;
     S->AddrSize     = ADDR_SIZE_DEFAULT;
@@ -119,11 +121,23 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
     S->TableSlots   = Slots;
     S->TableEntries = 0;
     S->Parent       = Parent;
-    S->Name         = GetStringId (Name);
+    S->Name         = GetStrBufId (Name);
     while (Slots--) {
                S->Table[Slots] = 0;
     }
 
+    /* Insert the symbol table into the list of all symbol tables and maintain
+     * a unqiue id for each scope.
+     */
+    S->Next = LastScope;
+    if (RootScope == 0) {
+        S->Id = 0;
+        RootScope = S;
+    } else {
+        S->Id = LastScope->Id + 1;
+    }
+    LastScope = S;
+
     /* Insert the symbol table into the child tree of the parent */
     if (Parent) {
         SymTable* T = Parent->Childs;
@@ -133,7 +147,7 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
         } else {
             while (1) {
                 /* Choose next entry */
-                int Cmp = strcmp (Name, GetString (T->Name));
+                int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
                 if (Cmp < 0) {
                     if (T->Left) {
                         T = T->Left;
@@ -147,10 +161,10 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
                     } else {
                         T->Right = S;
                         break;
-                    }
+                    }  
                 } else {
                     /* Duplicate scope name */
-                    Internal ("Duplicate scope name: `%s'", Name);
+                    Internal ("Duplicate scope name: `%m%p'", Name);
                 }
             }
         }
@@ -163,12 +177,13 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
 
-void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize)
+void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
+                    unsigned char AddrSize, SymEntry* OwnerSym)
 /* Enter a new lexical level */
 {
     /* Map a default address size to something real */
@@ -187,17 +202,18 @@ void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char Add
 
         /* Check if the scope has been defined before */
         if (CurrentScope->Flags & ST_DEFINED) {
-            Error ("Duplicate scope `%s'", ScopeName);
+            Error ("Duplicate scope `%m%p'", ScopeName);
         }
 
     } else {
         CurrentScope = RootScope = NewSymTable (0, ScopeName);
     }
 
-    /* Mark the scope as defined and set type and address size */
+    /* Mark the scope as defined and set type, address size and owner symbol */
     CurrentScope->Flags    |= ST_DEFINED;
     CurrentScope->AddrSize = AddrSize;
     CurrentScope->Type     = Type;
+    CurrentScope->OwnerSym = OwnerSym;
 
     /* If this is a scope that allows to emit data into segments, add segment
      * ranges for all currently existing segments. Doing this for just a few
@@ -222,11 +238,16 @@ void SymLeaveLevel (void)
 
     /* If we have segment ranges, the first one is the segment that was
      * active, when the scope was opened. Set the size of the scope to the
-     * number of data bytes emitted into this segment.
+     * number of data bytes emitted into this segment. If we have an owner
+     * symbol set the size of this symbol, too.
      */
     if (CollCount (&CurrentScope->SegRanges) > 0) {
         const SegRange* R = CollAtUnchecked (&CurrentScope->SegRanges, 0);
-        DefSizeOfScope (CurrentScope, GetSegRangeSize (R));
+        unsigned long Size = GetSegRangeSize (R);
+        DefSizeOfScope (CurrentScope, Size);
+        if (CurrentScope->OwnerSym) {              
+            DefSizeOfSymbol (CurrentScope->OwnerSym, Size);
+        }
     }
 
     /* Leave the scope */
@@ -235,12 +256,12 @@ void SymLeaveLevel (void)
 
 
 
-SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
+SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew)
 /* Find a scope in the given enclosing scope */
 {
     SymTable** T = &Parent->Childs;
     while (*T) {
-        int Cmp = strcmp (Name, GetString ((*T)->Name));
+        int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
         if (Cmp < 0) {
             T = &(*T)->Left;
         } else if (Cmp > 0) {
@@ -262,7 +283,7 @@ SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
 
 
 
-SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
+SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
 /* Find a scope in the given or any of its parent scopes. The function will
  * never create a new symbol, since this can only be done in one specific
  * scope.
@@ -283,7 +304,7 @@ SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
 
 
 
-SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew)
+SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, int AllocNew)
 /* Find a cheap local symbol. If AllocNew is given and the entry is not
  * found, create a new one. Return the entry found, or the new entry created,
  * or - in case AllocNew is zero - return 0.
@@ -315,6 +336,7 @@ SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew)
 
         /* Otherwise create a new entry, insert and return it */
         SymEntry* N = NewSymEntry (Name, SF_LOCAL);
+        N->Sym.Entry = Parent;
         if (S == 0) {
             Parent->Locals = N;
         } else if (Cmp < 0) {
@@ -331,7 +353,7 @@ SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew)
 
 
 
-SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
+SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew)
 /* Find a new symbol table entry in the given table. If AllocNew is given and
  * the entry is not found, create a new one. Return the entry found, or the
  * new entry created, or - in case AllocNew is zero - return 0.
@@ -340,7 +362,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
     SymEntry* S;
 
     /* Global symbol: Get the hash value for the name */
-    unsigned Hash = HashStr (Name) % Scope->TableSlots;
+    unsigned Hash = HashBuf (Name) % Scope->TableSlots;
 
     /* Search for the entry */
     int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
@@ -354,6 +376,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
 
         /* Otherwise create a new entry, insert and return it */
         SymEntry* N = NewSymEntry (Name, SF_NONE);
+        N->Sym.Tab = Scope;
         if (S == 0) {
             Scope->Table[Hash] = N;
         } else if (Cmp < 0) {
@@ -361,7 +384,6 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
         } else {
             S->Right = N;
         }
-        N->SymTab = Scope;
         ++Scope->TableEntries;
         return N;
 
@@ -373,7 +395,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
 
 
 
-SymEntry* SymFindAny (SymTable* Scope, const char* Name)
+SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
 /* Find a symbol in the given or any of its parent scopes. The function will
  * never create a new symbol, since this can only be done in one specific
  * scope.
@@ -424,7 +446,7 @@ static void SymCheckUndefined (SymEntry* S)
     SymEntry* Sym = 0;
     SymTable* Tab = GetSymParentScope (S);
     while (Tab) {
-        Sym = SymFind (Tab, GetString (S->Name), SYM_FIND_EXISTING);
+        Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING);
         if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
             /* We've found a symbol in a higher level that is
              * either defined in the source, or an import.
@@ -444,15 +466,18 @@ static void SymCheckUndefined (SymEntry* S)
         if (S->Flags & SF_EXPORT) {
            if (Sym->Flags & SF_IMPORT) {
                /* The symbol is already marked as import */
-               PError (&S->Pos, "Symbol `%s' is already an import",
-                        GetString (Sym->Name));
+                       LIError (&S->LineInfos,
+                         "Symbol `%s' is already an import",
+                         GetString (Sym->Name));
            }
             if (Sym->Flags & SF_EXPORT) {
                 /* The symbol is already marked as an export. */
                 if (Sym->AddrSize > S->ExportSize) {
                     /* We're exporting a symbol smaller than it actually is */
-                    PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
-                              GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
+                    LIWarning (&S->LineInfos, 1,
+                               "Symbol `%m%p' is %s but exported %s",
+                              GetSymName (Sym),
+                              AddrSizeToStr (Sym->AddrSize),
                               AddrSizeToStr (S->ExportSize));
                 }
             } else {
@@ -465,9 +490,11 @@ static void SymCheckUndefined (SymEntry* S)
                 }
                 if (Sym->AddrSize > Sym->ExportSize) {
                     /* We're exporting a symbol smaller than it actually is */
-                    PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
-                              GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
-                              AddrSizeToStr (Sym->ExportSize));
+                    LIWarning (&S->LineInfos, 1,
+                               "Symbol `%m%p' is %s but exported %s",
+                               GetSymName (Sym),
+                               AddrSizeToStr (Sym->AddrSize),
+                               AddrSizeToStr (Sym->ExportSize));
                 }
             }
         }
@@ -483,8 +510,9 @@ static void SymCheckUndefined (SymEntry* S)
        /* The symbol is definitely undefined */
        if (S->Flags & SF_EXPORT) {
            /* We will not auto-import an export */
-           PError (&S->Pos, "Exported symbol `%s' was never defined",
-                    GetString (S->Name));
+           LIError (&S->LineInfos,
+                     "Exported symbol `%m%p' was never defined",
+                     GetSymName (S));
        } else {
            if (AutoImport) {
                /* Mark as import, will be indexed later */
@@ -493,7 +521,9 @@ static void SymCheckUndefined (SymEntry* S)
                 S->AddrSize = CodeAddrSize;
            } else {
                /* Error */
-               PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
+               LIError (&S->LineInfos,
+                         "Symbol `%m%p' is undefined",
+                         GetSymName (S));
            }
        }
     }
@@ -549,11 +579,11 @@ void SymCheck (void)
 
             /* Check for defined symbols that were never referenced */
            if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
-                const char* Name = GetString (S->Name);
-                if (Name[0] != '.') {           /* Ignore internals */
-                    PWarning (&S->Pos, 2,
-                              "Symbol `%s' is defined but never used",
-                              GetString (S->Name));
+                const StrBuf* Name = GetStrBuf (S->Name);
+                if (SB_At (Name, 0) != '.') {           /* Ignore internals */
+                    LIWarning (&S->LineInfos, 2,
+                               "Symbol `%m%p' is defined but never used",
+                               GetSymName (S));
                 }
            }
 
@@ -561,21 +591,18 @@ void SymCheck (void)
            if (S->Flags & SF_IMPORT) {
                if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
                    /* Imported symbol is not referenced */
-                   PWarning (&S->Pos, 2,
-                              "Symbol `%s' is imported but never used",
-                              GetString (S->Name));
+                   LIWarning (&S->LineInfos, 2,
+                               "Symbol `%m%p' is imported but never used",
+                               GetSymName (S));
                } else {
-                   /* Give the import an index, count imports */
-                   S->Index = ImportCount++;
-                   S->Flags |= SF_INDEXED;
+                   /* Give the import an id, count imports */
+                   S->ImportId = ImportCount++;
                }
            }
 
-            /* Assign an index to all exports */
+            /* Count exports */
            if (S->Flags & SF_EXPORT) {
-               /* Give the export an index, count exports */
-               S->Index = ExportCount++;
-               S->Flags |= SF_INDEXED;
+               ++ExportCount;
            }
 
             /* If the symbol is defined but has an unknown address size,
@@ -592,14 +619,34 @@ void SymCheck (void)
                         S->ExportSize = S->AddrSize;
                     } else if (S->AddrSize > S->ExportSize) {
                         /* We're exporting a symbol smaller than it actually is */
-                        PWarning (&S->Pos, 1,
-                                  "Symbol `%s' is %s but exported %s",
-                                  GetSymName (S), AddrSizeToStr (S->AddrSize),
-                                  AddrSizeToStr (S->ExportSize));
+                        LIWarning (&S->LineInfos, 1,
+                                   "Symbol `%m%p' is %s but exported %s",
+                                   GetSymName (S),
+                                   AddrSizeToStr (S->AddrSize),
+                                   AddrSizeToStr (S->ExportSize));
                     }
                 }
                 ED_Done (&ED);
             }
+
+            /* If the address size of the symbol was guessed, check the guess
+             * against the actual address size and print a warning if the two
+             * differ.
+             */
+            if (S->AddrSize != ADDR_SIZE_DEFAULT) {
+                /* Do we have data for this address size? */
+                if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
+                    /* Get the file position where the symbol was used */
+                    const FilePos* P = S->GuessedUse[S->AddrSize - 1];
+                    if (P) {
+                        PWarning (P, 0,
+                                  "Didn't use %s addressing for `%m%p'",
+                                  AddrSizeToStr (S->AddrSize),
+                                  GetSymName (S));
+                    }
+                }
+            }
+
        }
 
        /* Next symbol */
@@ -618,8 +665,8 @@ void SymDump (FILE* F)
        /* Ignore unused symbols */
        if ((S->Flags & SF_UNUSED) != 0) {
            fprintf (F,
-                    "%-24s %s %s %s %s %s\n",
-                    GetString (S->Name),
+                    "%m%-24p %s %s %s %s %s\n",
+                    GetSymName (S),
                     (S->Flags & SF_DEFINED)? "DEF" : "---",
                     (S->Flags & SF_REFERENCED)? "REF" : "---",
                     (S->Flags & SF_IMPORT)? "IMP" : "---",
@@ -656,7 +703,7 @@ void WriteImports (void)
 
             ObjWrite8 (S->AddrSize);
                    ObjWriteVar (S->Name);
-           ObjWritePos (&S->Pos);
+           WriteLineInfo (&S->LineInfos);
        }
        S = S->List;
     }
@@ -684,38 +731,45 @@ void WriteExports (void)
     while (S) {
                if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
 
+           /* Get the expression bits and the value */
             long ConstVal;
+            unsigned ExprMask = GetSymInfoFlags (S, &ConstVal);
 
-           /* Get the expression bits */
-            unsigned char ExprMask = SymIsConst (S, &ConstVal)? EXP_CONST : EXP_EXPR;
-            ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
+            /* Check if this symbol has a size. If so, remember it in the
+             * flags.
+             */
+            long Size;
+            SymEntry* SizeSym = FindSizeOfSymbol (S);
+            if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
+                ExprMask |= SYM_SIZE;
+            }
 
            /* Count the number of ConDes types */
            for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
-               if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
-                   INC_EXP_CONDES_COUNT (ExprMask);
-               }
+               if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
+                   SYM_INC_CONDES_COUNT (ExprMask);
+               }
            }
 
            /* Write the type and the export size */
-           ObjWrite8 (ExprMask);
+           ObjWriteVar (ExprMask);
             ObjWrite8 (S->ExportSize);
 
            /* Write any ConDes declarations */
-           if (GET_EXP_CONDES_COUNT (ExprMask) > 0) {
-               for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
-                   unsigned char Prio = S->ConDesPrio[Type];
-                   if (Prio != CD_PRIO_NONE) {
-                       ObjWrite8 (CD_BUILD (Type, Prio));
-                   }
-               }
+           if (SYM_GET_CONDES_COUNT (ExprMask) > 0) {
+               for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
+                   unsigned char Prio = S->ConDesPrio[Type];
+                   if (Prio != CD_PRIO_NONE) {
+                       ObjWrite8 (CD_BUILD (Type, Prio));
+                   }
+               }
            }
 
            /* Write the name */
                    ObjWriteVar (S->Name);
 
            /* Write the value */
-           if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
+           if (SYM_IS_CONST (ExprMask)) {
                /* Constant value */
                ObjWrite32 (ConstVal);
            } else {
@@ -723,8 +777,13 @@ void WriteExports (void)
                WriteExpr (S->Expr);
             }
 
-           /* Write the source file position */
-           ObjWritePos (&S->Pos);
+            /* If the symbol has a size, write it to the file */
+            if (SYM_HAS_SIZE (ExprMask)) {
+                ObjWriteVar (Size);
+            }
+
+           /* Write the line infos */
+           WriteLineInfo (&S->LineInfos);
        }
        S = S->List;
     }
@@ -747,12 +806,13 @@ void WriteDbgSyms (void)
     /* Check if debug info is requested */
     if (DbgSyms) {
 
-       /* Walk through the list and count the symbols */
+       /* Walk through the list, give each symbol an id and count them */
        Count = 0;
        S = SymList;
        while (S) {
-           if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
-               ++Count;
+           if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL &&
+                !IsSizeOfSymbol (S)) {
+                S->DebugSymId = Count++;
            }
            S = S->List;
        }
@@ -760,19 +820,29 @@ void WriteDbgSyms (void)
        /* Write the symbol count to the list */
                ObjWriteVar (Count);
 
-               /* Walk through list and write all symbols to the file */
+               /* Walk through list and write all symbols to the file. Ignore size
+         * symbols.
+         */
        S = SymList;
        while (S) {
-           if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
+           if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL &&
+                !IsSizeOfSymbol (S)) {
 
+                /* Get the expression bits and the value */
                 long ConstVal;
-
-               /* Get the expression bits */
-                unsigned char ExprMask = (SymIsConst (S, &ConstVal))? EXP_CONST : EXP_EXPR;
-                ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
+                unsigned ExprMask = GetSymInfoFlags (S, &ConstVal);
+
+                /* Check if this symbol has a size. If so, remember it in the
+                 * flags.
+                 */
+                long Size;
+                SymEntry* SizeSym = FindSizeOfSymbol (S);
+                if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
+                    ExprMask |= SYM_SIZE;
+                }
 
                /* Write the type */
-               ObjWrite8 (ExprMask);
+               ObjWriteVar (ExprMask);
 
                 /* Write the address size */
                 ObjWrite8 (S->AddrSize);
@@ -781,7 +851,7 @@ void WriteDbgSyms (void)
                        ObjWriteVar (S->Name);
 
                /* Write the value */
-               if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
+               if (SYM_IS_CONST (ExprMask)) {
                    /* Constant value */
                    ObjWrite32 (ConstVal);
                } else {
@@ -789,8 +859,13 @@ void WriteDbgSyms (void)
                    WriteExpr (S->Expr);
                }
 
-               /* Write the source file position */
-               ObjWritePos (&S->Pos);
+                /* If the symbol has a size, write it to the file */
+                if (SYM_HAS_SIZE (ExprMask)) {
+                    ObjWriteVar (Size);
+                }
+
+               /* Write the line infos */
+               WriteLineInfo (&S->LineInfos);
            }
            S = S->List;
        }
@@ -814,7 +889,7 @@ void WriteScopes (void)
     /* Tell the object file module that we're about to start the scopes */
     ObjStartScopes ();
 
-    /* For now ...*/
+    /* No debug info requested */
     ObjWriteVar (0);
 
     /* Done writing the scopes */