]> git.sur5r.net Git - cc65/commitdiff
Added processing of modules, libraries, etc. Many other changes for new debug
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 9 Aug 2011 19:11:38 +0000 (19:11 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 9 Aug 2011 19:11:38 +0000 (19:11 +0000)
info format.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5141 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/dbginfo/dbginfo.c
src/dbginfo/dbginfo.h
src/dbginfo/dbgtest.c

index 076461caefbbd9bb42cf44440eab02919f1593c3..f6cac5c58fb04aef9ec2870a05ed46d0434d2323 100644 (file)
@@ -165,6 +165,7 @@ struct DbgInfo {
      */
     Collection          FileInfoById;   /* File infos sorted by id */
     Collection          LibInfoById;    /* Library infos sorted by id */
+    Collection          LineInfoById;   /* Line infos sorted by id */
     Collection          ModInfoById;    /* Module infos sorted by id */
     Collection          ScopeInfoById;  /* Scope infos sorted by id */
     Collection          SegInfoById;    /* Segment infos sorted by id */
@@ -172,7 +173,6 @@ struct DbgInfo {
 
     /* Collections with other sort criteria */
     Collection          FileInfoByName; /* File infos sorted by name */
-    Collection          LineInfos;      /* List of all line infos */
     Collection          SegInfoByName;  /* Segment infos sorted by name */
     Collection          SymInfoByName;  /* Symbol infos sorted by name */
     Collection          SymInfoByVal;   /* Symbol infos sorted by value */
@@ -220,7 +220,7 @@ struct FileInfo {
         ModInfo*        Info;           /* Pointer to module info */
     } Mod;
     Collection          LineInfoByLine; /* Line infos sorted by line */
-    char                FileName[1];    /* Name of file with full path */
+    char                Name[1];        /* Name of file with full path */
 };
 
 /* Internally used library info struct */
@@ -231,6 +231,7 @@ struct LibInfo {
 
 /* Internally used line info struct */
 struct LineInfo {
+    unsigned            Id;             /* Id of line info */
     cc65_addr           Start;          /* Start of data range */
     cc65_addr           End;            /* End of data range */
     cc65_line           Line;           /* Line number */
@@ -255,7 +256,7 @@ struct ModInfo {
     } File;
     union {
         unsigned        Id;             /* Id of library if any */
-        LibInfo*        Info;           /* Pointer to library info or NULL */
+        LibInfo*        Info;           /* Pointer to library info */
     } Lib;
     char                Name[1];        /* Name of module with path */
 };
@@ -265,20 +266,19 @@ struct ScopeInfo {
     unsigned            Id;             /* Id of scope */
     cc65_scope_type     Type;           /* Type of scope */
     cc65_size           Size;           /* Size of scope */
-    unsigned            Flags;          /* Scope flags */
     union {
         unsigned        Id;             /* Id of module */
         ModInfo*        Info;           /* Pointer to module info */
     } Mod;
     union {
         unsigned        Id;             /* Id of parent scope */
-        ScopeInfo*      Scope;          /* Pointer to parent scope */
+        ScopeInfo*      Info;           /* Pointer to parent scope */
     } Parent;
     union {
         unsigned        Id;             /* Id of label symbol */
         SymInfo*        Info;           /* Pointer to label symbol */
-    } Sym;
-    char                ScopeName[1];   /* Name of scope */
+    } Label;
+    char                Name[1];        /* Name of scope */
 };
 
 /* Internally used segment info struct */
@@ -288,7 +288,7 @@ struct SegInfo {
     cc65_addr           Size;           /* Size of segment */
     char*               OutputName;     /* Name of output file */
     unsigned long       OutputOffs;     /* Offset in output file */
-    char                SegName[1];     /* Name of segment */
+    char                Name[1];        /* Name of segment */
 };
 
 /* Internally used symbol info struct */
@@ -297,10 +297,19 @@ struct SymInfo {
     cc65_symbol_type    Type;           /* Type of symbol */
     long                Value;          /* Value of symbol */
     cc65_size           Size;           /* Size of symbol */
-    unsigned            Segment;        /* Id of segment if any */
-    unsigned            Scope;          /* Id of symbol scope */
-    unsigned            Parent;         /* Parent symbol if any */
-    char                SymName[1];     /* Name of symbol */
+    union {
+        unsigned        Id;             /* Id of segment if any */
+        SegInfo*        Info;           /* Pointer to segment if any */
+    } Seg;
+    union {
+        unsigned        Id;             /* Id of symbol scope */
+        ScopeInfo*      Info;           /* Pointer to symbol scope */
+    } Scope;
+    union {
+        unsigned        Id;             /* Parent symbol if any */
+        SymInfo*        Info;           /* Pointer to parent symbol if any */
+    } Parent;
+    char                Name[1];        /* Name of symbol */
 };
 
 
@@ -366,71 +375,6 @@ static void xfree (void* Block)
 
 
 
-static cc65_lineinfo* new_cc65_lineinfo (unsigned Count)
-/* Allocate and return a cc65_lineinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
-{
-    cc65_lineinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) +
-                                Count * sizeof (L->data[0]));
-    L->count = Count;
-    return L;
-}
-
-
-
-static cc65_sourceinfo* new_cc65_sourceinfo (unsigned Count)
-/* Allocate and return a cc65_sourceinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
-{
-    cc65_sourceinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
-                                  Count * sizeof (S->data[0]));
-    S->count = Count;
-    return S;
-}
-
-
-
-static cc65_segmentinfo* new_cc65_segmentinfo (unsigned Count)
-/* Allocate and return a cc65_segmentinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
-{
-    cc65_segmentinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
-                                   Count * sizeof (S->data[0]));
-    S->count = Count;
-    return S;
-}
-
-
-
-static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count)
-/* Allocate and return a cc65_symbolinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
-{
-    cc65_symbolinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
-                                  Count * sizeof (S->data[0]));
-    S->count = Count;
-    return S;
-}
-
-
-
-static cc65_scopeinfo* new_cc65_scopeinfo (unsigned Count)
-/* Allocate and return a cc65_scopeinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
-{
-    cc65_scopeinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
-                                 Count * sizeof (S->data[0]));
-    S->count = Count;
-    return S;
-}
-
-
-
 /*****************************************************************************/
 /*                              Dynamic strings                              */
 /*****************************************************************************/
@@ -764,22 +708,6 @@ static void* CollFirst (Collection* C)
 
 
 
-static void CollDelete (Collection* C, unsigned Index)
-/* Remove the item with the given index from the collection. This will not
- * free the item itself, just the pointer. All items with higher indices
- * will get moved to a lower position.
- */
-{
-    /* Check the index */
-    assert (Index < C->Count);
-
-    /* Remove the item pointer */
-    --C->Count;
-    memmove (C->Items+Index, C->Items+Index+1, (C->Count-Index) * sizeof (void*));
-}
-
-
-
 static void CollQuickSort (Collection* C, int Lo, int Hi,
                           int (*Compare) (const void*, const void*))
 /* Internal recursive sort function. */
@@ -861,7 +789,7 @@ static void DumpFileInfo (Collection* FileInfos)
                 "  Size:   %lu\n"
                 "  MTime:  %lu\n",
                 FI->Id,
-                FI->FileName,
+                FI->Name,
                 (unsigned long) FI->Size,
                 (unsigned long) FI->MTime);
     }
@@ -879,7 +807,7 @@ static void DumpOneLineInfo (unsigned Num, LineInfo* LI)
             "    Type:   %u\n"
             "    Count:  %u\n",
             Num,
-            LI->File.Info->FileName,
+            LI->File.Info->Name,
             (unsigned long) LI->Line,
             (unsigned long) LI->Start,
             (unsigned long) LI->End,
@@ -934,15 +862,15 @@ static void DumpData (InputData* D)
 
 
 
-static FileInfo* NewFileInfo (const StrBuf* FileName)
+static FileInfo* NewFileInfo (const StrBuf* Name)
 /* Create a new FileInfo struct and return it */
 {
     /* Allocate memory */
-    FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (FileName));
+    FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (Name));
 
     /* Initialize it */
     InitCollection (&F->LineInfoByLine);
