mirror of
https://github.com/cc65/cc65.git
synced 2024-10-01 15:54:59 +00:00
Postprocess file infos. New function cc65_sourceinfo_bymodule.
git-svn-id: svn://svn.cc65.org/cc65/trunk@5145 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
d9a35e9652
commit
9d2538f12b
@ -226,10 +226,7 @@ struct FileInfo {
|
|||||||
unsigned Id; /* Id of file */
|
unsigned Id; /* Id of file */
|
||||||
unsigned long Size; /* Size of file */
|
unsigned long Size; /* Size of file */
|
||||||
unsigned long MTime; /* Modification time */
|
unsigned long MTime; /* Modification time */
|
||||||
union {
|
Collection ModInfoByName; /* Modules in which this file is used */
|
||||||
unsigned Id; /* Id of module */
|
|
||||||
ModInfo* Info; /* Pointer to module info */
|
|
||||||
} Mod;
|
|
||||||
Collection LineInfoByLine; /* Line infos sorted by line */
|
Collection LineInfoByLine; /* Line infos sorted by line */
|
||||||
char Name[1]; /* Name of file with full path */
|
char Name[1]; /* Name of file with full path */
|
||||||
};
|
};
|
||||||
@ -608,13 +605,33 @@ static unsigned CollCount (const Collection* C)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CollMove (Collection* Source, Collection* Target)
|
||||||
|
/* Move all data from one collection to another. This function will first free
|
||||||
|
* the data in the target collection, and - after the move - clear the data
|
||||||
|
* from the source collection.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Free the target collection data */
|
||||||
|
xfree (Target->Items);
|
||||||
|
|
||||||
|
/* Now copy the whole bunch over */
|
||||||
|
*Target = *Source;
|
||||||
|
|
||||||
|
/* Empty Source */
|
||||||
|
Source->Count = 0;
|
||||||
|
Source->Size = 0;
|
||||||
|
Source->Items = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void CollGrow (Collection* C, unsigned Size)
|
static void CollGrow (Collection* C, unsigned Size)
|
||||||
/* Grow the collection C so it is able to hold Size items without a resize
|
/* Grow the collection C so it is able to hold Size items without a resize
|
||||||
* being necessary. This can be called for performance reasons if the number
|
* being necessary. This can be called for performance reasons if the number
|
||||||
* of items to be placed in the collection is known in advance.
|
* of items to be placed in the collection is known in advance.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
CollEntry* NewItems;
|
CollEntry* NewItems;
|
||||||
|
|
||||||
/* Ignore the call if the collection is already large enough */
|
/* Ignore the call if the collection is already large enough */
|
||||||
if (Size <= C->Size) {
|
if (Size <= C->Size) {
|
||||||
@ -631,8 +648,8 @@ static void CollGrow (Collection* C, unsigned Size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void CollInsert (Collection* C, void* Item, unsigned Index)
|
static void CollPrepareInsert (Collection* C, unsigned Index)
|
||||||
/* Insert the data at the given position in the collection */
|
/* Prepare for insertion of the data at a given position in the collection */
|
||||||
{
|
{
|
||||||
/* Check for invalid indices */
|
/* Check for invalid indices */
|
||||||
assert (Index <= C->Count);
|
assert (Index <= C->Count);
|
||||||
@ -648,6 +665,15 @@ static void CollInsert (Collection* C, void* Item, unsigned Index)
|
|||||||
memmove (C->Items+Index+1, C->Items+Index, (C->Count-Index) * sizeof (void*));
|
memmove (C->Items+Index+1, C->Items+Index, (C->Count-Index) * sizeof (void*));
|
||||||
}
|
}
|
||||||
++C->Count;
|
++C->Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CollInsert (Collection* C, void* Item, unsigned Index)
|
||||||
|
/* Insert the data at the given position in the collection */
|
||||||
|
{
|
||||||
|
/* Prepare for insertion (free the given slot) */
|
||||||
|
CollPrepareInsert (C, Index);
|
||||||
|
|
||||||
/* Store the new item */
|
/* Store the new item */
|
||||||
C->Items[Index].Ptr = Item;
|
C->Items[Index].Ptr = Item;
|
||||||
@ -655,6 +681,30 @@ static void CollInsert (Collection* C, void* Item, unsigned Index)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CollInsertId (Collection* C, unsigned Id, unsigned Index)
|
||||||
|
/* Insert the data at the given position in the collection */
|
||||||
|
{
|
||||||
|
/* Prepare for insertion (free the given slot) */
|
||||||
|
CollPrepareInsert (C, Index);
|
||||||
|
|
||||||
|
/* Store the new item */
|
||||||
|
C->Items[Index].Id = Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CollReplace (Collection* C, void* Item, unsigned Index)
|
||||||
|
/* Replace the item at the given position by a new one */
|
||||||
|
{
|
||||||
|
/* Check the index */
|
||||||
|
assert (Index < C->Count);
|
||||||
|
|
||||||
|
/* Replace the element */
|
||||||
|
C->Items[Index].Ptr = Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void CollReplaceExpand (Collection* C, void* Item, unsigned Index)
|
static void CollReplaceExpand (Collection* C, void* Item, unsigned Index)
|
||||||
/* If Index is a valid index for the collection, replace the item at this
|
/* If Index is a valid index for the collection, replace the item at this
|
||||||
* position by the one passed. If the collection is too small, expand it,
|
* position by the one passed. If the collection is too small, expand it,
|
||||||
@ -697,6 +747,15 @@ static void CollAppend (Collection* C, void* Item)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CollAppendId (Collection* C, unsigned Id)
|
||||||
|
/* Append an id to the end of the collection */
|
||||||
|
{
|
||||||
|
/* Insert the id at the end of the current list */
|
||||||
|
CollInsertId (C, Id, C->Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void* CollAt (Collection* C, unsigned Index)
|
static void* CollAt (Collection* C, unsigned Index)
|
||||||
/* Return the item at the given index */
|
/* Return the item at the given index */
|
||||||
{
|
{
|
||||||
@ -709,6 +768,18 @@ static void* CollAt (Collection* C, unsigned Index)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned CollIdAt (Collection* C, unsigned Index)
|
||||||
|
/* Return the id at the given index */
|
||||||
|
{
|
||||||
|
/* Check the index */
|
||||||
|
assert (Index < C->Count);
|
||||||
|
|
||||||
|
/* Return the element */
|
||||||
|
return C->Items[Index].Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void* CollFirst (Collection* C)
|
static void* CollFirst (Collection* C)
|
||||||
/* Return the first item in a collection */
|
/* Return the first item in a collection */
|
||||||
{
|
{
|
||||||
@ -882,6 +953,7 @@ static FileInfo* NewFileInfo (const StrBuf* Name)
|
|||||||
FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (Name));
|
FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (Name));
|
||||||
|
|
||||||
/* Initialize it */
|
/* Initialize it */
|
||||||
|
InitCollection (&F->ModInfoByName);
|
||||||
InitCollection (&F->LineInfoByLine);
|
InitCollection (&F->LineInfoByLine);
|
||||||
memcpy (F->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
|
memcpy (F->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
|
||||||
|
|
||||||
@ -1361,6 +1433,15 @@ static void CopyModInfo (cc65_moduledata* D, const ModInfo* M)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int CompareModInfoByName (const void* L, const void* R)
|
||||||
|
/* Helper function to sort module infos in a collection by name */
|
||||||
|
{
|
||||||
|
/* Compare module name */
|
||||||
|
return strcmp (((const ModInfo*) L)->Name, ((const ModInfo*) R)->Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Scope info */
|
/* Scope info */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -1428,7 +1509,7 @@ static void CopyScopeInfo (cc65_scopedata* D, const ScopeInfo* S)
|
|||||||
static int CompareScopeInfoByName (const void* L, const void* R)
|
static int CompareScopeInfoByName (const void* L, const void* R)
|
||||||
/* Helper function to sort scope infos in a collection by name */
|
/* Helper function to sort scope infos in a collection by name */
|
||||||
{
|
{
|
||||||
/* Compare symbol name */
|
/* Compare scope name */
|
||||||
return strcmp (((const ScopeInfo*) L)->Name,
|
return strcmp (((const ScopeInfo*) L)->Name,
|
||||||
((const ScopeInfo*) R)->Name);
|
((const ScopeInfo*) R)->Name);
|
||||||
}
|
}
|
||||||
@ -2064,7 +2145,7 @@ static void ParseFile (InputData* D)
|
|||||||
unsigned Id = 0;
|
unsigned Id = 0;
|
||||||
unsigned long Size = 0;
|
unsigned long Size = 0;
|
||||||
unsigned long MTime = 0;
|
unsigned long MTime = 0;
|
||||||
unsigned ModId = CC65_INV_ID;
|
Collection ModIds = COLLECTION_INITIALIZER;
|
||||||
StrBuf Name = STRBUF_INITIALIZER;
|
StrBuf Name = STRBUF_INITIALIZER;
|
||||||
FileInfo* F;
|
FileInfo* F;
|
||||||
enum {
|
enum {
|
||||||
@ -2133,14 +2214,14 @@ static void ParseFile (InputData* D)
|
|||||||
if (!IntConstFollows (D)) {
|
if (!IntConstFollows (D)) {
|
||||||
goto ErrorExit;
|
goto ErrorExit;
|
||||||
}
|
}
|
||||||
ModId = D->IVal;
|
CollAppendId (&ModIds, (unsigned) D->IVal);
|
||||||
InfoBits |= ibModId;
|
|
||||||
NextToken (D);
|
NextToken (D);
|
||||||
if (D->Tok != TOK_PLUS) {
|
if (D->Tok != TOK_PLUS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NextToken (D);
|
NextToken (D);
|
||||||
}
|
}
|
||||||
|
InfoBits |= ibModId;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_NAME:
|
case TOK_NAME:
|
||||||
@ -2194,12 +2275,13 @@ static void ParseFile (InputData* D)
|
|||||||
F->Id = Id;
|
F->Id = Id;
|
||||||
F->Size = Size;
|
F->Size = Size;
|
||||||
F->MTime = MTime;
|
F->MTime = MTime;
|
||||||
F->Mod.Id = ModId;
|
CollMove (&F->ModInfoByName, &ModIds);
|
||||||
CollReplaceExpand (&D->Info->FileInfoById, F, Id);
|
CollReplaceExpand (&D->Info->FileInfoById, F, Id);
|
||||||
CollAppend (&D->Info->FileInfoByName, F);
|
CollAppend (&D->Info->FileInfoByName, F);
|
||||||
|
|
||||||
ErrorExit:
|
ErrorExit:
|
||||||
/* Entry point in case of errors */
|
/* Entry point in case of errors */
|
||||||
|
DoneCollection (&ModIds);
|
||||||
SB_Done (&Name);
|
SB_Done (&Name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3446,6 +3528,54 @@ static void ProcessSegInfo (InputData* D)
|
|||||||
static void ProcessFileInfo (InputData* D)
|
static void ProcessFileInfo (InputData* D)
|
||||||
/* Postprocess file infos */
|
/* Postprocess file infos */
|
||||||
{
|
{
|
||||||
|
/* Walk over all file infos and resolve the module ids */
|
||||||
|
unsigned I;
|
||||||
|
for (I = 0; I < CollCount (&D->Info->FileInfoById); ++I) {
|
||||||
|
|
||||||
|
/* Get this file info */
|
||||||
|
FileInfo* F = CollAt (&D->Info->FileInfoById, I);
|
||||||
|
|
||||||
|
/* Resolve the module ids */
|
||||||
|
unsigned J;
|
||||||
|
for (J = 0; I < CollCount (&F->ModInfoByName); ++J) {
|
||||||
|
|
||||||
|
/* Get the id of this module */
|
||||||
|
unsigned ModId = CollIdAt (&F->ModInfoByName, J);
|
||||||
|
if (ModId >= CollCount (&D->Info->ModInfoById)) {
|
||||||
|
ParseError (D,
|
||||||
|
CC65_ERROR,
|
||||||
|
"Invalid module id %u for file with id %u",
|
||||||
|
ModId, F->Id);
|
||||||
|
CollReplace (&F->ModInfoByName, 0, J);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Get a pointer to the module */
|
||||||
|
ModInfo* M = CollAt (&D->Info->ModInfoById, ModId);
|
||||||
|
|
||||||
|
/* Replace the id by the pointer */
|
||||||
|
CollReplace (&F->ModInfoByName, M, J);
|
||||||
|
|
||||||
|
/* Insert a backpointer into the module */
|
||||||
|
CollAppend (&M->FileInfoByName, F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we didn't have any errors, sort the modules by name */
|
||||||
|
if (D->Errors == 0) {
|
||||||
|
CollSort (&F->ModInfoByName, CompareModInfoByName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now walk over all modules and sort the file infos by name */
|
||||||
|
for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) {
|
||||||
|
|
||||||
|
/* Get this module info */
|
||||||
|
ModInfo* M = CollAt (&D->Info->ModInfoById, I);
|
||||||
|
|
||||||
|
/* Sort the files by name */
|
||||||
|
CollSort (&M->FileInfoByName, CompareFileInfoByName);
|
||||||
|
}
|
||||||
|
|
||||||
/* Sort the file infos by name, so we can do a binary search */
|
/* Sort the file infos by name, so we can do a binary search */
|
||||||
CollSort (&D->Info->FileInfoByName, CompareFileInfoByName);
|
CollSort (&D->Info->FileInfoByName, CompareFileInfoByName);
|
||||||
}
|
}
|
||||||
@ -4419,6 +4549,45 @@ cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo Handle, unsigned Id)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cc65_sourceinfo* cc65_sourceinfo_bymodule (cc65_dbginfo Handle, unsigned ModId)
|
||||||
|
/* Return information about the source files used to build a module. The
|
||||||
|
* function returns NULL if the module id is invalid (no such module) and
|
||||||
|
* otherwise a cc65_sourceinfo structure with one entry per source file.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
DbgInfo* Info;
|
||||||
|
ModInfo* M;
|
||||||
|
cc65_sourceinfo* D;
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Check the parameter */
|
||||||
|
assert (Handle != 0);
|
||||||
|
|
||||||
|
/* The handle is actually a pointer to a debug info struct */
|
||||||
|
Info = (DbgInfo*) Handle;
|
||||||
|
|
||||||
|
/* 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_sourceinfo (CollCount (&M->FileInfoByName));
|
||||||
|
|
||||||
|
/* Fill in the data */
|
||||||
|
for (I = 0; I < CollCount (&M->FileInfoByName); ++I) {
|
||||||
|
CopyFileInfo (D->data + I, CollAt (&M->FileInfoByName, I));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the result */
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cc65_free_sourceinfo (cc65_dbginfo Handle, cc65_sourceinfo* Info)
|
void cc65_free_sourceinfo (cc65_dbginfo Handle, cc65_sourceinfo* Info)
|
||||||
/* Free a source info record */
|
/* Free a source info record */
|
||||||
{
|
{
|
||||||
|
@ -275,6 +275,13 @@ cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo handle, unsigned id);
|
|||||||
* source file information.
|
* source file information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
cc65_sourceinfo* cc65_sourceinfo_bymodule (cc65_dbginfo handle,
|
||||||
|
unsigned module_id);
|
||||||
|
/* Return information about the source files used to build a module. The
|
||||||
|
* function returns NULL if the module id is invalid (no such module) and
|
||||||
|
* otherwise a cc65_sourceinfo structure with one entry per source file.
|
||||||
|
*/
|
||||||
|
|
||||||
void cc65_free_sourceinfo (cc65_dbginfo handle, cc65_sourceinfo* info);
|
void cc65_free_sourceinfo (cc65_dbginfo handle, cc65_sourceinfo* info);
|
||||||
/* Free a source info record */
|
/* Free a source info record */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user