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 */ /* Version numbers of the debug format we understand */
#define VER_MAJOR 1U #define VER_MAJOR 1U
#define VER_MINOR 2U #define VER_MINOR 3U
/* Dynamic strings */ /* Dynamic strings */
typedef struct StrBuf StrBuf; typedef struct StrBuf StrBuf;
@@ -108,8 +108,10 @@ struct DbgInfo {
Collection FileInfoById; /* File infos sorted by id */ Collection FileInfoById; /* File infos sorted by id */
Collection LineInfos; /* List of all line infos */ Collection LineInfos; /* List of all line infos */
LineInfoList LineInfoByAddr; /* Line infos sorted by unique address */ LineInfoList LineInfoByAddr; /* Line infos sorted by unique address */
Collection SymInfoById; /* Symbol infos sorted by id */
Collection SymInfoByName; /* Symbol infos sorted by name */ Collection SymInfoByName; /* Symbol infos sorted by name */
Collection SymInfoByVal; /* Symbol infos sorted by value */ Collection SymInfoByVal; /* Symbol infos sorted by value */
Collection ScopeInfoById; /* Scope infos sorted by id */
}; };
/* Input tokens */ /* Input tokens */
@@ -143,9 +145,11 @@ typedef enum {
TOK_NAME, /* NAME keyword */ TOK_NAME, /* NAME keyword */
TOK_OUTPUTNAME, /* OUTPUTNAME keyword */ TOK_OUTPUTNAME, /* OUTPUTNAME keyword */
TOK_OUTPUTOFFS, /* OUTPUTOFFS keyword */ TOK_OUTPUTOFFS, /* OUTPUTOFFS keyword */
TOK_PARENT, /* PARENT keyword */
TOK_RANGE, /* RANGE keyword */ TOK_RANGE, /* RANGE keyword */
TOK_RO, /* RO keyword */ TOK_RO, /* RO keyword */
TOK_RW, /* RW keyword */ TOK_RW, /* RW keyword */
TOK_SCOPE, /* SCOPE keyword */
TOK_SEGMENT, /* SEGMENT keyword */ TOK_SEGMENT, /* SEGMENT keyword */
TOK_SIZE, /* SIZE keyword */ TOK_SIZE, /* SIZE keyword */
TOK_START, /* START keyword */ TOK_START, /* START keyword */
@@ -221,13 +225,30 @@ struct LineInfo {
/* Internally used symbol info struct */ /* Internally used symbol info struct */
typedef struct SymInfo SymInfo; typedef struct SymInfo SymInfo;
struct SymInfo { struct SymInfo {
unsigned Id; /* Id of symbol */
cc65_symbol_type Type; /* Type of symbol */ cc65_symbol_type Type; /* Type of symbol */
long Value; /* Value of symbol */ long Value; /* Value of symbol */
cc65_size Size; /* Size of symbol */ cc65_size Size; /* Size of symbol */
unsigned Segment; /* Id of segment if any */ 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 */ 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 */ /* Dynamic strings */
/*****************************************************************************/ /*****************************************************************************/
@@ -1039,19 +1073,13 @@ static int CompareFileInfoById (const void* L, const void* R)
static SymInfo* NewSymInfo (const StrBuf* Name, long Val, static SymInfo* NewSymInfo (const StrBuf* Name)
cc65_symbol_type Type, cc65_size Size,
unsigned Segment)
/* Create a new SymInfo struct, intialize and return it */ /* Create a new SymInfo struct, intialize and return it */
{ {
/* Allocate memory */ /* Allocate memory */
SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name)); SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name));
/* Initialize it */ /* Initialize the name */
S->Type = Type;
S->Value = Val;
S->Size = Size;
S->Segment = Segment;
memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
/* Return it */ /* 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) static int CompareSymInfoByName (const void* L, const void* R)
/* Helper function to sort symbol infos in a collection by name */ /* 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 */ /* Debug info */
/*****************************************************************************/ /*****************************************************************************/
@@ -1305,8 +1402,10 @@ static DbgInfo* NewDbgInfo (void)
InitCollection (&Info->FileInfoById); InitCollection (&Info->FileInfoById);
InitCollection (&Info->LineInfos); InitCollection (&Info->LineInfos);
InitLineInfoList (&Info->LineInfoByAddr); InitLineInfoList (&Info->LineInfoByAddr);
InitCollection (&Info->SymInfoById);
InitCollection (&Info->SymInfoByName); InitCollection (&Info->SymInfoByName);
InitCollection (&Info->SymInfoByVal); InitCollection (&Info->SymInfoByVal);
InitCollection (&Info->ScopeInfoById);
/* Return it */ /* Return it */
return Info; return Info;
@@ -1344,9 +1443,16 @@ static void FreeDbgInfo (DbgInfo* Info)
for (I = 0; I < CollCount (&Info->SymInfoByName); ++I) { for (I = 0; I < CollCount (&Info->SymInfoByName); ++I) {
FreeSymInfo (CollAt (&Info->SymInfoByName, I)); FreeSymInfo (CollAt (&Info->SymInfoByName, I));
} }
DoneCollection (&Info->SymInfoById);
DoneCollection (&Info->SymInfoByName); DoneCollection (&Info->SymInfoByName);
DoneCollection (&Info->SymInfoByVal); 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 */ /* Free the structure itself */
xfree (Info); xfree (Info);
} }
@@ -1384,7 +1490,7 @@ static void CopyLineInfo (cc65_linedata* D, const LineInfo* L)
static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F) static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F)
/* Copy data from a FileInfo struct to a cc65_sourcedata struct */ /* 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_name = F->FileName;
D->source_size = F->Size; D->source_size = F->Size;
D->source_mtime = F->MTime; 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) static void CopySegInfo (cc65_segmentdata* D, const SegInfo* S)
/* Copy data from a SegInfo struct to a cc65_segmentdata struct */ /* 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_name = S->SegName;
D->segment_start = S->Start; D->segment_start = S->Start;
D->segment_size = S->Size; 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) static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
/* Copy data from a SymInfo struct to a cc65_symboldata struct */ /* Copy data from a SymInfo struct to a cc65_symboldata struct */
{ {
D->symbol_id = S->Id;
D->symbol_name = S->SymName; D->symbol_name = S->SymName;
D->symbol_type = S->Type; D->symbol_type = S->Type;
D->symbol_size = S->Size; D->symbol_size = S->Size;
D->symbol_value = S->Value; D->symbol_value = S->Value;
D->symbol_segment = S->Segment; 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 }, { "name", TOK_NAME },
{ "outputname", TOK_OUTPUTNAME }, { "outputname", TOK_OUTPUTNAME },
{ "outputoffs", TOK_OUTPUTOFFS }, { "outputoffs", TOK_OUTPUTOFFS },
{ "parent", TOK_PARENT },
{ "range", TOK_RANGE }, { "range", TOK_RANGE },
{ "ro", TOK_RO }, { "ro", TOK_RO },
{ "rw", TOK_RW }, { "rw", TOK_RW },
{ "scope", TOK_SCOPE },
{ "seg", TOK_SEGMENT }, { "seg", TOK_SEGMENT },
{ "segment", TOK_SEGMENT }, { "segment", TOK_SEGMENT },
{ "size", TOK_SIZE }, { "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) static void ParseSegment (InputData* D)
/* Parse a SEGMENT line */ /* Parse a SEGMENT line */
{ {
@@ -2066,15 +2345,17 @@ static void ParseSegment (InputData* D)
unsigned long OutputOffs = 0; unsigned long OutputOffs = 0;
SegInfo* S; SegInfo* S;
enum { enum {
ibNone = 0x00, ibNone = 0x000,
ibId = 0x01,
ibSegName = 0x02, ibAddrSize = 0x001,
ibStart = 0x04, ibId = 0x002,
ibSize = 0x08, ibOutputName= 0x004,
ibAddrSize = 0x10, ibOutputOffs= 0x008,
ibType = 0x20, ibSegName = 0x010,
ibOutputName= 0x40, ibSize = 0x020,
ibOutputOffs= 0x80, ibStart = 0x040,
ibType = 0x080,
ibRequired = ibId | ibSegName | ibStart | ibSize | ibAddrSize | ibType, ibRequired = ibId | ibSegName | ibStart | ibSize | ibAddrSize | ibType,
} InfoBits = ibNone; } InfoBits = ibNone;
@@ -2230,26 +2511,37 @@ ErrorExit:
static void ParseSym (InputData* D) static void ParseSym (InputData* D)
/* Parse a SYM line */ /* Parse a SYM line */
{ {
/* Most of the following variables are initialized with a value that is /* Most of the following variables are initialized with a value that is
* overwritten later. This is just to avoid compiler warnings. * 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; cc65_symbol_type Type = CC65_SYM_EQUATE;
long Value = 0; long Value = 0;
cc65_size Size = 0;
StrBuf SymName = STRBUF_INITIALIZER;
unsigned Segment = CC65_INV_ID;
SymInfo* S; SymInfo* S;
enum { enum {
ibNone = 0x00, ibNone = 0x000,
ibSymName = 0x01,
ibValue = 0x02, ibAddrSize = 0x001,
ibAddrSize = 0x04, ibFile = 0x002,
ibType = 0x08, ibId = 0x004,
ibSize = 0x10, ibParent = 0x008,
ibSegment = 0x20, ibScope = 0x010,
ibFile = 0x40, ibSegment = 0x020,
ibRequired = ibSymName | ibValue | ibAddrSize | ibType, ibSize = 0x040,
ibName = 0x080,
ibType = 0x100,
ibValue = 0x200,
ibRequired = ibAddrSize | ibId | ibScope | ibName |
ibType | ibValue,
} InfoBits = ibNone; } InfoBits = ibNone;
/* Skip the SYM token */ /* Skip the SYM token */
@@ -2262,9 +2554,10 @@ static void ParseSym (InputData* D)
/* Something we know? */ /* Something we know? */
if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_FILE && if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_FILE &&
D->Tok != TOK_NAME && D->Tok != TOK_SEGMENT&& D->Tok != TOK_ID && D->Tok != TOK_NAME &&
D->Tok != TOK_SIZE && D->Tok != TOK_TYPE && D->Tok != TOK_PARENT && D->Tok != TOK_SCOPE &&
D->Tok != TOK_VALUE) { D->Tok != TOK_SEGMENT && D->Tok != TOK_SIZE &&
D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) {
/* Try smart error recovery */ /* Try smart error recovery */
if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
@@ -2295,21 +2588,48 @@ static void ParseSym (InputData* D)
if (!IntConstFollows (D)) { if (!IntConstFollows (D)) {
goto ErrorExit; goto ErrorExit;
} }
/* ### Drop value for now */ File = D->IVal;
InfoBits |= ibFile; InfoBits |= ibFile;
NextToken (D); NextToken (D);
break; break;
case TOK_ID:
if (!IntConstFollows (D)) {
goto ErrorExit;
}
Id = D->IVal;
NextToken (D);
InfoBits |= ibId;
break;
case TOK_NAME: case TOK_NAME:
if (!StrConstFollows (D)) { if (!StrConstFollows (D)) {
goto ErrorExit; goto ErrorExit;
} }
SB_Copy (&SymName, &D->SVal); SB_Copy (&Name, &D->SVal);
SB_Terminate (&SymName); SB_Terminate (&Name);
InfoBits |= ibSymName; InfoBits |= ibName;
NextToken (D); NextToken (D);
break; 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: case TOK_SEGMENT:
if (!IntConstFollows (D)) { if (!IntConstFollows (D)) {
goto ErrorExit; goto ErrorExit;
@@ -2382,14 +2702,24 @@ static void ParseSym (InputData* D)
goto ErrorExit; goto ErrorExit;
} }
/* Create the symbol info and remember it */ /* Create the symbol info */
S = NewSymInfo (&SymName, Value, Type, Size, Segment); 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->SymInfoByName, S);
CollAppend (&D->Info->SymInfoByVal, S); CollAppend (&D->Info->SymInfoByVal, S);
ErrorExit: ErrorExit:
/* Entry point in case of errors */ /* Entry point in case of errors */
SB_Done (&SymName); SB_Done (&Name);
return; return;
} }
@@ -2821,16 +3151,56 @@ static void ProcessSymInfo (InputData* D)
/* Postprocess symbol infos */ /* Postprocess symbol infos */
{ {
/* Get pointers to the symbol info collections */ /* Get pointers to the symbol info collections */
Collection* SymInfoById = &D->Info->SymInfoById;
Collection* SymInfoByName = &D->Info->SymInfoByName; Collection* SymInfoByName = &D->Info->SymInfoByName;
Collection* SymInfoByVal = &D->Info->SymInfoByVal; Collection* SymInfoByVal = &D->Info->SymInfoByVal;
/* Sort the symbol infos */ /* Sort the symbol infos */
CollSort (SymInfoById, CompareSymInfoById);
CollSort (SymInfoByName, CompareSymInfoByName); CollSort (SymInfoByName, CompareSymInfoByName);
CollSort (SymInfoByVal, CompareSymInfoByVal); 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) static int FindSymInfoByName (Collection* SymInfos, const char* SymName, unsigned* Index)
/* Find the SymInfo for a given file name. The function returns true if the /* 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 * 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 */ /* Debug info files */
/*****************************************************************************/ /*****************************************************************************/
@@ -3018,6 +3452,10 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
ParseLine (&D); ParseLine (&D);
break; break;
case TOK_SCOPE:
ParseScope (&D);
break;
case TOK_SEGMENT: case TOK_SEGMENT:
ParseSegment (&D); ParseSegment (&D);
break; break;
@@ -3074,6 +3512,7 @@ CloseAndExit:
ProcessFileInfo (&D); ProcessFileInfo (&D);
ProcessLineInfo (&D); ProcessLineInfo (&D);
ProcessSymInfo (&D); ProcessSymInfo (&D);
ProcessScopeInfo (&D);
#if DEBUG #if DEBUG
/* Debug output */ /* 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) 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 /* Return a list of symbols with a given name. The function returns NULL if
* no symbol with this name was found. * 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); D = new_cc65_symbolinfo (Count);
/* Fill in the data */ /* Fill in the data */
D->count = Count;
for (I = 0; I < Count; ++I) { for (I = 0; I < Count; ++I) {
/* Copy the data */ /* Copy the data */
CopySymInfo (D->data + I, CollAt (SymInfoByName, Index++)); 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)); D = new_cc65_symbolinfo (CollCount (&SymInfoList));
/* Fill in the data */ /* Fill in the data */
D->count = CollCount (&SymInfoList);
for (I = 0; I < CollCount (&SymInfoList); ++I) { for (I = 0; I < CollCount (&SymInfoList); ++I) {
/* Copy the data */ /* Copy the data */
CopySymInfo (D->data + I, CollAt (&SymInfoList, I)); 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 */ /* Source file information */
typedef struct cc65_sourcedata cc65_sourcedata; typedef struct cc65_sourcedata cc65_sourcedata;
struct 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 */ const char* source_name; /* Name of the file */
unsigned long source_size; /* Size of file */ unsigned long source_size; /* Size of file */
unsigned long source_mtime; /* Modification time */ unsigned long source_mtime; /* Modification time */
@@ -144,7 +144,7 @@ struct cc65_sourceinfo {
*/ */
typedef struct cc65_segmentdata cc65_segmentdata; typedef struct cc65_segmentdata cc65_segmentdata;
struct 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 */ const char* segment_name; /* Name of the segment */
cc65_addr segment_start; /* Start address of segment */ cc65_addr segment_start; /* Start address of segment */
cc65_addr segment_size; /* Size of segment */ cc65_addr segment_size; /* Size of segment */
@@ -161,19 +161,21 @@ struct cc65_segmentinfo {
/* Symbol information */ /* Symbol information */
typedef enum { typedef enum {
CC65_SYM_EQUATE, CC65_SYM_EQUATE,
CC65_SYM_LABEL /* Some sort of address */ CC65_SYM_LABEL, /* Some sort of address */
} cc65_symbol_type; } cc65_symbol_type;
typedef struct cc65_symboldata cc65_symboldata; typedef struct cc65_symboldata cc65_symboldata;
struct cc65_symboldata { struct cc65_symboldata {
unsigned symbol_id; /* Id of symbol */
const char* symbol_name; /* Name of symbol */ const char* symbol_name; /* Name of symbol */
cc65_symbol_type symbol_type; /* Type of symbol */ cc65_symbol_type symbol_type; /* Type of symbol */
cc65_size symbol_size; /* Size of symbol, 0 if unknown */ cc65_size symbol_size; /* Size of symbol, 0 if unknown */
long symbol_value; /* Value of symbol */ long symbol_value; /* Value of symbol */
unsigned symbol_segment; /* If the symbol is segment relative, unsigned symbol_segment; /* If the symbol is segment relative,
* this contains the id of segment, * 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; typedef struct cc65_symbolinfo cc65_symbolinfo;
@@ -182,6 +184,30 @@ struct cc65_symbolinfo {
cc65_symboldata data[1]; /* Data sets, number is dynamic */ 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); 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 /* Return a list of symbols with a given name. The function returns NULL if
* no symbol with this name was found. * 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++ */ /* Allow usage from C++ */
#ifdef __cplusplus #ifdef __cplusplus
} }