-    memcpy (F->FileName, SB_GetConstBuf (FileName), SB_GetLen (FileName) + 1);
+    memcpy (F->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
 
     /* Return it */
     return F;
@@ -962,6 +890,30 @@ static void FreeFileInfo (FileInfo* F)
 
 
 
+static cc65_sourceinfo* new_cc65_sourceinfo (unsigned Count)
+/* Allocate and return a cc65_sourceinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_sourceinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
+                                  Count * sizeof (S->data[0]));
+    S->count = Count;
+    return S;
+}
+
+
+
+static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F)
+/* Copy data from a FileInfo struct to a cc65_sourcedata struct */
+{
+    D->source_id    = F->Id;
+    D->source_name  = F->Name;
+    D->source_size  = F->Size;
+    D->source_mtime = F->MTime;
+}
+
+
+
 static int CompareFileInfoByName (const void* L, const void* R)
 /* Helper function to sort file infos in a collection by name */
 {
@@ -969,8 +921,8 @@ static int CompareFileInfoByName (const void* L, const void* R)
      * then sort by size. Which means, identical files will go
      * together.
      */
-    int Res = strcmp (((const FileInfo*) L)->FileName,
-                      ((const FileInfo*) R)->FileName);
+    int Res = strcmp (((const FileInfo*) L)->Name,
+                      ((const FileInfo*) R)->Name);
     if (Res != 0) {
         return Res;
     }
@@ -1019,31 +971,39 @@ static void FreeLibInfo (LibInfo* L)
 
 
 
+static cc65_libraryinfo* new_cc65_libraryinfo (unsigned Count)
+/* Allocate and return a cc65_libraryinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_libraryinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) +
+                                   Count * sizeof (L->data[0]));
+    L->count = Count;
+    return L;
+}
+
+
+
+static void CopyLibInfo (cc65_librarydata* D, const LibInfo* L)
+/* Copy data from a LibInfo struct to a cc65_librarydata struct */
+{
+    D->library_id   = L->Id;
+    D->library_name = L->Name;
+}
+
+
+
 /*****************************************************************************/
 /*                                 Line info                                 */
 /*****************************************************************************/
 
 
 
-static LineInfo* NewLineInfo (unsigned File, unsigned Seg, cc65_line Line,
-                              cc65_addr Start, cc65_addr End,
-                              cc65_line_type Type, unsigned Count)
+static LineInfo* NewLineInfo (void)
 /* Create a new LineInfo struct and return it */
 {
-    /* Allocate memory */
-    LineInfo* L = xmalloc (sizeof (LineInfo));
-
-    /* Initialize it */
-    L->Start    = Start;
-    L->End      = End;
-    L->Line     = Line;
-    L->File.Id  = File;
-    L->Seg.Id   = Seg;
-    L->Type     = Type;
-    L->Count    = Count;
-
-    /* Return it */
-    return L;
+    /* Allocate memory and return it */
+    return xmalloc (sizeof (LineInfo));
 }
 
 
@@ -1056,6 +1016,41 @@ static void FreeLineInfo (LineInfo* L)
 
 
 
+static cc65_lineinfo* new_cc65_lineinfo (unsigned Count)
+/* Allocate and return a cc65_lineinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_lineinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) +
+                                Count * sizeof (L->data[0]));
+    L->count = Count;
+    return L;
+}
+
+
+
+static void CopyLineInfo (cc65_linedata* D, const LineInfo* L)
+/* Copy data from a LineInfo struct to a cc65_linedata struct */
+{
+    D->source_name  = L->File.Info->Name;
+    D->source_size  = L->File.Info->Size;
+    D->source_mtime = L->File.Info->MTime;
+    D->source_line  = L->Line;
+    D->line_start   = L->Start;
+    D->line_end     = L->End;
+    if (L->Seg.Info->OutputName) {
+        D->output_name  = L->Seg.Info->OutputName;
+        D->output_offs  = L->Seg.Info->OutputOffs + L->Start - L->Seg.Info->Start;
+    } else {
+        D->output_name  = 0;
+        D->output_offs  = 0;
+    }
+    D->line_type    = L->Type;
+    D->count        = L->Count;
+}
+
+
+
 static int CompareLineInfoByAddr (const void* L, const void* R)
 /* Helper function to sort line infos in a collection by address. Line infos
  * with smaller start address are considered smaller. If start addresses are
@@ -1317,6 +1312,30 @@ static void FreeModInfo (ModInfo* M)
 
 
 
+static cc65_moduleinfo* new_cc65_moduleinfo (unsigned Count)
+/* Allocate and return a cc65_moduleinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_moduleinfo* M = xmalloc (sizeof (*M) - sizeof (M->data[0]) +
+                                  Count * sizeof (M->data[0]));
+    M->count = Count;
+    return M;
+}
+
+
+
+static void CopyModInfo (cc65_moduledata* D, const ModInfo* M)
+/* Copy data from a ModInfo struct to a cc65_moduledata struct */
+{
+    D->module_id      = M->Id;
+    D->module_name    = M->Name;
+    D->source_id      = M->File.Info->Id;
+    D->library_id     = M->Lib.Info->Id;
+}
+
+
+
 /*****************************************************************************/
 /*                                Scope info                                 */
 /*****************************************************************************/
@@ -1330,7 +1349,7 @@ static ScopeInfo* NewScopeInfo (const StrBuf* Name)
     ScopeInfo* S = xmalloc (sizeof (ScopeInfo) + SB_GetLen (Name));
 
     /* Initialize the name */
-    memcpy (S->ScopeName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
+    memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
 
     /* Return it */
     return S;
@@ -1346,12 +1365,39 @@ static void FreeScopeInfo (ScopeInfo* S)
 
 
 
+static cc65_scopeinfo* new_cc65_scopeinfo (unsigned Count)
+/* Allocate and return a cc65_scopeinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_scopeinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
+                                 Count * sizeof (S->data[0]));
+    S->count = Count;
+    return S;
+}
+
+
+
+static void CopyScopeInfo (cc65_scopedata* D, const ScopeInfo* S)
+/* Copy data from a ScopeInfo struct to a cc65_scopedata struct */
+{
+    D->scope_id       = S->Id;
+    D->scope_name     = S->Name;
+    D->scope_type     = S->Type;
+    D->scope_size     = S->Size;
+    D->scope_parent   = S->Parent.Info->Id;
+    D->symbol_id      = S->Label.Info->Id;
+    D->module_id      = S->Mod.Info->Id;
+}
+
+
+
 static int CompareScopeInfoByName (const void* L, const void* R)
 /* Helper function to sort scope infos in a collection by name */
 {
-    /* Sort by symbol name */
-    return strcmp (((const ScopeInfo*) L)->ScopeName,
-                   ((const ScopeInfo*) R)->ScopeName);
+    /* Compare symbol name */
+    return strcmp (((const ScopeInfo*) L)->Name,
+                   ((const ScopeInfo*) R)->Name);
 }
 
 
@@ -1362,13 +1408,13 @@ static int CompareScopeInfoByName (const void* L, const void* R)
 
 
 
-static SegInfo* NewSegInfo (const StrBuf* SegName, unsigned Id,
+static SegInfo* NewSegInfo (const StrBuf* Name, unsigned Id,
                             cc65_addr Start, cc65_addr Size,
                             const StrBuf* OutputName, unsigned long OutputOffs)
 /* Create a new SegInfo struct and return it */
 {
     /* Allocate memory */
-    SegInfo* S = xmalloc (sizeof (SegInfo) + SB_GetLen (SegName));
+    SegInfo* S = xmalloc (sizeof (SegInfo) + SB_GetLen (Name));
 
     /* Initialize it */
     S->Id         = Id;
@@ -1383,7 +1429,7 @@ static SegInfo* NewSegInfo (const StrBuf* SegName, unsigned Id,
         S->OutputName = 0;
         S->OutputOffs = 0;
     }
-    memcpy (S->SegName, SB_GetConstBuf (SegName), SB_GetLen (SegName) + 1);
+    memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
 
     /* Return it */
     return S;
@@ -1400,12 +1446,38 @@ static void FreeSegInfo (SegInfo* S)
 
 
 
+static cc65_segmentinfo* new_cc65_segmentinfo (unsigned Count)
+/* Allocate and return a cc65_segmentinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_segmentinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
+                                   Count * sizeof (S->data[0]));
+    S->count = Count;
+    return S;
+}
+
+
+
+static void CopySegInfo (cc65_segmentdata* D, const SegInfo* S)
+/* Copy data from a SegInfo struct to a cc65_segmentdata struct */
+{
+    D->segment_id    = S->Id;
+    D->segment_name  = S->Name;
+    D->segment_start = S->Start;
+    D->segment_size  = S->Size;
+    D->output_name   = S->OutputName;
+    D->output_offs   = S->OutputOffs;
+}
+
+
+
 static int CompareSegInfoByName (const void* L, const void* R)
 /* Helper function to sort segment infos in a collection by name */
 {
     /* Sort by file name */
-    return strcmp (((const SegInfo*) L)->SegName,
-                   ((const SegInfo*) R)->SegName);
+    return strcmp (((const SegInfo*) L)->Name,
+                   ((const SegInfo*) R)->Name);
 }
 
 
@@ -1423,7 +1495,7 @@ static SymInfo* NewSymInfo (const StrBuf* Name)
     SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name));
 
     /* Initialize the name */
-    memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
+    memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
 
     /* Return it */
     return S;
@@ -1439,12 +1511,40 @@ static void FreeSymInfo (SymInfo* S)
 
 
 
+static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count)
+/* Allocate and return a cc65_symbolinfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+    cc65_symbolinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
+                                  Count * sizeof (S->data[0]));
+    S->count = Count;
+    return S;
+}
+
+
+
+static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
+/* Copy data from a SymInfo struct to a cc65_symboldata struct */
+{
+    D->symbol_id      = S->Id;
+    D->symbol_name    = S->Name;
+    D->symbol_type    = S->Type;
+    D->symbol_size    = S->Size;
+    D->symbol_value   = S->Value;
+    D->segment_id     = S->Seg.Info->Id;
+    D->scope_id       = S->Scope.Info->Id;
+    D->parent_id      = S->Parent.Info->Id;
+}
+
+
+
 static int CompareSymInfoByName (const void* L, const void* R)
 /* Helper function to sort symbol infos in a collection by name */
 {
     /* Sort by symbol name */
-    return strcmp (((const SymInfo*) L)->SymName,
-                   ((const SymInfo*) R)->SymName);
+    return strcmp (((const SymInfo*) L)->Name,
+                   ((const SymInfo*) R)->Name);
 }
 
 
@@ -1481,13 +1581,13 @@ static DbgInfo* NewDbgInfo (void)
     /* Initialize it */
     InitCollection (&Info->FileInfoById);
     InitCollection (&Info->LibInfoById);
+    InitCollection (&Info->LineInfoById);
     InitCollection (&Info->ModInfoById);
     InitCollection (&Info->ScopeInfoById);
     InitCollection (&Info->SegInfoById);
     InitCollection (&Info->SymInfoById);
 
     InitCollection (&Info->FileInfoByName);
-    InitCollection (&Info->LineInfos);
     InitCollection (&Info->SegInfoByName);
     InitCollection (&Info->SymInfoByName);
     InitCollection (&Info->SymInfoByVal);
@@ -1512,6 +1612,9 @@ static void FreeDbgInfo (DbgInfo* Info)
     for (I = 0; I < CollCount (&Info->LibInfoById); ++I) {
         FreeLibInfo (CollAt (&Info->LibInfoById, I));
     }
+    for (I = 0; I < CollCount (&Info->LineInfoById); ++I) {
+        FreeLineInfo (CollAt (&Info->LineInfoById, I));
+    }
     for (I = 0; I < CollCount (&Info->ModInfoById); ++I) {
         FreeModInfo (CollAt (&Info->ModInfoById, I));
     }
@@ -1528,21 +1631,18 @@ static void FreeDbgInfo (DbgInfo* Info)
     /* Free the memory used by the collections themselves */
     DoneCollection (&Info->FileInfoById);
     DoneCollection (&Info->LibInfoById);
+    DoneCollection (&Info->LineInfoById);
     DoneCollection (&Info->ModInfoById);
     DoneCollection (&Info->ScopeInfoById);
     DoneCollection (&Info->SegInfoById);
     DoneCollection (&Info->SymInfoById);
 
     DoneCollection (&Info->FileInfoByName);
-    DoneCollection (&Info->LineInfos);
     DoneCollection (&Info->SegInfoByName);
     DoneCollection (&Info->SymInfoByName);
     DoneCollection (&Info->SymInfoByVal);
 
     /* Free line info */
-    for (I = 0; I < CollCount (&Info->LineInfos); ++I) {
-        FreeLineInfo (CollAt (&Info->LineInfos, I));
-    }
     DoneLineInfoList (&Info->LineInfoByAddr);
 
     /* Free the structure itself */
@@ -1557,80 +1657,8 @@ static void FreeDbgInfo (DbgInfo* Info)
 
 
 
-static void CopyLineInfo (cc65_linedata* D, const LineInfo* L)
-/* Copy data from a LineInfo struct to a cc65_linedata struct */
-{
-    D->source_name  = L->File.Info->FileName;
-    D->source_size  = L->File.Info->Size;
-    D->source_mtime = L->File.Info->MTime;
-    D->source_line  = L->Line;
-    D->line_start   = L->Start;
-    D->line_end     = L->End;
-    if (L->Seg.Info->OutputName) {
-        D->output_name  = L->Seg.Info->OutputName;
-        D->output_offs  = L->Seg.Info->OutputOffs + L->Start - L->Seg.Info->Start;
-    } else {
-        D->output_name  = 0;
-        D->output_offs  = 0;
-    }
-    D->line_type    = L->Type;
-    D->count        = L->Count;
-}
-
-
-
-static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F)
-/* Copy data from a FileInfo struct to a cc65_sourcedata struct */
-{
-    D->source_id    = F->Id;
-    D->source_name  = F->FileName;
-    D->source_size  = F->Size;
-    D->source_mtime = F->MTime;
-}
-
-
-
-static void CopySegInfo (cc65_segmentdata* D, const SegInfo* S)
-/* Copy data from a SegInfo struct to a cc65_segmentdata struct */
-{
-    D->segment_id    = S->Id;
-    D->segment_name  = S->SegName;
-    D->segment_start = S->Start;
-    D->segment_size  = S->Size;
-    D->output_name   = S->OutputName;
-    D->output_offs   = S->OutputOffs;
-}
-
-
-
-static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
-/* Copy data from a SymInfo struct to a cc65_symboldata struct */
-{
-    D->symbol_id      = S->Id;
-    D->symbol_name    = S->SymName;
-    D->symbol_type    = S->Type;
-    D->symbol_size    = S->Size;
-    D->symbol_value   = S->Value;
-    D->symbol_segment = S->Segment;
-    D->scope_id       = S->Scope;
-}
-
-
-
-static void CopyScopeInfo (cc65_scopedata* D, const ScopeInfo* S)
-/* Copy data from a ScopeInfo struct to a cc65_scopedata struct */
-{
-    D->scope_id       = S->Id;
-    D->scope_name     = S->ScopeName;
-    D->scope_type     = S->Type;
-    D->scope_size     = S->Size;
-    D->scope_parent   = S->Parent.Scope->Id;
-}
-
-
-
-static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...)
-/* Call the user supplied parse error function */
+static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...)
+/* Call the user supplied parse error function */
 {
     va_list             ap;
     int                 MsgSize;
@@ -1997,16 +2025,16 @@ static void ParseFile (InputData* D)
     unsigned long Size = 0;
     unsigned long MTime = 0;
     unsigned      ModId = CC65_INV_ID;
-    StrBuf        FileName = STRBUF_INITIALIZER;
+    StrBuf        Name = STRBUF_INITIALIZER;
     FileInfo*     F;
     enum {
         ibNone      = 0x00,
         ibId        = 0x01,
-        ibFileName  = 0x02,
+        ibName      = 0x02,
         ibSize      = 0x04,
         ibMTime     = 0x08,
         ibModId     = 0x10,
-        ibRequired  = ibId | ibFileName | ibSize | ibMTime | ibModId,
+        ibRequired  = ibId | ibName | ibSize | ibMTime | ibModId,
     } InfoBits = ibNone;
 
     /* Skip the FILE token */
@@ -2079,9 +2107,9 @@ static void ParseFile (InputData* D)
                 if (!StrConstFollows (D)) {
                     goto ErrorExit;
                 }
-                SB_Copy (&FileName, &D->SVal);
-                SB_Terminate (&FileName);
-                InfoBits |= ibFileName;
+                SB_Copy (&Name, &D->SVal);
+                SB_Terminate (&Name);
+                InfoBits |= ibName;
                 NextToken (D);
                 break;
 
@@ -2122,7 +2150,7 @@ static void ParseFile (InputData* D)
     }
 
     /* Create the file info and remember it */
