1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00

Preparations for adding scopes.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5100 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2011-07-31 21:32:46 +00:00
parent 0dbe4454a5
commit 2b32c14661
2 changed files with 625 additions and 49 deletions

View File

@ -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);
}

View File

@ -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
}