]> git.sur5r.net Git - cc65/commitdiff
Added code to parse type strings and convert them into a set of cc65_typedata
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 25 Aug 2011 18:59:25 +0000 (18:59 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 25 Aug 2011 18:59:25 +0000 (18:59 +0000)
structures. Added cc65_type_byid and cc65_free_typedata (a dummy).

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

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

index f0a902190de5352909998e16ee1d0d576d250b98..ca089cd3b244a3ff379413433528816c551961bf 100644 (file)
@@ -171,8 +171,6 @@ typedef enum {
     TOK_IDENT,                          /* To catch unknown keywords */
 } Token;
 
-
-
 /* Data structure containing information from the debug info file. A pointer
  * to this structure is passed as handle to callers from the outside.
  */
@@ -369,8 +367,21 @@ struct SymInfo {
 /* Internally used type info struct */
 struct TypeInfo {
     unsigned            Id;             /* Id of type */
-    unsigned            Length;         /* Length of following data */
-    unsigned char       Data[1];        /* Data, dynamically allocated */
+    cc65_typedata       Data[1];        /* Data, dynamically allocated */
+};
+
+/* A structure used when parsing a type string into a set of cc65_typedata
+ * structures.
+ */
+typedef struct TypeParseData TypeParseData;
+struct TypeParseData {
+    TypeInfo*           Info;
+    unsigned            ItemCount;
+    unsigned            ItemIndex;
+    cc65_typedata*      ItemData;
+    const StrBuf*       Type;
+    unsigned            Pos;
+    unsigned            Error;
 };
 
 
@@ -525,6 +536,14 @@ static unsigned SB_GetLen (const StrBuf* B)
 
 
 
+static char* SB_GetBuf (StrBuf* B)
+/* Return a buffer pointer */
+{
+    return B->Buf;
+}
+
+
+
 static const char* SB_GetConstBuf (const StrBuf* B)
 /* Return a buffer pointer */
 {
@@ -533,6 +552,15 @@ static const char* SB_GetConstBuf (const StrBuf* B)
 
 
 
+static char SB_At (const StrBuf* B, unsigned Pos)
+/* Return the character from a specific position */
+{
+    assert (Pos <= B->Len);
+    return B->Buf[Pos];
+}
+
+
+
 static void SB_Terminate (StrBuf* B)
 /* Zero terminate the given string buffer. NOTE: The terminating zero is not
  * accounted for in B->Len, if you want that, you have to use AppendChar!
@@ -1001,6 +1029,112 @@ static void DBGPRINT(const char* format, ...) {}
 
 
 
+/*****************************************************************************/
+/*                             Helper functions                              */
+/*****************************************************************************/
+
+
+
+static unsigned HexValue (char C)
+/* Convert the ascii representation of a hex nibble into the hex nibble */
+{
+    if (isdigit (C)) {
+        return C - '0';
+    } else if (islower (C)) {
+        return C - 'a' + 10;
+    } else {
+        return C - 'A' + 10;
+    }
+}
+
+
+
+static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...)
+/* Call the user supplied parse error function */
+{
+    va_list             ap;
+    int                 MsgSize;
+    cc65_parseerror*    E;
+
+    /* Test-format the error message so we know how much space to allocate */
+    va_start (ap, Msg);
+    MsgSize = vsnprintf (0, 0, Msg, ap);
+    va_end (ap);
+
+    /* Allocate memory */
+    E = xmalloc (sizeof (*E) + MsgSize);
+
+    /* Write data to E */
+    E->type   = Type;
+    E->name   = D->FileName;
+    E->line   = D->SLine;
+    E->column = D->SCol;
+    va_start (ap, Msg);
+    vsnprintf (E->errormsg, MsgSize+1, Msg, ap);
+    va_end (ap);
+
+    /* Call the caller:-) */
+    D->Error (E);
+
+    /* Free the data structure */
+    xfree (E);
+
+    /* Count errors */
+    if (Type == CC65_ERROR) {
+        ++D->Errors;
+    }
+}
+
+
+
+static void SkipLine (InputData* D)
+/* Error recovery routine. Skip tokens until EOL or EOF is reached */
+{
+    while (D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
+        NextToken (D);
+    }
+}
+
+
+
+static void UnexpectedToken (InputData* D)
+/* Call ParseError with a message about an unexpected input token */
+{
+    ParseError (D, CC65_ERROR, "Unexpected input token %d", D->Tok);
+    SkipLine (D);
+}
+
+
+
+static void UnknownKeyword (InputData* D)
+/* Print a warning about an unknown keyword in the file. Try to do smart
+ * recovery, so if later versions of the debug information add additional
+ * keywords, this code may be able to at least ignore them.
+ */
+{
+    /* Output a warning */
+    ParseError (D, CC65_WARNING, "Unknown keyword \"%s\" - skipping",
+                SB_GetConstBuf (&D->SVal));
+
+    /* Skip the identifier */
+    NextToken (D);
+
+    /* If an equal sign follows, ignore anything up to the next line end
+     * or comma. If a comma or line end follows, we're already done. If
+     * we have none of both, we ignore the remainder of the line.
+     */
+    if (D->Tok == TOK_EQUAL) {
+        NextToken (D);
+        while (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
+            NextToken (D);
+        }
+    } else if (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
+        SkipLine (D);
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                                 File info                                 */
 /*****************************************************************************/
@@ -1663,52 +1797,283 @@ static int CompareSymInfoByVal (const void* L, const void* R)
 
 
 
-static unsigned HexValue (char C)
-/* Convert the ascii representation of a hex nibble into the hex nibble */
+/* The following definitions are actually just taken from gentype.h */
+
+/* Size of a data type */
+#define GT_SIZE_1               0x00U
+#define GT_SIZE_2               0x01U
+#define GT_SIZE_3               0x02U
+#define GT_SIZE_4               0x03U
+#define GT_SIZE_MASK            0x07U
+
+#define GT_GET_SIZE(x)          (((x) & GT_SIZE_MASK) + 1U)
+
+/* Sign of the data type */
+#define GT_UNSIGNED             0x00U
+#define GT_SIGNED               0x08U
+#define GT_SIGN_MASK            0x08U
+
+#define GT_HAS_SIGN(x)          (((x) & GT_SIZE_MASK) == GT_SIGNED)
+
+/* Byte order */
+#define GT_LITTLE_ENDIAN        0x00U
+#define GT_BIG_ENDIAN           0x10U
+#define GT_BYTEORDER_MASK       0x10U
+
+#define GT_IS_LITTLE_ENDIAN(x)  (((x) & GT_BYTEORDER_MASK) == GT_LITTLE_ENDIAN)
+#define GT_IS_BIG_ENDIAN(x)     (((x) & GT_BYTEORDER_MASK) == GT_BIG_ENDIAN)
+
+/* Type of the data. */
+#define GT_TYPE_VOID            0x00U
+#define GT_TYPE_INT             0x20U
+#define GT_TYPE_PTR             0x40U
+#define GT_TYPE_FLOAT           0x60U
+#define GT_TYPE_ARRAY           0x80U
+#define GT_TYPE_FUNC            0xA0U
+#define GT_TYPE_STRUCT          0xC0U
+#define GT_TYPE_UNION           0xE0U
+#define GT_TYPE_MASK            0xE0U
+
+#define GT_GET_TYPE(x)          ((x) & GT_TYPE_MASK)
+#define GT_IS_INTEGER(x)        (GT_GET_TYPE(x) == GT_TYPE_INTEGER)
+#define GT_IS_POINTER(x)        (GT_GET_TYPE(x) == GT_TYPE_POINTER)
+#define GT_IS_FLOAT(x)          (GT_GET_TYPE(x) == GT_TYPE_FLOAT)
+#define GT_IS_ARRAY(x)          (GT_GET_TYPE(x) == GT_TYPE_ARRAY)
+#define GT_IS_FUNCTION(x)       (GT_GET_TYPE(x) == GT_TYPE_FUNCTION)
+#define GT_IS_STRUCT(x)         (GT_GET_TYPE(x) == GT_TYPE_STRUCT)
+#define GT_IS_UNION(x)          (GT_GET_TYPE(x) == GT_TYPE_UNION)
+
+/* Combined values for the 6502 family */
+#define GT_VOID         (GT_TYPE_VOID)
+#define GT_BYTE         (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_1)
+#define GT_WORD         (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_2)
+#define GT_DWORD        (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_4)
+#define GT_DBYTE        (GT_TYPE_PTR | GT_BIG_ENDIAN    | GT_UNSIGNED | GT_SIZE_2)
+#define GT_PTR          (GT_TYPE_PTR | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_2)
+#define GT_FAR_PTR      (GT_TYPE_PTR | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_3)
+#define GT_ARRAY(size)  (GT_TYPE_ARRAY | ((size) - 1))
+
+
+
+static void FreeTypeInfo (TypeInfo* T)
+/* Free a TypeInfo struct */
 {
-    if (isdigit (C)) {
-        return C - '0';
-    } else if (islower (C)) {
-        return C - 'a' + 10;
-    } else {
-        return C - 'A' + 10;
-    }
+    xfree (T);
 }
 
 
 
-static TypeInfo* NewTypeInfo (const StrBuf* ReadableValue)
-/* Create a new TypeInfo struct, intialize and return it */
+static void InitTypeParseData (TypeParseData* P, const StrBuf* Type,
+                               unsigned ItemCount)
+/* Initialize a TypeParseData structure */
 {
-    unsigned I;
-    const char* P;
+    P->Info      = xmalloc (sizeof (*P->Info) - sizeof (P->Info->Data[0]) +
+                            ItemCount * sizeof (P->Info->Data[0]));
+    P->ItemCount = ItemCount;
+    P->ItemIndex = 0;
+    P->ItemData  = P->Info->Data;
+    P->Type      = Type;
+    P->Pos       = 0;
+    P->Error     = 0;
+}
 
-    /* Calculate the length of the final data. Since we have hex encoding, it
-     * is half of the length of ReadableValue.
-     */
-    unsigned Length = SB_GetLen (ReadableValue) / 2;
 
-    /* Allocate memory */
-    TypeInfo* T = xmalloc (sizeof (TypeInfo) + Length - 1);
 
-    /* Initialize it as necessary */
-    T->Length = Length;
-    P = SB_GetConstBuf (ReadableValue);
-    for (I = 0; I < Length; ++I) {
-        unsigned char V = (HexValue (*P++) << 4);
-        T->Data[I] = (V | HexValue (*P++));
+static cc65_typedata* TypeFromString (TypeParseData* P)
+/* Parse a type string and return a set of typedata structures. Will be called
+ * recursively. Will set P->Error and return NULL in case of problems.
+ */
+{
+    unsigned char B;
+    unsigned      I;
+    unsigned      Count;
+
+    /* Allocate a new entry */
+    if (P->ItemIndex >= P->ItemCount) {
+        P->Error = 1;
+        return 0;
     }
+    cc65_typedata* Data = &P->ItemData[P->ItemIndex++];
 
-    /* Return it */
-    return T;
+    /* Assume no following node */
+    Data->next = 0;
+
+    /* Get the next char, then skip it */
+    if (P->Pos >= SB_GetLen (P->Type)) {
+        P->Error = 1;
+        return 0;
+    }
+    B = SB_At (P->Type, P->Pos++);
+
+    switch (B) {
+
+        /* We only handle those that are currently in use */
+        case GT_VOID:
+            Data->what = CC65_TYPE_VOID;
+            Data->size = 0;
+            break;
+
+        case GT_BYTE:
+            Data->what = CC65_TYPE_BYTE;
+            Data->size = GT_GET_SIZE (B);
+            break;
+
+        case GT_WORD:
+            Data->what = CC65_TYPE_WORD;
+            Data->size = GT_GET_SIZE (B);
+            break;
+
+        case GT_DWORD:
+            Data->what = CC65_TYPE_DWORD;
+            Data->size = GT_GET_SIZE (B);
+            break;
+
+        case GT_DBYTE:
+            Data->what = CC65_TYPE_DBYTE;
+            Data->size = GT_GET_SIZE (B);
+            break;
+
+        case GT_PTR:
+            Data->what = CC65_TYPE_PTR;
+            Data->data.ptr.ind_type = TypeFromString (P);
+            Data->size = GT_GET_SIZE (B);
+            break;
+
+        case GT_FAR_PTR:
+            Data->what = CC65_TYPE_FARPTR;
+            Data->data.ptr.ind_type = TypeFromString (P);
+            Data->size = GT_GET_SIZE (B);
+            break;
+
+        default:
+            if (GT_GET_TYPE (B) == GT_TYPE_ARRAY) {
+                Count = 0;
+                I = GT_GET_SIZE (B);
+                if (I == 0 || I > 4) {
+                    P->Error = 1;
+                    break;
+                }
+                P->Pos += I;
+                if (P->Pos > SB_GetLen (P->Type)) {
+                    P->Error = 1;
+                    break;
+                }
+                while (I) {
+                    Count <<= 8;
+                    Count |= (unsigned char)  SB_At (P->Type, P->Pos - I);
+                    --I;
+                }
+                Data->what = CC65_TYPE_ARRAY;
+                Data->data.array.ele_count = Count;
+                Data->data.array.ele_type = TypeFromString (P);
+                if (!P->Error) {
+                    Data->size = Data->data.array.ele_count *
+                                 Data->data.array.ele_type->size;
+                }
+            } else {
+                /* OOPS! */
+                P->Error = 1;
+            }
+            break;
+    }
+
+    /* Return our structure or NULL in case of errors */
+    return P->Error? 0 : Data;
 }
 
 
 
-static void FreeTypeInfo (TypeInfo* T)
-/* Free a TypeInfo struct */
+
+static TypeInfo* ParseTypeString (InputData* D, StrBuf* Type)
+/* Check if the string T contains a valid type string. Convert it from readable
+ * to binary. Calculate how many cc65_typedata structures are necessary when it
+ * is converted. Convert the string into a set of cc65_typedata structures and
+ * return them.
+ */
 {
-    xfree (T);
+    unsigned        I;
+    unsigned        Count;
+    const char*     A;
+    char*           B;
+    TypeParseData   P;
+
+
+    /* The length must not be zero and divideable by two */
+    unsigned Length = SB_GetLen (Type);
+    if (Length < 2 || (Length & 0x01) != 0) {
+        ParseError (D, CC65_ERROR, "Type value has invalid length");
+        return 0;
+    }
+
+    /* The string must consist completely of hex digit chars */
+    A = SB_GetConstBuf (Type);
+    for (I = 0; I < Length; ++I) {
+        if (!isxdigit (A[I])) {
+            ParseError (D, CC65_ERROR, "Type value contains invalid characters");
+            return 0;
+        }
+    }
+
+    /* Convert the type to binary */
+    B = SB_GetBuf (Type);
+    while (A < SB_GetConstBuf (Type) + Length) {
+        /* Since we know, there are only hex digits, there can't be any errors */
+        *B++ = (HexValue (A[0]) << 4) | HexValue (A[1]);
+        A += 2;
+    }
+    Type->Len = (Length /= 2);
+
+    /* Get a pointer to the type data, then count the number of cc65_typedata
+     * items needed.
+     */
+    A = SB_GetConstBuf (Type);
+    Count = 0;
+    I = 0;
+    while (I < Length) {
+        switch (A[I]) {
+            /* We only handle those that are currently in use */
+            case GT_VOID:
+            case GT_BYTE:
+            case GT_WORD:
+            case GT_DWORD:
+            case GT_DBYTE:
+            case GT_PTR:
+            case GT_FAR_PTR:
+                ++Count;
+                ++I;
+                break;
+
+            default:
+                if (GT_GET_TYPE (A[I]) == GT_TYPE_ARRAY) {
+                    ++Count;
+                    I += GT_GET_SIZE (A[I]) + 1;
+                } else {
+                    /* Unknown type in type string */
+                    ParseError (D, CC65_ERROR, "Unkown type in type value");
+                    return 0;
+                }
+                break;
+        }
+    }
+
+    /* Check that we're even */
+    if (I != Length) {
+        ParseError (D, CC65_ERROR, "Syntax error in type in type value");
+        return 0;
+    }
+
+    /* Initialize the data structure for parsing the type string */
+    InitTypeParseData (&P, Type, Count);
+
+    /* Parse the type string and check for errors */
+    if (TypeFromString (&P) == 0 || P.ItemCount != P.ItemIndex) {
+        ParseError (D, CC65_ERROR, "Error parsing the type value");
+        FreeTypeInfo (P.Info);
+        return 0;
+    }
+
+    /* Return the result of the parse operation */
+    return P.Info;
 }
 
 
@@ -2013,114 +2378,22 @@ static void FreeDbgInfo (DbgInfo* Info)
 
 
 /*****************************************************************************/
-/*                             Helper functions                              */
+/*                            Scanner and parser                             */
 /*****************************************************************************/
 
 
 
-static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...)
-/* Call the user supplied parse error function */
+static int DigitVal (int C)
+/* Return the value for a numeric digit. Return -1 if C is invalid */
 {
-    va_list             ap;
-    int                 MsgSize;
-    cc65_parseerror*    E;
-
-    /* Test-format the error message so we know how much space to allocate */
-    va_start (ap, Msg);
-    MsgSize = vsnprintf (0, 0, Msg, ap);
-    va_end (ap);
-
-    /* Allocate memory */
-    E = xmalloc (sizeof (*E) + MsgSize);
-
-    /* Write data to E */
-    E->type   = Type;
-    E->name   = D->FileName;
-    E->line   = D->SLine;
-    E->column = D->SCol;
-    va_start (ap, Msg);
-    vsnprintf (E->errormsg, MsgSize+1, Msg, ap);
-    va_end (ap);
-
-    /* Call the caller:-) */
-    D->Error (E);
-
-    /* Free the data structure */
-    xfree (E);
-
-    /* Count errors */
-    if (Type == CC65_ERROR) {
-        ++D->Errors;
-    }
-}
-
-
-
-static void SkipLine (InputData* D)
-/* Error recovery routine. Skip tokens until EOL or EOF is reached */
-{
-    while (D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
-        NextToken (D);
-    }
-}
-
-
-
-static void UnexpectedToken (InputData* D)
-/* Call ParseError with a message about an unexpected input token */
-{
-    ParseError (D, CC65_ERROR, "Unexpected input token %d", D->Tok);
-    SkipLine (D);
-}
-
-
-
-static void UnknownKeyword (InputData* D)
-/* Print a warning about an unknown keyword in the file. Try to do smart
- * recovery, so if later versions of the debug information add additional
- * keywords, this code may be able to at least ignore them.
- */
-{
-    /* Output a warning */
-    ParseError (D, CC65_WARNING, "Unknown keyword \"%s\" - skipping",
-                SB_GetConstBuf (&D->SVal));
-
-    /* Skip the identifier */
-    NextToken (D);
-
-    /* If an equal sign follows, ignore anything up to the next line end
-     * or comma. If a comma or line end follows, we're already done. If
-     * we have none of both, we ignore the remainder of the line.
-     */
-    if (D->Tok == TOK_EQUAL) {
-        NextToken (D);
-        while (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
-            NextToken (D);
-        }
-    } else if (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
-        SkipLine (D);
-    }
-}
-
-
-
-/*****************************************************************************/
-/*                            Scanner and parser                             */
-/*****************************************************************************/
-
-
-
-static int DigitVal (int C)
-/* Return the value for a numeric digit. Return -1 if C is invalid */
-{
-    if (isdigit (C)) {
-       return C - '0';
-    } else if (isxdigit (C)) {
-       return toupper (C) - 'A' + 10;
-    } else {
-        return -1;
-    }
-}
+    if (isdigit (C)) {
+       return C - '0';
+    } else if (isxdigit (C)) {
+       return toupper (C) - 'A' + 10;
+    } else {
+        return -1;
+    }
+}
 
 
 
@@ -3933,14 +4206,11 @@ static void ParseType (InputData* D)
         goto ErrorExit;
     }
 
-    /* Check Value */
-    if (SB_GetLen (&Value) < 2 || (SB_GetLen (&Value) & 0x01) != 0) {
-        ParseError (D, CC65_ERROR, "Invalid type value");
+    /* Parse the type string to create the type info */
+    T = ParseTypeString (D, &Value);
+    if (T == 0) {
         goto ErrorExit;
     }
-
-    /* Create the type info */
-    T = NewTypeInfo (&Value);
     T->Id       = Id;
 
     /* Remember it */
@@ -5786,16 +6056,16 @@ void cc65_free_sourceinfo (cc65_dbginfo Handle, const cc65_sourceinfo* Info)
 
 
 /*****************************************************************************/
-/*                                 Segments                                  */
+/*                                  Scopes                                   */
 /*****************************************************************************/
 
 
 
-const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
-/* Return a list of all segments referenced in the debug information */
+const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo Handle)
+/* Return a list of all scopes in the debug information */
 {
     const DbgInfo*      Info;
-    cc65_segmentinfo*   D;
+    cc65_scopeinfo*     D;
     unsigned            I;
 
     /* Check the parameter */
@@ -5805,12 +6075,12 @@ const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
     Info = Handle;
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_segmentinfo (CollCount (&Info->SegInfoById));
+    D = new_cc65_scopeinfo (CollCount (&Info->ScopeInfoById));
 
     /* Fill in the data */
-    for (I = 0; I < CollCount (&Info->SegInfoById); ++I) {
+    for (I = 0; I < CollCount (&Info->ScopeInfoById); ++I) {
         /* Copy the data */
-        CopySegInfo (D->data + I, CollAt (&Info->SegInfoById, I));
+        CopyScopeInfo (D->data + I, CollAt (&Info->ScopeInfoById, I));
     }
 
     /* Return the result */
@@ -5819,14 +6089,13 @@ const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
 
 
 
-const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id)
-/* Return information about a segment with a specific id. The function returns
- * NULL if the id is invalid (no such segment) and otherwise a segmentinfo
- * structure with one entry that contains the requested segment information.
+const 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.
  */
 {
     const DbgInfo*      Info;
-    cc65_segmentinfo*   D;
+    cc65_scopeinfo*     D;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -5835,15 +6104,15 @@ const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id)
     Info = Handle;
 
     /* Check if the id is valid */
-    if (Id >= CollCount (&Info->SegInfoById)) {
+    if (Id >= CollCount (&Info->ScopeInfoById)) {
         return 0;
     }
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_segmentinfo (1);
+    D = new_cc65_scopeinfo (1);
 
     /* Fill in the data */
-    CopySegInfo (D->data, CollAt (&Info->SegInfoById, Id));
+    CopyScopeInfo (D->data, CollAt (&Info->ScopeInfoById, Id));
 
     /* Return the result */
     return D;
@@ -5851,17 +6120,15 @@ const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id)
 
 
 
-const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle,
-                                             const char* Name)
-/* Return information about a segment with a specific name. The function
- * returns NULL if no segment with this name exists and otherwise a
- * cc65_segmentinfo structure with one entry that contains the requested
- * information.
+const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId)
+/* Return the list of scopes for one module. The function returns NULL if no
+ * scope with the given id was found.
  */
 {
     const DbgInfo*      Info;
-    const SegInfo*      S;
-    cc65_segmentinfo*   D;
+    const ModInfo*      M;
+    cc65_scopeinfo*     D;
+    unsigned            I;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -5869,17 +6136,21 @@ const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle,
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Search for the segment */
-    S = FindSegInfoByName (&Info->SegInfoByName, Name);
-    if (S == 0) {
+    /* Check if the module id is valid */
+    if (ModId >= CollCount (&Info->ModInfoById)) {
         return 0;
     }
 
+    /* Get a pointer to the module info */
+    M = CollAt (&Info->ModInfoById, ModId);
+
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_segmentinfo (1);
+    D = new_cc65_scopeinfo (CollCount (&M->ScopeInfoByName));
 
     /* Fill in the data */
-    CopySegInfo (D->data, S);
+    for (I = 0; I < CollCount (&M->ScopeInfoByName); ++I) {
+        CopyScopeInfo (D->data + I, CollAt (&M->ScopeInfoByName, I));
+    }
 
     /* Return the result */
     return D;
@@ -5887,31 +6158,18 @@ const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle,
 
 
 
-void cc65_free_segmentinfo (cc65_dbginfo Handle, const cc65_segmentinfo* Info)
-/* Free a segment info record */
-{
-    /* Just for completeness, check the handle */
-    assert (Handle != 0);
-
-    /* Free the memory */
-    xfree ((cc65_segmentinfo*) Info);
-}
-
-
-
-/*****************************************************************************/
-/*                                  Symbols                                  */
-/*****************************************************************************/
-
-
-
-const 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.
+const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name)
+/* Return the list of scopes with a given name. Returns NULL if no scope with
+ * the given name was found, otherwise a non empty scope list.
  */
 {
     const DbgInfo*      Info;
-    cc65_symbolinfo*    D;
+    unsigned            Index;
+    const ScopeInfo*    S;
+    cc65_scopeinfo*     D;
+    unsigned            Count;
+    unsigned            I;
+
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -5919,16 +6177,34 @@ const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Check if the id is valid */
-    if (Id >= CollCount (&Info->SymInfoById)) {
+    /* Search for the first item with the given name */
+    if (!FindScopeInfoByName (&Info->ScopeInfoByName, Name, &Index)) {
+        /* Not found */
         return 0;
     }
 
+    /* Count scopes with this name */
+    Count = 1;
+    I = Index;
+    while (1) {
+        if (++I >= CollCount (&Info->ScopeInfoByName)) {
+            break;
+        }
+        S = CollAt (&Info->ScopeInfoByName, I);
+        if (strcmp (S->Name, Name) != 0) {
+            /* Next symbol has another name */
+            break;
+        }
+        ++Count;
+    }
+
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_symbolinfo (1);
+    D = new_cc65_scopeinfo (Count);
 
     /* Fill in the data */
-    CopySymInfo (D->data, CollAt (&Info->SymInfoById, Id));
+    for (I = 0; I < Count; ++I, ++Index) {
+        CopyScopeInfo (D->data + I, CollAt (&Info->ScopeInfoByName, Index));
+    }
 
     /* Return the result */
     return D;
@@ -5936,16 +6212,15 @@ const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id)
 
 
 
-const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
-/* Return a list of symbols with a given name. The function returns NULL if
- * no symbol with this name was found.
+const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId)
+/* Return scope information for a a span. The function returns NULL if the
+ * span id is invalid, otherwise a list of line scopes.
  */
 {
     const DbgInfo*      Info;
-    cc65_symbolinfo*    D;
+    const SpanInfo*     S;
+    cc65_scopeinfo*     D;
     unsigned            I;
-    unsigned            Index;
-    unsigned            Count;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -5953,52 +6228,42 @@ const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Search for the symbol */
-    if (!FindSymInfoByName (&Info->SymInfoByName, Name, &Index)) {
-        /* Not found */
+    /* Check if the span id is valid */
+    if (SpanId >= CollCount (&Info->SpanInfoById)) {
         return 0;
     }
 
-    /* Index contains the position. Count how many symbols with this name
-     * we have. Skip the first one, since we have at least one.
-     */
-    Count = 1;
-    while ((unsigned) Index + Count < CollCount (&Info->SymInfoByName)) {
-        const SymInfo* S = CollAt (&Info->SymInfoByName, (unsigned) Index + Count);
-        if (strcmp (S->Name, Name) != 0) {
-            break;
-        }
-        ++Count;
-    }
+    /* Get the span */
+    S = CollAt (&Info->SpanInfoById, SpanId);
 
-    /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_symbolinfo (Count);
+    /* Prepare the struct we will return to the caller */
+    D = new_cc65_scopeinfo (S->ScopeInfoList? CollCount (S->ScopeInfoList) : 0);
 
-    /* Fill in the data */
-    for (I = 0; I < Count; ++I) {
+    /* Fill in the data. Since D->ScopeInfoList may be NULL, we will use the
+     * count field of the returned data struct instead.
+     */
+    for (I = 0; I < D->count; ++I) {
         /* Copy the data */
-        CopySymInfo (D->data + I, CollAt (&Info->SymInfoByName, Index++));
+        CopyScopeInfo (D->data + I, CollAt (S->ScopeInfoList, I));
     }
 
-    /* Return the result */
+    /* Return the allocated struct */
     return D;
 }
 
 
 
-const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeId)
-/* Return a list of symbols in the given scope. This includes cheap local
- * symbols, but not symbols in subscopes. The function returns NULL if the
- * scope id is invalid (no such scope) and otherwise a - possibly empty -
- * symbol list.
+const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo Handle, unsigned Id)
+/* Return the direct child scopes of a scope with a given id. The function
+ * returns NULL if no scope with this id was found, otherwise a list of the
+ * direct childs.
  */
 {
     const DbgInfo*      Info;
-    cc65_symbolinfo*    D;
+    cc65_scopeinfo*     D;
     const ScopeInfo*    S;
     unsigned            I;
 
-
     /* Check the parameter */
     assert (Handle != 0);
 
@@ -6006,20 +6271,19 @@ const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeI
     Info = Handle;
 
     /* Check if the id is valid */
-    if (ScopeId >= CollCount (&Info->ScopeInfoById)) {
+    if (Id >= CollCount (&Info->ScopeInfoById)) {
         return 0;
     }
 
     /* Get the scope */
-    S = CollAt (&Info->ScopeInfoById, ScopeId);
+    S = CollAt (&Info->ScopeInfoById, Id);
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_symbolinfo (CollCount (&S->SymInfoByName));
+    D = new_cc65_scopeinfo (S->ChildScopeList? CollCount (S->ChildScopeList) : 0);
 
     /* Fill in the data */
-    for (I = 0; I < CollCount (&S->SymInfoByName); ++I) {
-        /* Copy the data */
-        CopySymInfo (D->data + I, CollAt (&S->SymInfoByName, I));
+    for (I = 0; I < D->count; ++I) {
+        CopyScopeInfo (D->data + I, CollAt (S->ChildScopeList, I));
     }
 
     /* Return the result */
@@ -6028,103 +6292,60 @@ const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeI
 
 
 
-const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start,
-                                            cc65_addr End)
-/* Return a list of labels in the given range. End is inclusive. The function
- * return NULL if no symbols within the given range are found. Non label
- * symbols are ignored and not returned.
- */
+void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info)
+/* Free a scope info record */
 {
-    const DbgInfo*      Info;
-    Collection          SymInfoList = COLLECTION_INITIALIZER;
-    cc65_symbolinfo*    D;
-    unsigned            I;
-    unsigned            Index;
-
-    /* Check the parameter */
+    /* Just for completeness, check the handle */
     assert (Handle != 0);
 
-    /* The handle is actually a pointer to a debug info struct */
-    Info = Handle;
+    /* Free the memory */
+    xfree ((cc65_scopeinfo*) Info);
+}
 
-    /* Search for the symbol. Because we're searching for a range, we cannot
-     * make use of the function result.
-     */
-    FindSymInfoByValue (&Info->SymInfoByVal, Start, &Index);
 
-    /* Start from the given index, check all symbols until the end address is
-     * reached. Place all symbols into SymInfoList for later.
-     */
-    for (I = Index; I < CollCount (&Info->SymInfoByVal); ++I) {
 
-        /* Get the item */
-        SymInfo* Item = CollAt (&Info->SymInfoByVal, I);
+/*****************************************************************************/
+/*                                 Segments                                  */
+/*****************************************************************************/
 
-        /* The collection is sorted by address, so if we get a value larger
-         * than the end address, we're done.
-         */
-        if (Item->Value > (long) End) {
-            break;
-        }
 
-        /* Ignore non-labels (this will also ignore imports) */
-        if (Item->Type != CC65_SYM_LABEL) {
-            continue;
-        }
 
-        /* Ok, remember this one */
-        CollAppend (&SymInfoList, Item);
-    }
+const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
+/* Return a list of all segments referenced in the debug information */
+{
+    const DbgInfo*      Info;
+    cc65_segmentinfo*   D;
+    unsigned            I;
 
-    /* If we don't have any labels within the range, bail out. No memory has
-     * been allocated for SymInfoList.
-     */
-    if (CollCount (&SymInfoList) == 0) {
-        return 0;
-    }
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = Handle;
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_symbolinfo (CollCount (&SymInfoList));
+    D = new_cc65_segmentinfo (CollCount (&Info->SegInfoById));
 
     /* Fill in the data */
-    for (I = 0; I < CollCount (&SymInfoList); ++I) {
+    for (I = 0; I < CollCount (&Info->SegInfoById); ++I) {
         /* Copy the data */
-        CopySymInfo (D->data + I, CollAt (&SymInfoList, I));
+        CopySegInfo (D->data + I, CollAt (&Info->SegInfoById, I));
     }
 
-    /* Free the collection */
-    CollDone (&SymInfoList);
-
     /* Return the result */
     return D;
 }
 
 
 
-void cc65_free_symbolinfo (cc65_dbginfo Handle, const cc65_symbolinfo* Info)
-/* Free a symbol info record */
-{
-    /* Just for completeness, check the handle */
-    assert (Handle != 0);
-
-    /* Free the memory */
-    xfree ((cc65_symbolinfo*) Info);
-}
-
-
-
-/*****************************************************************************/
-/*                                  Scopes                                   */
-/*****************************************************************************/
-
-
-
-const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo Handle)
-/* Return a list of all scopes in the debug information */
+const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id)
+/* Return information about a segment with a specific id. The function returns
+ * NULL if the id is invalid (no such segment) and otherwise a segmentinfo
+ * structure with one entry that contains the requested segment information.
+ */
 {
     const DbgInfo*      Info;
-    cc65_scopeinfo*     D;
-    unsigned            I;
+    cc65_segmentinfo*   D;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -6132,14 +6353,16 @@ const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo Handle)
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->SegInfoById)) {
+        return 0;
+    }
+
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_scopeinfo (CollCount (&Info->ScopeInfoById));
+    D = new_cc65_segmentinfo (1);
 
     /* Fill in the data */
-    for (I = 0; I < CollCount (&Info->ScopeInfoById); ++I) {
-        /* Copy the data */
-        CopyScopeInfo (D->data + I, CollAt (&Info->ScopeInfoById, I));
-    }
+    CopySegInfo (D->data, CollAt (&Info->SegInfoById, Id));
 
     /* Return the result */
     return D;
@@ -6147,13 +6370,17 @@ const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo Handle)
 
 
 
-const 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.
+const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle,
+                                             const char* Name)
+/* Return information about a segment with a specific name. The function
+ * returns NULL if no segment with this name exists and otherwise a
+ * cc65_segmentinfo structure with one entry that contains the requested
+ * information.
  */
 {
     const DbgInfo*      Info;
-    cc65_scopeinfo*     D;
+    const SegInfo*      S;
+    cc65_segmentinfo*   D;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -6161,16 +6388,17 @@ const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Check if the id is valid */
-    if (Id >= CollCount (&Info->ScopeInfoById)) {
+    /* Search for the segment */
+    S = FindSegInfoByName (&Info->SegInfoByName, Name);
+    if (S == 0) {
         return 0;
     }
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_scopeinfo (1);
+    D = new_cc65_segmentinfo (1);
 
     /* Fill in the data */
-    CopyScopeInfo (D->data, CollAt (&Info->ScopeInfoById, Id));
+    CopySegInfo (D->data, S);
 
     /* Return the result */
     return D;
@@ -6178,15 +6406,31 @@ const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id)
 
 
 
-const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId)
-/* Return the list of scopes for one module. The function returns NULL if no
- * scope with the given id was found.
+void cc65_free_segmentinfo (cc65_dbginfo Handle, const cc65_segmentinfo* Info)
+/* Free a segment info record */
+{
+    /* Just for completeness, check the handle */
+    assert (Handle != 0);
+
+    /* Free the memory */
+    xfree ((cc65_segmentinfo*) Info);
+}
+
+
+
+/*****************************************************************************/
+/*                                  Symbols                                  */
+/*****************************************************************************/
+
+
+
+const 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.
  */
 {
     const DbgInfo*      Info;
-    const ModInfo*      M;
-    cc65_scopeinfo*     D;
-    unsigned            I;
+    cc65_symbolinfo*    D;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -6194,21 +6438,16 @@ const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId)
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Check if the module id is valid */
-    if (ModId >= CollCount (&Info->ModInfoById)) {
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->SymInfoById)) {
         return 0;
     }
 