-    F = NewFileInfo (&FileName);
+    F = NewFileInfo (&Name);
     F->Id       = Id;
     F->Size     = Size;
     F->MTime    = MTime;
@@ -2132,7 +2160,7 @@ static void ParseFile (InputData* D)
 
 ErrorExit:
     /* Entry point in case of errors */
-    SB_Done (&FileName);
+    SB_Done (&Name);
     return;
 }
 
@@ -2345,8 +2373,9 @@ ErrorExit:
 static void ParseLine (InputData* D)
 /* Parse a LINE line */
 {
-    unsigned        File = 0;
-    unsigned        Segment = 0;
+    unsigned        Id = CC65_INV_ID;
+    unsigned        FileId = CC65_INV_ID;
+    unsigned        SegId = CC65_INV_ID;
     cc65_line       Line = 0;
     cc65_addr       Start = 0;
     cc65_addr       End = 0;
@@ -2355,13 +2384,16 @@ static void ParseLine (InputData* D)
     LineInfo*   L;
     enum {
         ibNone      = 0x00,
-        ibFile      = 0x01,
-        ibSegment   = 0x02,
-        ibLine      = 0x04,
-        ibRange     = 0x08,
-        ibType      = 0x10,
-        ibCount     = 0x20,
-        ibRequired  = ibFile | ibSegment | ibLine | ibRange,
+
+        ibCount     = 0x01,
+        ibFileId    = 0x02,
+        ibId        = 0x04,
+        ibLine      = 0x08,
+        ibRange     = 0x10,
+        ibSegId     = 0x20,
+        ibType      = 0x40,
+
+        ibRequired  = ibFileId | ibId | ibLine | ibSegId | ibRange,
     } InfoBits = ibNone;
 
     /* Skip the LINE token */
@@ -2373,9 +2405,10 @@ static void ParseLine (InputData* D)
         Token Tok;
 
         /* Something we know? */
-        if (D->Tok != TOK_COUNT   && D->Tok != TOK_FILE  &&
-            D->Tok != TOK_LINE    && D->Tok != TOK_RANGE &&
-            D->Tok != TOK_SEGMENT && D->Tok != TOK_TYPE) {
+        if (D->Tok != TOK_COUNT   && D->Tok != TOK_FILE         &&
+            D->Tok != TOK_ID      && D->Tok != TOK_LINE         &&
+            D->Tok != TOK_RANGE   && D->Tok != TOK_SEGMENT      &&
+            D->Tok != TOK_TYPE) {
 
             /* Try smart error recovery */
             if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
@@ -2401,8 +2434,17 @@ static void ParseLine (InputData* D)
                 if (!IntConstFollows (D)) {
                     goto ErrorExit;
                 }
-                File = D->IVal;
-                InfoBits |= ibFile;
+                FileId = D->IVal;
+                InfoBits |= ibFileId;
+                NextToken (D);
+                break;
+
+            case TOK_ID:
+                if (!IntConstFollows (D)) {
+                    goto ErrorExit;
+                }
+                Id = D->IVal;
+                InfoBits |= ibId;
                 NextToken (D);
                 break;
 
@@ -2440,8 +2482,8 @@ static void ParseLine (InputData* D)
                 if (!IntConstFollows (D)) {
                     goto ErrorExit;
                 }
-                Segment = D->IVal;
-                InfoBits |= ibSegment;
+                SegId = D->IVal;
+                InfoBits |= ibSegId;
                 NextToken (D);
                 break;
 
@@ -2491,8 +2533,16 @@ static void ParseLine (InputData* D)
     }
 
     /* Create the line info and remember it */
-    L = NewLineInfo (File, Segment, Line, Start, End, Type, Count);
-    CollAppend (&D->Info->LineInfos, L);
+    L = NewLineInfo ();
+    L->Id       = Id;
+    L->Start    = Start;
+    L->End      = End;
+    L->Line     = Line;
+    L->File.Id  = FileId;
+    L->Seg.Id   = SegId;
+    L->Type     = Type;
+    L->Count    = Count;
+    CollReplaceExpand (&D->Info->LineInfoById, L, Id);
 
 ErrorExit:
     /* Entry point in case of errors */
@@ -2621,9 +2671,9 @@ static void ParseModule (InputData* D)
 
     /* Create the scope info */
     M = NewModInfo (&Name);
-    M->File.Id  = FileId;
-    M->Id       = Id;
-    M->Lib.Id   = LibId;
+    M->File.Id = FileId;
+    M->Id      = Id;
+    M->Lib.Id  = LibId;
 
     /* ... and remember it */
     CollReplaceExpand (&D->Info->ModInfoById, M, Id);
@@ -2807,7 +2857,7 @@ static void ParseScope (InputData* D)
     S->Size      = Size;
     S->Mod.Id    = ModId;
     S->Parent.Id = ParentId;
-    S->Sym.Id    = SymId;
+    S->Label.Id  = SymId;
 
     /* ... and remember it */
     CollReplaceExpand (&D->Info->ScopeInfoById, S, Id);
@@ -2826,7 +2876,7 @@ static void ParseSegment (InputData* D)
     unsigned        Id = 0;
     cc65_addr       Start = 0;
     cc65_addr       Size = 0;
-    StrBuf          SegName = STRBUF_INITIALIZER;
+    StrBuf          Name = STRBUF_INITIALIZER;
     StrBuf          OutputName = STRBUF_INITIALIZER;
     unsigned long   OutputOffs = 0;
     SegInfo*        S;
@@ -2837,12 +2887,12 @@ static void ParseSegment (InputData* D)
         ibId        = 0x002,
         ibOutputName= 0x004,
         ibOutputOffs= 0x008,
-        ibSegName   = 0x010,
+        ibName      = 0x010,
         ibSize      = 0x020,
         ibStart     = 0x040,
         ibType      = 0x080,
 
-        ibRequired  = ibId | ibSegName | ibStart | ibSize | ibAddrSize | ibType,
+        ibRequired  = ibId | ibName | ibStart | ibSize | ibAddrSize | ibType,
     } InfoBits = ibNone;
 
     /* Skip the SEGMENT token */
@@ -2896,9 +2946,9 @@ static void ParseSegment (InputData* D)
                 if (!StrConstFollows (D)) {
                     goto ErrorExit;
                 }
-                SB_Copy (&SegName, &D->SVal);
-                SB_Terminate (&SegName);
-                InfoBits |= ibSegName;
+                SB_Copy (&Name, &D->SVal);
+                SB_Terminate (&Name);
+                InfoBits |= ibName;
                 NextToken (D);
                 break;
 
@@ -2983,13 +3033,13 @@ static void ParseSegment (InputData* D)
     }
 
     /* Create the segment info and remember it */
