1 /* TK interface routines.
2 Copyright 1994 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
37 #include <sys/stropts.h>
41 /* Non-zero means that we're doing the gdbtk interface. */
44 /* Non-zero means we are reloading breakpoints, etc from the
45 Gdbtk kernel, and we should suppress various messages */
46 static int gdbtk_reloading
= 0;
48 /* Handle for TCL interpreter */
49 static Tcl_Interp
*interp
= NULL
;
51 /* Handle for TK main window */
52 static Tk_Window mainWindow
= NULL
;
54 static int x_fd
; /* X network socket */
62 /* The following routines deal with stdout/stderr data, which is created by
63 {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
64 lowest level of these routines and capture all output from the rest of GDB.
65 Normally they present their data to tcl via callbacks to the following tcl
66 routines: gdbtk_tcl_fputs, gdbtk_tcl_fputs_error, and gdbtk_flush. These
67 in turn call tk routines to update the display.
69 Under some circumstances, you may want to collect the output so that it can
70 be returned as the value of a tcl procedure. This can be done by
71 surrounding the output routines with calls to start_saving_output and
72 finish_saving_output. The saved data can then be retrieved with
73 get_saved_output (but this must be done before the call to
74 finish_saving_output). */
76 /* Dynamic string header for stdout. */
78 static Tcl_DString stdout_buffer
;
80 /* Use this to collect stdout output that will be returned as the result of a
83 static int saving_output
= 0;
86 start_saving_output ()
91 #define get_saved_output() (Tcl_DStringValue (&stdout_buffer))
94 finish_saving_output ()
98 Tcl_DStringFree (&stdout_buffer
);
101 /* This routine redirects the output of fputs_unfiltered so that
102 the user can see what's going on in his debugger window. */
109 /* We use Tcl_Merge to quote braces and funny characters as necessary. */
111 argv
[0] = Tcl_DStringValue (&stdout_buffer
);
112 s
= Tcl_Merge (1, argv
);
114 Tcl_DStringFree (&stdout_buffer
);
116 Tcl_VarEval (interp
, "gdbtk_tcl_fputs ", s
, NULL
);
125 if (stream
!= gdb_stdout
|| saving_output
)
128 /* Flush output from C to tcl land. */
132 /* Force immediate screen update */
134 Tcl_VarEval (interp
, "gdbtk_tcl_flush", NULL
);
138 gdbtk_fputs (ptr
, stream
)
144 if (stream
!= gdb_stdout
)
146 Tcl_VarEval (interp
, "gdbtk_tcl_fputs_error ", "{", ptr
, "}", NULL
);
150 Tcl_DStringAppend (&stdout_buffer
, ptr
, -1);
155 if (Tcl_DStringLength (&stdout_buffer
) > 1000)
167 query
= va_arg (args
, char *);
169 vsprintf(buf
, query
, args
);
170 Tcl_VarEval (interp
, "gdbtk_tcl_query ", "{", buf
, "}", NULL
);
172 val
= atol (interp
->result
);
177 breakpoint_notify(b
, action
)
178 struct breakpoint
*b
;
182 char bpnum
[50], line
[50], pc
[50];
183 struct symtab_and_line sal
;
187 if (b
->type
!= bp_breakpoint
)
190 sal
= find_pc_line (b
->address
, 0);
192 filename
= symtab_to_filename (sal
.symtab
);
194 sprintf (bpnum
, "%d", b
->number
);
195 sprintf (line
, "%d", sal
.line
);
196 sprintf (pc
, "0x%lx", b
->address
);
198 v
= Tcl_VarEval (interp
,
199 "gdbtk_tcl_breakpoint ",
209 gdbtk_fputs (interp
->result
, gdb_stdout
);
210 gdbtk_fputs ("\n", gdb_stdout
);
215 gdbtk_create_breakpoint(b
)
216 struct breakpoint
*b
;
218 breakpoint_notify(b
, "create");
222 gdbtk_delete_breakpoint(b
)
223 struct breakpoint
*b
;
225 breakpoint_notify(b
, "delete");
229 gdbtk_enable_breakpoint(b
)
230 struct breakpoint
*b
;
232 breakpoint_notify(b
, "enable");
236 gdbtk_disable_breakpoint(b
)
237 struct breakpoint
*b
;
239 breakpoint_notify(b
, "disable");
242 /* This implements the TCL command `gdb_loc', which returns a list consisting
243 of the source and line number associated with the current pc. */
246 gdb_loc (clientData
, interp
, argc
, argv
)
247 ClientData clientData
;
254 struct symtab_and_line sal
;
260 pc
= selected_frame
? selected_frame
->pc
: stop_pc
;
261 sal
= find_pc_line (pc
, 0);
265 struct symtabs_and_lines sals
;
268 sals
= decode_line_spec (argv
[1], 1);
276 Tcl_SetResult (interp
, "Ambiguous line spec", TCL_STATIC
);
284 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
289 Tcl_AppendElement (interp
, sal
.symtab
->filename
);
291 Tcl_AppendElement (interp
, "");
293 find_pc_partial_function (pc
, &funcname
, NULL
, NULL
);
294 Tcl_AppendElement (interp
, funcname
);
296 filename
= symtab_to_filename (sal
.symtab
);
297 Tcl_AppendElement (interp
, filename
);
299 sprintf (buf
, "%d", sal
.line
);
300 Tcl_AppendElement (interp
, buf
); /* line number */
302 sprintf (buf
, "0x%lx", pc
);
303 Tcl_AppendElement (interp
, buf
); /* PC */
308 /* This implements the TCL command `gdb_sourcelines', which returns a list of
309 all of the lines containing executable code for the specified source file
310 (ie: lines where you can put breakpoints). */
313 gdb_sourcelines (clientData
, interp
, argc
, argv
)
314 ClientData clientData
;
319 struct symtab
*symtab
;
320 struct linetable_entry
*le
;
326 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
330 symtab
= lookup_symtab (argv
[1]);
334 Tcl_SetResult (interp
, "No such file", TCL_STATIC
);
338 /* If there's no linetable, or no entries, then we are done. */
340 if (!symtab
->linetable
341 || symtab
->linetable
->nitems
== 0)
343 Tcl_AppendElement (interp
, "");
347 le
= symtab
->linetable
->item
;
348 nlines
= symtab
->linetable
->nitems
;
350 for (;nlines
> 0; nlines
--, le
++)
352 /* If the pc of this line is the same as the pc of the next line, then
355 && le
->pc
== (le
+ 1)->pc
)
358 sprintf (buf
, "%d", le
->line
);
359 Tcl_AppendElement (interp
, buf
);
366 map_arg_registers (argc
, argv
, func
, argp
)
369 int (*func
) PARAMS ((int regnum
, void *argp
));
374 /* Note that the test for a valid register must include checking the
375 reg_names array because NUM_REGS may be allocated for the union of the
376 register sets within a family of related processors. In this case, the
377 trailing entries of reg_names will change depending upon the particular
378 processor being debugged. */
380 if (argc
== 0) /* No args, just do all the regs */
384 && reg_names
[regnum
] != NULL
385 && *reg_names
[regnum
] != '\000';
392 /* Else, list of register #s, just do listed regs */
393 for (; argc
> 0; argc
--, argv
++)
395 regnum
= atoi (*argv
);
399 && reg_names
[regnum
] != NULL
400 && *reg_names
[regnum
] != '\000')
404 Tcl_SetResult (interp
, "bad register number", TCL_STATIC
);
414 get_register_name (regnum
, argp
)
416 void *argp
; /* Ignored */
418 Tcl_AppendElement (interp
, reg_names
[regnum
]);
421 /* This implements the TCL command `gdb_regnames', which returns a list of
422 all of the register names. */
425 gdb_regnames (clientData
, interp
, argc
, argv
)
426 ClientData clientData
;
434 return map_arg_registers (argc
, argv
, get_register_name
, 0);
437 #ifndef REGISTER_CONVERTIBLE
438 #define REGISTER_CONVERTIBLE(x) (0 != 0)
441 #ifndef REGISTER_CONVERT_TO_VIRTUAL
442 #define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a)
445 #ifndef INVALID_FLOAT
446 #define INVALID_FLOAT(x, y) (0 != 0)
450 get_register (regnum
, fp
)
453 char raw_buffer
[MAX_REGISTER_RAW_SIZE
];
454 char virtual_buffer
[MAX_REGISTER_VIRTUAL_SIZE
];
455 int format
= (int)fp
;
457 if (read_relative_register_raw_bytes (regnum
, raw_buffer
))
459 Tcl_AppendElement (interp
, "Optimized out");
463 start_saving_output (); /* Start collecting stdout */
465 /* Convert raw data to virtual format if necessary. */
467 if (REGISTER_CONVERTIBLE (regnum
))
469 REGISTER_CONVERT_TO_VIRTUAL (regnum
, REGISTER_VIRTUAL_TYPE (regnum
),
470 raw_buffer
, virtual_buffer
);
473 memcpy (virtual_buffer
, raw_buffer
, REGISTER_VIRTUAL_SIZE (regnum
));
475 val_print (REGISTER_VIRTUAL_TYPE (regnum
), virtual_buffer
, 0,
476 gdb_stdout
, format
, 1, 0, Val_pretty_default
);
478 Tcl_AppendElement (interp
, get_saved_output ());
480 finish_saving_output (); /* Set stdout back to normal */
484 gdb_fetch_registers (clientData
, interp
, argc
, argv
)
485 ClientData clientData
;
494 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
504 return map_arg_registers (argc
, argv
, get_register
, format
);
507 /* This contains the previous values of the registers, since the last call to
508 gdb_changed_register_list. */
510 static char old_regs
[REGISTER_BYTES
];
513 register_changed_p (regnum
, argp
)
514 void *argp
; /* Ignored */
516 char raw_buffer
[MAX_REGISTER_RAW_SIZE
];
519 if (read_relative_register_raw_bytes (regnum
, raw_buffer
))
522 if (memcmp (&old_regs
[REGISTER_BYTE (regnum
)], raw_buffer
,
523 REGISTER_RAW_SIZE (regnum
)) == 0)
526 /* Found a changed register. Save new value and return it's number. */
528 memcpy (&old_regs
[REGISTER_BYTE (regnum
)], raw_buffer
,
529 REGISTER_RAW_SIZE (regnum
));
531 sprintf (buf
, "%d", regnum
);
532 Tcl_AppendElement (interp
, buf
);
536 gdb_changed_register_list (clientData
, interp
, argc
, argv
)
537 ClientData clientData
;
547 return map_arg_registers (argc
, argv
, register_changed_p
, NULL
);
550 /* This implements the TCL command `gdb_cmd', which sends it's argument into
551 the GDB command scanner. */
554 gdb_cmd (clientData
, interp
, argc
, argv
)
555 ClientData clientData
;
562 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
566 execute_command (argv
[1], 1);
568 bpstat_do_actions (&stop_bpstat
);
570 /* Drain all buffered command output */
572 gdb_flush (gdb_stdout
);
577 /* This routine acts as a top-level for all GDB code called by tcl/Tk. It
578 handles cleanups, and calls to return_to_top_level (usually via error).
579 This is necessary in order to prevent a longjmp out of the bowels of Tk,
580 possibly leaving things in a bad state. Since this routine can be called
581 recursively, it needs to save and restore the contents of the jmp_buf as
585 call_wrapper (clientData
, interp
, argc
, argv
)
586 ClientData clientData
;
592 struct cleanup
*saved_cleanup_chain
;
594 jmp_buf saved_error_return
;
596 func
= (Tcl_CmdProc
*)clientData
;
597 memcpy (saved_error_return
, error_return
, sizeof (jmp_buf));
599 saved_cleanup_chain
= save_cleanups ();
601 if (!setjmp (error_return
))
602 val
= func (clientData
, interp
, argc
, argv
);
605 val
= TCL_ERROR
; /* Flag an error for TCL */
607 finish_saving_output (); /* Restore stdout to normal */
609 gdb_flush (gdb_stderr
); /* Flush error output */
611 /* In case of an error, we may need to force the GUI into idle mode because
612 gdbtk_call_command may have bombed out while in the command routine. */
614 Tcl_VarEval (interp
, "gdbtk_tcl_idle", NULL
);
617 do_cleanups (ALL_CLEANUPS
);
619 restore_cleanups (saved_cleanup_chain
);
621 memcpy (error_return
, saved_error_return
, sizeof (jmp_buf));
627 gdb_listfiles (clientData
, interp
, argc
, argv
)
628 ClientData clientData
;
634 struct objfile
*objfile
;
635 struct partial_symtab
*psymtab
;
636 struct symtab
*symtab
;
638 ALL_PSYMTABS (objfile
, psymtab
)
639 Tcl_AppendElement (interp
, psymtab
->filename
);
641 ALL_SYMTABS (objfile
, symtab
)
642 Tcl_AppendElement (interp
, symtab
->filename
);
648 gdb_stop (clientData
, interp
, argc
, argv
)
649 ClientData clientData
;
661 tk_command (cmd
, from_tty
)
667 struct cleanup
*old_chain
;
669 retval
= Tcl_Eval (interp
, cmd
);
671 result
= strdup (interp
->result
);
673 old_chain
= make_cleanup (free
, result
);
675 if (retval
!= TCL_OK
)
678 printf_unfiltered ("%s\n", result
);
680 do_cleanups (old_chain
);
684 cleanup_init (ignored
)
687 if (mainWindow
!= NULL
)
688 Tk_DestroyWindow (mainWindow
);
692 Tcl_DeleteInterp (interp
);
696 /* Come here during long calculations to check for GUI events. Usually invoked
697 via the QUIT macro. */
702 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
705 /* Come here when there is activity on the X file descriptor. */
711 /* Process pending events */
713 while (Tk_DoOneEvent (TK_DONT_WAIT
|TK_ALL_EVENTS
) != 0);
717 gdbtk_wait (pid
, ourstatus
)
719 struct target_waitstatus
*ourstatus
;
722 signal (SIGIO
, x_event
);
725 sigset (SIGIO
, x_event
);
727 /* This is possibly needed for SVR4... */
729 struct sigaction action
;
730 static sigset_t nullsigmask
= {0};
732 action
.sa_handler
= iosig
;
733 action
.sa_mask
= nullsigmask
;
734 action
.sa_flags
= SA_RESTART
;
735 sigaction(SIGIO
, &action
, NULL
);
740 pid
= target_wait (pid
, ourstatus
);
742 signal (SIGIO
, SIG_IGN
);
747 /* This is called from execute_command, and provides a wrapper around
748 various command routines in a place where both protocol messages and
749 user input both flow through. Mostly this is used for indicating whether
750 the target process is running or not.
754 gdbtk_call_command (cmdblk
, arg
, from_tty
)
755 struct cmd_list_element
*cmdblk
;
759 if (cmdblk
->class == class_run
)
761 Tcl_VarEval (interp
, "gdbtk_tcl_busy", NULL
);
762 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
763 Tcl_VarEval (interp
, "gdbtk_tcl_idle", NULL
);
766 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
772 struct cleanup
*old_chain
;
773 char *gdbtk_filename
;
776 old_chain
= make_cleanup (cleanup_init
, 0);
778 /* First init tcl and tk. */
780 interp
= Tcl_CreateInterp ();
783 error ("Tcl_CreateInterp failed");
785 Tcl_DStringInit (&stdout_buffer
); /* Setup stdout buffer */
787 mainWindow
= Tk_CreateMainWindow (interp
, NULL
, "gdb", "Gdb");
790 return; /* DISPLAY probably not set */
792 if (Tcl_Init(interp
) != TCL_OK
)
793 error ("Tcl_Init failed: %s", interp
->result
);
795 if (Tk_Init(interp
) != TCL_OK
)
796 error ("Tk_Init failed: %s", interp
->result
);
798 Tcl_CreateCommand (interp
, "gdb_cmd", call_wrapper
, gdb_cmd
, NULL
);
799 Tcl_CreateCommand (interp
, "gdb_loc", call_wrapper
, gdb_loc
, NULL
);
800 Tcl_CreateCommand (interp
, "gdb_sourcelines", call_wrapper
, gdb_sourcelines
,
802 Tcl_CreateCommand (interp
, "gdb_listfiles", call_wrapper
, gdb_listfiles
,
804 Tcl_CreateCommand (interp
, "gdb_stop", call_wrapper
, gdb_stop
, NULL
);
805 Tcl_CreateCommand (interp
, "gdb_regnames", call_wrapper
, gdb_regnames
, NULL
);
806 Tcl_CreateCommand (interp
, "gdb_fetch_registers", call_wrapper
,
807 gdb_fetch_registers
, NULL
);
808 Tcl_CreateCommand (interp
, "gdb_changed_register_list", call_wrapper
,
809 gdb_changed_register_list
, NULL
);
811 gdbtk_filename
= getenv ("GDBTK_FILENAME");
813 if (access ("gdbtk.tcl", R_OK
) == 0)
814 gdbtk_filename
= "gdbtk.tcl";
816 gdbtk_filename
= GDBTK_FILENAME
;
818 if (Tcl_EvalFile (interp
, gdbtk_filename
) != TCL_OK
)
819 error ("Failure reading %s: %s", gdbtk_filename
, interp
->result
);
821 /* Get the file descriptor for the X server */
823 x_fd
= ConnectionNumber (Tk_Display (mainWindow
));
825 /* Setup for I/O interrupts */
827 signal (SIGIO
, SIG_IGN
);
830 i
= fcntl (x_fd
, F_GETFL
, 0);
831 fcntl (x_fd
, F_SETFL
, i
|FASYNC
);
832 fcntl (x_fd
, F_SETOWN
, getpid());
834 if (ioctl (x_fd
, I_SETSIG
, S_INPUT
|S_RDNORM
) < 0)
835 perror ("gdbtk_init: ioctl I_SETSIG failed");
836 #endif /* ifndef FASYNC */
838 command_loop_hook
= Tk_MainLoop
;
839 fputs_unfiltered_hook
= gdbtk_fputs
;
840 print_frame_info_listing_hook
= null_routine
;
841 query_hook
= gdbtk_query
;
842 flush_hook
= gdbtk_flush
;
843 create_breakpoint_hook
= gdbtk_create_breakpoint
;
844 delete_breakpoint_hook
= gdbtk_delete_breakpoint
;
845 enable_breakpoint_hook
= gdbtk_enable_breakpoint
;
846 disable_breakpoint_hook
= gdbtk_disable_breakpoint
;
847 interactive_hook
= gdbtk_interactive
;
848 target_wait_hook
= gdbtk_wait
;
849 call_command_hook
= gdbtk_call_command
;
851 discard_cleanups (old_chain
);
853 add_com ("tk", class_obscure
, tk_command
,
854 "Send a command directly into tk.");
857 /* Come here during initialze_all_files () */
864 /* Tell the rest of the world that Gdbtk is now set up. */
866 init_ui_hook
= gdbtk_init
;