1 /* $Id: do_comm.c,v 1.6 1994/06/24 10:59:41 ceriel Exp $ */
3 /* Implementation of the do_ routines */
22 extern t_lineno listline, currline;
23 extern int interrupted;
24 extern int stack_offset;
28 extern void set_bytes();
36 /* ------------------------------------------------------------- */
38 /* implementation of the help command */
44 if (p && p->t_idf) switch(p->t_idf->id_reserved) {
46 fputs("help [ <commandname> ]\n", db_out);
47 fputs("? [ <commandname> ]\n", db_out);
48 fputs(" Print a command summary, or some more help on <commandname>.\n", db_out);
51 fputs("list [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
52 fputs("l [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
53 fputs(" List lines from the current source file, starting with either\n", db_out);
54 fputs(" line <start> or some lines before the first statement of <func> or\n", db_out);
55 fputs(" the current line. Either list <cnt> lines or <wsize> lines,\n", db_out);
56 fputs(" except when a range is given.\n", db_out);
57 fputs(" <wsize> is the last <cnt> given, or 10.\n", db_out);
60 fputs("file [ <name> | ? ]\n", db_out);
61 fputs(" Print the name of the current source file, or change the\n", db_out);
62 fputs(" current source file to <name>, or print the files that\n", db_out);
63 fputs(" the debugger knows about.\n", db_out);
66 fputs("source <filename>\n", db_out);
67 fputs(" Read commands from the file <filename>\n", db_out);
70 fputs("frame [ [ + | - ] <num> ]\n", db_out);
71 fputs(" Sets the 'current' frame to frame <num>. The currently active\n", db_out);
72 fputs(" procedure has frame 0. If <num> is not given, print the 'current' frame.\n", db_out);
73 fputs(" If <num> is given with a + or -, go up or down <num> frames relative\n", db_out);
74 fputs(" to the current one.\n", db_out);
77 fputs("log [ <name> | off ]\n", db_out);
78 fputs(" Creates a logfile <name> of the commands given.\n", db_out);
79 fputs(" When no argument is given, the current logfile is printed.\n", db_out);
80 fputs(" If the argument is 'off', logging is turned off.\n", db_out);
83 fputs("run [ <args> ] [ < <infile> ] [ > <outfile> ]\n", db_out);
84 fputs(" Start executing debuggee with command line arguments <args> and\n", db_out);
85 fputs(" possible redirection of standard input and/or standard output.\n", db_out);
88 fputs("rerun [ ? ]\n", db_out);
89 fputs(" If the ? is given, prints the last run command;\n", db_out);
90 fputs(" otherwise repeats the last run command.\n", db_out);
93 fputs("stop [ <pos> ] [ if <cond> ]\n", db_out);
94 fputs(" Stop execution when position <pos> is reached, and then when\n", db_out);
95 fputs(" <cond> becomes true. If no <pos> is given, stop when <cond>\n", db_out);
96 fputs(" becomes true. If no <cond> is given, stop when <pos> is reached.\n", db_out);
97 fputs(" Either a position or a condition (or both) must be given.\n", db_out);
100 fputs("when [ <pos> ] [ if <cond> ] { <command> [ ; <command> ] ... } \n", db_out);
101 fputs(" Execute the <command>s when position <pos> is reached, and then when\n", db_out);
102 fputs(" <cond> becomes true. If no <pos> is given, do this when <cond>\n", db_out);
103 fputs(" becomes true. If no <cond> is given, do this when <pos> is reached.\n", db_out);
104 fputs(" Either a position or a condition (or both) must be given.\n", db_out);
107 fputs("cont [ <cnt> ] [ at <line> ]\n", db_out);
108 fputs("c [ <cnt> ] [ at <line> ]\n", db_out);
109 fputs(" Continue execution, skipping <cnt> or 1 breakpoints;a\n", db_out);
110 fputs(" if <line> is given, continue at <line>.\n", db_out);
114 fputs("step [ <cnt> ]\n", db_out);
115 fputs("s [ <cnt> ]\n", db_out);
116 fputs("next [ <cnt> ]\n", db_out);
117 fputs("n [ <cnt> ]\n", db_out);
118 fputs(" Execute the next <cnt> or 1 source line(s).\n", db_out);
119 fputs(" Step (s) steps into function-calls.\n", db_out);
120 fputs(" Next (n) steps past function-calls.\n", db_out);
123 fputs("where [ <cnt> ]\n", db_out);
124 fputs("w [ <cnt> ]\n", db_out);
125 fputs(" List all, or the top <cnt> or the bottom -<cnt> active functions.\n", db_out);
128 fputs("status\n", db_out);
129 fputs(" display active traces, stops, whens, displays, and dumps.\n", db_out);
132 fputs("delete [ <num> [ , <num> ] ... ]\n", db_out);
133 fputs("d [ <num> [ , <num> ] ...] \n", db_out);
134 fputs(" Remove the command(s) corresponding to <num> (as displayed by 'status').\n", db_out);
135 fputs(" If no <num> is given, remove the current stopping point.\n", db_out);
138 fputs("set <desig> to <exp>\n", db_out);
139 fputs(" Assign the value of <exp> to <desig>.\n", db_out);
142 fputs("print [ <exp> [ , <exp> ] ...]\n", db_out);
143 fputs("p [ <exp> [ , <exp> ] ...]\n", db_out);
144 fputs(" Print the value of each <exp>, or repeat the last print command\n", db_out);
147 fputs("display <exp> [ , <exp> ] ...\n", db_out);
148 fputs(" Print the value of each <exp> whenever the debuggee stops.\n", db_out);
151 fputs("dump\n", db_out);
152 fputs(" Saves the state of the debuggee; it can be restored with the restore command.\n", db_out);
155 fputs("restore [ <num> ]\n", db_out);
156 fputs("r [ <num> ]\n", db_out);
157 fputs(" Restore the state of the dump associated with <num>,\n", db_out);
158 fputs(" or restore the state of the last dump.\n", db_out);
161 fputs("trace [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
162 fputs("t [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
163 fputs(" Without args, display each source line before execution.\n", db_out);
164 fputs(" In addition, display <exp> in the on-clause.\n", db_out);
165 fputs(" If <pos> is given and indicates a function, only display\n", db_out);
166 fputs(" tracing information while executing this function.\n", db_out);
167 fputs(" If it indicates a line number, only display tracing information\n", db_out);
168 fputs(" whenever the source line is reached.\n", db_out);
169 fputs(" If <cond> is given, only display tracing info when it evaluates to non-zero.\n", db_out);
172 fputs("find <name>\n", db_out);
173 fputs(" Prints the fully qualified name of all symbols matching <name>.\n", db_out);
176 fputs("which <name>\n", db_out);
177 fputs(" Prints the fully qualified name of <name>.\n", db_out);
180 fputs("disable [ <num> [ , <num> ] ... ]\n", db_out);
181 fputs(" Disable the command(s) corresponding to <num> (as displayed by 'status').\n", db_out);
182 fputs(" If no <num> is given, disable the current stopping point.\n", db_out);
185 fputs("enable [ <num> [ , <num> ] ... ]\n", db_out);
186 fputs(" Enable the command(s) corresponding to <num> (as displayed by 'status'.)\n", db_out);
187 fputs(" If no <num> is given, enable the current stopping point (not effective).\n", db_out);
190 else if (p && p->t_str) {
191 if (! strcmp(p->t_str, "!")) {
192 fputs("! <shell command>\n", db_out);
193 fputs(" Execute the given shell command.\n", db_out);
197 fputs("cont [ <cnt> ] [ at <line> ]\n", db_out);
198 fputs("delete [ <num> [ , <num> ] ... ]\n", db_out);
199 fputs("disable [ <num> [ , <num> ] ... ]\n", db_out);
200 fputs("display <exp> [ , <exp> ] ...\n", db_out);
201 fputs("dump\n", db_out);
202 fputs("enable [ <num> [ , <num> ] ... ]\n", db_out);
203 fputs("file [ <name> | ? ]\n", db_out);
204 fputs("find <name>\n", db_out);
205 fputs("frame [ [ + | - ] <num> ]\n", db_out);
206 fputs("help [ <commandname> ]\n", db_out);
207 fputs("list [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
208 fputs("log [ <name> | off ]\n", db_out);
209 fputs("next [ <cnt> ]\n", db_out);
210 fputs("print [ <exp> [ , <exp> ] ... ]\n", db_out);
211 fputs("rerun [ ? ]\n", db_out);
212 fputs("restore [ <num> ]\n", db_out);
213 fputs("run [ <args> ] [ < <infile> ] [ > <outfile> ]\n", db_out);
214 fputs("set <desig> to <exp>\n", db_out);
215 fputs("source <filename>\n", db_out);
216 fputs("status\n", db_out);
217 fputs("step [ <cnt> ]\n", db_out);
218 fputs("stop [ <pos> ] [ if <cond> ]\n", db_out);
219 fputs("trace [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
220 fputs("when [ <pos> ] [ if <cond> ] { <command> [ ; <command> ] ... } \n", db_out);
221 fputs("where [ <cnt> ]\n", db_out);
222 fputs("which <name>\n", db_out);
223 fputs("! <shell command>\n", db_out);
226 /* ------------------------------------------------------------- */
228 /* implementation of dump/restore commands */
230 extern p_tree get_from_item_list();
231 extern t_addr get_dump();
234 char *globals, *stack;
238 static struct dump *last_dump;
243 struct dump *d = (struct dump *) malloc(sizeof(struct dump));
246 error("could not allocate enough memory");
249 p->t_address = get_dump(&d->globals, &d->stack);
250 if (! p->t_address) {
254 p->t_args[0] = (struct tree *) d;
266 p = get_from_item_list((int) p->t_args[0]->t_ival);
267 if (!p || p->t_oper != OP_DUMP) {
268 error("no such dump");
271 d = (struct dump *) p->t_args[0];
280 if (! put_dump(d->globals, d->stack)) {
281 error("restoring failed");
289 struct dump *d = (struct dump *) p->t_args[0];
293 if (d == last_dump) last_dump = d->next;
295 register struct dump *d1 = last_dump;
297 while (d1->next != d) d1 = d1->next;
303 /* ------------------------------------------------------------- */
305 /* implementation of the find command */
310 /* Print all identifications of p->t_args[0]. */
317 s = p->t_idf->id_def;
326 assert(arg->t_oper == OP_NAME);
327 s = arg->t_idf->id_def;
329 if (consistent(p, s->sy_scope)) {
341 /* ------------------------------------------------------------- */
343 /* implementation of the which command */
348 p_symbol sym = identify(p->t_args[0], 0xffff);
350 if ( sym) pr_sym(sym);
353 /* ------------------------------------------------------------- */
355 /* implementation of the list command */
357 extern t_addr get_addr_from_node();
363 static int wsize = 10;
366 l2 = p->t_args[1]->t_ival;
374 if (! p->t_args[0]) {
377 listline = currline - (wsize/2);
382 if (p->t_args[0]->t_oper == OP_AT) {
383 l1 = p->t_args[0]->t_lino;
384 if (p->t_args[0]->t_filename) {
385 newfile(str2idf(p->t_args[0]->t_filename, 0));
389 t_addr a = get_addr_from_node(p->t_args[0]);
391 p_symbol oldlistfile = listfile;
396 pos = get_position_from_addr(a);
397 newfile(str2idf(pos->filename, 1));
398 if (listfile != oldlistfile) {
399 warning("switching to file %s", listfile->sy_idf->id_text);
401 l1 = pos->lineno - (l2 > 0 ? l2 : wsize)/2;
411 lines(listfile->sy_file, l1, l2);
414 else error("no current file");
417 /* ------------------------------------------------------------- */
419 /* implementation of the file command */
427 if (! strcmp(p->t_args[0]->t_str, "?")) {
428 register p_symbol sym = PervasiveScope->sc_symbs;
431 if (sym->sy_class == FILESYM) {
432 fprintf(db_out, "%s\n", sym->sy_idf->id_text);
434 sym = sym->sy_prev_sc;
438 if ((f = fopen(p->t_args[0]->t_str, "r")) == NULL) {
439 error("could not open %s", p->t_args[0]->t_str);
443 newfile(p->t_args[0]->t_idf);
445 else if (listfile) fprintf(db_out, "%s\n", listfile->sy_idf->id_text);
446 else error("no current file");
449 /* ------------------------------------------------------------- */
451 /* implementation of stop/when command */
457 t_addr a = get_addr_from_node(p->t_args[0]);
459 if (a == ILL_ADDR) return 0;
463 if (! set_or_clear_breakpoint(a, kind)) {
473 if (! setstop(p, 1)) {
479 /* ------------------------------------------------------------- */
481 /* implementation of the trace command */
489 a = get_addr_from_node(p->t_args[0]);
490 if (a == NO_ADDR) return 1;
491 if (a == ILL_ADDR) return 0;
492 if (p->t_args[0]->t_oper == OP_AT) {
497 p_scope sc = get_next_scope_from_addr(a+1);
499 if (sc) e = sc->sc_start - 1;
502 return set_or_clear_trace(a, e, kind);
508 p->t_address = NO_ADDR;
509 if (! settrace(p, 1)) {
515 /* ------------------------------------------------------------- */
517 /* implementation of the enable/disable commands */
530 able(p->t_args[0], kind);
531 able(p->t_args[1], kind);
534 able_item((int)p->t_ival, kind);
544 able(p->t_args[0], 0);
550 able(p->t_args[0], 1);
553 /* ------------------------------------------------------------- */
555 /* implementation of the cont command */
563 count = p->t_args[0]->t_ival;
565 t_addr a = get_addr_from_position(&(p->t_args[1]->t_pos));
566 p_scope sc = get_scope_from_addr(a);
568 if (a == ILL_ADDR || base_scope(sc) != base_scope(CurrentScope)) {
569 error("cannot continue at line %d",
570 p->t_args[1]->t_lino);
580 if (! send_cont(count==0)) {
585 fprintf(db_out, "Only %ld breakpoints skipped\n",
586 p->t_args[0]->t_ival - count);
590 /* ------------------------------------------------------------- */
592 /* implementation of the step command */
598 if (! singlestep(0, p ? p->t_ival : 1L)) {
602 /* ------------------------------------------------------------- */
604 /* implementation of the next command */
610 if (! singlestep(1, p? p->t_ival : 1L)) {
614 extern t_addr *get_EM_regs();
616 /* ------------------------------------------------------------- */
618 /* implementation of the regs command (temporarily) */
627 if (p) n = p->t_ival;
628 if (! (buf = get_EM_regs(n))) {
631 fprintf(db_out, "EM registers %d levels back:\n", n);
632 fprintf(db_out, "\tLocalBase =\t0x%lx\n\tArgumentBase =\t0x%lx\n",
633 (long) buf[0], (long) buf[1]);
634 fprintf(db_out, "\tProgramCounter=\t0x%lx\n\tHeapPointer = \t0x%lx\n",
637 fprintf(db_out, "\tStackPointer =\t0x%lx\n", (long) buf[4]);
640 /* ------------------------------------------------------------- */
642 /* implementation of the where command */
644 static t_addr where_PC;
654 if (! (buf = get_EM_regs(num))) return 0;
658 sc = base_scope(get_scope_from_addr(where_PC));
659 if (! sc || sc->sc_start > where_PC) return 0;
660 fprintf(db_out, "%s(", sc->sc_definedby->sy_idf->id_text);
661 print_params(sc->sc_definedby->sy_type, AB, has_static_link(sc));
663 (void) print_position(where_PC, 0);
674 unsigned int maxcnt = 0xffff;
680 if (p && p->t_ival < 0) {
682 buf = get_EM_regs(i++);
683 if (! buf || ! buf[1]) break;
685 sc = base_scope(get_scope_from_addr(PC));
686 if (! sc || sc->sc_start > PC) break;
687 if (interrupted) return;
690 maxcnt = - p->t_ival;
694 else if (p) maxcnt = p->t_ival;
695 for (cnt = maxcnt; cnt != 0; cnt--) {
696 if (interrupted) return;
697 if (! where_entry(i++)) return;
701 /* ------------------------------------------------------------- */
703 /* implementation of the delete command */
710 if (! p->t_args[0]) {
711 remove_from_item_list(0);
713 else do_delete(p->t_args[0]);
716 do_delete(p->t_args[0]);
717 do_delete(p->t_args[1]);
720 remove_from_item_list((int) p->t_ival);
727 /* ------------------------------------------------------------- */
729 /* implementation of the print command */
741 if (p->t_args[0] == 0) {
744 error("no previous print command");
748 else if (p != print_command) {
749 /* freenode(print_command); No, could be in when-list */
754 do_print(p->t_args[0]);
757 do_print(p->t_args[0]);
758 do_print(p->t_args[1]);
761 if (interrupted || ! eval_expr(p, &buf, &size, &tp)) return;
762 print_node(db_out, p, 0);
763 fputs(" = ", db_out);
764 if (p->t_oper == OP_FORMAT) {
765 format = p->t_args[1]->t_str;
767 print_val(tp, size, buf, 0, 0, format);
774 /* ------------------------------------------------------------- */
776 /* implementation of the set command */
786 if (interrupted || ! eval_desig(p->t_args[0], &a, &size, &tp) ||
787 ! eval_expr(p->t_args[1], &buf, &size2, &tp2) ||
788 ! convert(&buf, &size2, &tp2, tp, size)) {
797 set_bytes(size, buf, a);
801 /* ------------------------------------------------------------- */
803 /* implementation of the source command */
810 FILE *old_db_in = db_in;
813 if ((db_in = fopen(p->t_str, "r")) == NULL) {
815 error("could not open %s", p->t_str);
823 /* ------------------------------------------------------------- */
828 print_node(db_out, p->t_args[0], 1);
831 /* ------------------------------------------------------------- */
833 /* stack frame commands: frame, down, up */
835 extern int stack_offset;
841 if (stack_offset+diff < 0) diff = - stack_offset;
842 if (! where_entry(stack_offset+diff)) {
843 error("no frame %d", stack_offset+diff);
846 stack_offset += diff;
847 list_position(get_position_from_addr(where_PC));
848 CurrentScope = get_scope_from_addr(where_PC);
855 frame_pos((int) p->t_args[0]->t_ival - stack_offset);
864 frame_pos((int) p->t_args[0]->t_ival);
873 frame_pos(-(int) p->t_args[0]->t_ival);
878 /* ------------------------------------------------------------- */
882 static char *logfile;
890 if (logfd && ! strcmp(p->t_str, "off")) {
891 fprintf(db_out, "stopped logging on %s\n", logfile);
897 error("already logging on %s", logfile);
901 if ((logfd = fopen(logfile, "w")) == NULL) {
902 error("could not open %s", logfile);
905 fprintf(db_out, "started logging on %s\n", logfile);
908 fprintf(db_out, "the current logfile is %s\n", logfile);
911 error("no current logfile");
915 extern int item_count;
916 extern int in_wheninvoked;
923 if (logfd && ! in_wheninvoked) {
932 /* Change absolute item numbers into relative ones
936 while (p1 && p1->t_oper == OP_LINK) {
937 register p_tree p2 = p1->t_args[0];
938 if (p2->t_ival > 0 && p2->t_ival <= item_count) {
939 p2->t_ival = p2->t_ival - item_count - 1;
943 if (p1 && p1->t_ival > 0 && p1->t_ival <= item_count) {
944 p1->t_ival = p1->t_ival - item_count - 1;
948 print_node(logfd, p, 1);