-    S = NewSegInfo (&SegName, Id, Start, Size, &OutputName, OutputOffs);
+    S = NewSegInfo (&Name, Id, Start, Size, &OutputName, OutputOffs);
     CollReplaceExpand (&D->Info->SegInfoById, S, Id);
     CollAppend (&D->Info->SegInfoByName, S);
 
 ErrorExit:
     /* Entry point in case of errors */
-    SB_Done (&SegName);
+    SB_Done (&Name);
     SB_Done (&OutputName);
     return;
 }
@@ -3192,13 +3242,13 @@ static void ParseSym (InputData* D)
 
     /* Create the symbol info */
     S = NewSymInfo (&Name);
-    S->Id      = Id;
-    S->Type    = Type;
-    S->Value   = Value;
-    S->Size    = Size;
-    S->Segment = SegId;
-    S->Scope   = ScopeId;
-    S->Parent  = ParentId;
+    S->Id         = Id;
+    S->Type       = Type;
+    S->Value      = Value;
+    S->Size       = Size;
+    S->Seg.Id     = SegId;
+    S->Scope.Id   = ScopeId;
+    S->Parent.Id  = ParentId;
 
     /* Remember it */
     CollReplaceExpand (&D->Info->SymInfoById, S, Id);
@@ -3300,46 +3350,12 @@ ErrorExit:
 
 
 