-    /* Get a pointer to the module info */
-    M = CollAt (&Info->ModInfoById, ModId);
-
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_scopeinfo (CollCount (&M->ScopeInfoByName));
+    D = new_cc65_symbolinfo (1);
 
     /* Fill in the data */
-    for (I = 0; I < CollCount (&M->ScopeInfoByName); ++I) {
-        CopyScopeInfo (D->data + I, CollAt (&M->ScopeInfoByName, I));
-    }
+    CopySymInfo (D->data, CollAt (&Info->SymInfoById, Id));
 
     /* Return the result */
     return D;
@@ -6216,18 +6455,16 @@ const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId)
 
 
 
-const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name)
-/* Return the list of scopes with a given name. Returns NULL if no scope with
- * the given name was found, otherwise a non empty scope list.
+const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
+/* Return a list of symbols with a given name. The function returns NULL if
+ * no symbol with this name was found.
  */
 {
     const DbgInfo*      Info;
+    cc65_symbolinfo*    D;
+    unsigned            I;
     unsigned            Index;
-    const ScopeInfo*    S;
-    cc65_scopeinfo*     D;
     unsigned            Count;
-    unsigned            I;
-
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -6235,33 +6472,31 @@ const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name)
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Search for the first item with the given name */
-    if (!FindScopeInfoByName (&Info->ScopeInfoByName, Name, &Index)) {
+    /* Search for the symbol */
+    if (!FindSymInfoByName (&Info->SymInfoByName, Name, &Index)) {
         /* Not found */
         return 0;
     }
 
-    /* Count scopes with this name */
+    /* Index contains the position. Count how many symbols with this name
+     * we have. Skip the first one, since we have at least one.
+     */
     Count = 1;
-    I = Index;
-    while (1) {
-        if (++I >= CollCount (&Info->ScopeInfoByName)) {
-            break;
-        }
-        S = CollAt (&Info->ScopeInfoByName, I);
+    while ((unsigned) Index + Count < CollCount (&Info->SymInfoByName)) {
+        const SymInfo* S = CollAt (&Info->SymInfoByName, (unsigned) Index + Count);
         if (strcmp (S->Name, Name) != 0) {
-            /* Next symbol has another name */
             break;
         }
         ++Count;
     }
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_scopeinfo (Count);
+    D = new_cc65_symbolinfo (Count);
 
     /* Fill in the data */
-    for (I = 0; I < Count; ++I, ++Index) {
-        CopyScopeInfo (D->data + I, CollAt (&Info->ScopeInfoByName, Index));
+    for (I = 0; I < Count; ++I) {
+        /* Copy the data */
+        CopySymInfo (D->data + I, CollAt (&Info->SymInfoByName, Index++));
     }
 
     /* Return the result */
@@ -6270,57 +6505,60 @@ const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name)
 
 
 
-const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId)
-/* Return scope information for a a span. The function returns NULL if the
- * span id is invalid, otherwise a list of line scopes.
+const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeId)
+/* Return a list of symbols in the given scope. This includes cheap local
+ * symbols, but not symbols in subscopes. The function returns NULL if the
+ * scope id is invalid (no such scope) and otherwise a - possibly empty -
+ * symbol list.
  */
 {
     const DbgInfo*      Info;
-    const SpanInfo*     S;
-    cc65_scopeinfo*     D;
+    cc65_symbolinfo*    D;
+    const ScopeInfo*    S;
     unsigned            I;
 
+
     /* Check the parameter */
     assert (Handle != 0);
 
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Check if the span id is valid */
-    if (SpanId >= CollCount (&Info->SpanInfoById)) {
+    /* Check if the id is valid */
+    if (ScopeId >= CollCount (&Info->ScopeInfoById)) {
         return 0;
     }
 
-    /* Get the span */
-    S = CollAt (&Info->SpanInfoById, SpanId);
+    /* Get the scope */
+    S = CollAt (&Info->ScopeInfoById, ScopeId);
 
-    /* Prepare the struct we will return to the caller */
-    D = new_cc65_scopeinfo (S->ScopeInfoList? CollCount (S->ScopeInfoList) : 0);
+    /* Allocate memory for the data structure returned to the caller */
+    D = new_cc65_symbolinfo (CollCount (&S->SymInfoByName));
 
-    /* Fill in the data. Since D->ScopeInfoList may be NULL, we will use the
-     * count field of the returned data struct instead.
-     */
-    for (I = 0; I < D->count; ++I) {
+    /* Fill in the data */
+    for (I = 0; I < CollCount (&S->SymInfoByName); ++I) {
         /* Copy the data */
-        CopyScopeInfo (D->data + I, CollAt (S->ScopeInfoList, I));
+        CopySymInfo (D->data + I, CollAt (&S->SymInfoByName, I));
     }
 
-    /* Return the allocated struct */
+    /* Return the result */
     return D;
 }
 
 
 
-const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo Handle, unsigned Id)
-/* Return the direct child scopes of a scope with a given id. The function
- * returns NULL if no scope with this id was found, otherwise a list of the
- * direct childs.
+const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start,
+                                            cc65_addr End)
+/* Return a list of labels in the given range. End is inclusive. The function
+ * return NULL if no symbols within the given range are found. Non label
+ * symbols are ignored and not returned.
  */
 {
     const DbgInfo*      Info;
-    cc65_scopeinfo*     D;
-    const ScopeInfo*    S;
+    Collection          SymInfoList = COLLECTION_INITIALIZER;
+    cc65_symbolinfo*    D;
     unsigned            I;
+    unsigned            Index;
 
     /* Check the parameter */
     assert (Handle != 0);
@@ -6328,38 +6566,114 @@ const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo Handle, unsigned Id)
     /* The handle is actually a pointer to a debug info struct */
     Info = Handle;
 
-    /* Check if the id is valid */
-    if (Id >= CollCount (&Info->ScopeInfoById)) {
-        return 0;
+    /* Search for the symbol. Because we're searching for a range, we cannot
+     * make use of the function result.
+     */
+    FindSymInfoByValue (&Info->SymInfoByVal, Start, &Index);
+
+    /* Start from the given index, check all symbols until the end address is
+     * reached. Place all symbols into SymInfoList for later.
+     */
+    for (I = Index; I < CollCount (&Info->SymInfoByVal); ++I) {
+
+        /* Get the item */
+        SymInfo* Item = CollAt (&Info->SymInfoByVal, I);
+
+        /* The collection is sorted by address, so if we get a value larger
+         * than the end address, we're done.
+         */
+        if (Item->Value > (long) End) {
+            break;
+        }
+
+        /* Ignore non-labels (this will also ignore imports) */
+        if (Item->Type != CC65_SYM_LABEL) {
+            continue;
+        }
+
+        /* Ok, remember this one */
+        CollAppend (&SymInfoList, Item);
     }
 
-    /* Get the scope */
-    S = CollAt (&Info->ScopeInfoById, Id);
+    /* If we don't have any labels within the range, bail out. No memory has
+     * been allocated for SymInfoList.
+     */
+    if (CollCount (&SymInfoList) == 0) {
+        return 0;
+    }
 
     /* Allocate memory for the data structure returned to the caller */
-    D = new_cc65_scopeinfo (S->ChildScopeList? CollCount (S->ChildScopeList) : 0);
+    D = new_cc65_symbolinfo (CollCount (&SymInfoList));
 
     /* Fill in the data */
-    for (I = 0; I < D->count; ++I) {
-        CopyScopeInfo (D->data + I, CollAt (S->ChildScopeList, I));
+    for (I = 0; I < CollCount (&SymInfoList); ++I) {
+        /* Copy the data */
+        CopySymInfo (D->data + I, CollAt (&SymInfoList, I));
     }
 
+    /* Free the collection */
+    CollDone (&SymInfoList);
+
     /* Return the result */
     return D;
 }
 
 
 
-void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info)
-/* Free a scope info record */
+void cc65_free_symbolinfo (cc65_dbginfo Handle, const cc65_symbolinfo* Info)
+/* Free a symbol info record */
 {
     /* Just for completeness, check the handle */
     assert (Handle != 0);
 
     /* Free the memory */
-    xfree ((cc65_scopeinfo*) Info);
+    xfree ((cc65_symbolinfo*) Info);
 }
 
 
 
+/*****************************************************************************/
+/*                                   Types                                   */
+/*****************************************************************************/
+
+
+
+const cc65_typedata* cc65_type_byid (cc65_dbginfo Handle, unsigned Id)
+/* Return the data for the type with the given id. The function returns NULL
+ * if no type with this id was found.
+ */
+{
+    const DbgInfo*        Info;
+    const TypeInfo*       T;
+
+    /* Check the parameter */
+    assert (Handle != 0);
+
+    /* The handle is actually a pointer to a debug info struct */
+    Info = Handle;
+
+    /* Check if the id is valid */
+    if (Id >= CollCount (&Info->TypeInfoById)) {
+        return 0;
+    }
+
+    /* Get the type info with the given id */
+    T = CollAt (&Info->TypeInfoById, Id);
+
+    /* We do already have the type data. Return it. */
+    return T->Data;
+}
+
+
+
+void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data)
+/* Free a symbol info record */
+{
+    /* Just for completeness, check the handle and the data*/
+    assert (Handle != 0 && data != 0);
+
+    /* Nothing to do */
+}
+
+
 
index 48d3982999b64b7a2ae02afea62d9700e9bb89c1..b2d77340ca16ba7ad6880d8a2f391d32a6c96153 100644 (file)
@@ -359,6 +359,74 @@ void cc65_free_sourceinfo (cc65_dbginfo handle, const cc65_sourceinfo* info);
 
 
 
+/*****************************************************************************/
+/*                                  Scopes                                   */
+/*****************************************************************************/
+
+
+
+/* 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            parent_id;      /* 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 */
+};
+
+
+
+const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo handle);
+/* Return a list of all scopes in the debug information */
+
+const 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.
+ */
+
+const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo handle, unsigned module_id);
+/* Return the list of scopes for one module. The function returns NULL if no
+ * scope with the given id was found.
+ */
+
+const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo handle, const char* name);
+/* Return the list of scopes with a given name. Returns NULL if no scope with
+ * the given name was found, otherwise a non empty scope list.
+ */
+
+const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo handle, unsigned span_id);
+/* Return scope information for a a span. The function returns NULL if the
+ * span id is invalid, otherwise a list of line scopes.
+ */
+
+const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo handle, unsigned id);
+/* Return the direct child scopes of a scope with a given id. The function
+ * returns NULL if no scope with this id was found, otherwise a list of the
+ * direct childs.
+ */
+
+void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info);
+/* Free a scope info record */
+
+
+
 /*****************************************************************************/
 /*                                 Segments                                  */
 /*****************************************************************************/
