From 5edd1f701731fa6d09342c5347d0acc82184d0fe Mon Sep 17 00:00:00 2001 From: uz Date: Wed, 17 Aug 2011 16:27:34 +0000 Subject: [PATCH] Added several commands to display debug file items. git-svn-id: svn://svn.cc65.org/cc65/trunk@5195 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbgsh.c | 1092 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 1011 insertions(+), 81 deletions(-) diff --git a/src/dbginfo/dbgsh.c b/src/dbginfo/dbgsh.c index 172f6a8f5..f5c49dd4f 100644 --- a/src/dbginfo/dbgsh.c +++ b/src/dbginfo/dbgsh.c @@ -37,14 +37,13 @@ #include #include #include -#include -#include -#include +#include #include /* common */ #include "attrib.h" #include "chartype.h" +#include "cmdline.h" #include "coll.h" /* dbginfo */ @@ -52,6 +51,50 @@ +/*****************************************************************************/ +/* 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 */ + +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 */ + +static void CmdUnload (Collection* Args attribute ((unused))); +/* Unload a debug info file */ + + + /*****************************************************************************/ /* Data */ /*****************************************************************************/ @@ -68,24 +111,556 @@ static cc65_dbginfo Info = 0; static unsigned FileErrors = 0; static unsigned FileWarnings = 0; +/* Type of an id */ +enum { + InvalidId, + LibraryId, + LineId, + ModuleId, + ScopeId, + SegmentId, + SourceId, + SpanId, +}; + /* Structure that contains a command description */ typedef struct CmdEntry CmdEntry; struct CmdEntry { - char Cmd[12]; - int ArgCount; - void (*Func) (Collection*); + char Cmd[12]; + const char* Help; + int ArgCount; + void (*Func) (Collection*); +}; + +/* Table with main commands */ +static const CmdEntry MainCmds[] = { + { + "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[] = { + { + "help", + "Show available subcommands", + 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 + }, }; +/*****************************************************************************/ +/* 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 */ +{ + PrintLine ("-----------------------------------------------------------------------"); +} + + + +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 + * the argument count, then execute it. If there are problems, output a + * diagnostic. + */ +{ + /* 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 + * 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. + */ + 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--) { + PrintLine ("%-*s%s", (int) sizeof (Tab->Cmd) + 2, Tab->Cmd, Tab->Help); + ++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 }, + { "sc", ScopeId }, + { "scope", ScopeId }, + { "seg", SegmentId }, + { "segment", SegmentId }, + { "source", SourceId }, + { "src", SourceId }, + { "sp", SpanId }, + { "span", SpanId }, + }; + + 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 + * 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. + */ +{ + 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, ""); + } +} + + + +static void PrintNumber (unsigned long Num, unsigned Width, unsigned FieldWidth) +/* Output a number */ +{ + Print ("%*lu", Width, Num); + 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, ""); + } +} + + + +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); + Print ("%7lu ", D->source_size); + PrintTime (D->source_mtime, 0); + NewLine (); + } +} + + + /*****************************************************************************/ /* Debug file handling */ /*****************************************************************************/ -static void CloseFile (void) -/* Close the debug info file */ +static void UnloadFile (void) +/* Unload the debug info file */ { if (Info) { cc65_free_dbginfo (Info); @@ -95,26 +670,26 @@ static void CloseFile (void) -static int FileIsOpen (void) +static int FileIsLoaded (void) /* Return true if the file is open and has loaded without errors: If not, * print an error message and return false. */ { /* File open? */ if (Info == 0) { - printf ("No debug info file\n"); + PrintLine ("No debug info file"); return 0; } /* Errors on load? */ if (FileErrors > 0) { - printf ("File had load errors!\n"); + PrintLine ("File had load errors!"); return 0; } /* Warnings on load? */ if (FileWarnings > 0) { - printf ("Beware - file had load warnings!\n"); + PrintLine ("Beware - file had load warnings!"); } /* Ok */ @@ -124,74 +699,442 @@ static int FileIsOpen (void) /*****************************************************************************/ -/* Helpers */ +/* Command handlers */ /*****************************************************************************/ -static void FileError (const cc65_parseerror* Info) -/* Callback function - is called in case of errors */ +static void CmdHelp (Collection* Args attribute ((unused))) +/* Output a help text */ { - /* Output a message */ - printf ("%s:%s(%lu): %s\n", - Info->type? "Error" : "Warning", - Info->name, - (unsigned long) Info->line, - Info->errormsg); + PrintHelp (MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0])); +} - /* Bump the counters */ - switch (Info->type) { - case CC65_WARNING: ++FileWarnings; break; - default: ++FileErrors; break; + + +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"); } } -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ +static void CmdQuit (Collection* Args attribute ((unused))) +/* Terminate the application */ +{ + UnloadFile (); + Terminate = 1; +} -static void CmdOpen (Collection* Args) -/* Open a debug info file */ +static void CmdShow (Collection* Args) +/* Show items from the debug info file */ { - /* Argument is file name */ - if (CollCount (Args) != 2) { - printf ("Command requires exactly one argument\n"); + /* 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])); +} + + + +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 ()) { return; } - /* Close an open file */ - CloseFile (); + /* 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) { + case LineId: + L = cc65_line_byid (Info, Id); + break; + case SourceId: + L = cc65_line_bysource (Info, Id); + break; + default: + L = 0; + PrintLine ("Invalid id type"); + break; + } + } else { + /* Ignore the invalid id */ + L = 0; + } - /* Clear the counters */ - FileErrors = 0; - FileWarnings = 0; + /* Output the list */ + if (L) { + PrintLines (L); + cc65_free_lineinfo (Info, L); + } - /* Open the debug info file */ - Info = cc65_read_dbginfo (CollAt (Args, 1), FileError); + } } -static void CmdClose (Collection* Args attribute ((unused))) -/* Close a debug info file */ +static void CmdShowLibrary (Collection* Args) +/* Show libraries from the debug info file */ { - CloseFile (); + 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); + } + } + } } -static void CmdQuit (Collection* Args attribute ((unused))) -/* Terminate the application */ +static void CmdShowModule (Collection* Args) +/* Show modules from the debug info file */ { - Terminate = 1; + 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 */ + //S = cc65_scope_byname (Info, CollConstAt (Args, I)); + S = 0; + } + + /* 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); + } + } + } + +} + + + +static void CmdUnload (Collection* Args attribute ((unused))) +/* Unload a debug info file */ +{ + UnloadFile (); } +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + static int Parse (char* CmdLine, Collection* Args) /* Parse the command line and store the arguments in Args. Return true if ok, * false on error. @@ -222,7 +1165,7 @@ static int Parse (char* CmdLine, Collection* Args) End = CmdLine; while (*End != Term) { if (*End == '\0') { - fputs ("Unterminated argument\n", stdout); + PrintLine ("Unterminated argument"); return 0; } ++End; @@ -232,7 +1175,7 @@ static int Parse (char* CmdLine, Collection* Args) End = CmdLine; while (!IsSpace (*End)) { if (*End == '\0') { - fputs ("Unterminated argument\n", stdout); + PrintLine ("Unterminated argument"); return 0; } ++End; @@ -249,41 +1192,34 @@ static int Parse (char* CmdLine, Collection* Args) -static const CmdEntry* FindCmd (const char* Cmd) -/* Search for a command */ -{ - static const CmdEntry CmdTab[] = { - { "close", 0, CmdClose }, - { "open", 1, CmdOpen }, - { "quit", 0, CmdQuit }, - }; - - unsigned I; - for (I = 0; I < sizeof (CmdTab) / sizeof (CmdTab[0]); ++I) { - if (strcmp (Cmd, CmdTab[I].Cmd) == 0) { - return CmdTab + I; - } - } - return 0; -} - - - -int main (void) +int main (int argc, char* argv[]) /* Main program */ { char Input[256]; Collection Args = STATIC_COLLECTION_INITIALIZER; - const char* Cmd; - const CmdEntry* E; + /* 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 */ while (!Terminate) { /* Output a prompt, then read the input */ - fputs ("dbgsh> ", stdout); + Print ("dbgsh> "); fflush (stdout); if (fgets (Input, sizeof (Input), stdin) == 0) { - fputs ("(EOF)\n", stdout); + PrintLine ("(EOF)"); break; } @@ -292,14 +1228,8 @@ int main (void) continue; } - /* Search for the command, then execute it */ - Cmd = CollAt (&Args, 0); - E = FindCmd (Cmd); - if (E == 0) { - printf ("No such command: %s\n", Cmd); - } else { - E->Func (&Args); - } + /* Search for the command, check number of args, then execute it */ + ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0])); } /* Free arguments */ -- 2.39.5