-static SegInfo* FindSegInfoById (DbgInfo* D, unsigned Id)
-/* Find the SegInfo with a given Id */
-{
-    /* Get a pointer to the segment info collection */
-    Collection* SegInfos = &D->SegInfoById;
-
-    /* Do a binary search */
-    int Lo = 0;
-    int Hi = (int) CollCount (SegInfos) - 1;
-    while (Lo <= Hi) {
-
-        /* Mid of range */
-        int Cur = (Lo + Hi) / 2;
-
-        /* Get item */
-        SegInfo* CurItem = CollAt (SegInfos, Cur);
-
-        /* Found? */
-        if (Id > CurItem->Id) {
-            Lo = Cur + 1;
-        } else if (Id < CurItem->Id) {
-            Hi = Cur - 1;
-        } else {
-            /* Found! */
-            return CurItem;
-        }
-    }
-
-    /* Not found */
-    return 0;
-}
-
-
-
-static int FindFileInfoByName (Collection* FileInfos, const char* FileName,
+static int FindFileInfoByName (Collection* FileInfos, const char* Name,
                                unsigned* Index)
 /* Find the FileInfo for a given file name. The function returns true if the
  * name was found. In this case, Index contains the index of the first item
  * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for FileName.
+ * Index contains the insert position for Name.
  */
 {
     /* Do a binary search */
@@ -3355,7 +3371,7 @@ static int FindFileInfoByName (Collection* FileInfos, const char* FileName,
         FileInfo* CurItem = CollAt (FileInfos, Cur);
 
         /* Compare */
-        int Res = strcmp (CurItem->FileName, FileName);
+        int Res = strcmp (CurItem->Name, Name);
 
         /* Found? */
         if (Res < 0) {
@@ -3378,40 +3394,6 @@ static int FindFileInfoByName (Collection* FileInfos, const char* FileName,
 
 
 
-static FileInfo* FindFileInfoById (DbgInfo* D, unsigned Id)
-/* Find the FileInfo with a given Id */
-{
-    /* Get a pointer to the collection */
-    Collection* FileInfos = &D->FileInfoById;
-
-    /* Do a binary search */
-    int Lo = 0;
-    int Hi = (int) CollCount (FileInfos) - 1;
-    while (Lo <= Hi) {
-
-        /* Mid of range */
-        int Cur = (Lo + Hi) / 2;
-
-        /* Get item */
-        FileInfo* CurItem = CollAt (FileInfos, Cur);
-
-        /* Found? */
-        if (Id > CurItem->Id) {
-            Lo = Cur + 1;
-        } else if (Id < CurItem->Id) {
-            Hi = Cur - 1;
-        } else {
-            /* Found! */
-            return CurItem;
-        }
-    }
-
-    /* Not found */
-    return 0;
-}
-
-
-
 static void ProcessSegInfo (InputData* D)
 /* Postprocess segment infos */
 {
@@ -3433,83 +3415,57 @@ static void ProcessFileInfo (InputData* D)
 static void ProcessLineInfo (InputData* D)
 /* Postprocess line infos */
 {
+    unsigned I;
+
+    /* Temporary collection with line infos sorted by address */
+    Collection LineInfoByAddr = COLLECTION_INITIALIZER;
+
     /* Get pointers to the collections */
-    Collection* LineInfos = &D->Info->LineInfos;
-    Collection* FileInfos = &D->Info->FileInfoByName;
+    Collection* LineInfos = &D->Info->LineInfoById;
+    Collection* FileInfos = &D->Info->FileInfoById;
+    Collection* SegInfos  = &D->Info->SegInfoById;
+
+    /* Resize the temporary collection */
+    CollGrow (&LineInfoByAddr, CollCount (LineInfos));
 
     /* Walk over the line infos and replace the id numbers of file and segment
      * with pointers to the actual structs. Add the line info to each file
      * where it is defined.
      */
-    unsigned I = 0;
-    FileInfo* LastFileInfo = 0;
-    SegInfo*  LastSegInfo  = 0;
-    while (I < CollCount (LineInfos)) {
-
-        FileInfo* F;
-        SegInfo*  S;
+    for (I = 0; I < CollCount (LineInfos); ++I) {
 
         /* Get LineInfo struct */
         LineInfo* L = CollAt (LineInfos, I);
 
-        /* Find the FileInfo that corresponds to Id. We cache the last file
-         * info in LastFileInfo to speedup searching.
+        /* Replace the file id by a pointer to the FileInfo. Add a back
+         * pointer
          */
-        if (LastFileInfo && LastFileInfo->Id == L->File.Id) {
-            F = LastFileInfo;
+        if (L->File.Id >= CollCount (FileInfos)) {
+            ParseError (D,
+                        CC65_ERROR,
+                        "Invalid file id %u for line with id %u",
+                        L->File.Id, L->Id);
+            L->File.Info = 0;
         } else {
-            F = FindFileInfoById (D->Info, L->File.Id);
-
-            /* If we have no corresponding file info, print a warning and
-             * remove the line info.
-             */
-            if (F == 0) {
-                ParseError (D,
-                            CC65_ERROR,
-                            "No file info for file with id %u",
-                            L->File.Id);
-                FreeLineInfo (L);
-                CollDelete (LineInfos, I);
-                continue;
-            }
-
-            /* Otherwise remember it for later */
-            LastFileInfo = F;
+            L->File.Info = CollAt (FileInfos, L->File.Id);
+            CollAppend (&L->File.Info->LineInfoByLine, L);
         }
 
-        /* Replace the file id by a pointer to the file info */
-        L->File.Info = F;
-
-        /* Find the SegInfo that corresponds to Id. We cache the last file
-         * info in LastSegInfo to speedup searching.
-         */
-        if (LastSegInfo && LastSegInfo->Id == L->Seg.Id) {
-            S = LastSegInfo;
+        /* Replace the segment id by a pointer to the SegInfo */
+        if (L->Seg.Id >= CollCount (SegInfos)) {
+            ParseError (D,
+                        CC65_ERROR,
+                        "Invalid segment id %u for line with id %u",
+                        L->Seg.Id, L->Id);
+            L->Seg.Info = 0;
         } else {
-            S = FindSegInfoById (D->Info, L->Seg.Id);
-
-            /* If we have no corresponding segment info, print a warning and
-             * remove the line info.
-             */
-            if (S == 0) {
-                ParseError (D,
-                            CC65_ERROR,
-                            "No segment info for segment with id %u",
-                            L->Seg.Id);
-                FreeLineInfo (L);
-                CollDelete (LineInfos, I);
-                continue;
-            }
-
-            /* Otherwise remember it for later */
-            LastSegInfo = S;
+            L->Seg.Info = CollAt (SegInfos, L->Seg.Id);
         }
 
-        /* Replace the segment id by a pointer to the segment info */
-        L->Seg.Info = S;
-
-        /* Add this line info to the file where it is defined */
-        CollAppend (&F->LineInfoByLine, L);
+        /* Append this line info to the temporary collection that is later
+         * sorted by address.
+         */
+        CollAppend (&LineInfoByAddr, L);
 
         /* Next one */
         ++I;
@@ -3528,10 +3484,13 @@ static void ProcessLineInfo (InputData* D)
     }
 
     /* Sort the collection with all line infos by address */
-    CollSort (LineInfos, CompareLineInfoByAddr);
+    CollSort (&LineInfoByAddr, CompareLineInfoByAddr);
 
     /* Create the line info list from the line info collection */
-    CreateLineInfoList (&D->Info->LineInfoByAddr, LineInfos);
+    CreateLineInfoList (&D->Info->LineInfoByAddr, &LineInfoByAddr);
+
+    /* Remove the temporary collection */
+    DoneCollection (&LineInfoByAddr);
 }
 
 
@@ -3620,49 +3579,11 @@ static void ProcessSymInfo (InputData* D)
 
 
 
-static int FindSymInfoById (Collection* SymInfos, unsigned Id, unsigned* Index)
-/* Find the SymInfo for a given id. The function returns true if the id
- * was found. In this case, Index contains the index of the first item that
- * matches. If the item wasn't found, the function returns false and Index
- * contains the insert position for the given id.
- */
-{
-    /* Do a binary search */
-    int Lo = 0;
-    int Hi = (int) CollCount (SymInfos) - 1;
-    int Found = 0;
-    while (Lo <= Hi) {
-
-        /* Mid of range */
-        int Cur = (Lo + Hi) / 2;
-
-        /* Get item */
-        SymInfo* CurItem = CollAt (SymInfos, Cur);
-
-        /* Found? */
-        if (Id > CurItem->Id) {
-            Lo = Cur + 1;
-        } else if (Id < CurItem->Id) {
-            Hi = Cur - 1;
-        } else {
-            Found = 1;
-            Lo = Cur;
-            break;
-        }
-    }
-
-    /* Pass back the index. This is also the insert position */
-    *Index = Lo;
-    return Found;
-}
-
-
-
-static int FindSymInfoByName (Collection* SymInfos, const char* SymName, unsigned* Index)
+static int FindSymInfoByName (Collection* SymInfos, const char* Name, unsigned* Index)
 /* Find the SymInfo for a given file name. The function returns true if the
  * name was found. In this case, Index contains the index of the first item
  * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for SymName.
+ * Index contains the insert position for Name.
  */
 {
     /* Do a binary search */
@@ -3678,7 +3599,7 @@ static int FindSymInfoByName (Collection* SymInfos, const char* SymName, unsigne
         SymInfo* CurItem = CollAt (SymInfos, Cur);
 
         /* Compare */
-        int Res = strcmp (CurItem->SymName, SymName);
+        int Res = strcmp (CurItem->Name, Name);
 
         /* Found? */
         if (Res < 0) {
@@ -3744,65 +3665,8 @@ static int FindSymInfoByValue (Collection* SymInfos, long Value, unsigned* Index
 static void ProcessScopeInfo (InputData* D)
 /* Postprocess scope infos */
 {
-    unsigned I;
-
     /* Get pointers to the scope info collections */
     Collection* ScopeInfoById = &D->Info->ScopeInfoById;
-
-    /* Walk over all scope infos and replace the parent scope id by a pointer
-     * to the parent scope.
-     */
-    for (I = 0; I < CollCount (ScopeInfoById); ++I) {
-
-        /* Get this scope info */
-        ScopeInfo* S = CollAt (ScopeInfoById, I);
-
-        /* Replace the parent id by a pointer */
-        if (S->Parent.Id != CC65_INV_ID) {
-            S->Parent.Scope = CollAt (ScopeInfoById, S->Parent.Id);
-        } else {
-            /* No parent */
-            S->Parent.Scope = 0;
-        }
-    }
-}
-
-
-
-static int FindScopeInfoById (Collection* ScopeInfos, unsigned Id, unsigned* Index)
-/* Find the ScopeInfo for a given id. The function returns true if the id
- * was found. In this case, Index contains the index of the first item that
- * matches. If the item wasn't found, the function returns false and Index
- * contains the insert position for the given id.
- */
-{
-    /* Do a binary search */
-    int Lo = 0;
-    int Hi = (int) CollCount (ScopeInfos) - 1;
-    int Found = 0;
-    while (Lo <= Hi) {
-
-        /* Mid of range */
-        int Cur = (Lo + Hi) / 2;
-
-        /* Get item */
-        SymInfo* CurItem = CollAt (ScopeInfos, Cur);
-
-        /* Found? */
-        if (Id > CurItem->Id) {
-            Lo = Cur + 1;
-        } else if (Id < CurItem->Id) {
-            Hi = Cur - 1;
-        } else {
-            Found = 1;
-            Lo = Cur;
-            break;
-        }
-    }
-
-    /* Pass back the index. This is also the insert position */
-    *Index = Lo;
-    return Found;
 }
 
 
@@ -3967,11 +3831,6 @@ CloseAndExit:
      */
     if (D.Errors > 0) {
         /* Free allocated stuff */
-        unsigned I;
-        for (I = 0; I < CollCount (&D.Info->LineInfos); ++I) {
-            FreeLineInfo (CollAt (&D.Info->LineInfos, I));
-        }
-        DoneCollection (&D.Info->LineInfos);
         FreeDbgInfo (D.Info);
         return 0;
     }
@@ -4006,6 +3865,89 @@ void cc65_free_dbginfo (cc65_dbginfo Handle)
 
 
 
+/*****************************************************************************/
+/*                                 Libraries                                 */
+/*****************************************************************************/
+
+
+
+cc65_libraryinfo* cc65_get_librarylist (cc65_dbginfo Handle)
+/* Return a list of all libraries */
+{
+    DbgInfo*            Info;
+    Collection*         LibInfoById;
+    cc65_libraryinfo*   D;
+    unsigned            I;
+
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = (DbgInfo*) Handle;
+
+    /* Get a pointer to the library list */
+    LibInfoById = &Info->LibInfoById;
+
+    /* Allocate memory for the data structure returned to the caller */
+    D = new_cc65_libraryinfo (CollCount (LibInfoById));
+
+    /* Fill in the data */
+    for (I = 0; I < CollCount (LibInfoById); ++I) {
+        /* Copy the data */
+        CopyLibInfo (D->data + I, CollAt (LibInfoById, I));
+    }
+
+    /* Return the result */
+    return D;
+}
+
+
+
+cc65_libraryinfo* cc65_libraryinfo_byid (cc65_dbginfo Handle, unsigned Id)
+/* Return information about a library with a specific id. The function
+ * returns NULL if the id is invalid (no such library) and otherwise a
+ * cc65_libraryinfo structure with one entry that contains the requested
+ * library information.
+ */
+{
+    DbgInfo*            Info;
+    cc65_libraryinfo*   D;
+
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = (DbgInfo*) Handle;
+
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->LibInfoById)) {
+        return 0;
+    }
+
+    /* Allocate memory for the data structure returned to the caller */
+    D = new_cc65_libraryinfo (1);
+
+    /* Fill in the data */
+    CopyLibInfo (D->data, CollAt (&Info->LibInfoById, Id));
+
+    /* Return the result */
+    return D;
+}
+
+
+
+void cc65_free_libraryinfo (cc65_dbginfo Handle, cc65_libraryinfo* Info)
+/* Free a library info record */
+{
+    /* Just for completeness, check the handle */
+    assert (Handle != 0);
+
+    /* Just free the memory */
+    xfree (Info);
+}
+
+
+
 /*****************************************************************************/
 /*                                 Line info                                 */
 /*****************************************************************************/
@@ -4111,7 +4053,7 @@ cc65_lineinfo* cc65_lineinfo_byname (cc65_dbginfo Handle, const char* FileName,
          */
         if (FileIndex < CollCount (&Info->FileInfoByName)) {
             F = CollAt (&Info->FileInfoByName, FileIndex);
-            Found = (strcmp (F->FileName, FileName) == 0);
+            Found = (strcmp (F->Name, FileName) == 0);
         } else {
             Found = 0;
         }
@@ -4152,6 +4094,89 @@ void cc65_free_lineinfo (cc65_dbginfo Handle, cc65_lineinfo* Info)
 
 
 
+/*****************************************************************************/
+/*                                  Modules                                  */
+/*****************************************************************************/
+
+
+
+cc65_moduleinfo* cc65_get_modulelist (cc65_dbginfo Handle)
+/* Return a list of all modules */
+{
+    DbgInfo*            Info;
+    Collection*         ModInfoById;
+    cc65_moduleinfo*    D;
+    unsigned            I;
+
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = (DbgInfo*) Handle;
+
+    /* Get a pointer to the module list */
+    ModInfoById = &Info->ModInfoById;
+
+    /* Allocate memory for the data structure returned to the caller */
+    D = new_cc65_moduleinfo (CollCount (ModInfoById));
+
+    /* Fill in the data */
+    for (I = 0; I < CollCount (ModInfoById); ++I) {
+        /* Copy the data */
+        CopyModInfo (D->data + I, CollAt (ModInfoById, I));
+    }
+
+    /* Return the result */
+    return D;
+}
+
+
+
+cc65_moduleinfo* cc65_moduleinfo_byid (cc65_dbginfo Handle, unsigned Id)
+/* Return information about a module with a specific id. The function
+ * returns NULL if the id is invalid (no such module) and otherwise a
+ * cc65_moduleinfo structure with one entry that contains the requested
+ * module information.
+ */
+{
+    DbgInfo*            Info;
+    cc65_moduleinfo*    D;
+
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = (DbgInfo*) Handle;
+
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->ModInfoById)) {
+        return 0;
+    }
+
+    /* Allocate memory for the data structure returned to the caller */
+    D = new_cc65_moduleinfo (1);
+
+    /* Fill in the data */
+    CopyModInfo (D->data, CollAt (&Info->ModInfoById, Id));
+
+    /* Return the result */
+    return D;
+}
+
+
+
+void cc65_free_moduleinfo (cc65_dbginfo Handle, cc65_moduleinfo* Info)
+/* Free a module info record */
+{
+    /* Just for completeness, check the handle */
+    assert (Handle != 0);
+
+    /* Just free the memory */
+    xfree (Info);
+}
+
+
+
 /*****************************************************************************/
 /*                               Source files                                */
 /*****************************************************************************/
@@ -4162,7 +4187,7 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle)
 /* Return a list of all source files */
 {
     DbgInfo*            Info;
-    Collection*         FileInfoByName;
+    Collection*         FileInfoById;
     cc65_sourceinfo*    D;
     unsigned            I;
 
@@ -4173,34 +4198,15 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle)
     Info = (DbgInfo*) Handle;
 
     /* Get a pointer to the file list */
-    FileInfoByName = &Info->FileInfoByName;
-
-    /* Allocate memory for the data structure returned to the caller.
-     * Note: To simplify things, we will allocate the maximum amount of
-     * memory, we may need later. This saves us the overhead of walking
-     * the list twice.
-     */
-    D = new_cc65_sourceinfo (CollCount (FileInfoByName));
+    FileInfoById = &Info->FileInfoById;
 
-    /* Fill in the data, skipping duplicate entries */
-    D->count = 0;
-    for (I = 0; I < CollCount (FileInfoByName); ++I) {
-
-        /* Get this item */
-        const FileInfo* F = CollAt (FileInfoByName, I);
-
-        /* If this is not the first entry, compare it to the last one and
-         * don't add it if it is identical.
-         */
-        if (I > 0 && CompareFileInfoByName (F, CollAt (FileInfoByName, I-1)) == 0) {
-            continue;
-        }
+    /* Allocate memory for the data structure returned to the caller. */
+    D = new_cc65_sourceinfo (CollCount (FileInfoById));
 
+    /* Fill in the data */
+    for (I = 0; I < CollCount (FileInfoById); ++I) {
         /* Copy the data */
-        CopyFileInfo (D->data + D->count, F);
-
-        /* One more valid entry */
-        ++D->count;
+        CopyFileInfo (D->data + I, CollAt (FileInfoById, I));
     }
 
     /* Return the result */
@@ -4217,7 +4223,6 @@ cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo Handle, unsigned Id)
  */
 {
     DbgInfo*            Info;
-    const FileInfo*     F;
     cc65_sourceinfo*    D;
 
     /* Check the parameter */
@@ -4226,11 +4231,8 @@ cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = (DbgInfo*) Handle;
 
-    /* Search for the Id */
-    F = FindFileInfoById (Info, Id);
-
-    /* If not found return NULL */
-    if (F == 0) {
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->FileInfoById)) {
         return 0;
     }
 
@@ -4238,7 +4240,7 @@ cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo Handle, unsigned Id)
     D = new_cc65_sourceinfo (1);
 
     /* Fill in the data */
-    CopyFileInfo (D->data, F);
+    CopyFileInfo (D->data, CollAt (&Info->FileInfoById, Id));
 
     /* Return the result */
     return D;
@@ -4286,7 +4288,6 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
     D = new_cc65_segmentinfo (CollCount (SegInfoByName));
 
     /* Fill in the data */
-    D->count = CollCount (SegInfoByName);
     for (I = 0; I < CollCount (SegInfoByName); ++I) {
         /* Copy the data */
         CopySegInfo (D->data + I, CollAt (SegInfoByName, I));
@@ -4305,7 +4306,6 @@ cc65_segmentinfo* cc65_segmentinfo_byid (cc65_dbginfo Handle, unsigned Id)
  */
 {
     DbgInfo*            Info;
-    const SegInfo*      S;
     cc65_segmentinfo*   D;
 
     /* Check the parameter */
@@ -4314,11 +4314,8 @@ cc65_segmentinfo* cc65_segmentinfo_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = (DbgInfo*) Handle;
 
-    /* Search for the Id */
-    S = FindSegInfoById (Info, Id);
-
-    /* If not found return NULL */
-    if (S == 0) {
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->SegInfoById)) {
         return 0;
     }
 
@@ -4326,7 +4323,7 @@ cc65_segmentinfo* cc65_segmentinfo_byid (cc65_dbginfo Handle, unsigned Id)
     D = new_cc65_segmentinfo (1);
 
     /* Fill in the data */
-    CopySegInfo (D->data, S);
+    CopySegInfo (D->data, CollAt (&Info->SegInfoById, Id));
 
     /* Return the result */
     return D;
@@ -4358,9 +4355,7 @@ cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id)
  */
 {
     DbgInfo*            Info;
-    Collection*         SymInfoById;
     cc65_symbolinfo*    D;
-    unsigned            Index;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -4368,12 +4363,8 @@ cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = (DbgInfo*) Handle;
 
-    /* Get a pointer to the symbol list */
-    SymInfoById = &Info->SymInfoById;
-
-    /* Search for the symbol */
-    if (!FindSymInfoById (SymInfoById, Id, &Index)) {
-        /* Not found */
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->SymInfoById)) {
         return 0;
     }
 
@@ -4381,7 +4372,7 @@ cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id)
     D = new_cc65_symbolinfo (1);
 
     /* Fill in the data */
-    CopySymInfo (D->data, CollAt (SymInfoById, Index));
+    CopySymInfo (D->data, CollAt (&Info->SymInfoById, Id));
 
     /* Return the result */
     return D;
@@ -4422,7 +4413,7 @@ cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
     Count = 1;
     while ((unsigned) Index + Count < CollCount (SymInfoByName)) {
         const SymInfo* S = CollAt (SymInfoByName, (unsigned) Index + Count);
-        if (strcmp (S->SymName, Name) != 0) {
+        if (strcmp (S->Name, Name) != 0) {
             break;
         }
         ++Count;
@@ -4543,9 +4534,7 @@ cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id)
  */
 {
     DbgInfo*            Info;
-    Collection*         ScopeInfoById;
     cc65_scopeinfo*     D;
-    unsigned            Index;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -4553,12 +4542,8 @@ cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = (DbgInfo*) Handle;
 
-    /* Get a pointer to the scope list */
-    ScopeInfoById = &Info->ScopeInfoById;
-
-    /* Search for the scope */
-    if (!FindScopeInfoById (ScopeInfoById, Id, &Index)) {
-        /* Not found */
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->ScopeInfoById)) {
         return 0;
     }
 
@@ -4566,7 +4551,7 @@ cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id)
     D = new_cc65_scopeinfo (1);
 
     /* Fill in the data */
-    CopyScopeInfo (D->data, CollAt (ScopeInfoById, Index));
+    CopyScopeInfo (D->data, CollAt (&Info->ScopeInfoById, Id));
 
     /* Return the result */
     return D;
index ef80377008af13f6112135b5f0ed64ebb8a3d4b7..5342ed15797df0f1f61431aa291e3da182eda6fd 100644 (file)
@@ -58,14 +58,17 @@ typedef unsigned cc65_line;             /* Used to store line numbers */
 typedef unsigned cc65_addr;             /* Used to store (65xx) addresses */
 typedef unsigned cc65_size;             /* Used to store (65xx) sizes */
 
-/* Pointer to an opaque data structure containing information from the debug
- * info file. Actually a handle to the data in the file.
- */
-typedef void* cc65_dbginfo;
-
 /* A value that is used to mark invalid ids */
 #define CC65_INV_ID     (~0U)
 
+
+
+/*****************************************************************************/
+/*                             Debug info files                              */
+/*****************************************************************************/
+
+
+
 /* Severity for cc65_parseerror */
 typedef enum {
     CC65_WARNING,
@@ -85,6 +88,68 @@ struct cc65_parseerror {
 /* Function that is called in case of parse errors */
 typedef void (*cc65_errorfunc) (const struct cc65_parseerror*);
 
+/* Pointer to an opaque data structure containing information from the debug
+ * info file. Actually a handle to the data in the file.
+ */
+typedef void* cc65_dbginfo;
+
+
+
+cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc);
+/* Parse the debug info file with the given name. On success, the function
+ * will return a pointer to an opaque cc65_dbginfo structure, that must be
+ * passed to the other functions in this module to retrieve information.
+ * errorfunc is called in case of warnings and errors. If the file cannot be
+ * read successfully, NULL is returned.
+ */
+
+void cc65_free_dbginfo (cc65_dbginfo Handle);
+/* Free debug information read from a file */
+
+
+
+/*****************************************************************************/
+/*                                 Libraries                                 */
+/*****************************************************************************/
+
+
+
+/* Library information */
+typedef struct cc65_librarydata cc65_librarydata;
+struct cc65_librarydata {
+    unsigned            library_id;     /* The internal library id */
+    const char*         library_name;   /* Name of the library */
+};
+
+typedef struct cc65_libraryinfo cc65_libraryinfo;
+struct cc65_libraryinfo {
+    unsigned            count;          /* Number of data sets that follow */
+    cc65_librarydata    data[1];        /* Data sets, number is dynamic */
+};
+
+
+
+cc65_libraryinfo* cc65_get_librarylist (cc65_dbginfo handle);
+/* Return a list of all libraries */
+
+cc65_libraryinfo* cc65_libraryinfo_byid (cc65_dbginfo handle, unsigned id);
+/* Return information about a library with a specific id. The function
+ * returns NULL if the id is invalid (no such library) and otherwise a
+ * cc65_libraryinfo structure with one entry that contains the requested
+ * library information.
+ */
+
+void cc65_free_libraryinfo (cc65_dbginfo handle, cc65_libraryinfo* info);
+/* Free a library info record */
+
+
+
+/*****************************************************************************/
+/*                                 Line info                                 */
+/*****************************************************************************/
+
+
+
 /* Type of line */
 typedef enum {
     CC65_LINE_ASM,                      /* Assembler source */
@@ -120,140 +185,82 @@ struct cc65_lineinfo {
     cc65_linedata       data[1];        /* Data sets, number is dynamic */
 };
 
-/* Source file information */
-typedef struct cc65_sourcedata cc65_sourcedata;
-struct cc65_sourcedata {
-    unsigned            source_id;      /* The internal file id */
-    const char*         source_name;    /* Name of the file */
-    unsigned long       source_size;    /* Size of file */
-    unsigned long       source_mtime;   /* Modification time */
-};
 
-typedef struct cc65_sourceinfo cc65_sourceinfo;
-struct cc65_sourceinfo {
-    unsigned            count;          /* Number of data sets that follow */
-    cc65_sourcedata     data[1];        /* Data sets, number is dynamic */
-};
 
-/* Segment information.
- * Notes:
- *   - output_name may be NULL if the data wasn't written to the output file
- *     (example: bss segment)
- *   - output_offs is invalid if there is no output_name, and may not be of
- *     much use in case of a relocatable output file
+cc65_lineinfo* cc65_lineinfo_byaddr (cc65_dbginfo handle, unsigned long addr);
+/* Return line information for the given address. The function returns NULL
+ * if no line information was found.
  */
-typedef struct cc65_segmentdata cc65_segmentdata;
-struct cc65_segmentdata {
-    unsigned            segment_id;     /* The internal segment id */
-    const char*         segment_name;   /* Name of the segment */
-    cc65_addr           segment_start;  /* Start address of segment */
-    cc65_addr           segment_size;   /* Size of segment */
-    const char*         output_name;    /* Output file this seg was written to */
-    unsigned long       output_offs;    /* Offset of this seg in output file */
-};
 
-typedef struct cc65_segmentinfo cc65_segmentinfo;
-struct cc65_segmentinfo {
-    unsigned            count;          /* Number of data sets that follow */
-    cc65_segmentdata    data[1];        /* Data sets, number is dynamic */
-};
+cc65_lineinfo* cc65_lineinfo_byname (cc65_dbginfo handle, const char* filename,
+                                     cc65_line line);
+/* Return line information for a file/line number combination. The function
+ * returns NULL if no line information was found.
+ */
 
-/* Symbol information */
-typedef enum {
-    CC65_SYM_EQUATE,
-    CC65_SYM_LABEL,                     /* Some sort of address */
-} cc65_symbol_type;
+void cc65_free_lineinfo (cc65_dbginfo handle, cc65_lineinfo* info);
+/* Free line info returned by one of the other functions */
 
-typedef struct cc65_symboldata cc65_symboldata;
-struct cc65_symboldata {
-    unsigned            symbol_id;      /* Id of symbol */
-    const char*         symbol_name;    /* Name of symbol */
-    cc65_symbol_type    symbol_type;    /* Type of symbol */
-    cc65_size           symbol_size;    /* Size of symbol, 0 if unknown */
-    long                symbol_value;   /* Value of symbol */
-    unsigned            symbol_segment; /* If the symbol is segment relative,
-                                         * this contains the id of segment,
-                                         * otherwise CC65_INV_ID
-                                         */
-    unsigned            scope_id;       /* The scope this symbol is in */
-};
 
-typedef struct cc65_symbolinfo cc65_symbolinfo;
-struct cc65_symbolinfo {
-    unsigned            count;          /* Number of data sets that follow */
-    cc65_symboldata     data[1];        /* Data sets, number is dynamic */
-};
 
-/* Scope information */
-typedef enum {
-    CC65_SCOPE_GLOBAL,                  /* Global scope */
-    CC65_SCOPE_MODULE,                  /* Module scope */
-    CC65_SCOPE_SCOPE,                   /* .PROC/.SCOPE */
-    CC65_SCOPE_STRUCT,                  /* .STRUCT */
-    CC65_SCOPE_ENUM,                    /* .ENUM */
-} cc65_scope_type;
+/*****************************************************************************/
+/*                                  Modules                                  */
+/*****************************************************************************/
 
-typedef struct cc65_scopedata cc65_scopedata;
-struct cc65_scopedata {
-    unsigned            scope_id;       /* Id of scope */
-    const char*         scope_name;     /* Name of scope */
-    cc65_scope_type     scope_type;     /* Type of scope */
-    cc65_size           scope_size;     /* Size of scope, 0 if unknown */
-    unsigned            scope_parent;   /* Id of parent scope */
+
+
+/* Module information */
+typedef struct cc65_moduledata cc65_moduledata;
+struct cc65_moduledata {
+    unsigned            module_id;      /* The internal module id */
+    const char*         module_name;    /* Name of the module */
+    unsigned            source_id;      /* Id of the module main file */
+    unsigned            library_id;     /* Id of the library if any */
 };
 
-typedef struct cc65_scopeinfo cc65_scopeinfo;
-struct cc65_scopeinfo {
+typedef struct cc65_moduleinfo cc65_moduleinfo;
+struct cc65_moduleinfo {
     unsigned            count;          /* Number of data sets that follow */
-    cc65_scopedata      data[1];        /* Data sets, number is dynamic */
+    cc65_moduledata     data[1];        /* Data sets, number is dynamic */
 };
 
 
 
-/*****************************************************************************/
-/*                             Debug info files                              */
-/*****************************************************************************/
-
-
+cc65_moduleinfo* cc65_get_modulelist (cc65_dbginfo handle);
+/* Return a list of all modules */
 
-cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc);
-/* Parse the debug info file with the given name. On success, the function
- * will return a pointer to an opaque cc65_dbginfo structure, that must be
- * passed to the other functions in this module to retrieve information.
- * errorfunc is called in case of warnings and errors. If the file cannot be
- * read successfully, NULL is returned.
+cc65_moduleinfo* cc65_moduleinfo_byid (cc65_dbginfo handle, unsigned id);
+/* Return information about a module with a specific id. The function
+ * returns NULL if the id is invalid (no such module) and otherwise a
+ * cc65_moduleinfo structure with one entry that contains the requested
+ * module information.
  */
 
-void cc65_free_dbginfo (cc65_dbginfo Handle);
-/* Free debug information read from a file */
+void cc65_free_moduleinfo (cc65_dbginfo handle, cc65_moduleinfo* info);
+/* Free a module info record */
 
 
 
 /*****************************************************************************/
-/*                                 Line info                                 */
+/*                               Source files                                */
 /*****************************************************************************/
 
 
 
-cc65_lineinfo* cc65_lineinfo_byaddr (cc65_dbginfo handle, unsigned long addr);
-/* Return line information for the given address. The function returns NULL
- * if no line information was found.
- */
-
-cc65_lineinfo* cc65_lineinfo_byname (cc65_dbginfo handle, const char* filename,
-                                     cc65_line line);
-/* Return line information for a file/line number combination. The function
- * returns NULL if no line information was found.
- */
-
-void cc65_free_lineinfo (cc65_dbginfo handle, cc65_lineinfo* info);
-/* Free line info returned by one of the other functions */
-
-
+/* Source file information */
+typedef struct cc65_sourcedata cc65_sourcedata;
+struct cc65_sourcedata {
+    unsigned            source_id;      /* The internal file id */
+    const char*         source_name;    /* Name of the file */
+    unsigned long       source_size;    /* Size of file */
+    unsigned long       source_mtime;   /* Modification time */
+};
 
-/*****************************************************************************/
-/*                               Source files                                */
-/*****************************************************************************/
+typedef struct cc65_sourceinfo cc65_sourceinfo;
+struct cc65_sourceinfo {
+    unsigned            count;          /* Number of data sets that follow */
+    cc65_sourcedata     data[1];        /* Data sets, number is dynamic */
+};
 
 
 
@@ -278,6 +285,31 @@ void cc65_free_sourceinfo (cc65_dbginfo handle, cc65_sourceinfo* info);
 
 
 
+/* Segment information.
+ * Notes:
+ *   - output_name may be NULL if the data wasn't written to the output file
+ *     (example: bss segment)
+ *   - output_offs is invalid if there is no output_name, and may not be of
+ *     much use in case of a relocatable output file
+ */
+typedef struct cc65_segmentdata cc65_segmentdata;
+struct cc65_segmentdata {
+    unsigned            segment_id;     /* The internal segment id */
+    const char*         segment_name;   /* Name of the segment */
+    cc65_addr           segment_start;  /* Start address of segment */
+    cc65_addr           segment_size;   /* Size of segment */
+    const char*         output_name;    /* Output file this seg was written to */
+    unsigned long       output_offs;    /* Offset of this seg in output file */
+};
+
+typedef struct cc65_segmentinfo cc65_segmentinfo;
+struct cc65_segmentinfo {
+    unsigned            count;          /* Number of data sets that follow */
+    cc65_segmentdata    data[1];        /* Data sets, number is dynamic */
+};
+
+
+
 cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo handle);
 /* Return a list of all segments referenced in the debug information */
 
@@ -298,6 +330,35 @@ void cc65_free_segmentinfo (cc65_dbginfo handle, cc65_segmentinfo* info);
 
 
 
+/* Symbol information */
+typedef enum {
+    CC65_SYM_EQUATE,
+    CC65_SYM_LABEL,                     /* Some sort of address */
+} cc65_symbol_type;
+
+typedef struct cc65_symboldata cc65_symboldata;
+struct cc65_symboldata {
+    unsigned            symbol_id;      /* Id of symbol */
+    const char*         symbol_name;    /* Name of symbol */
+    cc65_symbol_type    symbol_type;    /* Type of symbol */
+    cc65_size           symbol_size;    /* Size of symbol, 0 if unknown */
+    long                symbol_value;   /* Value of symbol */
+    unsigned            segment_id;     /* If the symbol is segment relative,
+                                         * this contains the id of segment,
+                                         * otherwise CC65_INV_ID
+                                         */
+    unsigned            scope_id;       /* The scope this symbol is in */
+    unsigned            parent_id;      /* Parent symbol for cheap locals */
+};
+
+typedef struct cc65_symbolinfo cc65_symbolinfo;
+struct cc65_symbolinfo {
+    unsigned            count;          /* Number of data sets that follow */
+    cc65_symboldata     data[1];        /* Data sets, number is dynamic */
+};
+
+
+
 cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo handle, unsigned id);
 /* Return the symbol with a given id. The function returns NULL if no symbol
  * with this id was found.
@@ -326,6 +387,34 @@ void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info);
 
 
 
+/* Scope information */
+typedef enum {
+    CC65_SCOPE_GLOBAL,                  /* Global scope */
+    CC65_SCOPE_MODULE,                  /* Module scope */
+    CC65_SCOPE_SCOPE,                   /* .PROC/.SCOPE */
+    CC65_SCOPE_STRUCT,                  /* .STRUCT */
+    CC65_SCOPE_ENUM,                    /* .ENUM */
+} cc65_scope_type;
+
+typedef struct cc65_scopedata cc65_scopedata;
+struct cc65_scopedata {
+    unsigned            scope_id;       /* Id of scope */
+    const char*         scope_name;     /* Name of scope */
+    cc65_scope_type     scope_type;     /* Type of scope */
+    cc65_size           scope_size;     /* Size of scope, 0 if unknown */
+    unsigned            scope_parent;   /* Id of parent scope */
+    unsigned            symbol_id;      /* Id of scope symbol if any */
+    unsigned            module_id;      /* Id of the module */
+};
+
+typedef struct cc65_scopeinfo cc65_scopeinfo;
+struct cc65_scopeinfo {
+    unsigned            count;          /* Number of data sets that follow */
+    cc65_scopedata      data[1];        /* Data sets, number is dynamic */
+};
+
+
+
 cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo handle, unsigned id);
 /* Return the scope with a given id. The function returns NULL if no scope
  * with this id was found.
index 197816c1441f16d0e8dd0559defde721395f47e2..5846007176686344a263f86bf94e96262a1916ac 100644 (file)
@@ -118,8 +118,8 @@ static void PrintSymbolData (const cc65_symboldata* D)
 /* Print the data for one symbol */
 {
     char Segment[256] = { 0 };  /* Needs dynamic alloc ### */
-    if (D->symbol_segment != CC65_INV_ID) {
-        cc65_segmentinfo* I = cc65_segmentinfo_byid (Info, D->symbol_segment);
+    if (D->segment_id != CC65_INV_ID) {
+        cc65_segmentinfo* I = cc65_segmentinfo_byid (Info, D->segment_id);
         if (I && I->count == 1) {
             sprintf (Segment, "segment=%s,", I->data[0].segment_name);
             cc65_free_segmentinfo (Info, I);