@@ -484,76 +552,74 @@ const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo handle,
  * symbols are ignored and not returned.
  */
 
-void cc65_free_symbolinfo (cc65_dbginfo Handle, const cc65_symbolinfo* Info);
+void cc65_free_symbolinfo (cc65_dbginfo handle, const cc65_symbolinfo* info);
 /* Free a symbol info record */
 
 
 
 /*****************************************************************************/
-/*                                  Scopes                                   */
+/*                                   Types                                   */
 /*****************************************************************************/
 
 
 
-/* Scope information */
+/* Type 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            parent_id;      /* 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 */
-};
-
-
-
-const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo handle);
-/* Return a list of all scopes in the debug information */
-
-const 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.
- */
-
-const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo handle, unsigned module_id);
-/* Return the list of scopes for one module. The function returns NULL if no
- * scope with the given id was found.
+    CC65_TYPE_VOID,
+    CC65_TYPE_BYTE,
+    CC65_TYPE_WORD,
+    CC65_TYPE_DBYTE,
+    CC65_TYPE_DWORD,
+    CC65_TYPE_PTR,
+    CC65_TYPE_FARPTR,
+    CC65_TYPE_ARRAY,
+
+    /* The following ones are currently unavailable: */
+    CC65_TYPE_UNION,
+    CC65_TYPE_STRUCT,
+    CC65_TYPE_FUNC,
+} cc65_typetoken;
+
+
+/* A type is a linked list of typedata structures. In case of arrays, the
+ * structure will contain an element count and the element type. In case of
+ * pointers, the structure will contain the type of the data, the pointer
+ * points to (currently, there are only VOID pointers).
+ * The next pointer points to the next entry in the list. It is NULL if the
+ * end of the list is reached.
  */
