2011-08-16 22:37:01 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* dbgsh.c */
|
|
|
|
/* */
|
|
|
|
/* debug info test shell */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* (C) 2011, Ullrich von Bassewitz */
|
|
|
|
/* Roemerstrasse 52 */
|
|
|
|
/* D-70794 Filderstadt */
|
|
|
|
/* EMail: uz@cc65.org */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* This software is provided 'as-is', without any expressed or implied */
|
|
|
|
/* warranty. In no event will the authors be held liable for any damages */
|
|
|
|
/* arising from the use of this software. */
|
|
|
|
/* */
|
|
|
|
/* Permission is granted to anyone to use this software for any purpose, */
|
|
|
|
/* including commercial applications, and to alter it and redistribute it */
|
|
|
|
/* freely, subject to the following restrictions: */
|
|
|
|
/* */
|
|
|
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
|
|
|
/* claim that you wrote the original software. If you use this software */
|
|
|
|
/* in a product, an acknowledgment in the product documentation would be */
|
|
|
|
/* appreciated but is not required. */
|
|
|
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
|
|
|
/* be misrepresented as being the original software. */
|
|
|
|
/* 3. This notice may not be removed or altered from any source */
|
|
|
|
/* distribution. */
|
|
|
|
/* */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
2011-08-17 16:27:34 +00:00
|
|
|
#include <time.h>
|
2011-08-16 22:37:01 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
/* common */
|
|
|
|
#include "attrib.h"
|
|
|
|
#include "chartype.h"
|
2011-08-17 16:27:34 +00:00
|
|
|
#include "cmdline.h"
|
2011-08-16 22:37:01 +00:00
|
|
|
#include "coll.h"
|
|
|
|
|
|
|
|
/* dbginfo */
|
|
|
|
#include "dbginfo.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Command handler forwards */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdHelp (Collection* Args attribute ((unused)));
|
|
|
|
/* Output a help text */
|
|
|
|
|
|
|
|
static void CmdLoad (Collection* Args);
|
|
|
|
/* Load a debug info file */
|
|
|
|
|
|
|
|
static void CmdQuit (Collection* Args attribute ((unused)));
|
|
|
|
/* Terminate the application */
|
|
|
|
|
|
|
|
static void CmdShow (Collection* Args);
|
|
|
|
/* Show items from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowHelp (Collection* Args);
|
|
|
|
/* Print help for the show command */
|
|
|
|
|
2011-08-17 21:20:10 +00:00
|
|
|
static void CmdShowChildScopes (Collection* Args);
|
|
|
|
/* Show child scopes from the debug info file */
|
|
|
|
|
2011-09-01 20:51:07 +00:00
|
|
|
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 */
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdShowLibrary (Collection* Args);
|
|
|
|
/* Show libraries from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowLine (Collection* Args);
|
|
|
|
/* Show lines from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowModule (Collection* Args);
|
|
|
|
/* Show modules from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowScope (Collection* Args);
|
|
|
|
/* Show scopes from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowSegment (Collection* Args);
|
|
|
|
/* Show segments from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowSource (Collection* Args);
|
|
|
|
/* Show source files from the debug info file */
|
|
|
|
|
2011-08-26 20:03:11 +00:00
|
|
|
static void CmdShowSpan (Collection* Args);
|
|
|
|
/* Show spans from the debug info file */
|
|
|
|
|
2011-08-18 20:34:31 +00:00
|
|
|
static void CmdShowSymbol (Collection* Args);
|
|
|
|
/* Show symbols */
|
|
|
|
|
|
|
|
static void CmdShowSymDef (Collection* Args);
|
2011-08-28 15:10:43 +00:00
|
|
|
/* Show lines from the debug info file */
|
2011-08-18 20:34:31 +00:00
|
|
|
|
|
|
|
static void CmdShowSymRef (Collection* Args);
|
2011-08-28 15:10:43 +00:00
|
|
|
/* Show lines from the debug info file */
|
|
|
|
|
|
|
|
static void CmdShowType (Collection* Args);
|
|
|
|
/* Show types from the debug info file */
|
2011-08-18 20:34:31 +00:00
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdUnload (Collection* Args attribute ((unused)));
|
|
|
|
/* Unload a debug info file */
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-16 22:37:01 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Data */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Terminate flag - end program when set to true */
|
|
|
|
static int Terminate = 0;
|
|
|
|
|
|
|
|
/* The debug file data */
|
|
|
|
static cc65_dbginfo Info = 0;
|
|
|
|
|
|
|
|
/* Error and warning counters */
|
|
|
|
static unsigned FileErrors = 0;
|
|
|
|
static unsigned FileWarnings = 0;
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Type of an id */
|
|
|
|
enum {
|
|
|
|
InvalidId,
|
2011-09-01 20:51:07 +00:00
|
|
|
CSymbolId,
|
2011-08-17 16:27:34 +00:00
|
|
|
LibraryId,
|
|
|
|
LineId,
|
|
|
|
ModuleId,
|
|
|
|
ScopeId,
|
|
|
|
SegmentId,
|
|
|
|
SourceId,
|
|
|
|
SpanId,
|
2011-08-28 15:10:43 +00:00
|
|
|
SymbolId,
|
|
|
|
TypeId
|
2011-08-17 16:27:34 +00:00
|
|
|
};
|
|
|
|
|
2011-08-16 22:37:01 +00:00
|
|
|
/* Structure that contains a command description */
|
|
|
|
typedef struct CmdEntry CmdEntry;
|
|
|
|
struct CmdEntry {
|
2011-08-17 16:27:34 +00:00
|
|
|
char Cmd[12];
|
|
|
|
const char* Help;
|
|
|
|
int ArgCount;
|
|
|
|
void (*Func) (Collection*);
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Table with main commands */
|
|
|
|
static const CmdEntry MainCmds[] = {
|
|
|
|
{
|
2011-08-28 15:10:43 +00:00
|
|
|
"exit",
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
CmdQuit
|
|
|
|
}, {
|
2011-08-17 16:27:34 +00:00
|
|
|
"help",
|
|
|
|
"Show available commands",
|
|
|
|
1,
|
|
|
|
CmdHelp
|
|
|
|
}, {
|
|
|
|
"load",
|
|
|
|
"Load a debug info file",
|
|
|
|
2,
|
|
|
|
CmdLoad
|
|
|
|
}, {
|
|
|
|
"quit",
|
|
|
|
"Terminate the shell",
|
|
|
|
1,
|
|
|
|
CmdQuit
|
|
|
|
}, {
|
|
|
|
"show",
|
|
|
|
"Show items from the info file",
|
|
|
|
-2,
|
|
|
|
CmdShow
|
|
|
|
}, {
|
|
|
|
"unload",
|
|
|
|
"Unload a debug info file",
|
|
|
|
1,
|
|
|
|
CmdUnload
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Table with show commands */
|
|
|
|
static const CmdEntry ShowCmds[] = {
|
|
|
|
{
|
2011-08-17 21:20:10 +00:00
|
|
|
"childscopes",
|
|
|
|
"Show child scopes of other scopes.",
|
|
|
|
-2,
|
|
|
|
CmdShowChildScopes
|
2011-09-01 20:51:07 +00:00
|
|
|
}, {
|
|
|
|
"csym",
|
|
|
|
0,
|
|
|
|
-1,
|
|
|
|
CmdShowCSymbol
|
|
|
|
}, {
|
|
|
|
"csymbol",
|
|
|
|
"Show c symbols.",
|
|
|
|
-1,
|
|
|
|
CmdShowCSymbol
|
|
|
|
}, {
|
|
|
|
"func",
|
|
|
|
0,
|
|
|
|
-2,
|
|
|
|
CmdShowFunction
|
|
|
|
}, {
|
|
|
|
"function",
|
|
|
|
"Show c functions.",
|
|
|
|
-2,
|
|
|
|
CmdShowFunction
|
2011-08-17 21:20:10 +00:00
|
|
|
}, {
|
2011-08-17 16:27:34 +00:00
|
|
|
"help",
|
2011-09-01 20:51:07 +00:00
|
|
|
"Show available subcommands.",
|
2011-08-17 16:27:34 +00:00
|
|
|
1,
|
|
|
|
CmdShowHelp
|
|
|
|
}, {
|
|
|
|
"line",
|
|
|
|
"Show line info. May be followed by one or more line ids.",
|
|
|
|
-2,
|
|
|
|
CmdShowLine
|
|
|
|
}, {
|
|
|
|
"library",
|
|
|
|
"Show libraries. May be followed by one or more library ids.",
|
|
|
|
-1,
|
|
|
|
CmdShowLibrary
|
|
|
|
}, {
|
|
|
|
"module",
|
|
|
|
"Show modules. May be followed by one or more module ids.",
|
|
|
|
-1,
|
|
|
|
CmdShowModule
|
|
|
|
}, {
|
|
|
|
"scope",
|
|
|
|
"Show scopes. May be followed by one or more segment ids.",
|
|
|
|
-1,
|
|
|
|
CmdShowScope
|
|
|
|
}, {
|
|
|
|
"segment",
|
|
|
|
"Show segments. May be followed by one or more segment ids.",
|
|
|
|
-1,
|
|
|
|
CmdShowSegment
|
|
|
|
}, {
|
|
|
|
"source",
|
|
|
|
"Show sources. May be followed by one or more source file ids.",
|
|
|
|
-1,
|
|
|
|
CmdShowSource
|
2011-08-26 20:03:11 +00:00
|
|
|
}, {
|
|
|
|
"span",
|
|
|
|
"Show spans. May be followed by one or more span ids.",
|
|
|
|
-1,
|
|
|
|
CmdShowSpan
|
2011-08-18 20:34:31 +00:00
|
|
|
}, {
|
|
|
|
"symbol",
|
|
|
|
"Show symbols. May be followed by one or more symbol or scope ids.",
|
|
|
|
-2,
|
|
|
|
CmdShowSymbol
|
|
|
|
}, {
|
|
|
|
"symdef",
|
|
|
|
"Show where a symbol was defined. May be followed by one or more symbol ids.",
|
|
|
|
-2,
|
|
|
|
CmdShowSymDef
|
|
|
|
}, {
|
|
|
|
"symref",
|
|
|
|
"Show where a symbol was referenced. May be followed by one or more symbol ids.",
|
|
|
|
-2,
|
|
|
|
CmdShowSymRef
|
2011-08-28 15:10:43 +00:00
|
|
|
}, {
|
|
|
|
"type",
|
|
|
|
"Show type information. May be followed by one or more type ids.",
|
|
|
|
-2,
|
|
|
|
CmdShowType
|
2011-08-17 16:27:34 +00:00
|
|
|
},
|
2011-08-16 22:37:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Helpers */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void NewLine (void)
|
|
|
|
/* Output a newline */
|
|
|
|
{
|
|
|
|
putchar ('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void Print (const char* Format, ...) attribute((format(printf,1,2)));
|
|
|
|
static void Print (const char* Format, ...)
|
|
|
|
/* Print a piece of output (no linefeed added) */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start (ap, Format);
|
|
|
|
vprintf (Format, ap);
|
|
|
|
va_end (ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintLine (const char* Format, ...) attribute((format(printf,1,2)));
|
|
|
|
static void PrintLine (const char* Format, ...)
|
|
|
|
/* Print one line of output. The linefeed is supplied by the function */
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start (ap, Format);
|
|
|
|
vprintf (Format, ap);
|
|
|
|
NewLine ();
|
|
|
|
va_end (ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSeparator (void)
|
|
|
|
/* Print a separator line */
|
|
|
|
{
|
2011-08-19 11:22:36 +00:00
|
|
|
PrintLine ("---------------------------------------------------------------------------");
|
2011-08-17 16:27:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void FileError (const cc65_parseerror* Info)
|
|
|
|
/* Callback function - is called in case of errors */
|
|
|
|
{
|
|
|
|
/* Output a message */
|
|
|
|
PrintLine ("%s:%s(%lu): %s",
|
|
|
|
Info->type? "Error" : "Warning",
|
|
|
|
Info->name,
|
|
|
|
(unsigned long) Info->line,
|
|
|
|
Info->errormsg);
|
|
|
|
|
|
|
|
/* Bump the counters */
|
|
|
|
switch (Info->type) {
|
|
|
|
case CC65_WARNING: ++FileWarnings; break;
|
|
|
|
default: ++FileErrors; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const CmdEntry* FindCmd (const char* Cmd, const CmdEntry* Tab, unsigned Count)
|
|
|
|
/* Search for a command in the given table */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < Count; ++I, ++Tab) {
|
|
|
|
if (strcmp (Cmd, Tab->Cmd) == 0) {
|
|
|
|
return Tab;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count)
|
|
|
|
/* Search for the command in slot 0 of the given collection. If found, check
|
2014-06-30 09:10:35 +00:00
|
|
|
** the argument count, then execute it. If there are problems, output a
|
|
|
|
** diagnostic.
|
|
|
|
*/
|
2011-08-17 16:27:34 +00:00
|
|
|
{
|
|
|
|
/* Search for the command, check number of args, then execute it */
|
|
|
|
const char* Cmd = CollAt (Args, 0);
|
|
|
|
const CmdEntry* E = FindCmd (Cmd, Tab, Count);
|
|
|
|
if (E == 0) {
|
|
|
|
PrintLine ("No such command: %s", Cmd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the number of arguments. Zero means that the function will check
|
2014-06-30 09:10:35 +00:00
|
|
|
** itself. A negative count means that the function needs at least
|
|
|
|
** abs(count) arguments. A positive count means that the function needs
|
|
|
|
** exactly this number of arguments.
|
|
|
|
** Note: The number includes the command itself.
|
|
|
|
*/
|
2011-08-17 16:27:34 +00:00
|
|
|
if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) {
|
|
|
|
/* Argument number mismatch */
|
|
|
|
switch (E->ArgCount) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
PrintLine ("Command doesn't accept an argument");
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
PrintLine ("Command requires an argument");
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
PrintLine ("Command requires %d arguments", E->ArgCount-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (E->ArgCount < 0 && (int)CollCount (Args) < -E->ArgCount) {
|
|
|
|
/* Argument number mismatch */
|
|
|
|
switch (E->ArgCount) {
|
|
|
|
|
|
|
|
case -2:
|
|
|
|
PrintLine ("Command requires at least one argument");
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
PrintLine ("Command requires at least %d arguments", E->ArgCount-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Remove the command from the argument list, then execute it */
|
|
|
|
CollDelete (Args, 0);
|
|
|
|
E->Func (Args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintHelp (const CmdEntry* Tab, unsigned Count)
|
|
|
|
/* Output help for one command table */
|
|
|
|
{
|
|
|
|
while (Count--) {
|
2011-08-28 15:10:43 +00:00
|
|
|
/* Ignore the commands without help text */
|
|
|
|
if (Tab->Help) {
|
|
|
|
PrintLine ("%-*s%s", (int) sizeof (Tab->Cmd) + 2, Tab->Cmd, Tab->Help);
|
|
|
|
}
|
2011-08-17 16:27:34 +00:00
|
|
|
++Tab;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned FindIdType (const char* TypeName)
|
|
|
|
/* Find an id type by its name. Returns the type or InvalidId. */
|
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
char Name[8];
|
|
|
|
unsigned Type;
|
|
|
|
} TypeTab[] = {
|
|
|
|
{ "l", LineId },
|
|
|
|
{ "lib", LibraryId },
|
|
|
|
{ "library", LibraryId },
|
|
|
|
{ "line", LineId },
|
|
|
|
{ "m", ModuleId },
|
|
|
|
{ "mod", ModuleId },
|
|
|
|
{ "module", ModuleId },
|
2011-08-18 20:34:31 +00:00
|
|
|
{ "s", SymbolId },
|
2011-08-17 16:27:34 +00:00
|
|
|
{ "sc", ScopeId },
|
|
|
|
{ "scope", ScopeId },
|
|
|
|
{ "seg", SegmentId },
|
|
|
|
{ "segment", SegmentId },
|
|
|
|
{ "source", SourceId },
|
|
|
|
{ "src", SourceId },
|
|
|
|
{ "sp", SpanId },
|
|
|
|
{ "span", SpanId },
|
2011-08-18 20:34:31 +00:00
|
|
|
{ "sym", SymbolId },
|
|
|
|
{ "symbol", SymbolId },
|
2011-08-28 15:10:43 +00:00
|
|
|
{ "t", TypeId },
|
|
|
|
{ "type", TypeId },
|
2011-08-17 16:27:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < sizeof(TypeTab) / sizeof(TypeTab[0]); ++I) {
|
|
|
|
if (strcmp (TypeName, TypeTab[I].Name) == 0) {
|
|
|
|
return TypeTab[I].Type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return InvalidId;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int GetId (const char* S, unsigned* Id, unsigned* IdType)
|
|
|
|
/* Parse a string for an id. If a valid id is found, it is placed in Id and
|
2014-06-30 09:10:35 +00:00
|
|
|
** the function returns true. If an optional type is found, it is placed in
|
|
|
|
** IdType, otherwise IdType is left unchanged. If no id is found, the
|
|
|
|
** function returns false.
|
|
|
|
*/
|
2011-08-17 16:27:34 +00:00
|
|
|
{
|
|
|
|
char TypeBuf[20];
|
|
|
|
char C;
|
|
|
|
if (sscanf (S, "%u%c", Id, &C) == 1) {
|
|
|
|
/* Just an id found, return it */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (sscanf (S, "%19[a-z]:%u%c", TypeBuf, Id, &C) == 2) {
|
|
|
|
*IdType = FindIdType (TypeBuf);
|
|
|
|
return (*IdType != InvalidId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not a valid id */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Output functions for item lists */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintAddr (cc65_addr Addr, unsigned FieldWidth)
|
|
|
|
/* Output an address */
|
|
|
|
{
|
|
|
|
Print ("$%06lX", (unsigned long) Addr);
|
|
|
|
if (FieldWidth > 7) {
|
|
|
|
Print ("%*s", FieldWidth - 7, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-09-01 20:51:07 +00:00
|
|
|
static void PrintNumber (long Num, unsigned Width, unsigned FieldWidth)
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Output a number */
|
|
|
|
{
|
2011-09-01 20:51:07 +00:00
|
|
|
Print ("%*ld", Width, Num);
|
2011-08-17 16:27:34 +00:00
|
|
|
if (FieldWidth > Width) {
|
|
|
|
Print ("%*s", FieldWidth - Width, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintId (unsigned Id, unsigned FieldWidth)
|
|
|
|
/* Output an id field */
|
|
|
|
{
|
|
|
|
if (Id == CC65_INV_ID) {
|
|
|
|
Print (" -");
|
|
|
|
} else {
|
|
|
|
Print ("%4u", Id);
|
|
|
|
}
|
|
|
|
if (FieldWidth > 4) {
|
|
|
|
Print ("%*s", FieldWidth - 4, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSize (cc65_size Size, unsigned FieldWidth)
|
|
|
|
/* Output a size */
|
|
|
|
{
|
|
|
|
Print ("$%04lX", (unsigned long) Size);
|
|
|
|
if (FieldWidth > 5) {
|
|
|
|
Print ("%*s", FieldWidth - 5, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintTime (time_t T, unsigned FieldWidth)
|
|
|
|
/* Output a time stamp of some sort */
|
|
|
|
{
|
|
|
|
/* Convert to string */
|
|
|
|
char Buf[100];
|
|
|
|
unsigned Len = strftime (Buf, sizeof (Buf), "%Y-%m-%d %H:%M:%S", localtime (&T));
|
|
|
|
|
|
|
|
/* Output */
|
|
|
|
Print ("%s", Buf);
|
|
|
|
if (FieldWidth > Len) {
|
|
|
|
Print ("%*s", FieldWidth - Len, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-09-01 20:51:07 +00:00
|
|
|
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);
|
2011-09-01 20:53:42 +00:00
|
|
|
PrintId (D->type_id, 6);
|
2011-09-01 20:51:07 +00:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void PrintLibraryHeader (void)
|
|
|
|
/* Output the header for a library list */
|
|
|
|
{
|
|
|
|
PrintLine (" id name");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintLibraries (const cc65_libraryinfo* L)
|
|
|
|
/* Output a list of libraries */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_librarydata* D;
|
|
|
|
|
|
|
|
/* Libraries */
|
|
|
|
for (I = 0, D = L->data; I < L->count; ++I, ++D) {
|
|
|
|
PrintId (D->library_id, 8);
|
|
|
|
Print ("%-24s", D->library_name);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintLineHeader (void)
|
|
|
|
/* Output a header for a line list */
|
|
|
|
{
|
|
|
|
/* Header */
|
|
|
|
PrintLine (" id source line type count");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintLines (const cc65_lineinfo* L)
|
|
|
|
/* Output a list of lines */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_linedata* D;
|
|
|
|
|
|
|
|
/* Lines */
|
|
|
|
for (I = 0, D = L->data; I < L->count; ++I, ++D) {
|
|
|
|
PrintId (D->line_id, 8);
|
|
|
|
PrintId (D->source_id, 8);
|
|
|
|
PrintNumber (D->source_line, 6, 9);
|
|
|
|
PrintNumber (D->line_type, 4, 6);
|
|
|
|
PrintNumber (D->count, 3, 0);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintModuleHeader (void)
|
|
|
|
/* Output a header for a module list */
|
|
|
|
{
|
|
|
|
/* Header */
|
|
|
|
PrintLine (" id name source library scope");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintModules (const cc65_moduleinfo* M)
|
|
|
|
/* Output a list of modules */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_moduledata* D;
|
|
|
|
|
|
|
|
/* Modules */
|
|
|
|
for (I = 0, D = M->data; I < M->count; ++I, ++D) {
|
|
|
|
PrintId (D->module_id, 8);
|
|
|
|
Print ("%-24s", D->module_name);
|
|
|
|
PrintId (D->source_id, 8);
|
|
|
|
PrintId (D->library_id, 9);
|
|
|
|
PrintId (D->scope_id, 6);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintScopeHeader (void)
|
|
|
|
/* Output a header for a list of scopes */
|
|
|
|
{
|
|
|
|
/* Header */
|
|
|
|
PrintLine (" id name type size parent symbol module");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintScopes (const cc65_scopeinfo* S)
|
|
|
|
/* Output a list of scopes */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_scopedata* D;
|
|
|
|
|
|
|
|
/* Segments */
|
|
|
|
for (I = 0, D = S->data; I < S->count; ++I, ++D) {
|
|
|
|
PrintId (D->scope_id, 8);
|
|
|
|
Print ("%-24s", D->scope_name);
|
|
|
|
PrintNumber (D->scope_type, 4, 8); /* ## */
|
|
|
|
PrintSize (D->scope_size, 8);
|
|
|
|
PrintId (D->parent_id, 8);
|
|
|
|
PrintId (D->symbol_id, 8);
|
|
|
|
PrintId (D->module_id, 0);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSegmentHeader (void)
|
|
|
|
/* Output a header for a list of segments */
|
|
|
|
{
|
|
|
|
/* Header */
|
|
|
|
PrintLine (" id name address size output file offs");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSegments (const cc65_segmentinfo* S)
|
|
|
|
/* Output a list of segments */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_segmentdata* D;
|
|
|
|
|
|
|
|
/* Segments */
|
|
|
|
for (I = 0, D = S->data; I < S->count; ++I, ++D) {
|
|
|
|
PrintId (D->segment_id, 8);
|
|
|
|
Print ("%-16s", D->segment_name);
|
|
|
|
PrintAddr (D->segment_start, 9);
|
|
|
|
PrintSize (D->segment_size, 7);
|
|
|
|
Print ("%-16s", D->output_name? D->output_name : "");
|
|
|
|
PrintSize (D->output_offs, 6);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSourceHeader (void)
|
|
|
|
/* Output a header for a list of source files */
|
|
|
|
{
|
|
|
|
/* Header */
|
|
|
|
PrintLine (" id name size modification time");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSources (const cc65_sourceinfo* S)
|
|
|
|
/* Output a list of sources */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_sourcedata* D;
|
|
|
|
|
|
|
|
/* Segments */
|
|
|
|
for (I = 0, D = S->data; I < S->count; ++I, ++D) {
|
|
|
|
PrintId (D->source_id, 8);
|
|
|
|
Print ("%-30s", D->source_name);
|
2011-08-18 20:34:31 +00:00
|
|
|
PrintNumber (D->source_size, 7, 9);
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintTime (D->source_mtime, 0);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-26 20:03:11 +00:00
|
|
|
static void PrintSpanHeader (void)
|
|
|
|
/* Output a header for a list of spans */
|
|
|
|
{
|
|
|
|
/* Header */
|
2011-08-28 14:44:41 +00:00
|
|
|
PrintLine (" id start end seg type lines scopes");
|
2011-08-26 20:03:11 +00:00
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSpans (const cc65_spaninfo* S)
|
|
|
|
/* Output a list of spans */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_spandata* D;
|
|
|
|
|
|
|
|
/* Segments */
|
|
|
|
for (I = 0, D = S->data; I < S->count; ++I, ++D) {
|
|
|
|
PrintId (D->span_id, 7);
|
|
|
|
PrintAddr (D->span_start, 8);
|
2011-08-28 14:44:41 +00:00
|
|
|
PrintAddr (D->span_end, 9);
|
2011-08-26 20:03:11 +00:00
|
|
|
PrintId (D->segment_id, 7);
|
2011-08-28 14:44:41 +00:00
|
|
|
PrintId (D->type_id, 6);
|
|
|
|
PrintNumber (D->line_count, 6, 7);
|
|
|
|
PrintNumber (D->scope_count, 7, 0);
|
2011-08-26 20:03:11 +00:00
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-18 20:34:31 +00:00
|
|
|
static void PrintSymbolHeader (void)
|
|
|
|
/* Output a header for a list of symbols */
|
|
|
|
{
|
|
|
|
/* Header */
|
2011-08-19 11:22:36 +00:00
|
|
|
PrintLine (" id name type size value export seg scope parent");
|
2011-08-18 20:34:31 +00:00
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintSymbols (const cc65_symbolinfo* S)
|
|
|
|
/* Output a list of symbols */
|
|
|
|
{
|
|
|
|
unsigned I;
|
|
|
|
const cc65_symboldata* D;
|
|
|
|
|
|
|
|
/* Segments */
|
|
|
|
for (I = 0, D = S->data; I < S->count; ++I, ++D) {
|
|
|
|
PrintId (D->symbol_id, 6);
|
2011-08-26 20:03:11 +00:00
|
|
|
Print ("%-24s", D->symbol_name);
|
2011-08-18 20:34:31 +00:00
|
|
|
PrintNumber (D->symbol_type, 4, 6);
|
|
|
|
PrintNumber (D->symbol_size, 4, 6);
|
|
|
|
PrintNumber (D->symbol_value, 5, 7);
|
|
|
|
PrintId (D->export_id, 7);
|
|
|
|
PrintId (D->segment_id, 6);
|
|
|
|
PrintId (D->scope_id, 6);
|
|
|
|
PrintId (D->parent_id, 0);
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-28 15:10:43 +00:00
|
|
|
static void PrintTypeHeader (void)
|
|
|
|
/* Output a header for a list of types */
|
|
|
|
{
|
|
|
|
/* Header */
|
|
|
|
PrintLine (" id description");
|
|
|
|
PrintSeparator ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrintType (unsigned Id, const cc65_typedata* T)
|
|
|
|
/* Output one type */
|
|
|
|
{
|
|
|
|
/* Output the id */
|
|
|
|
PrintId (Id, 6);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (T->what) {
|
|
|
|
|
|
|
|
case CC65_TYPE_VOID:
|
|
|
|
Print ("VOID");
|
|
|
|
goto ExitPoint;
|
|
|
|
|
|
|
|
case CC65_TYPE_BYTE:
|
|
|
|
Print ("BYTE");
|
|
|
|
goto ExitPoint;
|
|
|
|
|
|
|
|
case CC65_TYPE_WORD:
|
|
|
|
Print ("WORD");
|
|
|
|
goto ExitPoint;
|
|
|
|
|
|
|
|
case CC65_TYPE_DBYTE:
|
|
|
|
Print ("DBYTE");
|
|
|
|
goto ExitPoint;
|
|
|
|
|
|
|
|
case CC65_TYPE_DWORD:
|
|
|
|
Print ("DWORD");
|
|
|
|
goto ExitPoint;
|
|
|
|
|
|
|
|
case CC65_TYPE_FARPTR:
|
|
|
|
Print ("FAR ");
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
|
|
|
case CC65_TYPE_PTR:
|
|
|
|
Print ("POINTER TO ");
|
|
|
|
T = T->data.ptr.ind_type;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CC65_TYPE_ARRAY:
|
|
|
|
Print ("ARRAY[%u] OF ", T->data.array.ele_count);
|
|
|
|
T = T->data.array.ele_type;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Anything else is currently not implemented */
|
|
|
|
Print ("***NOT IMPLEMENTED***");
|
|
|
|
goto ExitPoint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ExitPoint:
|
|
|
|
NewLine ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-16 22:37:01 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Debug file handling */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void UnloadFile (void)
|
|
|
|
/* Unload the debug info file */
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
|
|
|
if (Info) {
|
|
|
|
cc65_free_dbginfo (Info);
|
|
|
|
Info = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static int FileIsLoaded (void)
|
2011-08-16 22:37:01 +00:00
|
|
|
/* Return true if the file is open and has loaded without errors: If not,
|
2014-06-30 09:10:35 +00:00
|
|
|
** print an error message and return false.
|
|
|
|
*/
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
|
|
|
/* File open? */
|
|
|
|
if (Info == 0) {
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintLine ("No debug info file");
|
2011-08-16 22:37:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Errors on load? */
|
|
|
|
if (FileErrors > 0) {
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintLine ("File had load errors!");
|
2011-08-16 22:37:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Warnings on load? */
|
|
|
|
if (FileWarnings > 0) {
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintLine ("Beware - file had load warnings!");
|
2011-08-16 22:37:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Ok */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Command handlers */
|
2011-08-16 22:37:01 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdHelp (Collection* Args attribute ((unused)))
|
|
|
|
/* Output a help text */
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintHelp (MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
|
|
|
|
}
|
2011-08-16 22:37:01 +00:00
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void CmdLoad (Collection* Args)
|
|
|
|
/* Load a debug info file */
|
|
|
|
{
|
|
|
|
/* Unload a loaded file */
|
|
|
|
UnloadFile ();
|
|
|
|
|
|
|
|
/* Clear the counters */
|
|
|
|
FileErrors = 0;
|
|
|
|
FileWarnings = 0;
|
|
|
|
|
|
|
|
/* Open the debug info file */
|
|
|
|
Info = cc65_read_dbginfo (CollAt (Args, 0), FileError);
|
|
|
|
|
|
|
|
/* Print a status */
|
|
|
|
if (FileErrors > 0) {
|
|
|
|
PrintLine ("File loaded with %u errors", FileErrors);
|
|
|
|
} else if (FileWarnings > 0) {
|
|
|
|
PrintLine ("File loaded with %u warnings", FileWarnings);
|
|
|
|
} else {
|
|
|
|
PrintLine ("File loaded successfully");
|
2011-08-16 22:37:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdQuit (Collection* Args attribute ((unused)))
|
|
|
|
/* Terminate the application */
|
|
|
|
{
|
|
|
|
UnloadFile ();
|
|
|
|
Terminate = 1;
|
|
|
|
}
|
2011-08-16 22:37:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdShow (Collection* Args)
|
|
|
|
/* Show items from the debug info file */
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Search for the subcommand, check number of args, then execute it */
|
|
|
|
ExecCmd (Args, ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdShowHelp (Collection* Args attribute ((unused)))
|
|
|
|
/* Print help for the show command */
|
|
|
|
{
|
|
|
|
PrintHelp (ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 21:20:10 +00:00
|
|
|
static void CmdShowChildScopes (Collection* Args)
|
|
|
|
/* Show child scopes from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_scopeinfo* S;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintScopeHeader ();
|
|
|
|
|
|
|
|
/* Output child scopes for all arguments */
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = ScopeId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
case ScopeId:
|
|
|
|
S = cc65_childscopes_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
S = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Invalid id */
|
|
|
|
S = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (S) {
|
|
|
|
PrintScopes (S);
|
|
|
|
cc65_free_scopeinfo (Info, S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-09-01 20:51:07 +00:00
|
|
|
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);
|
2011-09-01 20:53:42 +00:00
|
|
|
break;
|
2011-09-01 20:51:07 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdShowLine (Collection* Args)
|
|
|
|
/* Show lines from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_lineinfo* L;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
2011-08-16 22:37:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Output the header */
|
|
|
|
PrintLineHeader ();
|
|
|
|
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = LineId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
2011-08-18 20:34:31 +00:00
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
case LineId:
|
|
|
|
L = cc65_line_byid (Info, Id);
|
|
|
|
break;
|
2011-08-18 20:34:31 +00:00
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
case SourceId:
|
|
|
|
L = cc65_line_bysource (Info, Id);
|
|
|
|
break;
|
2011-08-18 20:34:31 +00:00
|
|
|
|
|
|
|
case SymbolId:
|
|
|
|
/* ### not very clean */
|
|
|
|
L = cc65_line_bysymdef (Info, Id);
|
|
|
|
if (L) {
|
|
|
|
PrintLines (L);
|
|
|
|
cc65_free_lineinfo (Info, L);
|
|
|
|
}
|
|
|
|
L = cc65_line_bysymref (Info, Id);
|
|
|
|
break;
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
default:
|
|
|
|
L = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
L = 0;
|
|
|
|
}
|
2011-08-16 22:37:01 +00:00
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Output the list */
|
|
|
|
if (L) {
|
|
|
|
PrintLines (L);
|
|
|
|
cc65_free_lineinfo (Info, L);
|
|
|
|
}
|
2011-08-16 22:37:01 +00:00
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
}
|
2011-08-16 22:37:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdShowLibrary (Collection* Args)
|
|
|
|
/* Show libraries from the debug info file */
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
2011-08-17 16:27:34 +00:00
|
|
|
const cc65_libraryinfo* L;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintLibraryHeader ();
|
|
|
|
|
|
|
|
/* No arguments means show all libraries */
|
|
|
|
if (CollCount (Args) == 0) {
|
|
|
|
|
|
|
|
/* Fetch the list of libraries */
|
|
|
|
L = cc65_get_librarylist (Info);
|
|
|
|
|
|
|
|
/* Output the libraries */
|
|
|
|
PrintLibraries (L);
|
|
|
|
|
|
|
|
/* Free the list */
|
|
|
|
cc65_free_libraryinfo (Info, L);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = LibraryId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
case LibraryId:
|
|
|
|
L = cc65_library_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
L = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
L = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (L) {
|
|
|
|
PrintLibraries (L);
|
|
|
|
cc65_free_libraryinfo (Info, L);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-08-16 22:37:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdShowModule (Collection* Args)
|
|
|
|
/* Show modules from the debug info file */
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
2011-08-17 16:27:34 +00:00
|
|
|
const cc65_moduleinfo* M;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintModuleHeader ();
|
|
|
|
|
|
|
|
/* No arguments means show all modules */
|
|
|
|
if (CollCount (Args) == 0) {
|
|
|
|
|
|
|
|
/* Fetch the list of modules */
|
|
|
|
M = cc65_get_modulelist (Info);
|
|
|
|
|
|
|
|
/* Output the modules */
|
|
|
|
PrintModules (M);
|
|
|
|
|
|
|
|
/* Free the list */
|
|
|
|
cc65_free_moduleinfo (Info, M);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsigned I;
|
|
|
|
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:
|
|
|
|
M = cc65_module_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
M = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
M = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (M) {
|
|
|
|
PrintModules (M);
|
|
|
|
cc65_free_moduleinfo (Info, M);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdShowScope (Collection* Args)
|
|
|
|
/* Show scopes from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_scopeinfo* S;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintScopeHeader ();
|
|
|
|
|
|
|
|
/* No arguments means show all modules */
|
|
|
|
if (CollCount (Args) == 0) {
|
|
|
|
|
|
|
|
/* Fetch the list of segments */
|
|
|
|
S = cc65_get_scopelist (Info);
|
|
|
|
|
|
|
|
/* Output the segments */
|
|
|
|
PrintScopes (S);
|
|
|
|
|
|
|
|
/* Free the list */
|
|
|
|
cc65_free_scopeinfo (Info, S);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = ScopeId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
case ModuleId:
|
|
|
|
S = cc65_scope_bymodule (Info, Id);
|
|
|
|
break;
|
|
|
|
case ScopeId:
|
|
|
|
S = cc65_scope_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
S = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* An invalid id may be a scope name */
|
2011-08-17 21:20:10 +00:00
|
|
|
S = cc65_scope_byname (Info, CollConstAt (Args, I));
|
2011-08-17 16:27:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (S) {
|
|
|
|
PrintScopes (S);
|
|
|
|
cc65_free_scopeinfo (Info, S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdShowSegment (Collection* Args)
|
|
|
|
/* Show segments from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_segmentinfo* S;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintSegmentHeader ();
|
|
|
|
|
|
|
|
/* No arguments means show all modules */
|
|
|
|
if (CollCount (Args) == 0) {
|
|
|
|
|
|
|
|
/* Fetch the list of segments */
|
|
|
|
S = cc65_get_segmentlist (Info);
|
|
|
|
|
|
|
|
/* Output the segments */
|
|
|
|
PrintSegments (S);
|
|
|
|
|
|
|
|
/* Free the list */
|
|
|
|
cc65_free_segmentinfo (Info, S);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = SegmentId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
case SegmentId:
|
|
|
|
S = cc65_segment_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
S = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* An invalid id may be a segment name */
|
|
|
|
S = cc65_segment_byname (Info, CollConstAt (Args, I));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (S) {
|
|
|
|
PrintSegments (S);
|
|
|
|
cc65_free_segmentinfo (Info, S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdShowSource (Collection* Args)
|
|
|
|
/* Show source files from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_sourceinfo* S;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintSourceHeader ();
|
|
|
|
|
|
|
|
/* No arguments means show all modules */
|
|
|
|
if (CollCount (Args) == 0) {
|
|
|
|
|
|
|
|
/* Fetch the list of source files */
|
|
|
|
S = cc65_get_sourcelist (Info);
|
|
|
|
|
|
|
|
/* Output the source files */
|
|
|
|
PrintSources (S);
|
|
|
|
|
|
|
|
/* Free the list */
|
|
|
|
cc65_free_sourceinfo (Info, S);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = SourceId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
case ModuleId:
|
|
|
|
S = cc65_source_bymodule (Info, Id);
|
|
|
|
break;
|
|
|
|
case SourceId:
|
|
|
|
S = cc65_source_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
S = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
S = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (S) {
|
|
|
|
PrintSources (S);
|
|
|
|
cc65_free_sourceinfo (Info, S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-08-18 20:34:31 +00:00
|
|
|
}
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
|
2011-08-18 20:34:31 +00:00
|
|
|
|
2011-08-26 20:03:11 +00:00
|
|
|
static void CmdShowSpan (Collection* Args)
|
|
|
|
/* Show spans from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_spaninfo* S;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintSpanHeader ();
|
|
|
|
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = SpanId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
case LineId:
|
|
|
|
S = cc65_span_byline (Info, Id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ScopeId:
|
|
|
|
S = cc65_span_byscope (Info, Id);
|
|
|
|
break;
|
|
|
|
case SpanId:
|
|
|
|
S = cc65_span_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
S = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
S = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (S) {
|
|
|
|
PrintSpans (S);
|
|
|
|
cc65_free_spaninfo (Info, S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-18 20:34:31 +00:00
|
|
|
static void CmdShowSymbol (Collection* Args)
|
2011-08-28 15:10:43 +00:00
|
|
|
/* Show symbols from the debug info file */
|
2011-08-18 20:34:31 +00:00
|
|
|
{
|
|
|
|
const cc65_symbolinfo* S;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintSymbolHeader ();
|
|
|
|
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = SymbolId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
|
|
|
|
case ScopeId:
|
|
|
|
S = cc65_symbol_byscope (Info, Id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SymbolId:
|
|
|
|
S = cc65_symbol_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
S = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
S = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (S) {
|
|
|
|
PrintSymbols (S);
|
|
|
|
cc65_free_symbolinfo (Info, S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdShowSymDef (Collection* Args)
|
2011-08-28 15:10:43 +00:00
|
|
|
/* Show symbol definitions from the debug info file */
|
2011-08-18 20:34:31 +00:00
|
|
|
{
|
|
|
|
const cc65_lineinfo* L;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintLineHeader ();
|
|
|
|
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = SymbolId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
|
|
|
|
case SymbolId:
|
|
|
|
L = cc65_line_bysymdef (Info, Id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
L = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
L = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (L) {
|
|
|
|
PrintLines (L);
|
|
|
|
cc65_free_lineinfo (Info, L);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CmdShowSymRef (Collection* Args)
|
2011-08-28 15:10:43 +00:00
|
|
|
/* Show symbol references from the debug info file */
|
2011-08-18 20:34:31 +00:00
|
|
|
{
|
|
|
|
const cc65_lineinfo* L;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintLineHeader ();
|
|
|
|
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = SymbolId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
|
|
|
|
case SymbolId:
|
|
|
|
L = cc65_line_bysymref (Info, Id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
L = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
L = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (L) {
|
|
|
|
PrintLines (L);
|
|
|
|
cc65_free_lineinfo (Info, L);
|
|
|
|
}
|
|
|
|
}
|
2011-08-17 16:27:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-28 15:10:43 +00:00
|
|
|
static void CmdShowType (Collection* Args)
|
|
|
|
/* Show types from the debug info file */
|
|
|
|
{
|
|
|
|
const cc65_typedata* T;
|
|
|
|
const cc65_spaninfo* S;
|
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Be sure a file is loaded */
|
|
|
|
if (!FileIsLoaded ()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the header */
|
|
|
|
PrintTypeHeader ();
|
|
|
|
|
|
|
|
for (I = 0; I < CollCount (Args); ++I) {
|
|
|
|
|
|
|
|
/* Parse the argument */
|
|
|
|
unsigned Id;
|
|
|
|
unsigned IdType = TypeId;
|
|
|
|
if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
|
|
|
|
/* Fetch list depending on type */
|
|
|
|
switch (IdType) {
|
|
|
|
|
|
|
|
case SpanId:
|
|
|
|
S = cc65_span_byid (Info, Id);
|
|
|
|
if (S == 0 || S->count == 0) {
|
|
|
|
T = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Id = S->data[0].type_id;
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
|
|
|
case TypeId:
|
|
|
|
T = cc65_type_byid (Info, Id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
T = 0;
|
|
|
|
PrintLine ("Invalid id type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Ignore the invalid id */
|
|
|
|
T = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the list */
|
|
|
|
if (T) {
|
|
|
|
PrintType (Id, T);
|
|
|
|
cc65_free_typedata (Info, T);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
static void CmdUnload (Collection* Args attribute ((unused)))
|
|
|
|
/* Unload a debug info file */
|
|
|
|
{
|
|
|
|
UnloadFile ();
|
2011-08-16 22:37:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Code */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-16 22:37:01 +00:00
|
|
|
static int Parse (char* CmdLine, Collection* Args)
|
|
|
|
/* Parse the command line and store the arguments in Args. Return true if ok,
|
2014-06-30 09:10:35 +00:00
|
|
|
** false on error.
|
|
|
|
*/
|
2011-08-16 22:37:01 +00:00
|
|
|
{
|
|
|
|
char* End;
|
|
|
|
|
|
|
|
/* Clear the collection */
|
|
|
|
CollDeleteAll (Args);
|
|
|
|
|
|
|
|
/* Parse the command line */
|
|
|
|
while (1) {
|
|
|
|
|
|
|
|
/* Break out on end of line */
|
|
|
|
if (*CmdLine == '\0') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for start of next command */
|
|
|
|
if (IsSpace (*CmdLine)) {
|
|
|
|
++CmdLine;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow double quotes to terminate a command */
|
|
|
|
if (*CmdLine == '\"' || *CmdLine == '\'') {
|
|
|
|
char Term = *CmdLine++;
|
|
|
|
End = CmdLine;
|
|
|
|
while (*End != Term) {
|
|
|
|
if (*End == '\0') {
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintLine ("Unterminated argument");
|
2011-08-16 22:37:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
++End;
|
|
|
|
}
|
|
|
|
*End++ = '\0';
|
|
|
|
} else {
|
|
|
|
End = CmdLine;
|
|
|
|
while (!IsSpace (*End)) {
|
|
|
|
if (*End == '\0') {
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintLine ("Unterminated argument");
|
2011-08-16 22:37:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
++End;
|
|
|
|
}
|
|
|
|
*End++ = '\0';
|
|
|
|
}
|
|
|
|
CollAppend (Args, CmdLine);
|
|
|
|
CmdLine = End;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ok */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
int main (int argc, char* argv[])
|
2011-08-16 22:37:01 +00:00
|
|
|
/* Main program */
|
|
|
|
{
|
|
|
|
char Input[256];
|
|
|
|
Collection Args = STATIC_COLLECTION_INITIALIZER;
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Initialize the command line */
|
|
|
|
InitCmdLine (&argc, &argv, "dbgsh");
|
|
|
|
|
|
|
|
/* If we have commands on the command line, execute them */
|
|
|
|
if (ArgCount > 1) {
|
|
|
|
unsigned I;
|
|
|
|
for (I = 1; I < ArgCount; ++I) {
|
|
|
|
CollAppend (&Args, ArgVec[I]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for the command, check number of args, then execute it */
|
|
|
|
ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Loop til program end */
|
2011-08-16 22:37:01 +00:00
|
|
|
while (!Terminate) {
|
|
|
|
|
|
|
|
/* Output a prompt, then read the input */
|
2011-08-17 16:27:34 +00:00
|
|
|
Print ("dbgsh> ");
|
2011-08-16 22:37:01 +00:00
|
|
|
fflush (stdout);
|
|
|
|
if (fgets (Input, sizeof (Input), stdin) == 0) {
|
2011-08-17 16:27:34 +00:00
|
|
|
PrintLine ("(EOF)");
|
2011-08-16 22:37:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse the command line */
|
|
|
|
if (Parse (Input, &Args) == 0 || CollCount (&Args) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-08-17 16:27:34 +00:00
|
|
|
/* Search for the command, check number of args, then execute it */
|
|
|
|
ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
|
2011-08-16 22:37:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free arguments */
|
|
|
|
DoneCollection (&Args);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|