unsigned Id; /* Id of scope */
ScopeInfo* Info; /* Pointer to scope */
} Scope;
- Collection* LocalsByName; /* Locals if this is a function */
char Name[1]; /* Name of file with full path */
};
static unsigned CollCount (const Collection* C)
-/* Return the number of items in the collection */
+/* Return the number of items in the collection. Return 0 if C is NULL. */
{
- return C->Count;
+ return C? C->Count : 0;
}
+static unsigned GetId (const void* Data)
+/* Return the id of one of the info structures. All structures have the Id
+ * field as first member, and the C standard allows converting a union pointer
+ * to the data type of the first member, so this is safe and portable.
+ */
+{
+ if (Data) {
+ return *(const unsigned*)Data;
+ } else {
+ return CC65_INV_ID;
+ }
+}
+
+
+
static unsigned HexValue (char C)
/* Convert the ascii representation of a hex nibble into the hex nibble */
{
CSymInfo* S = xmalloc (sizeof (CSymInfo) + SB_GetLen (Name));
/* Initialize it */
- S->LocalsByName = 0;
memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
/* Return it */
static void FreeCSymInfo (CSymInfo* S)
/* Free a CSymInfo struct */
{
- /* Free collections */
- CollFree (S->LocalsByName);
-
/* Free the structure itself */
xfree (S);
}
+static cc65_csyminfo* new_cc65_csyminfo (unsigned Count)
+/* Allocate and return a cc65_csyminfo struct that is able to hold Count
+ * entries. Initialize the count field of the returned struct.
+ */
+{
+ cc65_csyminfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
+ Count * sizeof (S->data[0]));
+ S->count = Count;
+ return S;
+}
+
+
+
+static void CopyCSymInfo (cc65_csymdata* D, const CSymInfo* S)
+/* Copy data from a CSymInfo struct to a cc65_csymdata struct */
+{
+ D->csym_id = S->Id;
+ D->csym_kind = S->Kind;
+ D->csym_sc = S->SC;
+ D->csym_offs = S->Offs;
+ D->symbol_id = GetId (S->Sym.Info);
+ D->scope_id = GetId (S->Scope.Info);
+ D->csym_name = S->Name;
+}
+
+
+
static int CompareCSymInfoByName (const void* L, const void* R)
/* Helper function to sort c symbol infos in a collection by name */
{
static void CopyModInfo (cc65_moduledata* D, const ModInfo* M)
/* Copy data from a ModInfo struct to a cc65_moduledata struct */
{
- D->module_id = M->Id;
- D->module_name = M->Name;
- D->source_id = M->File.Info->Id;
- if (M->Lib.Info) {
- D->library_id = M->Lib.Info->Id;
- } else {
- D->library_id = CC65_INV_ID;
- }
- if (M->MainScope) {
- D->scope_id = M->MainScope->Id;
- } else {
- D->scope_id = CC65_INV_ID;
- }
+ D->module_id = M->Id;
+ D->module_name = M->Name;
+ D->source_id = M->File.Info->Id;
+ D->library_id = GetId (M->Lib.Info);
+ D->scope_id = GetId (M->MainScope);
}
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->Name;
- D->scope_type = S->Type;
- D->scope_size = S->Size;
- if (S->Parent.Info) {
- D->parent_id = S->Parent.Info->Id;
- } else {
- D->parent_id = CC65_INV_ID;
- }
- if (S->Label.Info) {
- D->symbol_id = S->Label.Info->Id;
- } else {
- D->symbol_id = CC65_INV_ID;
- }
- D->module_id = S->Mod.Info->Id;
+ D->scope_id = S->Id;
+ D->scope_name = S->Name;
+ D->scope_type = S->Type;
+ D->scope_size = S->Size;
+ D->parent_id = GetId (S->Parent.Info);
+ D->symbol_id = GetId (S->Label.Info);
+ D->module_id = S->Mod.Info->Id;
}
static void CopySpanInfo (cc65_spandata* D, const SpanInfo* S)
/* Copy data from a SpanInfo struct to a cc65_spandata struct */
{
- D->span_id = S->Id;
- D->span_start = S->Start;
- D->span_end = S->End;
- D->segment_id = S->Seg.Info->Id;
- if (S->Type.Info) {
- D->type_id = S->Type.Info->Id;
- } else {
- D->type_id = CC65_INV_ID;
- }
- if (S->ScopeInfoList) {
- D->scope_count = CollCount (S->ScopeInfoList);
- } else {
- D->scope_count = 0;
- }
- if (S->LineInfoList) {
- D->line_count = CollCount (S->LineInfoList);
- } else {
- D->line_count = 0;
- }
+ D->span_id = S->Id;
+ D->span_start = S->Start;
+ D->span_end = S->End;
+ D->segment_id = S->Seg.Info->Id;
+ D->type_id = GetId (S->Type.Info);
+ D->scope_count = CollCount (S->ScopeInfoList);
+ D->line_count = CollCount (S->LineInfoList);
}
-static int FindFileInfoByName (Collection* FileInfos, const char* Name,
+static int FindCSymInfoByName (const Collection* CSymInfos, const char* Name,
+ unsigned* Index)
+/* Find the C symbol info with a given file name. The function returns true if
+ * the name 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 Name.
+ */
+{
+ /* Do a binary search */
+ int Lo = 0;
+ int Hi = (int) CollCount (CSymInfos) - 1;
+ int Found = 0;
+ while (Lo <= Hi) {
+
+ /* Mid of range */
+ int Cur = (Lo + Hi) / 2;
+
+ /* Get item */
+ const CSymInfo* CurItem = CollAt (CSymInfos, Cur);
+
+ /* Compare */
+ int Res = strcmp (CurItem->Name, Name);
+
+ /* Found? */
+ if (Res < 0) {
+ Lo = Cur + 1;
+ } else {
+ Hi = Cur - 1;
+ /* Since we may have duplicates, repeat the search until we've
+ * the first item that has a match.
+ */
+ if (Res == 0) {
+ Found = 1;
+ }
+ }
+ }
+
+ /* Pass back the index. This is also the insert position */
+ *Index = Lo;
+ return Found;
+}
+
+
+
+static int FindFileInfoByName (const Collection* FileInfos, const char* Name,
unsigned* Index)
/* Find the FileInfo 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
int Cur = (Lo + Hi) / 2;
/* Get item */
- FileInfo* CurItem = CollAt (FileInfos, Cur);
+ const FileInfo* CurItem = CollAt (FileInfos, Cur);
/* Compare */
int Res = strcmp (CurItem->Name, Name);
}
}
- /* Walk over all scopes and sort the c symbols by name */
+ /* Walk over all scopes and sort the c symbols by name. */
for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) {
/* Get this scope */
ScopeInfo* S = CollAt (&D->Info->ScopeInfoById, I);
/* Ignore scopes without C symbols */
- if (S->CSymInfoByName && CollCount (S->CSymInfoByName) > 1) {
+ if (CollCount (S->CSymInfoByName) > 1) {
/* Sort the c symbols for this scope by name */
CollSort (S->CSymInfoByName, CompareCSymInfoByName);
}
+/*****************************************************************************/
+/* C symbols */
+/*****************************************************************************/
+
+
+
+const cc65_csyminfo* cc65_get_csymlist (cc65_dbginfo Handle)
+/* Return a list of all c symbols */
+{
+ const DbgInfo* Info;
+ cc65_csyminfo* S;
+ unsigned I;
+
+ /* Check the parameter */
+ assert (Handle != 0);
+
+ /* The handle is actually a pointer to a debug info struct */
+ Info = Handle;
+
+ /* Allocate memory for the data structure returned to the caller */
+ S = new_cc65_csyminfo (CollCount (&Info->CSymInfoById));
+
+ /* Fill in the data */
+ for (I = 0; I < CollCount (&Info->CSymInfoById); ++I) {
+ /* Copy the data */
+ CopyCSymInfo (S->data + I, CollAt (&Info->CSymInfoById, I));
+ }
+
+ /* Return the result */
+ return S;
+}
+
+
+
+const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo Handle, unsigned Id)
+/* Return information about a c symbol with a specific id. The function
+ * returns NULL if the id is invalid (no such c symbol) and otherwise a
+ * cc65_csyminfo structure with one entry that contains the requested
+ * symbol information.
+ */
+{
+ const DbgInfo* Info;
+ cc65_csyminfo* S;
+
+ /* Check the parameter */
+ assert (Handle != 0);
+
+ /* The handle is actually a pointer to a debug info struct */
+ Info = Handle;
+
+ /* Check if the id is valid */
+ if (Id >= CollCount (&Info->CSymInfoById)) {
+ return 0;
+ }
+
+ /* Allocate memory for the data structure returned to the caller */
+ S = new_cc65_csyminfo (1);
+
+ /* Fill in the data */
+ CopyCSymInfo (S->data, CollAt (&Info->CSymInfoById, Id));
+
+ /* Return the result */
+ return S;
+}
+
+
+
+const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo Handle, unsigned ModId)
+/* Return the list of C functions (not symbols!) for a specific module. If
+ * the module id is invalid, the function will return NULL, otherwise a
+ * (possibly empty) c symbol list.
+ */
+{
+ const DbgInfo* Info;
+ const ModInfo* M;
+ cc65_csyminfo* D;
+ unsigned I;
+
+
+ /* Check the parameter */
+ assert (Handle != 0);
+
+ /* The handle is actually a pointer to a debug info struct */
+ Info = Handle;
+
+ /* Check if the module id is valid */
+ if (ModId >= CollCount (&Info->ModInfoById)) {
+ 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_csyminfo (CollCount (&M->CSymFuncByName));
+
+ /* Fill in the data */
+ for (I = 0; I < CollCount (&M->CSymFuncByName); ++I) {
+ CopyCSymInfo (D->data + I, CollAt (&M->CSymFuncByName, I));
+ }
+
+ /* Return the result */
+ return D;
+}
+
+
+
+const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo Handle, const char* Name)
+/* Return a list of all C functions with the given name that have a
+ * definition.
+ */
+{
+ const DbgInfo* Info;
+ unsigned Index;
+ unsigned Count;
+ const CSymInfo* S;
+ cc65_csyminfo* D;
+ unsigned I;
+
+
+ /* Check the parameter */
+ assert (Handle != 0);
+
+ /* The handle is actually a pointer to a debug info struct */
+ Info = Handle;
+
+ /* Search for a function with the given name */
+ if (!FindCSymInfoByName (&Info->CSymFuncByName, Name, &Index)) {
+ return 0;
+ }
+
+ /* Count functions with this name */
+ Count = 1;
+ I = Index;
+ while (1) {
+ if (++I >= CollCount (&Info->CSymFuncByName)) {
+ break;
+ }
+ S = CollAt (&Info->CSymFuncByName, I);
+ if (strcmp (S->Name, Name) != 0) {
+ /* Next symbol has another name */
+ break;
+ }
+ ++Count;
+ }
+
+ /* Allocate memory for the data structure returned to the caller */
+ D = new_cc65_csyminfo (Count);
+
+ /* Fill in the data */
+ for (I = 0; I < Count; ++I, ++Index) {
+ CopyCSymInfo (D->data + I, CollAt (&Info->CSymFuncByName, Index));
+ }
+
+ /* Return the result */
+ return D;
+}
+
+
+
+const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo Handle, unsigned ScopeId)
+/* Return all C symbols for a scope. The function will return NULL if the
+ * given id is invalid.
+ */
+{
+ const DbgInfo* Info;
+ const ScopeInfo* S;
+ cc65_csyminfo* D;
+ unsigned I;
+
+
+ /* Check the parameter */
+ assert (Handle != 0);
+
+ /* The handle is actually a pointer to a debug info struct */
+ Info = Handle;
+
+ /* Check if the scope id is valid */
+ if (ScopeId >= CollCount (&Info->ScopeInfoById)) {
+ return 0;
+ }
+
+ /* Get a pointer to the scope */
+ S = CollAt (&Info->ScopeInfoById, ScopeId);
+
+ /* Allocate memory for the data structure returned to the caller */
+ D = new_cc65_csyminfo (CollCount (S->CSymInfoByName));
+
+ /* Fill in the data */
+ for (I = 0; I < CollCount (S->CSymInfoByName); ++I) {
+ CopyCSymInfo (D->data + I, CollAt (S->CSymInfoByName, I));
+ }
+
+ /* Return the result */
+ return D;
+}
+
+
+
+void cc65_free_csyminfo (cc65_dbginfo Handle, const cc65_csyminfo* Info)
+/* Free a c symbol info record */
+{
+ /* Just for completeness, check the handle */
+ assert (Handle != 0);
+
+ /* Just free the memory */
+ xfree ((cc65_csyminfo*) Info);
+}
+
+
+
/*****************************************************************************/
/* Libraries */
/*****************************************************************************/
S = CollAt (&Info->SpanInfoById, SpanId);
/* Prepare the struct we will return to the caller */
- D = new_cc65_lineinfo (S->LineInfoList? CollCount (S->LineInfoList) : 0);
+ D = new_cc65_lineinfo (CollCount (S->LineInfoList));
- /* Fill in the data. Since D->LineInfoList may be NULL, we will use the
+ /* Fill in the data. Since S->LineInfoList may be NULL, we will use the
* count field of the returned data struct instead.
*/
for (I = 0; I < D->count; ++I) {
S = CollAt (&Info->SpanInfoById, SpanId);
/* Prepare the struct we will return to the caller */
- D = new_cc65_scopeinfo (S->ScopeInfoList? CollCount (S->ScopeInfoList) : 0);
+ D = new_cc65_scopeinfo (CollCount (S->ScopeInfoList));
/* Fill in the data. Since D->ScopeInfoList may be NULL, we will use the
* count field of the returned data struct instead.
S = CollAt (&Info->ScopeInfoById, Id);
/* Allocate memory for the data structure returned to the caller */
- D = new_cc65_scopeinfo (S->ChildScopeList? CollCount (S->ChildScopeList) : 0);
+ D = new_cc65_scopeinfo (CollCount (S->ChildScopeList));
/* Fill in the data */
for (I = 0; I < D->count; ++I) {
static void CmdShowChildScopes (Collection* Args);
/* Show child scopes from the debug info file */
+static void CmdShowCSymbol (Collection* Args);
+/* Show c symbols from the debug info file */
+
+static void CmdShowFunction (Collection* Args);
+/* Show C functions from the debug info file */
+
static void CmdShowLibrary (Collection* Args);
/* Show libraries from the debug info file */
/* Type of an id */
enum {
InvalidId,
+ CSymbolId,
LibraryId,
LineId,
ModuleId,
"Show child scopes of other scopes.",
-2,
CmdShowChildScopes
+ }, {
+ "csym",
+ 0,
+ -1,
+ CmdShowCSymbol
+ }, {
+ "csymbol",
+ "Show c symbols.",
+ -1,
+ CmdShowCSymbol
+ }, {
+ "func",
+ 0,
+ -2,
+ CmdShowFunction
+ }, {
+ "function",
+ "Show c functions.",
+ -2,
+ CmdShowFunction
}, {
"help",
- "Show available subcommands",
+ "Show available subcommands.",
1,
CmdShowHelp
}, {
-static void PrintNumber (unsigned long Num, unsigned Width, unsigned FieldWidth)
+static void PrintNumber (long Num, unsigned Width, unsigned FieldWidth)
/* Output a number */
{
- Print ("%*lu", Width, Num);
+ Print ("%*ld", Width, Num);
if (FieldWidth > Width) {
Print ("%*s", FieldWidth - Width, "");
}
+static void PrintCSymbolHeader (void)
+/* Output a header for a list of C symbols */
+{
+ /* Header */
+ PrintLine (" id name type kind sc offs symbol scope");
+ PrintSeparator ();
+}
+
+
+
+static void PrintCSymbols (const cc65_csyminfo* S)
+/* Output a list of C symbols */
+{
+ unsigned I;
+ const cc65_csymdata* D;
+
+ /* Segments */
+ for (I = 0, D = S->data; I < S->count; ++I, ++D) {
+ PrintId (D->csym_id, 6);
+ Print ("%-28s", D->csym_name);
+ PrintId (0, 6);
+ PrintNumber (D->csym_kind, 4, 6);
+ PrintNumber (D->csym_sc, 4, 6);
+ PrintNumber (D->csym_offs, 4, 8);
+ PrintId (D->symbol_id, 6);
+ PrintId (D->scope_id, 0);
+ NewLine ();
+ }
+}
+
+
+
static void PrintLibraryHeader (void)
/* Output the header for a library list */
{
+static void CmdShowCSymbol (Collection* Args)
+/* Show C symbols from the debug info file */
+{
+ const cc65_csyminfo* S;
+
+ /* Be sure a file is loaded */
+ if (!FileIsLoaded ()) {
+ return;
+ }
+
+ /* Output the header */
+ PrintCSymbolHeader ();
+
+ /* No arguments means show all libraries */
+ if (CollCount (Args) == 0) {
+
+ /* Fetch the list of c symbols */
+ S = cc65_get_csymlist (Info);
+
+ /* Output the c symbols */
+ PrintCSymbols (S);
+
+ /* Free the list */
+ cc65_free_csyminfo (Info, S);
+
+ } else {
+
+ /* Output c symbols for all arguments */
+ unsigned I;
+ for (I = 0; I < CollCount (Args); ++I) {
+
+ /* Parse the argument */
+ unsigned Id;
+ unsigned IdType = CSymbolId;
+ if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
+ /* Fetch list depending on type */
+ switch (IdType) {
+ case CSymbolId:
+ S = cc65_csym_byid (Info, Id);
+ break;
+ case ScopeId:
+ S = cc65_csym_byscope (Info, Id);
+ break;
+ default:
+ S = 0;
+ PrintLine ("Invalid id type");
+ break;
+ }
+ } else {
+ /* Invalid id */
+ S = 0;
+ }
+
+ /* Output the list */
+ if (S) {
+ PrintCSymbols (S);
+ cc65_free_csyminfo (Info, S);
+ }
+ }
+ }
+}
+
+
+
+static void CmdShowFunction (Collection* Args)
+/* Show C functions from the debug info file */
+{
+ const cc65_csyminfo* S;
+ unsigned I;
+
+ /* Be sure a file is loaded */
+ if (!FileIsLoaded ()) {
+ return;
+ }
+
+ /* Output the header */
+ PrintCSymbolHeader ();
+
+ /* Output c symbols for all arguments */
+ for (I = 0; I < CollCount (Args); ++I) {
+
+ /* Parse the argument */
+ unsigned Id;
+ unsigned IdType = ModuleId;
+ if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
+ /* Fetch list depending on type */
+ switch (IdType) {
+ case ModuleId:
+ S = cc65_cfunc_bymodule (Info, Id);
+ break;
+ default:
+ S = 0;
+ PrintLine ("Invalid id type");
+ break;
+ }
+ } else {
+ /* An invalid id may be a function name */
+ S = cc65_cfunc_byname (Info, CollConstAt (Args, I));
+ }
+
+ /* Output the list */
+ if (S) {
+ PrintCSymbols (S);
+ cc65_free_csyminfo (Info, S);
+ }
+ }
+}
+
+
+
static void CmdShowLine (Collection* Args)
/* Show lines from the debug info file */
{