From 2b32c1466106ae016f6f73ae8129db3f1266d3b1 Mon Sep 17 00:00:00 2001 From: uz Date: Sun, 31 Jul 2011 21:32:46 +0000 Subject: [PATCH] Preparations for adding scopes. git-svn-id: svn://svn.cc65.org/cc65/trunk@5100 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 619 +++++++++++++++++++++++++++++++++++++++--- src/dbginfo/dbginfo.h | 55 +++- 2 files changed, 625 insertions(+), 49 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 80c6600a9..fc212135b 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -57,7 +57,7 @@ /* Version numbers of the debug format we understand */ #define VER_MAJOR 1U -#define VER_MINOR 2U +#define VER_MINOR 3U /* Dynamic strings */ typedef struct StrBuf StrBuf; @@ -108,8 +108,10 @@ struct DbgInfo { Collection FileInfoById; /* File infos sorted by id */ Collection LineInfos; /* List of all line infos */ LineInfoList LineInfoByAddr; /* Line infos sorted by unique address */ + Collection SymInfoById; /* Symbol infos sorted by id */ Collection SymInfoByName; /* Symbol infos sorted by name */ Collection SymInfoByVal; /* Symbol infos sorted by value */ + Collection ScopeInfoById; /* Scope infos sorted by id */ }; /* Input tokens */ @@ -143,9 +145,11 @@ typedef enum { TOK_NAME, /* NAME keyword */ TOK_OUTPUTNAME, /* OUTPUTNAME keyword */ TOK_OUTPUTOFFS, /* OUTPUTOFFS keyword */ + TOK_PARENT, /* PARENT keyword */ TOK_RANGE, /* RANGE keyword */ TOK_RO, /* RO keyword */ TOK_RW, /* RW keyword */ + TOK_SCOPE, /* SCOPE keyword */ TOK_SEGMENT, /* SEGMENT keyword */ TOK_SIZE, /* SIZE keyword */ TOK_START, /* START keyword */ @@ -221,13 +225,30 @@ struct LineInfo { /* Internally used symbol info struct */ typedef struct SymInfo SymInfo; struct SymInfo { + unsigned Id; /* Id of symbol */ 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 */ }; +/* Internally used scope info struct */ +typedef struct ScopeInfo ScopeInfo; +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 parent scope */ + ScopeInfo* Scope; /* Pointer to parent scope */ + } Parent; + char ScopeName[1]; /* Name of scope */ +}; + /*****************************************************************************/ @@ -343,6 +364,19 @@ static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count) +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 */ /*****************************************************************************/ @@ -1039,19 +1073,13 @@ static int CompareFileInfoById (const void* L, const void* R) -static SymInfo* NewSymInfo (const StrBuf* Name, long Val, - cc65_symbol_type Type, cc65_size Size, - unsigned Segment) +static SymInfo* NewSymInfo (const StrBuf* Name) /* Create a new SymInfo struct, intialize and return it */ { /* Allocate memory */ SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name)); - /* Initialize it */ - S->Type = Type; - S->Value = Val; - S->Size = Size; - S->Segment = Segment; + /* Initialize the name */ memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ @@ -1068,6 +1096,21 @@ static void FreeSymInfo (SymInfo* S) +static int CompareSymInfoById (const void* L, const void* R) +/* Helper function to sort symbol infos in a collection by id */ +{ + /* Sort by symbol id. */ + if (((const SymInfo*) L)->Id > ((const SymInfo*) R)->Id) { + return 1; + } else if (((const SymInfo*) L)->Id < ((const SymInfo*) R)->Id ) { + return -1; + } else { + return 0; + } +} + + + static int CompareSymInfoByName (const void* L, const void* R) /* Helper function to sort symbol infos in a collection by name */ { @@ -1286,6 +1329,60 @@ static void DoneLineInfoList (LineInfoList* L) +/*****************************************************************************/ +/* Scope info */ +/*****************************************************************************/ + + + +static ScopeInfo* NewScopeInfo (const StrBuf* Name) +/* Create a new ScopeInfo struct, intialize and return it */ +{ + /* Allocate memory */ + ScopeInfo* S = xmalloc (sizeof (ScopeInfo) + SB_GetLen (Name)); + + /* Initialize the name */ + memcpy (S->ScopeName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); + + /* Return it */ + return S; +} + + + +static void FreeScopeInfo (ScopeInfo* S) +/* Free a ScopeInfo struct */ +{ + xfree (S); +} + + + +static int CompareScopeInfoById (const void* L, const void* R) +/* Helper function to sort scope infos in a collection by id */ +{ + /* Sort by symbol id. */ + if (((const ScopeInfo*) L)->Id > ((const ScopeInfo*) R)->Id) { + return 1; + } else if (((const ScopeInfo*) L)->Id < ((const ScopeInfo*) R)->Id ) { + return -1; + } else { + return 0; + } +} + + + +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); +} + + + /*****************************************************************************/ /* Debug info */ /*****************************************************************************/ @@ -1305,8 +1402,10 @@ static DbgInfo* NewDbgInfo (void) InitCollection (&Info->FileInfoById); InitCollection (&Info->LineInfos); InitLineInfoList (&Info->LineInfoByAddr); + InitCollection (&Info->SymInfoById); InitCollection (&Info->SymInfoByName); InitCollection (&Info->SymInfoByVal); + InitCollection (&Info->ScopeInfoById); /* Return it */ return Info; @@ -1344,9 +1443,16 @@ static void FreeDbgInfo (DbgInfo* Info) for (I = 0; I < CollCount (&Info->SymInfoByName); ++I) { FreeSymInfo (CollAt (&Info->SymInfoByName, I)); } + DoneCollection (&Info->SymInfoById); DoneCollection (&Info->SymInfoByName); DoneCollection (&Info->SymInfoByVal); + /* Free scope info */ + for (I = 0; I < CollCount (&Info->ScopeInfoById); ++I) { + FreeScopeInfo (CollAt (&Info->ScopeInfoById, I)); + } + DoneCollection (&Info->ScopeInfoById); + /* Free the structure itself */ xfree (Info); } @@ -1384,7 +1490,7 @@ static void CopyLineInfo (cc65_linedata* D, const LineInfo* L) static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F) /* Copy data from a FileInfo struct to a cc65_sourcedata struct */ { - D->id = F->Id; + D->source_id = F->Id; D->source_name = F->FileName; D->source_size = F->Size; D->source_mtime = F->MTime; @@ -1395,7 +1501,7 @@ static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F) static void CopySegInfo (cc65_segmentdata* D, const SegInfo* S) /* Copy data from a SegInfo struct to a cc65_segmentdata struct */ { - D->id = S->Id; + D->segment_id = S->Id; D->segment_name = S->SegName; D->segment_start = S->Start; D->segment_size = S->Size; @@ -1408,11 +1514,25 @@ static void CopySegInfo (cc65_segmentdata* D, const SegInfo* 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->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; } @@ -1562,9 +1682,11 @@ static void NextToken (InputData* D) { "name", TOK_NAME }, { "outputname", TOK_OUTPUTNAME }, { "outputoffs", TOK_OUTPUTOFFS }, + { "parent", TOK_PARENT }, { "range", TOK_RANGE }, { "ro", TOK_RO }, { "rw", TOK_RW }, + { "scope", TOK_SCOPE }, { "seg", TOK_SEGMENT }, { "segment", TOK_SEGMENT }, { "size", TOK_SIZE }, @@ -2055,6 +2177,163 @@ ErrorExit: +static void ParseScope (InputData* D) +/* Parse a SCOPE line */ +{ + /* Most of the following variables are initialized with a value that is + * overwritten later. This is just to avoid compiler warnings. + */ + unsigned Id = CC65_INV_ID; + cc65_scope_type Type = CC65_SCOPE_MODULE; + cc65_size Size = 0; + StrBuf Name = STRBUF_INITIALIZER; + unsigned Parent = CC65_INV_ID; + ScopeInfo* S; + enum { + ibNone = 0x000, + + ibId = 0x001, + ibName = 0x002, + ibParent = 0x004, + ibSize = 0x008, + ibType = 0x010, + + ibRequired = ibId | ibName | ibParent | ibType, + } InfoBits = ibNone; + + /* Skip the SCOPE token */ + NextToken (D); + + /* More stuff follows */ + while (1) { + + Token Tok; + + /* Something we know? */ + if (D->Tok != TOK_ID && D->Tok != TOK_NAME && + D->Tok != TOK_PARENT && D->Tok != TOK_SIZE && + D->Tok != TOK_TYPE) { + + /* Try smart error recovery */ + if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { + UnknownKeyword (D); + continue; + } + + /* Done */ + break; + } + + /* Remember the token, skip it, check for equal */ + Tok = D->Tok; + NextToken (D); + if (!ConsumeEqual (D)) { + goto ErrorExit; + } + + /* Check what the token was */ + switch (Tok) { + + case TOK_ID: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Id = D->IVal; + InfoBits |= ibId; + NextToken (D); + break; + + case TOK_NAME: + if (!StrConstFollows (D)) { + goto ErrorExit; + } + SB_Copy (&Name, &D->SVal); + SB_Terminate (&Name); + InfoBits |= ibName; + NextToken (D); + break; + + case TOK_PARENT: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Size = D->IVal; + NextToken (D); + InfoBits |= ibParent; + break; + + case TOK_SIZE: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Size = (cc65_size) D->IVal; + InfoBits |= ibSize; + NextToken (D); + break; + + case TOK_TYPE: + switch (D->Tok) { + case TOK_EQUATE: + Type = CC65_SYM_EQUATE; + break; + case TOK_LABEL: + Type = CC65_SYM_LABEL; + break; + default: + ParseError (D, CC65_ERROR, + "Unknown value for attribute \"type\""); + SkipLine (D); + goto ErrorExit; + } + NextToken (D); + InfoBits |= ibType; + break; + + default: + /* NOTREACHED */ + UnexpectedToken (D); + goto ErrorExit; + + } + + /* Comma or done */ + if (D->Tok != TOK_COMMA) { + break; + } + NextToken (D); + } + + /* Check for end of line */ + if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { + UnexpectedToken (D); + SkipLine (D); + goto ErrorExit; + } + + /* Check for required and/or matched information */ + if ((InfoBits & ibRequired) != ibRequired) { + ParseError (D, CC65_ERROR, "Required attributes missing"); + goto ErrorExit; + } + + /* Create the scope info */ + S = NewScopeInfo (&Name); + S->Id = Id; + S->Type = Type; + S->Size = Size; + S->Parent.Id = Parent; + + /* ... and remember it */ + CollAppend (&D->Info->ScopeInfoById, S); + +ErrorExit: + /* Entry point in case of errors */ + SB_Done (&Name); + return; +} + + + static void ParseSegment (InputData* D) /* Parse a SEGMENT line */ { @@ -2066,15 +2345,17 @@ static void ParseSegment (InputData* D) unsigned long OutputOffs = 0; SegInfo* S; enum { - ibNone = 0x00, - ibId = 0x01, - ibSegName = 0x02, - ibStart = 0x04, - ibSize = 0x08, - ibAddrSize = 0x10, - ibType = 0x20, - ibOutputName= 0x40, - ibOutputOffs= 0x80, + ibNone = 0x000, + + ibAddrSize = 0x001, + ibId = 0x002, + ibOutputName= 0x004, + ibOutputOffs= 0x008, + ibSegName = 0x010, + ibSize = 0x020, + ibStart = 0x040, + ibType = 0x080, + ibRequired = ibId | ibSegName | ibStart | ibSize | ibAddrSize | ibType, } InfoBits = ibNone; @@ -2230,26 +2511,37 @@ ErrorExit: static void ParseSym (InputData* D) /* Parse a SYM line */ -{ +{ /* Most of the following variables are initialized with a value that is * overwritten later. This is just to avoid compiler warnings. */ + unsigned File = CC65_INV_ID; + unsigned Id = CC65_INV_ID; + StrBuf Name = STRBUF_INITIALIZER; + unsigned Parent = CC65_INV_ID; + unsigned Scope = CC65_INV_ID; + unsigned Segment = CC65_INV_ID; + cc65_size Size = 0; cc65_symbol_type Type = CC65_SYM_EQUATE; long Value = 0; - cc65_size Size = 0; - StrBuf SymName = STRBUF_INITIALIZER; - unsigned Segment = CC65_INV_ID; + SymInfo* S; enum { - ibNone = 0x00, - ibSymName = 0x01, - ibValue = 0x02, - ibAddrSize = 0x04, - ibType = 0x08, - ibSize = 0x10, - ibSegment = 0x20, - ibFile = 0x40, - ibRequired = ibSymName | ibValue | ibAddrSize | ibType, + ibNone = 0x000, + + ibAddrSize = 0x001, + ibFile = 0x002, + ibId = 0x004, + ibParent = 0x008, + ibScope = 0x010, + ibSegment = 0x020, + ibSize = 0x040, + ibName = 0x080, + ibType = 0x100, + ibValue = 0x200, + + ibRequired = ibAddrSize | ibId | ibScope | ibName | + ibType | ibValue, } InfoBits = ibNone; /* Skip the SYM token */ @@ -2262,9 +2554,10 @@ static void ParseSym (InputData* D) /* Something we know? */ if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_FILE && - D->Tok != TOK_NAME && D->Tok != TOK_SEGMENT&& - D->Tok != TOK_SIZE && D->Tok != TOK_TYPE && - D->Tok != TOK_VALUE) { + D->Tok != TOK_ID && D->Tok != TOK_NAME && + D->Tok != TOK_PARENT && D->Tok != TOK_SCOPE && + D->Tok != TOK_SEGMENT && D->Tok != TOK_SIZE && + D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { @@ -2295,21 +2588,48 @@ static void ParseSym (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - /* ### Drop value for now */ + File = D->IVal; InfoBits |= ibFile; NextToken (D); break; + case TOK_ID: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Id = D->IVal; + NextToken (D); + InfoBits |= ibId; + break; + case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } - SB_Copy (&SymName, &D->SVal); - SB_Terminate (&SymName); - InfoBits |= ibSymName; + SB_Copy (&Name, &D->SVal); + SB_Terminate (&Name); + InfoBits |= ibName; NextToken (D); break; + case TOK_PARENT: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Parent = D->IVal; + NextToken (D); + InfoBits |= ibParent; + break; + + case TOK_SCOPE: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Scope = D->IVal; + NextToken (D); + InfoBits |= ibScope; + break; + case TOK_SEGMENT: if (!IntConstFollows (D)) { goto ErrorExit; @@ -2382,14 +2702,24 @@ static void ParseSym (InputData* D) goto ErrorExit; } - /* Create the symbol info and remember it */ - S = NewSymInfo (&SymName, Value, Type, Size, Segment); + /* Create the symbol info */ + S = NewSymInfo (&Name); + S->Id = Id; + S->Type = Type; + S->Value = Value; + S->Size = Size; + S->Segment = Segment; + S->Scope = Scope; + S->Parent = Parent; + + /* Remember it */ + CollAppend (&D->Info->SymInfoById, S); CollAppend (&D->Info->SymInfoByName, S); CollAppend (&D->Info->SymInfoByVal, S); ErrorExit: /* Entry point in case of errors */ - SB_Done (&SymName); + SB_Done (&Name); return; } @@ -2821,16 +3151,56 @@ static void ProcessSymInfo (InputData* D) /* Postprocess symbol infos */ { /* Get pointers to the symbol info collections */ + Collection* SymInfoById = &D->Info->SymInfoById; Collection* SymInfoByName = &D->Info->SymInfoByName; Collection* SymInfoByVal = &D->Info->SymInfoByVal; /* Sort the symbol infos */ + CollSort (SymInfoById, CompareSymInfoById); CollSort (SymInfoByName, CompareSymInfoByName); CollSort (SymInfoByVal, CompareSymInfoByVal); } +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) /* 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 @@ -2914,6 +3284,70 @@ 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; + + /* Sort the scope infos */ + CollSort (ScopeInfoById, CompareScopeInfoById); + + /* 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 */ + S->Parent.Scope = CollAt (ScopeInfoById, S->Parent.Id); + } +} + + + +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; +} + + + /*****************************************************************************/ /* Debug info files */ /*****************************************************************************/ @@ -3018,6 +3452,10 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) ParseLine (&D); break; + case TOK_SCOPE: + ParseScope (&D); + break; + case TOK_SEGMENT: ParseSegment (&D); break; @@ -3074,6 +3512,7 @@ CloseAndExit: ProcessFileInfo (&D); ProcessLineInfo (&D); ProcessSymInfo (&D); + ProcessScopeInfo (&D); #if DEBUG /* Debug output */ @@ -3424,6 +3863,43 @@ void cc65_free_segmentinfo (cc65_dbginfo Handle, cc65_segmentinfo* Info) +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. + */ +{ + DbgInfo* Info; + Collection* SymInfoById; + cc65_symbolinfo* D; + unsigned Index; + + /* 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 symbol list */ + SymInfoById = &Info->SymInfoById; + + /* Search for the symbol */ + if (!FindSymInfoById (SymInfoById, Id, &Index)) { + /* Not found */ + return 0; + } + + /* Allocate memory for the data structure returned to the caller */ + D = new_cc65_symbolinfo (1); + + /* Fill in the data */ + CopySymInfo (D->data, CollAt (SymInfoById, Index)); + + /* Return the result */ + return D; +} + + + 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. @@ -3467,7 +3943,6 @@ cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name) D = new_cc65_symbolinfo (Count); /* Fill in the data */ - D->count = Count; for (I = 0; I < Count; ++I) { /* Copy the data */ CopySymInfo (D->data + I, CollAt (SymInfoByName, Index++)); @@ -3541,7 +4016,6 @@ cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start, cc65 D = new_cc65_symbolinfo (CollCount (&SymInfoList)); /* Fill in the data */ - D->count = CollCount (&SymInfoList); for (I = 0; I < CollCount (&SymInfoList); ++I) { /* Copy the data */ CopySymInfo (D->data + I, CollAt (&SymInfoList, I)); @@ -3568,3 +4042,58 @@ void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info) +/*****************************************************************************/ +/* Scopes */ +/*****************************************************************************/ + + + +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. + */ +{ + DbgInfo* Info; + Collection* ScopeInfoById; + cc65_scopeinfo* D; + unsigned Index; + + /* 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 scope list */ + ScopeInfoById = &Info->ScopeInfoById; + + /* Search for the scope */ + if (!FindScopeInfoById (ScopeInfoById, Id, &Index)) { + /* Not found */ + return 0; + } + + /* Allocate memory for the data structure returned to the caller */ + D = new_cc65_scopeinfo (1); + + /* Fill in the data */ + CopyScopeInfo (D->data, CollAt (ScopeInfoById, Index)); + + /* Return the result */ + return D; +} + + + +void cc65_free_scopeinfo (cc65_dbginfo Handle, cc65_scopeinfo* Info) +/* Free a scope info record */ +{ + /* Just for completeness, check the handle */ + assert (Handle != 0); + + /* Free the memory */ + xfree (Info); +} + + + diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index d63bd68b2..ef8037700 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -123,7 +123,7 @@ struct cc65_lineinfo { /* Source file information */ typedef struct cc65_sourcedata cc65_sourcedata; struct cc65_sourcedata { - unsigned id; /* The internal file id */ + 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 */ @@ -144,7 +144,7 @@ struct cc65_sourceinfo { */ typedef struct cc65_segmentdata cc65_segmentdata; struct cc65_segmentdata { - unsigned id; /* The internal segment id */ + 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 */ @@ -161,19 +161,21 @@ struct cc65_segmentinfo { /* Symbol information */ typedef enum { CC65_SYM_EQUATE, - CC65_SYM_LABEL /* Some sort of address */ + 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 symbol_segment; /* If the symbol is segment relative, * this contains the id of segment, - * otherwise CC65_INV_ID + * otherwise CC65_INV_ID */ + unsigned scope_id; /* The scope this symbol is in */ }; typedef struct cc65_symbolinfo cc65_symbolinfo; @@ -182,6 +184,30 @@ struct cc65_symbolinfo { 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; + +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 */ +}; + +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 */ +}; + /*****************************************************************************/ @@ -272,6 +298,11 @@ void cc65_free_segmentinfo (cc65_dbginfo handle, cc65_segmentinfo* info); +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. + */ + 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. @@ -289,6 +320,22 @@ void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info); +/*****************************************************************************/ +/* Scopes */ +/*****************************************************************************/ + + + +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. + */ + +void cc65_free_scopeinfo (cc65_dbginfo Handle, cc65_scopeinfo* Info); +/* Free a scope info record */ + + + /* Allow usage from C++ */ #ifdef __cplusplus }