+typedef struct cc65_typedata cc65_typedata;
+struct cc65_typedata {
+    cc65_typedata*                next;         /* Pointer to next entry */
+    cc65_typetoken                what;         /* What kind of type is it? */
+    cc65_size                     size;         /* The size of the data */
+
+    /* Depending on "what", one of the members of this union follows */
+    union {
+
+        /* In case of CC65_TYPE_PTR or CC65_TYPE_FARPTR */
+        struct {
+            cc65_typedata*        ind_type;     /* Type the pointer points to */
+        } ptr;
+
+        /* In case of CC65_TYPE_ARRAY */
+        struct {
+            cc65_size             ele_count;    /* Element count */
+            const cc65_typedata*  ele_type;     /* Element type */
+        } array;
+
+    } data;
+};
 
-const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo handle, const char* name);
-/* Return the list of scopes with a given name. Returns NULL if no scope with
- * the given name was found, otherwise a non empty scope list.
- */
 
-const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo handle, unsigned span_id);
-/* Return scope information for a a span. The function returns NULL if the
- * span id is invalid, otherwise a list of line scopes.
- */
 
-const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo handle, unsigned id);
-/* Return the direct child scopes of a scope with a given id. The function
- * returns NULL if no scope with this id was found, otherwise a list of the
- * direct childs.
+const cc65_typedata* cc65_type_byid (cc65_dbginfo handle, unsigned id);
+/* Return the data for the type with the given id. The function returns NULL
+ * if no type with this id was found.
  */
 
-void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info);
-/* Free a scope info record */
+void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data);
+/* Free a symbol info record */