1 /*****************************************************************************/
2 /* */
3 /* dbgsh.c */
4 /* */
5 /* debug info test shell */
6 /* */
7 /* */
8 /* */
9 /* (C) 2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
13 /* */
14 /* */
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. */
18 /* */
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: */
22 /* */
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 */
30 /* distribution. */
31 /* */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <time.h>
41 #include <errno.h>
42
43 /* common */
44 #include "attrib.h"
45 #include "chartype.h"
46 #include "cmdline.h"
47 #include "coll.h"
48
49 /* dbginfo */
50 #include "dbginfo.h"
51
52
53
54 /*****************************************************************************/
55 /* Command handler forwards */
56 /*****************************************************************************/
57
58
59
60 static void CmdHelp (Collection* Args attribute ((unused)));
61 /* Output a help text */
62
63 static void CmdLoad (Collection* Args);
64 /* Load a debug info file */
65
66 static void CmdQuit (Collection* Args attribute ((unused)));
67 /* Terminate the application */
68
69 static void CmdShow (Collection* Args);
70 /* Show items from the debug info file */
71
72 static void CmdShowHelp (Collection* Args);
73 /* Print help for the show command */
74
75 static void CmdShowChildScopes (Collection* Args);
76 /* Show child scopes from the debug info file */
77
78 static void CmdShowCSymbol (Collection* Args);
79 /* Show c symbols from the debug info file */
80
81 static void CmdShowFunction (Collection* Args);
82 /* Show C functions from the debug info file */
83
84 static void CmdShowLibrary (Collection* Args);
85 /* Show libraries from the debug info file */
86
87 static void CmdShowLine (Collection* Args);
88 /* Show lines from the debug info file */
89
90 static void CmdShowModule (Collection* Args);
91 /* Show modules from the debug info file */
92
93 static void CmdShowScope (Collection* Args);
94 /* Show scopes from the debug info file */
95
96 static void CmdShowSegment (Collection* Args);
97 /* Show segments from the debug info file */
98
99 static void CmdShowSource (Collection* Args);
100 /* Show source files from the debug info file */
101
102 static void CmdShowSpan (Collection* Args);
103 /* Show spans from the debug info file */
104
105 static void CmdShowSymbol (Collection* Args);
106 /* Show symbols */
107
108 static void CmdShowSymDef (Collection* Args);
109 /* Show lines from the debug info file */
110
111 static void CmdShowSymRef (Collection* Args);
112 /* Show lines from the debug info file */
113
114 static void CmdShowType (Collection* Args);
115 /* Show types from the debug info file */
116
117 static void CmdUnload (Collection* Args attribute ((unused)));
118 /* Unload a debug info file */
119
120
121
122 /*****************************************************************************/
123 /* Data */
124 /*****************************************************************************/
125
126
127
128 /* Terminate flag - end program when set to true */
129 static int Terminate = 0;
130
131 /* The debug file data */
132 static cc65_dbginfo Info = 0;
133
134 /* Error and warning counters */
135 static unsigned FileErrors = 0;
136 static unsigned FileWarnings = 0;
137
138 /* Type of an id */
139 enum {
140 InvalidId,
141 CSymbolId,
142 LibraryId,
143 LineId,
144 ModuleId,
145 ScopeId,
146 SegmentId,
147 SourceId,
148 SpanId,
149 SymbolId,
150 TypeId
151 };
152
153 /* Structure that contains a command description */
154 typedef struct CmdEntry CmdEntry;
155 struct CmdEntry {
156 char Cmd[12];
157 const char* Help;
158 int ArgCount;
159 void (*Func) (Collection*);
160 };
161
162 /* Table with main commands */
163 static const CmdEntry MainCmds[] = {
164 {
165 "exit",
166 0,
167 1,
168 CmdQuit
169 }, {
170 "help",
171 "Show available commands",
172 1,
173 CmdHelp
174 }, {
175 "load",
176 "Load a debug info file",
177 2,
178 CmdLoad
179 }, {
180 "quit",
181 "Terminate the shell",
182 1,
183 CmdQuit
184 }, {
185 "show",
186 "Show items from the info file",
187 -2,
188 CmdShow
189 }, {
190 "unload",
191 "Unload a debug info file",
192 1,
193 CmdUnload
194 },
195 };
196
197 /* Table with show commands */
198 static const CmdEntry ShowCmds[] = {
199 {
200 "childscopes",
201 "Show child scopes of other scopes.",
202 -2,
203 CmdShowChildScopes
204 }, {
205 "csym",
206 0,
207 -1,
208 CmdShowCSymbol
209 }, {
210 "csymbol",
211 "Show c symbols.",
212 -1,
213 CmdShowCSymbol
214 }, {
215 "func",
216 0,
217 -2,
218 CmdShowFunction
219 }, {
220 "function",
221 "Show c functions.",
222 -2,
223 CmdShowFunction
224 }, {
225 "help",
226 "Show available subcommands.",
227 1,
228 CmdShowHelp
229 }, {
230 "line",
231 "Show line info. May be followed by one or more line ids.",
232 -2,
233 CmdShowLine
234 }, {
235 "library",
236 "Show libraries. May be followed by one or more library ids.",
237 -1,
238 CmdShowLibrary
239 }, {
240 "module",
241 "Show modules. May be followed by one or more module ids.",
242 -1,
243 CmdShowModule
244 }, {
245 "scope",
246 "Show scopes. May be followed by one or more segment ids.",
247 -1,
248 CmdShowScope
249 }, {
250 "segment",
251 "Show segments. May be followed by one or more segment ids.",
252 -1,
253 CmdShowSegment
254 }, {
255 "source",
256 "Show sources. May be followed by one or more source file ids.",
257 -1,
258 CmdShowSource
259 }, {
260 "span",
261 "Show spans. May be followed by one or more span ids.",
262 -1,
263 CmdShowSpan
264 }, {
265 "symbol",
266 "Show symbols. May be followed by one or more symbol or scope ids.",
267 -2,
268 CmdShowSymbol
269 }, {
270 "symdef",
271 "Show where a symbol was defined. May be followed by one or more symbol ids.",
272 -2,
273 CmdShowSymDef
274 }, {
275 "symref",
276 "Show where a symbol was referenced. May be followed by one or more symbol ids.",
277 -2,
278 CmdShowSymRef
279 }, {
280 "type",
281 "Show type information. May be followed by one or more type ids.",
282 -2,
283 CmdShowType
284 },
285 };
286
287
288
289 /*****************************************************************************/
290 /* Helpers */
291 /*****************************************************************************/
292
293
294
NewLine(void)295 static void NewLine (void)
296 /* Output a newline */
297 {
298 putchar ('\n');
299 }
300
301
302
303 static void Print (const char* Format, ...) attribute((format(printf,1,2)));
Print(const char * Format,...)304 static void Print (const char* Format, ...)
305 /* Print a piece of output (no linefeed added) */
306 {
307 va_list ap;
308 va_start (ap, Format);
309 vprintf (Format, ap);
310 va_end (ap);
311 }
312
313
314
315 static void PrintLine (const char* Format, ...) attribute((format(printf,1,2)));
PrintLine(const char * Format,...)316 static void PrintLine (const char* Format, ...)
317 /* Print one line of output. The linefeed is supplied by the function */
318 {
319 va_list ap;
320 va_start (ap, Format);
321 vprintf (Format, ap);
322 NewLine ();
323 va_end (ap);
324 }
325
326
327
PrintSeparator(void)328 static void PrintSeparator (void)
329 /* Print a separator line */
330 {
331 PrintLine ("---------------------------------------------------------------------------");
332 }
333
334
335
FileError(const cc65_parseerror * Info)336 static void FileError (const cc65_parseerror* Info)
337 /* Callback function - is called in case of errors */
338 {
339 /* Output a message */
340 PrintLine ("%s:%s(%lu): %s",
341 Info->type? "Error" : "Warning",
342 Info->name,
343 (unsigned long) Info->line,
344 Info->errormsg);
345
346 /* Bump the counters */
347 switch (Info->type) {
348 case CC65_WARNING: ++FileWarnings; break;
349 default: ++FileErrors; break;
350 }
351 }
352
353
354
FindCmd(const char * Cmd,const CmdEntry * Tab,unsigned Count)355 static const CmdEntry* FindCmd (const char* Cmd, const CmdEntry* Tab, unsigned Count)
356 /* Search for a command in the given table */
357 {
358 unsigned I;
359 for (I = 0; I < Count; ++I, ++Tab) {
360 if (strcmp (Cmd, Tab->Cmd) == 0) {
361 return Tab;
362 }
363 }
364 return 0;
365 }
366
367
368
ExecCmd(Collection * Args,const CmdEntry * Tab,unsigned Count)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
372 ** diagnostic.
373 */
374 {
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);
378 if (E == 0) {
379 PrintLine ("No such command: %s", Cmd);
380 return;
381 }
382
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.
388 */
389 if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) {
390 /* Argument number mismatch */
391 switch (E->ArgCount) {
392
393 case 1:
394 PrintLine ("Command doesn't accept an argument");
395 return;
396
397 case 2:
398 PrintLine ("Command requires an argument");
399 return;
400
401 default:
402 PrintLine ("Command requires %d arguments", E->ArgCount-1);
403 return;
404 }
405 } else if (E->ArgCount < 0 && (int)CollCount (Args) < -E->ArgCount) {
406 /* Argument number mismatch */
407 switch (E->ArgCount) {
408
409 case -2:
410 PrintLine ("Command requires at least one argument");
411 return;
412
413 default:
414 PrintLine ("Command requires at least %d arguments", E->ArgCount-1);
415 return;
416 }
417 } else {
418 /* Remove the command from the argument list, then execute it */
419 CollDelete (Args, 0);
420 E->Func (Args);
421 }
422 }
423
424
425
PrintHelp(const CmdEntry * Tab,unsigned Count)426 static void PrintHelp (const CmdEntry* Tab, unsigned Count)
427 /* Output help for one command table */
428 {
429 while (Count--) {
430 /* Ignore the commands without help text */
431 if (Tab->Help) {
432 PrintLine ("%-*s%s", (int) sizeof (Tab->Cmd) + 2, Tab->Cmd, Tab->Help);
433 }
434 ++Tab;
435 }
436 }
437
438
439
FindIdType(const char * TypeName)440 static unsigned FindIdType (const char* TypeName)
441 /* Find an id type by its name. Returns the type or InvalidId. */
442 {
443 static const struct {
444 char Name[8];
445 unsigned Type;
446 } TypeTab[] = {
447 { "l", LineId },
448 { "lib", LibraryId },
449 { "library", LibraryId },
450 { "line", LineId },
451 { "m", ModuleId },
452 { "mod", ModuleId },
453 { "module", ModuleId },
454 { "s", SymbolId },
455 { "sc", ScopeId },
456 { "scope", ScopeId },
457 { "seg", SegmentId },
458 { "segment", SegmentId },
459 { "source", SourceId },
460 { "src", SourceId },
461 { "sp", SpanId },
462 { "span", SpanId },
463 { "sym", SymbolId },
464 { "symbol", SymbolId },
465 { "t", TypeId },
466 { "type", TypeId },
467 };
468
469 unsigned I;
470 for (I = 0; I < sizeof(TypeTab) / sizeof(TypeTab[0]); ++I) {
471 if (strcmp (TypeName, TypeTab[I].Name) == 0) {
472 return TypeTab[I].Type;
473 }
474 }
475 return InvalidId;
476 }
477
478
479
GetId(const char * S,unsigned * Id,unsigned * IdType)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.
485 */
486 {
487 char TypeBuf[20];
488 char C;
489 if (sscanf (S, "%u%c", Id, &C) == 1) {
490 /* Just an id found, return it */
491 return 1;
492 }
493 if (sscanf (S, "%19[a-z]:%u%c", TypeBuf, Id, &C) == 2) {
494 *IdType = FindIdType (TypeBuf);
495 return (*IdType != InvalidId);
496 }
497
498 /* Not a valid id */
499 return 0;
500 }
501
502
503
504 /*****************************************************************************/
505 /* Output functions for item lists */
506 /*****************************************************************************/
507
508
509
PrintAddr(cc65_addr Addr,unsigned FieldWidth)510 static void PrintAddr (cc65_addr Addr, unsigned FieldWidth)
511 /* Output an address */
512 {
513 Print ("$%06lX", (unsigned long) Addr);
514 if (FieldWidth > 7) {
515 Print ("%*s", FieldWidth - 7, "");
516 }
517 }
518
519
520
PrintNumber(long Num,unsigned Width,unsigned FieldWidth)521 static void PrintNumber (long Num, unsigned Width, unsigned FieldWidth)
522 /* Output a number */
523 {
524 Print ("%*ld", Width, Num);
525 if (FieldWidth > Width) {
526 Print ("%*s", FieldWidth - Width, "");
527 }
528 }
529
530
531
PrintId(unsigned Id,unsigned FieldWidth)532 static void PrintId (unsigned Id, unsigned FieldWidth)
533 /* Output an id field */
534 {
535 if (Id == CC65_INV_ID) {
536 Print (" -");
537 } else {
538 Print ("%4u", Id);
539 }
540 if (FieldWidth > 4) {
541 Print ("%*s", FieldWidth - 4, "");
542 }
543 }
544
545
546
PrintSize(cc65_size Size,unsigned FieldWidth)547 static void PrintSize (cc65_size Size, unsigned FieldWidth)
548 /* Output a size */
549 {
550 Print ("$%04lX", (unsigned long) Size);
551 if (FieldWidth > 5) {
552 Print ("%*s", FieldWidth - 5, "");
553 }
554 }
555
556
557
PrintTime(time_t T,unsigned FieldWidth)558 static void PrintTime (time_t T, unsigned FieldWidth)
559 /* Output a time stamp of some sort */
560 {
561 /* Convert to string */
562 char Buf[100];
563 unsigned Len = strftime (Buf, sizeof (Buf), "%Y-%m-%d %H:%M:%S", localtime (&T));
564
565 /* Output */
566 Print ("%s", Buf);
567 if (FieldWidth > Len) {
568 Print ("%*s", FieldWidth - Len, "");
569 }
570 }
571
572
573
PrintCSymbolHeader(void)574 static void PrintCSymbolHeader (void)
575 /* Output a header for a list of C symbols */
576 {
577 /* Header */
578 PrintLine (" id name type kind sc offs symbol scope");
579 PrintSeparator ();
580 }
581
582
583
PrintCSymbols(const cc65_csyminfo * S)584 static void PrintCSymbols (const cc65_csyminfo* S)
585 /* Output a list of C symbols */
586 {
587 unsigned I;
588 const cc65_csymdata* D;
589
590 /* Segments */
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);
600 NewLine ();
601 }
602 }
603
604
605
PrintLibraryHeader(void)606 static void PrintLibraryHeader (void)
607 /* Output the header for a library list */
608 {
609 PrintLine (" id name");
610 PrintSeparator ();
611 }
612
613
614
PrintLibraries(const cc65_libraryinfo * L)615 static void PrintLibraries (const cc65_libraryinfo* L)
616 /* Output a list of libraries */
617 {
618 unsigned I;
619 const cc65_librarydata* D;
620
621 /* Libraries */
622 for (I = 0, D = L->data; I < L->count; ++I, ++D) {
623 PrintId (D->library_id, 8);
624 Print ("%-24s", D->library_name);
625 NewLine ();
626 }
627 }
628
629
630
PrintLineHeader(void)631 static void PrintLineHeader (void)
632 /* Output a header for a line list */
633 {
634 /* Header */
635 PrintLine (" id source line type count");
636 PrintSeparator ();
637 }
638
639
640
PrintLines(const cc65_lineinfo * L)641 static void PrintLines (const cc65_lineinfo* L)
642 /* Output a list of lines */
643 {
644 unsigned I;
645 const cc65_linedata* D;
646
647 /* Lines */
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);
654 NewLine ();
655 }
656 }
657
658
659
PrintModuleHeader(void)660 static void PrintModuleHeader (void)
661 /* Output a header for a module list */
662 {
663 /* Header */
664 PrintLine (" id name source library scope");
665 PrintSeparator ();
666 }
667
668
669
PrintModules(const cc65_moduleinfo * M)670 static void PrintModules (const cc65_moduleinfo* M)
671 /* Output a list of modules */
672 {
673 unsigned I;
674 const cc65_moduledata* D;
675
676 /* Modules */
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);
683 NewLine ();
684 }
685 }
686
687
688
PrintScopeHeader(void)689 static void PrintScopeHeader (void)
690 /* Output a header for a list of scopes */
691 {
692 /* Header */
693 PrintLine (" id name type size parent symbol module");
694 PrintSeparator ();
695 }
696
697
698
PrintScopes(const cc65_scopeinfo * S)699 static void PrintScopes (const cc65_scopeinfo* S)
700 /* Output a list of scopes */
701 {
702 unsigned I;
703 const cc65_scopedata* D;
704
705 /* Segments */
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);
714 NewLine ();
715 }
716 }
717
718
719
PrintSegmentHeader(void)720 static void PrintSegmentHeader (void)
721 /* Output a header for a list of segments */
722 {
723 /* Header */
724 PrintLine (" id name address size output file offs");
725 PrintSeparator ();
726 }
727
728
729
PrintSegments(const cc65_segmentinfo * S)730 static void PrintSegments (const cc65_segmentinfo* S)
731 /* Output a list of segments */
732 {
733 unsigned I;
734 const cc65_segmentdata* D;
735
736 /* Segments */
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);
744 NewLine ();
745 }
746 }
747
748
749
PrintSourceHeader(void)750 static void PrintSourceHeader (void)
751 /* Output a header for a list of source files */
752 {
753 /* Header */
754 PrintLine (" id name size modification time");
755 PrintSeparator ();
756 }
757
758
759
PrintSources(const cc65_sourceinfo * S)760 static void PrintSources (const cc65_sourceinfo* S)
761 /* Output a list of sources */
762 {
763 unsigned I;
764 const cc65_sourcedata* D;
765
766 /* Segments */
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);
772 NewLine ();
773 }
774 }
775
776
777
PrintSpanHeader(void)778 static void PrintSpanHeader (void)
779 /* Output a header for a list of spans */
780 {
781 /* Header */
782 PrintLine (" id start end seg type lines scopes");
783 PrintSeparator ();
784 }
785
786
787
PrintSpans(const cc65_spaninfo * S)788 static void PrintSpans (const cc65_spaninfo* S)
789 /* Output a list of spans */
790 {
791 unsigned I;
792 const cc65_spandata* D;
793
794 /* Segments */
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);
803 NewLine ();
804 }
805 }
806
807
808
PrintSymbolHeader(void)809 static void PrintSymbolHeader (void)
810 /* Output a header for a list of symbols */
811 {
812 /* Header */
813 PrintLine (" id name type size value export seg scope parent");
814 PrintSeparator ();
815 }
816
817
818
PrintSymbols(const cc65_symbolinfo * S)819 static void PrintSymbols (const cc65_symbolinfo* S)
820 /* Output a list of symbols */
821 {
822 unsigned I;
823 const cc65_symboldata* D;
824
825 /* Segments */
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);
836 NewLine ();
837 }
838 }
839
840
841
PrintTypeHeader(void)842 static void PrintTypeHeader (void)
843 /* Output a header for a list of types */
844 {
845 /* Header */
846 PrintLine (" id description");
847 PrintSeparator ();
848 }
849
850
851
PrintType(unsigned Id,const cc65_typedata * T)852 static void PrintType (unsigned Id, const cc65_typedata* T)
853 /* Output one type */
854 {
855 /* Output the id */
856 PrintId (Id, 6);
857
858 while (1) {
859 switch (T->what) {
860
861 case CC65_TYPE_VOID:
862 Print ("VOID");
863 goto ExitPoint;
864
865 case CC65_TYPE_BYTE:
866 Print ("BYTE");
867 goto ExitPoint;
868
869 case CC65_TYPE_WORD:
870 Print ("WORD");
871 goto ExitPoint;
872
873 case CC65_TYPE_DBYTE:
874 Print ("DBYTE");
875 goto ExitPoint;
876
877 case CC65_TYPE_DWORD:
878 Print ("DWORD");
879 goto ExitPoint;
880
881 case CC65_TYPE_FARPTR:
882 Print ("FAR ");
883 /* FALLTHROUGH */
884
885 case CC65_TYPE_PTR:
886 Print ("POINTER TO ");
887 T = T->data.ptr.ind_type;
888 break;
889
890 case CC65_TYPE_ARRAY:
891 Print ("ARRAY[%u] OF ", T->data.array.ele_count);
892 T = T->data.array.ele_type;
893 break;
894
895 default:
896 /* Anything else is currently not implemented */
897 Print ("***NOT IMPLEMENTED***");
898 goto ExitPoint;
899 }
900 }
901
902 ExitPoint:
903 NewLine ();
904 }
905
906
907
908 /*****************************************************************************/
909 /* Debug file handling */
910 /*****************************************************************************/
911
912
913
UnloadFile(void)914 static void UnloadFile (void)
915 /* Unload the debug info file */
916 {
917 if (Info) {
918 cc65_free_dbginfo (Info);
919 Info = 0;
920 }
921 }
922
923
924
FileIsLoaded(void)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.
928 */
929 {
930 /* File open? */
931 if (Info == 0) {
932 PrintLine ("No debug info file");
933 return 0;
934 }
935
936 /* Errors on load? */
937 if (FileErrors > 0) {
938 PrintLine ("File had load errors!");
939 return 0;
940 }
941
942 /* Warnings on load? */
943 if (FileWarnings > 0) {
944 PrintLine ("Beware - file had load warnings!");
945 }
946
947 /* Ok */
948 return 1;
949 }
950
951
952
953 /*****************************************************************************/
954 /* Command handlers */
955 /*****************************************************************************/
956
957
958
CmdHelp(Collection * Args attribute ((unused)))959 static void CmdHelp (Collection* Args attribute ((unused)))
960 /* Output a help text */
961 {
962 PrintHelp (MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
963 }
964
965
966
CmdLoad(Collection * Args)967 static void CmdLoad (Collection* Args)
968 /* Load a debug info file */
969 {
970 /* Unload a loaded file */
971 UnloadFile ();
972
973 /* Clear the counters */
974 FileErrors = 0;
975 FileWarnings = 0;
976
977 /* Open the debug info file */
978 Info = cc65_read_dbginfo (CollAt (Args, 0), FileError);
979
980 /* Print a status */
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);
985 } else {
986 PrintLine ("File loaded successfully");
987 }
988 }
989
990
991
CmdQuit(Collection * Args attribute ((unused)))992 static void CmdQuit (Collection* Args attribute ((unused)))
993 /* Terminate the application */
994 {
995 UnloadFile ();
996 Terminate = 1;
997 }
998
999
1000
CmdShow(Collection * Args)1001 static void CmdShow (Collection* Args)
1002 /* Show items from the debug info file */
1003 {
1004 /* Search for the subcommand, check number of args, then execute it */
1005 ExecCmd (Args, ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0]));
1006 }
1007
1008
1009
CmdShowHelp(Collection * Args attribute ((unused)))1010 static void CmdShowHelp (Collection* Args attribute ((unused)))
1011 /* Print help for the show command */
1012 {
1013 PrintHelp (ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0]));
1014 }
1015
1016
1017
CmdShowChildScopes(Collection * Args)1018 static void CmdShowChildScopes (Collection* Args)
1019 /* Show child scopes from the debug info file */
1020 {
1021 const cc65_scopeinfo* S;
1022 unsigned I;
1023
1024 /* Be sure a file is loaded */
1025 if (!FileIsLoaded ()) {
1026 return;
1027 }
1028
1029 /* Output the header */
1030 PrintScopeHeader ();
1031
1032 /* Output child scopes for all arguments */
1033 for (I = 0; I < CollCount (Args); ++I) {
1034
1035 /* Parse the argument */
1036 unsigned Id;
1037 unsigned IdType = ScopeId;
1038 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1039 /* Fetch list depending on type */
1040 switch (IdType) {
1041 case ScopeId:
1042 S = cc65_childscopes_byid (Info, Id);
1043 break;
1044 default:
1045 S = 0;
1046 PrintLine ("Invalid id type");
1047 break;
1048 }
1049 } else {
1050 /* Invalid id */
1051 S = 0;
1052 }
1053
1054 /* Output the list */
1055 if (S) {
1056 PrintScopes (S);
1057 cc65_free_scopeinfo (Info, S);
1058 }
1059 }
1060 }
1061
1062
1063
CmdShowCSymbol(Collection * Args)1064 static void CmdShowCSymbol (Collection* Args)
1065 /* Show C symbols from the debug info file */
1066 {
1067 const cc65_csyminfo* S;
1068
1069 /* Be sure a file is loaded */
1070 if (!FileIsLoaded ()) {
1071 return;
1072 }
1073
1074 /* Output the header */
1075 PrintCSymbolHeader ();
1076
1077 /* No arguments means show all libraries */
1078 if (CollCount (Args) == 0) {
1079
1080 /* Fetch the list of c symbols */
1081 S = cc65_get_csymlist (Info);
1082
1083 /* Output the c symbols */
1084 PrintCSymbols (S);
1085
1086 /* Free the list */
1087 cc65_free_csyminfo (Info, S);
1088
1089 } else {
1090
1091 /* Output c symbols for all arguments */
1092 unsigned I;
1093 for (I = 0; I < CollCount (Args); ++I) {
1094
1095 /* Parse the argument */
1096 unsigned Id;
1097 unsigned IdType = CSymbolId;
1098 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1099 /* Fetch list depending on type */
1100 switch (IdType) {
1101 case CSymbolId:
1102 S = cc65_csym_byid (Info, Id);
1103 break;
1104 case ScopeId:
1105 S = cc65_csym_byscope (Info, Id);
1106 break;
1107 default:
1108 S = 0;
1109 PrintLine ("Invalid id type");
1110 break;
1111 }
1112 } else {
1113 /* Invalid id */
1114 S = 0;
1115 }
1116
1117 /* Output the list */
1118 if (S) {
1119 PrintCSymbols (S);
1120 cc65_free_csyminfo (Info, S);
1121 }
1122 }
1123 }
1124 }
1125
1126
1127
CmdShowFunction(Collection * Args)1128 static void CmdShowFunction (Collection* Args)
1129 /* Show C functions from the debug info file */
1130 {
1131 const cc65_csyminfo* S;
1132 unsigned I;
1133
1134 /* Be sure a file is loaded */
1135 if (!FileIsLoaded ()) {
1136 return;
1137 }
1138
1139 /* Output the header */
1140 PrintCSymbolHeader ();
1141
1142 /* Output c symbols for all arguments */
1143 for (I = 0; I < CollCount (Args); ++I) {
1144
1145 /* Parse the argument */
1146 unsigned Id;
1147 unsigned IdType = ModuleId;
1148 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1149 /* Fetch list depending on type */
1150 switch (IdType) {
1151 case ModuleId:
1152 S = cc65_cfunc_bymodule (Info, Id);
1153 break;
1154 default:
1155 S = 0;
1156 PrintLine ("Invalid id type");
1157 break;
1158 }
1159 } else {
1160 /* An invalid id may be a function name */
1161 S = cc65_cfunc_byname (Info, CollConstAt (Args, I));
1162 }
1163
1164 /* Output the list */
1165 if (S) {
1166 PrintCSymbols (S);
1167 cc65_free_csyminfo (Info, S);
1168 }
1169 }
1170 }
1171
1172
1173
CmdShowLine(Collection * Args)1174 static void CmdShowLine (Collection* Args)
1175 /* Show lines from the debug info file */
1176 {
1177 const cc65_lineinfo* L;
1178 unsigned I;
1179
1180 /* Be sure a file is loaded */
1181 if (!FileIsLoaded ()) {
1182 return;
1183 }
1184
1185 /* Output the header */
1186 PrintLineHeader ();
1187
1188 for (I = 0; I < CollCount (Args); ++I) {
1189
1190 /* Parse the argument */
1191 unsigned Id;
1192 unsigned IdType = LineId;
1193 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1194 /* Fetch list depending on type */
1195 switch (IdType) {
1196
1197 case LineId:
1198 L = cc65_line_byid (Info, Id);
1199 break;
1200
1201 case SourceId:
1202 L = cc65_line_bysource (Info, Id);
1203 break;
1204
1205 case SymbolId:
1206 /* ### not very clean */
1207 L = cc65_line_bysymdef (Info, Id);
1208 if (L) {
1209 PrintLines (L);
1210 cc65_free_lineinfo (Info, L);
1211 }
1212 L = cc65_line_bysymref (Info, Id);
1213 break;
1214
1215 default:
1216 L = 0;
1217 PrintLine ("Invalid id type");
1218 break;
1219 }
1220 } else {
1221 /* Ignore the invalid id */
1222 L = 0;
1223 }
1224
1225 /* Output the list */
1226 if (L) {
1227 PrintLines (L);
1228 cc65_free_lineinfo (Info, L);
1229 }
1230
1231 }
1232 }
1233
1234
1235
CmdShowLibrary(Collection * Args)1236 static void CmdShowLibrary (Collection* Args)
1237 /* Show libraries from the debug info file */
1238 {
1239 const cc65_libraryinfo* L;
1240
1241 /* Be sure a file is loaded */
1242 if (!FileIsLoaded ()) {
1243 return;
1244 }
1245
1246 /* Output the header */
1247 PrintLibraryHeader ();
1248
1249 /* No arguments means show all libraries */
1250 if (CollCount (Args) == 0) {
1251
1252 /* Fetch the list of libraries */
1253 L = cc65_get_librarylist (Info);
1254
1255 /* Output the libraries */
1256 PrintLibraries (L);
1257
1258 /* Free the list */
1259 cc65_free_libraryinfo (Info, L);
1260
1261 } else {
1262
1263 unsigned I;
1264 for (I = 0; I < CollCount (Args); ++I) {
1265
1266 /* Parse the argument */
1267 unsigned Id;
1268 unsigned IdType = LibraryId;
1269 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1270 /* Fetch list depending on type */
1271 switch (IdType) {
1272 case LibraryId:
1273 L = cc65_library_byid (Info, Id);
1274 break;
1275 default:
1276 L = 0;
1277 PrintLine ("Invalid id type");
1278 break;
1279 }
1280 } else {
1281 /* Ignore the invalid id */
1282 L = 0;
1283 }
1284
1285 /* Output the list */
1286 if (L) {
1287 PrintLibraries (L);
1288 cc65_free_libraryinfo (Info, L);
1289 }
1290 }
1291 }
1292 }
1293
1294
1295
CmdShowModule(Collection * Args)1296 static void CmdShowModule (Collection* Args)
1297 /* Show modules from the debug info file */
1298 {
1299 const cc65_moduleinfo* M;
1300
1301 /* Be sure a file is loaded */
1302 if (!FileIsLoaded ()) {
1303 return;
1304 }
1305
1306 /* Output the header */
1307 PrintModuleHeader ();
1308
1309 /* No arguments means show all modules */
1310 if (CollCount (Args) == 0) {
1311
1312 /* Fetch the list of modules */
1313 M = cc65_get_modulelist (Info);
1314
1315 /* Output the modules */
1316 PrintModules (M);
1317
1318 /* Free the list */
1319 cc65_free_moduleinfo (Info, M);
1320
1321 } else {
1322
1323 unsigned I;
1324 for (I = 0; I < CollCount (Args); ++I) {
1325
1326 /* Parse the argument */
1327 unsigned Id;
1328 unsigned IdType = ModuleId;
1329 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1330 /* Fetch list depending on type */
1331 switch (IdType) {
1332 case ModuleId:
1333 M = cc65_module_byid (Info, Id);
1334 break;
1335 default:
1336 M = 0;
1337 PrintLine ("Invalid id type");
1338 break;
1339 }
1340 } else {
1341 /* Ignore the invalid id */
1342 M = 0;
1343 }
1344
1345 /* Output the list */
1346 if (M) {
1347 PrintModules (M);
1348 cc65_free_moduleinfo (Info, M);
1349 }
1350
1351 }
1352 }
1353 }
1354
1355
1356
CmdShowScope(Collection * Args)1357 static void CmdShowScope (Collection* Args)
1358 /* Show scopes from the debug info file */
1359 {
1360 const cc65_scopeinfo* S;
1361
1362 /* Be sure a file is loaded */
1363 if (!FileIsLoaded ()) {
1364 return;
1365 }
1366
1367 /* Output the header */
1368 PrintScopeHeader ();
1369
1370 /* No arguments means show all modules */
1371 if (CollCount (Args) == 0) {
1372
1373 /* Fetch the list of segments */
1374 S = cc65_get_scopelist (Info);
1375
1376 /* Output the segments */
1377 PrintScopes (S);
1378
1379 /* Free the list */
1380 cc65_free_scopeinfo (Info, S);
1381
1382 } else {
1383
1384 unsigned I;
1385 for (I = 0; I < CollCount (Args); ++I) {
1386
1387 /* Parse the argument */
1388 unsigned Id;
1389 unsigned IdType = ScopeId;
1390 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1391 /* Fetch list depending on type */
1392 switch (IdType) {
1393 case ModuleId:
1394 S = cc65_scope_bymodule (Info, Id);
1395 break;
1396 case ScopeId:
1397 S = cc65_scope_byid (Info, Id);
1398 break;
1399 default:
1400 S = 0;
1401 PrintLine ("Invalid id type");
1402 break;
1403 }
1404 } else {
1405 /* An invalid id may be a scope name */
1406 S = cc65_scope_byname (Info, CollConstAt (Args, I));
1407 }
1408
1409 /* Output the list */
1410 if (S) {
1411 PrintScopes (S);
1412 cc65_free_scopeinfo (Info, S);
1413 }
1414 }
1415 }
1416 }
1417
1418
1419
CmdShowSegment(Collection * Args)1420 static void CmdShowSegment (Collection* Args)
1421 /* Show segments from the debug info file */
1422 {
1423 const cc65_segmentinfo* S;
1424
1425 /* Be sure a file is loaded */
1426 if (!FileIsLoaded ()) {
1427 return;
1428 }
1429
1430 /* Output the header */
1431 PrintSegmentHeader ();
1432
1433 /* No arguments means show all modules */
1434 if (CollCount (Args) == 0) {
1435
1436 /* Fetch the list of segments */
1437 S = cc65_get_segmentlist (Info);
1438
1439 /* Output the segments */
1440 PrintSegments (S);
1441
1442 /* Free the list */
1443 cc65_free_segmentinfo (Info, S);
1444
1445 } else {
1446
1447 unsigned I;
1448 for (I = 0; I < CollCount (Args); ++I) {
1449
1450 /* Parse the argument */
1451 unsigned Id;
1452 unsigned IdType = SegmentId;
1453 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1454 /* Fetch list depending on type */
1455 switch (IdType) {
1456 case SegmentId:
1457 S = cc65_segment_byid (Info, Id);
1458 break;
1459 default:
1460 S = 0;
1461 PrintLine ("Invalid id type");
1462 break;
1463 }
1464 } else {
1465 /* An invalid id may be a segment name */
1466 S = cc65_segment_byname (Info, CollConstAt (Args, I));
1467 }
1468
1469 /* Output the list */
1470 if (S) {
1471 PrintSegments (S);
1472 cc65_free_segmentinfo (Info, S);
1473 }
1474 }
1475 }
1476 }
1477
1478
1479
CmdShowSource(Collection * Args)1480 static void CmdShowSource (Collection* Args)
1481 /* Show source files from the debug info file */
1482 {
1483 const cc65_sourceinfo* S;
1484
1485 /* Be sure a file is loaded */
1486 if (!FileIsLoaded ()) {
1487 return;
1488 }
1489
1490 /* Output the header */
1491 PrintSourceHeader ();
1492
1493 /* No arguments means show all modules */
1494 if (CollCount (Args) == 0) {
1495
1496 /* Fetch the list of source files */
1497 S = cc65_get_sourcelist (Info);
1498
1499 /* Output the source files */
1500 PrintSources (S);
1501
1502 /* Free the list */
1503 cc65_free_sourceinfo (Info, S);
1504
1505 } else {
1506
1507 unsigned I;
1508 for (I = 0; I < CollCount (Args); ++I) {
1509
1510 /* Parse the argument */
1511 unsigned Id;
1512 unsigned IdType = SourceId;
1513 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1514 /* Fetch list depending on type */
1515 switch (IdType) {
1516 case ModuleId:
1517 S = cc65_source_bymodule (Info, Id);
1518 break;
1519 case SourceId:
1520 S = cc65_source_byid (Info, Id);
1521 break;
1522 default:
1523 S = 0;
1524 PrintLine ("Invalid id type");
1525 break;
1526 }
1527 } else {
1528 /* Ignore the invalid id */
1529 S = 0;
1530 }
1531
1532 /* Output the list */
1533 if (S) {
1534 PrintSources (S);
1535 cc65_free_sourceinfo (Info, S);
1536 }
1537 }
1538 }
1539 }
1540
1541
1542
CmdShowSpan(Collection * Args)1543 static void CmdShowSpan (Collection* Args)
1544 /* Show spans from the debug info file */
1545 {
1546 const cc65_spaninfo* S;
1547 unsigned I;
1548
1549 /* Be sure a file is loaded */
1550 if (!FileIsLoaded ()) {
1551 return;
1552 }
1553
1554 /* Output the header */
1555 PrintSpanHeader ();
1556
1557 for (I = 0; I < CollCount (Args); ++I) {
1558
1559 /* Parse the argument */
1560 unsigned Id;
1561 unsigned IdType = SpanId;
1562 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1563 /* Fetch list depending on type */
1564 switch (IdType) {
1565 case LineId:
1566 S = cc65_span_byline (Info, Id);
1567 break;
1568
1569 case ScopeId:
1570 S = cc65_span_byscope (Info, Id);
1571 break;
1572 case SpanId:
1573 S = cc65_span_byid (Info, Id);
1574 break;
1575 default:
1576 S = 0;
1577 PrintLine ("Invalid id type");
1578 break;
1579 }
1580 } else {
1581 /* Ignore the invalid id */
1582 S = 0;
1583 }
1584
1585 /* Output the list */
1586 if (S) {
1587 PrintSpans (S);
1588 cc65_free_spaninfo (Info, S);
1589 }
1590 }
1591 }
1592
1593
1594
CmdShowSymbol(Collection * Args)1595 static void CmdShowSymbol (Collection* Args)
1596 /* Show symbols from the debug info file */
1597 {
1598 const cc65_symbolinfo* S;
1599 unsigned I;
1600
1601 /* Be sure a file is loaded */
1602 if (!FileIsLoaded ()) {
1603 return;
1604 }
1605
1606 /* Output the header */
1607 PrintSymbolHeader ();
1608
1609 for (I = 0; I < CollCount (Args); ++I) {
1610
1611 /* Parse the argument */
1612 unsigned Id;
1613 unsigned IdType = SymbolId;
1614 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1615 /* Fetch list depending on type */
1616 switch (IdType) {
1617
1618 case ScopeId:
1619 S = cc65_symbol_byscope (Info, Id);
1620 break;
1621
1622 case SymbolId:
1623 S = cc65_symbol_byid (Info, Id);
1624 break;
1625
1626 default:
1627 S = 0;
1628 PrintLine ("Invalid id type");
1629 break;
1630 }
1631 } else {
1632 /* Ignore the invalid id */
1633 S = 0;
1634 }
1635
1636 /* Output the list */
1637 if (S) {
1638 PrintSymbols (S);
1639 cc65_free_symbolinfo (Info, S);
1640 }
1641 }
1642 }
1643
1644
1645
CmdShowSymDef(Collection * Args)1646 static void CmdShowSymDef (Collection* Args)
1647 /* Show symbol definitions from the debug info file */
1648 {
1649 const cc65_lineinfo* L;
1650 unsigned I;
1651
1652 /* Be sure a file is loaded */
1653 if (!FileIsLoaded ()) {
1654 return;
1655 }
1656
1657 /* Output the header */
1658 PrintLineHeader ();
1659
1660 for (I = 0; I < CollCount (Args); ++I) {
1661
1662 /* Parse the argument */
1663 unsigned Id;
1664 unsigned IdType = SymbolId;
1665 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1666 /* Fetch list depending on type */
1667 switch (IdType) {
1668
1669 case SymbolId:
1670 L = cc65_line_bysymdef (Info, Id);
1671 break;
1672
1673 default:
1674 L = 0;
1675 PrintLine ("Invalid id type");
1676 break;
1677 }
1678 } else {
1679 /* Ignore the invalid id */
1680 L = 0;
1681 }
1682
1683 /* Output the list */
1684 if (L) {
1685 PrintLines (L);
1686 cc65_free_lineinfo (Info, L);
1687 }
1688 }
1689 }
1690
1691
1692
CmdShowSymRef(Collection * Args)1693 static void CmdShowSymRef (Collection* Args)
1694 /* Show symbol references from the debug info file */
1695 {
1696 const cc65_lineinfo* L;
1697 unsigned I;
1698
1699 /* Be sure a file is loaded */
1700 if (!FileIsLoaded ()) {
1701 return;
1702 }
1703
1704 /* Output the header */
1705 PrintLineHeader ();
1706
1707 for (I = 0; I < CollCount (Args); ++I) {
1708
1709 /* Parse the argument */
1710 unsigned Id;
1711 unsigned IdType = SymbolId;
1712 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1713 /* Fetch list depending on type */
1714 switch (IdType) {
1715
1716 case SymbolId:
1717 L = cc65_line_bysymref (Info, Id);
1718 break;
1719
1720 default:
1721 L = 0;
1722 PrintLine ("Invalid id type");
1723 break;
1724 }
1725 } else {
1726 /* Ignore the invalid id */
1727 L = 0;
1728 }
1729
1730 /* Output the list */
1731 if (L) {
1732 PrintLines (L);
1733 cc65_free_lineinfo (Info, L);
1734 }
1735 }
1736 }
1737
1738
1739
CmdShowType(Collection * Args)1740 static void CmdShowType (Collection* Args)
1741 /* Show types from the debug info file */
1742 {
1743 const cc65_typedata* T;
1744 const cc65_spaninfo* S;
1745 unsigned I;
1746
1747 /* Be sure a file is loaded */
1748 if (!FileIsLoaded ()) {
1749 return;
1750 }
1751
1752 /* Output the header */
1753 PrintTypeHeader ();
1754
1755 for (I = 0; I < CollCount (Args); ++I) {
1756
1757 /* Parse the argument */
1758 unsigned Id;
1759 unsigned IdType = TypeId;
1760 if (GetId (CollConstAt (Args, I), &Id, &IdType)) {
1761 /* Fetch list depending on type */
1762 switch (IdType) {
1763
1764 case SpanId:
1765 S = cc65_span_byid (Info, Id);
1766 if (S == 0 || S->count == 0) {
1767 T = 0;
1768 break;
1769 }
1770 Id = S->data[0].type_id;
1771 /* FALLTHROUGH */
1772
1773 case TypeId:
1774 T = cc65_type_byid (Info, Id);
1775 break;
1776
1777 default:
1778 T = 0;
1779 PrintLine ("Invalid id type");
1780 break;
1781 }
1782 } else {
1783 /* Ignore the invalid id */
1784 T = 0;
1785 }
1786
1787 /* Output the list */
1788 if (T) {
1789 PrintType (Id, T);
1790 cc65_free_typedata (Info, T);
1791 }
1792 }
1793 }
1794
1795
1796
CmdUnload(Collection * Args attribute ((unused)))1797 static void CmdUnload (Collection* Args attribute ((unused)))
1798 /* Unload a debug info file */
1799 {
1800 UnloadFile ();
1801 }
1802
1803
1804
1805 /*****************************************************************************/
1806 /* Code */
1807 /*****************************************************************************/
1808
1809
1810
Parse(char * CmdLine,Collection * Args)1811 static int Parse (char* CmdLine, Collection* Args)
1812 /* Parse the command line and store the arguments in Args. Return true if ok,
1813 ** false on error.
1814 */
1815 {
1816 char* End;
1817
1818 /* Clear the collection */
1819 CollDeleteAll (Args);
1820
1821 /* Parse the command line */
1822 while (1) {
1823
1824 /* Break out on end of line */
1825 if (*CmdLine == '\0') {
1826 break;
1827 }
1828
1829 /* Search for start of next command */
1830 if (IsSpace (*CmdLine)) {
1831 ++CmdLine;
1832 continue;
1833 }
1834
1835 /* Allow double quotes to terminate a command */
1836 if (*CmdLine == '\"' || *CmdLine == '\'') {
1837 char Term = *CmdLine++;
1838 End = CmdLine;
1839 while (*End != Term) {
1840 if (*End == '\0') {
1841 PrintLine ("Unterminated argument");
1842 return 0;
1843 }
1844 ++End;
1845 }
1846 *End++ = '\0';
1847 } else {
1848 End = CmdLine;
1849 while (!IsSpace (*End)) {
1850 if (*End == '\0') {
1851 PrintLine ("Unterminated argument");
1852 return 0;
1853 }
1854 ++End;
1855 }
1856 *End++ = '\0';
1857 }
1858 CollAppend (Args, CmdLine);
1859 CmdLine = End;
1860 }
1861
1862 /* Ok */
1863 return 1;
1864 }
1865
1866
1867
main(int argc,char * argv[])1868 int main (int argc, char* argv[])
1869 /* Main program */
1870 {
1871 char Input[256];
1872 Collection Args = STATIC_COLLECTION_INITIALIZER;
1873
1874 /* Initialize the command line */
1875 InitCmdLine (&argc, &argv, "dbgsh");
1876
1877 /* If we have commands on the command line, execute them */
1878 if (ArgCount > 1) {
1879 unsigned I;
1880 for (I = 1; I < ArgCount; ++I) {
1881 CollAppend (&Args, ArgVec[I]);
1882 }
1883
1884 /* Search for the command, check number of args, then execute it */
1885 ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
1886 }
1887
1888 /* Loop until program end */
1889 while (!Terminate) {
1890
1891 /* Output a prompt, then read the input */
1892 Print ("dbgsh> ");
1893 fflush (stdout);
1894 if (fgets (Input, sizeof (Input), stdin) == 0) {
1895 PrintLine ("(EOF)");
1896 break;
1897 }
1898
1899 /* Parse the command line */
1900 if (Parse (Input, &Args) == 0 || CollCount (&Args) == 0) {
1901 continue;
1902 }
1903
1904 /* Search for the command, check number of args, then execute it */
1905 ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0]));
1906 }
1907
1908 /* Free arguments */
1909 DoneCollection (&Args);
1910 return 0;
1911 }
1912
1913
1914
1915