1 /*****************************************************************************/
5 /* debug info test shell */
9 /* (C) 2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
54 /*****************************************************************************/
55 /* Command handler forwards */
56 /*****************************************************************************/
60 static void CmdHelp (Collection* Args attribute ((unused)));
61 /* Output a help text */
63 static void CmdLoad (Collection* Args);
64 /* Load a debug info file */
66 static void CmdQuit (Collection* Args attribute ((unused)));
67 /* Terminate the application */
69 static void CmdShow (Collection* Args);
70 /* Show items from the debug info file */
72 static void CmdShowHelp (Collection* Args);
73 /* Print help for the show command */
75 static void CmdShowChildScopes (Collection* Args);
76 /* Show child scopes from the debug info file */
78 static void CmdShowCSymbol (Collection* Args);
79 /* Show c symbols from the debug info file */
81 static void CmdShowFunction (Collection* Args);
82 /* Show C functions from the debug info file */
84 static void CmdShowLibrary (Collection* Args);
85 /* Show libraries from the debug info file */
87 static void CmdShowLine (Collection* Args);
88 /* Show lines from the debug info file */
90 static void CmdShowModule (Collection* Args);
91 /* Show modules from the debug info file */
93 static void CmdShowScope (Collection* Args);
94 /* Show scopes from the debug info file */
96 static void CmdShowSegment (Collection* Args);
97 /* Show segments from the debug info file */
99 static void CmdShowSource (Collection* Args);
100 /* Show source files from the debug info file */
102 static void CmdShowSpan (Collection* Args);
103 /* Show spans from the debug info file */
105 static void CmdShowSymbol (Collection* Args);
108 static void CmdShowSymDef (Collection* Args);
109 /* Show lines from the debug info file */
111 static void CmdShowSymRef (Collection* Args);
112 /* Show lines from the debug info file */
114 static void CmdShowType (Collection* Args);
115 /* Show types from the debug info file */
117 static void CmdUnload (Collection* Args attribute ((unused)));
118 /* Unload a debug info file */
122 /*****************************************************************************/
124 /*****************************************************************************/
128 /* Terminate flag - end program when set to true */
129 static int Terminate = 0;
131 /* The debug file data */
132 static cc65_dbginfo Info = 0;
134 /* Error and warning counters */
135 static unsigned FileErrors = 0;
136 static unsigned FileWarnings = 0;
153 /* Structure that contains a command description */
154 typedef struct CmdEntry CmdEntry;
159 void (*Func) (Collection*);
162 /* Table with main commands */
163 static const CmdEntry MainCmds[] = {
171 "Show available commands",
176 "Load a debug info file",
181 "Terminate the shell",
186 "Show items from the info file",
191 "Unload a debug info file",
197 /* Table with show commands */
198 static const CmdEntry ShowCmds[] = {
201 "Show child scopes of other scopes.",
226 "Show available subcommands.",
231 "Show line info. May be followed by one or more line ids.",
236 "Show libraries. May be followed by one or more library ids.",
241 "Show modules. May be followed by one or more module ids.",
246 "Show scopes. May be followed by one or more segment ids.",
251 "Show segments. May be followed by one or more segment ids.",
256 "Show sources. May be followed by one or more source file ids.",
261 "Show spans. May be followed by one or more span ids.",
266 "Show symbols. May be followed by one or more symbol or scope ids.",
271 "Show where a symbol was defined. May be followed by one or more symbol ids.",
276 "Show where a symbol was referenced. May be followed by one or more symbol ids.",
281 "Show type information. May be followed by one or more type ids.",
289 /*****************************************************************************/
291 /*****************************************************************************/
295 static void NewLine (void)
296 /* Output a newline */
303 static void Print (const char* Format, ...) attribute((format(printf,1,2)));
304 static void Print (const char* Format, ...)
305 /* Print a piece of output (no linefeed added) */
308 va_start (ap, Format);
309 vprintf (Format, ap);
315 static void PrintLine (const char* Format, ...) attribute((format(printf,1,2)));
316 static void PrintLine (const char* Format, ...)
317 /* Print one line of output. The linefeed is supplied by the function */
320 va_start (ap, Format);
321 vprintf (Format, ap);
328 static void PrintSeparator (void)
329 /* Print a separator line */
331 PrintLine ("---------------------------------------------------------------------------");
336 static void FileError (const cc65_parseerror* Info)
337 /* Callback function - is called in case of errors */
339 /* Output a message */
340 PrintLine ("%s:%s(%lu): %s",
341 Info->type? "Error" : "Warning",
343 (unsigned long) Info->line,
346 /* Bump the counters */
347 switch (Info->type) {
348 case CC65_WARNING: ++FileWarnings; break;
349 default: ++FileErrors; break;
355 static const CmdEntry* FindCmd (const char* Cmd, const CmdEntry* Tab, unsigned Count)
356 /* Search for a command in the given table */
359 for (I = 0; I < Count; ++I, ++Tab) {
360 if (strcmp (Cmd, Tab->Cmd) == 0) {
369 static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count)
370 /* Search for the command in slot 0 of the given collection. If found, check
371 ** the argument count, then execute it. If there are problems, output a
375 /* Search for the command, check number of args, then execute it */
376 const char* Cmd = CollAt (Args, 0);
377 const CmdEntry* E = FindCmd (Cmd, Tab, Count);
379 PrintLine ("No such command: %s", Cmd);
383 /* Check the number of arguments. Zero means that the function will check
384 ** itself. A negative count means that the function needs at least
385 ** abs(count) arguments. A positive count means that the function needs
386 ** exactly this number of arguments.
387 ** Note: The number includes the command itself.
389 if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) {
390 /* Argument number mismatch */
391 switch (E->ArgCount) {
394 PrintLine ("Command doesn't accept an argument");
398 PrintLine ("Command requires an argument");
402 PrintLine ("Command requires %d arguments", E->ArgCount-1);
405 } else if (E->ArgCount < 0 && (int)CollCount (Args) < -E->ArgCount) {
406 /* Argument number mismatch */
407 switch (E->ArgCount) {
410 PrintLine ("Command requires at least one argument");
414 PrintLine ("Command requires at least %d arguments", E->ArgCount-1);
418 /* Remove the command from the argument list, then execute it */
419 CollDelete (Args, 0);
426 static void PrintHelp (const CmdEntry* Tab, unsigned Count)
427 /* Output help for one command table */
430 /* Ignore the commands without help text */
432 PrintLine ("%-*s%s", (int) sizeof (Tab->Cmd) + 2, Tab->Cmd, Tab->Help);
440 static unsigned FindIdType (const char* TypeName)
441 /* Find an id type by its name. Returns the type or InvalidId. */
443 static const struct {
448 { "lib", LibraryId },
449 { "library", LibraryId },
453 { "module", ModuleId },
456 { "scope", ScopeId },
457 { "seg", SegmentId },
458 { "segment", SegmentId },
459 { "source", SourceId },
464 { "symbol", SymbolId },
470 for (I = 0; I < sizeof(TypeTab) / sizeof(TypeTab[0]); ++I) {
471 if (strcmp (TypeName, TypeTab[I].Name) == 0) {
472 return TypeTab[I].Type;
480 static int GetId (const char* S, unsigned* Id, unsigned* IdType)
481 /* Parse a string for an id. If a valid id is found, it is placed in Id and
482 ** the function returns true. If an optional type is found, it is placed in
483 ** IdType, otherwise IdType is left unchanged. If no id is found, the
484 ** function returns false.
489 if (sscanf (S, "%u%c", Id, &C) == 1) {
490 /* Just an id found, return it */
493 if (sscanf (S, "%19[a-z]:%u%c", TypeBuf, Id, &C) == 2) {
494 *IdType = FindIdType (TypeBuf);
495 return (*IdType != InvalidId);
504 /*****************************************************************************/
505 /* Output functions for item lists */
506 /*****************************************************************************/
510 static void PrintAddr (cc65_addr Addr, unsigned FieldWidth)
511 /* Output an address */
513 Print ("$%06lX", (unsigned long) Addr);
514 if (FieldWidth > 7) {
515 Print ("%*s", FieldWidth - 7, "");
521 static void PrintNumber (long Num, unsigned Width, unsigned FieldWidth)
522 /* Output a number */
524 Print ("%*ld", Width, Num);
525 if (FieldWidth > Width) {
526 Print ("%*s", FieldWidth - Width, "");
532 static void PrintId (unsigned Id, unsigned FieldWidth)
533 /* Output an id field */
535 if (Id == CC65_INV_ID) {
540 if (FieldWidth > 4) {
541 Print ("%*s", FieldWidth - 4, "");
547 static void PrintSize (cc65_size Size, unsigned FieldWidth)
550 Print ("$%04lX", (unsigned long) Size);
551 if (FieldWidth > 5) {
552 Print ("%*s", FieldWidth - 5, "");
558 static void PrintTime (time_t T, unsigned FieldWidth)
559 /* Output a time stamp of some sort */
561 /* Convert to string */
563 unsigned Len = strftime (Buf, sizeof (Buf), "%Y-%m-%d %H:%M:%S", localtime (&T));
567 if (FieldWidth > Len) {
568 Print ("%*s", FieldWidth - Len, "");
574 static void PrintCSymbolHeader (void)
575 /* Output a header for a list of C symbols */
578 PrintLine (" id name type kind sc offs symbol scope");
584 static void PrintCSymbols (const cc65_csyminfo* S)
585 /* Output a list of C symbols */
588 const cc65_csymdata* D;
591 for (I = 0, D = S->data; I < S->count; ++I, ++D) {
592 PrintId (D->csym_id, 6);
593 Print ("%-28s", D->csym_name);
594 PrintId (D->type_id, 6);
595 PrintNumber (D->csym_kind, 4, 6);
596 PrintNumber (D->csym_sc, 4, 6);
597 PrintNumber (D->csym_offs, 4, 8);
598 PrintId (D->symbol_id, 6);
599 PrintId (D->scope_id, 0);
606 static void PrintLibraryHeader (void)
607 /* Output the header for a library list */
609 PrintLine (" id name");
615 static void PrintLibraries (const cc65_libraryinfo* L)
616 /* Output a list of libraries */
619 const cc65_librarydata* D;
622 for (I = 0, D = L->data; I < L->count; ++I, ++D) {
623 PrintId (D->library_id, 8);
624 Print ("%-24s", D->library_name);
631 static void PrintLineHeader (void)
632 /* Output a header for a line list */
635 PrintLine (" id source line type count");
641 static void PrintLines (const cc65_lineinfo* L)
642 /* Output a list of lines */
645 const cc65_linedata* D;
648 for (I = 0, D = L->data; I < L->count; ++I, ++D) {
649 PrintId (D->line_id, 8);
650 PrintId (D->source_id, 8);
651 PrintNumber (D->source_line, 6, 9);
652 PrintNumber (D->line_type, 4, 6);
653 PrintNumber (D->count, 3, 0);
660 static void PrintModuleHeader (void)
661 /* Output a header for a module list */
664 PrintLine (" id name source library scope");
670 static void PrintModules (const cc65_moduleinfo* M)
671 /* Output a list of modules */
674 const cc65_moduledata* D;
677 for (I = 0, D = M->data; I < M->count; ++I, ++D) {
678 PrintId (D->module_id, 8);
679 Print ("%-24s", D->module_name);
680 PrintId (D->source_id, 8);
681 PrintId (D->library_id, 9);
682 PrintId (D->scope_id, 6);
689 static void PrintScopeHeader (void)
690 /* Output a header for a list of scopes */
693 PrintLine (" id name type size parent symbol module");
699 static void PrintScopes (const cc65_scopeinfo* S)
700 /* Output a list of scopes */
703 const cc65_scopedata* D;
706 for (I = 0, D = S->data; I < S->count; ++I, ++D) {
707 PrintId (D->scope_id, 8);
708 Print ("%-24s", D->scope_name);
709 PrintNumber (D->scope_type, 4, 8); /* ## */
710 PrintSize (D->scope_size, 8);
711 PrintId (D->parent_id, 8);
712 PrintId (D->symbol_id, 8);
713 PrintId (D->module_id, 0);
720 static void PrintSegmentHeader (void)
721 /* Output a header for a list of segments */
724 PrintLine (" id name address size output file offs");
730 static void PrintSegments (const cc65_segmentinfo* S)
731 /* Output a list of segments */
734 const cc65_segmentdata* D;
737 for (I = 0, D = S->data; I < S->count; ++I, ++D) {
738 PrintId (D->segment_id, 8);
739 Print ("%-16s", D->segment_name);
740 PrintAddr (D->segment_start, 9);
741 PrintSize (D->segment_size, 7);
742 Print ("%-16s", D->output_name? D->output_name : "");
743 PrintSize (D->output_offs, 6);
750 static void PrintSourceHeader (void)
751 /* Output a header for a list of source files */
754 PrintLine (" id name size modification time");
760 static void PrintSources (const cc65_sourceinfo* S)
761 /* Output a list of sources */
764 const cc65_sourcedata* D;
767 for (I = 0, D = S->data; I < S->count; ++I, ++D) {
768 PrintId (D->source_id, 8);
769 Print ("%-30s", D->source_name);
770 PrintNumber (D->source_size, 7, 9);
771 PrintTime (D->source_mtime, 0);
778 static void PrintSpanHeader (void)
779 /* Output a header for a list of spans */
782 PrintLine (" id start end seg type lines scopes");
788 static void PrintSpans (const cc65_spaninfo* S)
789 /* Output a list of spans */
792 const cc65_spandata* D;
795 for (I = 0, D = S->data; I < S->count; ++I, ++D) {
796 PrintId (D->span_id, 7);
797 PrintAddr (D->span_start, 8);
798 PrintAddr (D->span_end, 9);
799 PrintId (D->segment_id, 7);
800 PrintId (D->type_id, 6);
801 PrintNumber (D->line_count, 6, 7);
802 PrintNumber (D->scope_count, 7, 0);
809 static void PrintSymbolHeader (void)
810 /* Output a header for a list of symbols */
813 PrintLine (" id name type size value export seg scope parent");
819 static void PrintSymbols (const cc65_symbolinfo* S)
820 /* Output a list of symbols */
823 const cc65_symboldata* D;
826 for (I = 0, D = S->data; I < S->count; ++I, ++D) {
827 PrintId (D->symbol_id, 6);
828 Print ("%-24s", D->symbol_name);
829 PrintNumber (D->symbol_type, 4, 6);
830 PrintNumber (D->symbol_size, 4, 6);
831 PrintNumber (D->symbol_value, 5, 7);
832 PrintId (D->export_id, 7);
833 PrintId (D->segment_id, 6);
834 PrintId (D->scope_id, 6);
835 PrintId (D->parent_id, 0);
842 static void PrintTypeHeader (void)
843 /* Output a header for a list of types */
846 PrintLine (" id description");
852 static void PrintType (unsigned Id, const cc65_typedata* T)
853 /* Output one type */
873 case CC65_TYPE_DBYTE:
877 case CC65_TYPE_DWORD:
881 case CC65_TYPE_FARPTR:
886 Print ("POINTER TO ");
887 T = T->data.ptr.ind_type;
890 case CC65_TYPE_ARRAY:
891 Print ("ARRAY[%u] OF ", T->data.array.ele_count);
892 T = T->data.array.ele_type;
896 /* Anything else is currently not implemented */
897 Print ("***NOT IMPLEMENTED***");
908 /*****************************************************************************/
909 /* Debug file handling */
910 /*****************************************************************************/
914 static void UnloadFile (void)
915 /* Unload the debug info file */
918 cc65_free_dbginfo (Info);
925 static int FileIsLoaded (void)
926 /* Return true if the file is open and has loaded without errors: If not,
927 ** print an error message and return false.
932 PrintLine ("No debug info file");
936 /* Errors on load? */
937 if (FileErrors > 0) {
938 PrintLine ("File had load errors!");
942 /* Warnings on load? */
943 if (FileWarnings > 0) {
944 PrintLine ("Beware - file had load warnings!");
953 /*****************************************************************************/
954 /* Command handlers */
955 /*****************************************************************************/
959 static void CmdHelp (Collection* Args attribute ((unused)))
960 /* Output a help text */
962 PrintHelp (MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
967 static void CmdLoad (Collection* Args)
968 /* Load a debug info file */
970 /* Unload a loaded file */
973 /* Clear the counters */
977 /* Open the debug info file */
978 Info = cc65_read_dbginfo (CollAt (Args, 0), FileError);
981 if (FileErrors > 0) {
982 PrintLine ("File loaded with %u errors", FileErrors);
983 } else if (FileWarnings > 0) {
984 PrintLine ("File loaded with %u warnings", FileWarnings);
986 PrintLine ("File loaded successfully");
992 static void CmdQuit (Collection* Args attribute ((unused)))
993 /* Terminate the application */
1001 static void CmdShow (Collection* Args)
1002 /* Show items from the debug info file */
1004 /* Search for the subcommand, check number of args, then execute it */
1005 ExecCmd (Args, ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0]));
1010 static void CmdShowHelp (Collection* Args attribute ((unused)))
1011 /* Print help for the show command */
1013 PrintHelp (ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0]));
1018 static void CmdShowChildScopes (Collection* Args)
1019 /* Show child scopes from the debug info file */
1021 const cc65_scopeinfo* S;
1024 /* Be sure a file is loaded */
1025 if (!FileIsLoaded ()) {
1029 /* Output the header */
1030 PrintScopeHeader ();
1032 /* Output child scopes for all arguments */
1033 for (I = 0; I < CollCount (Args); ++I) {
1035 /* Parse the argument */
1037 unsigned IdType = ScopeId;
1038 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1039 /* Fetch list depending on type */
1042 S = cc65_childscopes_byid (Info, Id);
1046 PrintLine ("Invalid id type");
1054 /* Output the list */
1057 cc65_free_scopeinfo (Info, S);
1064 static void CmdShowCSymbol (Collection* Args)
1065 /* Show C symbols from the debug info file */
1067 const cc65_csyminfo* S;
1069 /* Be sure a file is loaded */
1070 if (!FileIsLoaded ()) {
1074 /* Output the header */
1075 PrintCSymbolHeader ();
1077 /* No arguments means show all libraries */
1078 if (CollCount (Args) == 0) {
1080 /* Fetch the list of c symbols */
1081 S = cc65_get_csymlist (Info);
1083 /* Output the c symbols */
1087 cc65_free_csyminfo (Info, S);
1091 /* Output c symbols for all arguments */
1093 for (I = 0; I < CollCount (Args); ++I) {
1095 /* Parse the argument */
1097 unsigned IdType = CSymbolId;
1098 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1099 /* Fetch list depending on type */
1102 S = cc65_csym_byid (Info, Id);
1105 S = cc65_csym_byscope (Info, Id);
1109 PrintLine ("Invalid id type");
1117 /* Output the list */
1120 cc65_free_csyminfo (Info, S);
1128 static void CmdShowFunction (Collection* Args)
1129 /* Show C functions from the debug info file */
1131 const cc65_csyminfo* S;
1134 /* Be sure a file is loaded */
1135 if (!FileIsLoaded ()) {
1139 /* Output the header */
1140 PrintCSymbolHeader ();
1142 /* Output c symbols for all arguments */
1143 for (I = 0; I < CollCount (Args); ++I) {
1145 /* Parse the argument */
1147 unsigned IdType = ModuleId;
1148 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1149 /* Fetch list depending on type */
1152 S = cc65_cfunc_bymodule (Info, Id);
1156 PrintLine ("Invalid id type");
1160 /* An invalid id may be a function name */
1161 S = cc65_cfunc_byname (Info, CollConstAt (Args, I));
1164 /* Output the list */
1167 cc65_free_csyminfo (Info, S);
1174 static void CmdShowLine (Collection* Args)
1175 /* Show lines from the debug info file */
1177 const cc65_lineinfo* L;
1180 /* Be sure a file is loaded */
1181 if (!FileIsLoaded ()) {
1185 /* Output the header */
1188 for (I = 0; I < CollCount (Args); ++I) {
1190 /* Parse the argument */
1192 unsigned IdType = LineId;
1193 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1194 /* Fetch list depending on type */
1198 L = cc65_line_byid (Info, Id);
1202 L = cc65_line_bysource (Info, Id);
1206 /* ### not very clean */
1207 L = cc65_line_bysymdef (Info, Id);
1210 cc65_free_lineinfo (Info, L);
1212 L = cc65_line_bysymref (Info, Id);
1217 PrintLine ("Invalid id type");
1221 /* Ignore the invalid id */
1225 /* Output the list */
1228 cc65_free_lineinfo (Info, L);
1236 static void CmdShowLibrary (Collection* Args)
1237 /* Show libraries from the debug info file */
1239 const cc65_libraryinfo* L;
1241 /* Be sure a file is loaded */
1242 if (!FileIsLoaded ()) {
1246 /* Output the header */
1247 PrintLibraryHeader ();
1249 /* No arguments means show all libraries */
1250 if (CollCount (Args) == 0) {
1252 /* Fetch the list of libraries */
1253 L = cc65_get_librarylist (Info);
1255 /* Output the libraries */
1259 cc65_free_libraryinfo (Info, L);
1264 for (I = 0; I < CollCount (Args); ++I) {
1266 /* Parse the argument */
1268 unsigned IdType = LibraryId;
1269 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1270 /* Fetch list depending on type */
1273 L = cc65_library_byid (Info, Id);
1277 PrintLine ("Invalid id type");
1281 /* Ignore the invalid id */
1285 /* Output the list */
1288 cc65_free_libraryinfo (Info, L);
1296 static void CmdShowModule (Collection* Args)
1297 /* Show modules from the debug info file */
1299 const cc65_moduleinfo* M;
1301 /* Be sure a file is loaded */
1302 if (!FileIsLoaded ()) {
1306 /* Output the header */
1307 PrintModuleHeader ();
1309 /* No arguments means show all modules */
1310 if (CollCount (Args) == 0) {
1312 /* Fetch the list of modules */
1313 M = cc65_get_modulelist (Info);
1315 /* Output the modules */
1319 cc65_free_moduleinfo (Info, M);
1324 for (I = 0; I < CollCount (Args); ++I) {
1326 /* Parse the argument */
1328 unsigned IdType = ModuleId;
1329 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1330 /* Fetch list depending on type */
1333 M = cc65_module_byid (Info, Id);
1337 PrintLine ("Invalid id type");
1341 /* Ignore the invalid id */
1345 /* Output the list */
1348 cc65_free_moduleinfo (Info, M);
1357 static void CmdShowScope (Collection* Args)
1358 /* Show scopes from the debug info file */
1360 const cc65_scopeinfo* S;
1362 /* Be sure a file is loaded */
1363 if (!FileIsLoaded ()) {
1367 /* Output the header */
1368 PrintScopeHeader ();
1370 /* No arguments means show all modules */
1371 if (CollCount (Args) == 0) {
1373 /* Fetch the list of segments */
1374 S = cc65_get_scopelist (Info);
1376 /* Output the segments */
1380 cc65_free_scopeinfo (Info, S);
1385 for (I = 0; I < CollCount (Args); ++I) {
1387 /* Parse the argument */
1389 unsigned IdType = ScopeId;
1390 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1391 /* Fetch list depending on type */
1394 S = cc65_scope_bymodule (Info, Id);
1397 S = cc65_scope_byid (Info, Id);
1401 PrintLine ("Invalid id type");
1405 /* An invalid id may be a scope name */
1406 S = cc65_scope_byname (Info, CollConstAt (Args, I));
1409 /* Output the list */
1412 cc65_free_scopeinfo (Info, S);
1420 static void CmdShowSegment (Collection* Args)
1421 /* Show segments from the debug info file */
1423 const cc65_segmentinfo* S;
1425 /* Be sure a file is loaded */
1426 if (!FileIsLoaded ()) {
1430 /* Output the header */
1431 PrintSegmentHeader ();
1433 /* No arguments means show all modules */
1434 if (CollCount (Args) == 0) {
1436 /* Fetch the list of segments */
1437 S = cc65_get_segmentlist (Info);
1439 /* Output the segments */
1443 cc65_free_segmentinfo (Info, S);
1448 for (I = 0; I < CollCount (Args); ++I) {
1450 /* Parse the argument */
1452 unsigned IdType = SegmentId;
1453 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1454 /* Fetch list depending on type */
1457 S = cc65_segment_byid (Info, Id);
1461 PrintLine ("Invalid id type");
1465 /* An invalid id may be a segment name */
1466 S = cc65_segment_byname (Info, CollConstAt (Args, I));
1469 /* Output the list */
1472 cc65_free_segmentinfo (Info, S);
1480 static void CmdShowSource (Collection* Args)
1481 /* Show source files from the debug info file */
1483 const cc65_sourceinfo* S;
1485 /* Be sure a file is loaded */
1486 if (!FileIsLoaded ()) {
1490 /* Output the header */
1491 PrintSourceHeader ();
1493 /* No arguments means show all modules */
1494 if (CollCount (Args) == 0) {
1496 /* Fetch the list of source files */
1497 S = cc65_get_sourcelist (Info);
1499 /* Output the source files */
1503 cc65_free_sourceinfo (Info, S);
1508 for (I = 0; I < CollCount (Args); ++I) {
1510 /* Parse the argument */
1512 unsigned IdType = SourceId;
1513 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1514 /* Fetch list depending on type */
1517 S = cc65_source_bymodule (Info, Id);
1520 S = cc65_source_byid (Info, Id);
1524 PrintLine ("Invalid id type");
1528 /* Ignore the invalid id */
1532 /* Output the list */
1535 cc65_free_sourceinfo (Info, S);
1543 static void CmdShowSpan (Collection* Args)
1544 /* Show spans from the debug info file */
1546 const cc65_spaninfo* S;
1549 /* Be sure a file is loaded */
1550 if (!FileIsLoaded ()) {
1554 /* Output the header */
1557 for (I = 0; I < CollCount (Args); ++I) {
1559 /* Parse the argument */
1561 unsigned IdType = SpanId;
1562 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1563 /* Fetch list depending on type */
1566 S = cc65_span_byline (Info, Id);
1570 S = cc65_span_byscope (Info, Id);
1573 S = cc65_span_byid (Info, Id);
1577 PrintLine ("Invalid id type");
1581 /* Ignore the invalid id */
1585 /* Output the list */
1588 cc65_free_spaninfo (Info, S);
1595 static void CmdShowSymbol (Collection* Args)
1596 /* Show symbols from the debug info file */
1598 const cc65_symbolinfo* S;
1601 /* Be sure a file is loaded */
1602 if (!FileIsLoaded ()) {
1606 /* Output the header */
1607 PrintSymbolHeader ();
1609 for (I = 0; I < CollCount (Args); ++I) {
1611 /* Parse the argument */
1613 unsigned IdType = SymbolId;
1614 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1615 /* Fetch list depending on type */
1619 S = cc65_symbol_byscope (Info, Id);
1623 S = cc65_symbol_byid (Info, Id);
1628 PrintLine ("Invalid id type");
1632 /* Ignore the invalid id */
1636 /* Output the list */
1639 cc65_free_symbolinfo (Info, S);
1646 static void CmdShowSymDef (Collection* Args)
1647 /* Show symbol definitions from the debug info file */
1649 const cc65_lineinfo* L;
1652 /* Be sure a file is loaded */
1653 if (!FileIsLoaded ()) {
1657 /* Output the header */
1660 for (I = 0; I < CollCount (Args); ++I) {
1662 /* Parse the argument */
1664 unsigned IdType = SymbolId;
1665 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1666 /* Fetch list depending on type */
1670 L = cc65_line_bysymdef (Info, Id);
1675 PrintLine ("Invalid id type");
1679 /* Ignore the invalid id */
1683 /* Output the list */
1686 cc65_free_lineinfo (Info, L);
1693 static void CmdShowSymRef (Collection* Args)
1694 /* Show symbol references from the debug info file */
1696 const cc65_lineinfo* L;
1699 /* Be sure a file is loaded */
1700 if (!FileIsLoaded ()) {
1704 /* Output the header */
1707 for (I = 0; I < CollCount (Args); ++I) {
1709 /* Parse the argument */
1711 unsigned IdType = SymbolId;
1712 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1713 /* Fetch list depending on type */
1717 L = cc65_line_bysymref (Info, Id);
1722 PrintLine ("Invalid id type");
1726 /* Ignore the invalid id */
1730 /* Output the list */
1733 cc65_free_lineinfo (Info, L);
1740 static void CmdShowType (Collection* Args)
1741 /* Show types from the debug info file */
1743 const cc65_typedata* T;
1744 const cc65_spaninfo* S;
1747 /* Be sure a file is loaded */
1748 if (!FileIsLoaded ()) {
1752 /* Output the header */
1755 for (I = 0; I < CollCount (Args); ++I) {
1757 /* Parse the argument */
1759 unsigned IdType = TypeId;
1760 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1761 /* Fetch list depending on type */
1765 S = cc65_span_byid (Info, Id);
1766 if (S == 0 || S->count == 0) {
1770 Id = S->data[0].type_id;
1774 T = cc65_type_byid (Info, Id);
1779 PrintLine ("Invalid id type");
1783 /* Ignore the invalid id */
1787 /* Output the list */
1790 cc65_free_typedata (Info, T);
1797 static void CmdUnload (Collection* Args attribute ((unused)))
1798 /* Unload a debug info file */
1805 /*****************************************************************************/
1807 /*****************************************************************************/
1811 static int Parse (char* CmdLine, Collection* Args)
1812 /* Parse the command line and store the arguments in Args. Return true if ok,
1818 /* Clear the collection */
1819 CollDeleteAll (Args);
1821 /* Parse the command line */
1824 /* Break out on end of line */
1825 if (*CmdLine == '\0') {
1829 /* Search for start of next command */
1830 if (IsSpace (*CmdLine)) {
1835 /* Allow double quotes to terminate a command */
1836 if (*CmdLine == '\"' || *CmdLine == '\'') {
1837 char Term = *CmdLine++;
1839 while (*End != Term) {
1841 PrintLine ("Unterminated argument");
1849 while (!IsSpace (*End)) {
1851 PrintLine ("Unterminated argument");
1858 CollAppend (Args, CmdLine);
1868 int main (int argc, char* argv[])
1872 Collection Args = STATIC_COLLECTION_INITIALIZER;
1874 /* Initialize the command line */
1875 InitCmdLine (&argc, &argv, "dbgsh");
1877 /* If we have commands on the command line, execute them */
1880 for (I = 1; I < ArgCount; ++I) {
1881 CollAppend (&Args, ArgVec[I]);
1884 /* Search for the command, check number of args, then execute it */
1885 ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
1888 /* Loop until program end */
1889 while (!Terminate) {
1891 /* Output a prompt, then read the input */
1894 if (fgets (Input, sizeof (Input), stdin) == 0) {
1895 PrintLine ("(EOF)");
1899 /* Parse the command line */
1900 if (Parse (Input, &Args) == 0 || CollCount (&Args) == 0) {
1904 /* Search for the command, check number of args, then execute it */
1905 ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
1908 /* Free arguments */
1909 DoneCollection (&Args);