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. */
35 /* Non-zero means that we're doing the gdbtk interface. */
38 /* Non-zero means we are reloading breakpoints, etc from the
39 Gdbtk kernel, and we should suppress various messages */
40 static int gdbtk_reloading
= 0;
42 /* Handle for TCL interpreter */
43 static Tcl_Interp
*interp
= NULL
;
45 /* Handle for TK main window */
46 static Tk_Window mainWindow
= NULL
;
48 static int x_fd
; /* X network socket */
57 /* This routine redirects the output of fputs_unfiltered so that
58 the user can see what's going on in his debugger window. */
60 static char holdbuf
[200];
61 static char *holdbufp
= holdbuf
;
62 static int holdfree
= sizeof (holdbuf
);
67 if (holdbufp
== holdbuf
)
70 Tcl_VarEval (interp
, "gdbtk_tcl_fputs ", "{", holdbuf
, "}", NULL
);
72 holdfree
= sizeof (holdbuf
);
81 Tcl_VarEval (interp
, "gdbtk_tcl_flush", NULL
);
90 len
= strlen (ptr
) + 1;
96 if (len
> sizeof (holdbuf
))
98 Tcl_VarEval (interp
, "gdbtk_tcl_fputs ", "{", ptr
, "}", NULL
);
103 strncpy (holdbufp
, ptr
, len
);
116 query
= va_arg (args
, char *);
118 vsprintf(buf
, query
, args
);
119 Tcl_VarEval (interp
, "gdbtk_tcl_query ", "{", buf
, "}", NULL
);
121 val
= atol (interp
->result
);
127 full_filename(symtab
)
128 struct symtab
*symtab
;
136 if (symtab
->fullname
)
137 return savestring(symtab
->fullname
, strlen(symtab
->fullname
));
139 if (symtab
->filename
[0] == '/')
140 return savestring(symtab
->filename
, strlen(symtab
->filename
));
143 pathlen
= strlen(symtab
->dirname
);
146 if (symtab
->filename
)
147 pathlen
+= strlen(symtab
->filename
);
149 filename
= xmalloc(pathlen
+1);
152 strcpy(filename
, symtab
->dirname
);
155 if (symtab
->filename
)
156 strcat(filename
, symtab
->filename
);
163 breakpoint_notify(b
, action
)
164 struct breakpoint
*b
;
168 char bpnum
[50], line
[50], pc
[50];
169 struct symtab_and_line sal
;
173 if (b
->type
!= bp_breakpoint
)
176 sal
= find_pc_line (b
->address
, 0);
178 filename
= symtab_to_filename (sal
.symtab
);
180 sprintf (bpnum
, "%d", b
->number
);
181 sprintf (line
, "%d", sal
.line
);
182 sprintf (pc
, "0x%x", b
->address
);
184 v
= Tcl_VarEval (interp
,
185 "gdbtk_tcl_breakpoint ",
195 gdbtk_fputs (interp
->result
);
201 gdbtk_create_breakpoint(b
)
202 struct breakpoint
*b
;
204 breakpoint_notify(b
, "create");
208 gdbtk_delete_breakpoint(b
)
209 struct breakpoint
*b
;
211 breakpoint_notify(b
, "delete");
215 gdbtk_enable_breakpoint(b
)
216 struct breakpoint
*b
;
218 breakpoint_notify(b
, "enable");
222 gdbtk_disable_breakpoint(b
)
223 struct breakpoint
*b
;
225 breakpoint_notify(b
, "disable");
228 /* This implements the TCL command `gdb_loc', which returns a list consisting
229 of the source and line number associated with the current pc. */
232 gdb_loc (clientData
, interp
, argc
, argv
)
233 ClientData clientData
;
240 struct symtab_and_line sal
;
246 struct frame_info
*frame
;
249 frame
= get_frame_info (selected_frame
);
251 pc
= frame
? frame
->pc
: stop_pc
;
253 sal
= find_pc_line (pc
, 0);
257 struct symtabs_and_lines sals
;
260 sals
= decode_line_spec (argv
[1], 1);
268 Tcl_SetResult (interp
, "Ambiguous line spec", TCL_STATIC
);
276 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
281 Tcl_AppendElement (interp
, sal
.symtab
->filename
);
283 Tcl_AppendElement (interp
, "");
285 find_pc_partial_function (pc
, &funcname
, NULL
, NULL
);
286 Tcl_AppendElement (interp
, funcname
);
288 filename
= symtab_to_filename (sal
.symtab
);
289 Tcl_AppendElement (interp
, filename
);
291 sprintf (buf
, "%d", sal
.line
);
292 Tcl_AppendElement (interp
, buf
); /* line number */
294 sprintf (buf
, "0x%x", pc
);
295 Tcl_AppendElement (interp
, buf
); /* PC */
304 execute_command (cmd
, 1);
306 return 1; /* Indicate success */
309 /* This implements the TCL command `gdb_cmd', which sends it's argument into
310 the GDB command scanner. */
313 gdb_cmd (clientData
, interp
, argc
, argv
)
314 ClientData clientData
;
320 struct cleanup
*old_chain
;
324 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
328 old_chain
= make_cleanup (null_routine
, 0);
330 val
= catch_errors (gdb_cmd_stub
, argv
[1], "", RETURN_MASK_ERROR
);
332 /* In case of an error, we may need to force the GUI into idle mode because
333 gdbtk_call_command may have bombed out while in the command routine. */
336 Tcl_VarEval (interp
, "gdbtk_tcl_idle", NULL
);
338 bpstat_do_actions (&stop_bpstat
);
339 do_cleanups (old_chain
);
341 /* Drain all buffered command output */
343 gdb_flush (gdb_stderr
);
344 gdb_flush (gdb_stdout
);
346 /* We could base the return value on val, but that would require most users
347 to use catch. Since GDB errors are already being handled elsewhere, I
348 see no reason to pass them up to the caller. */
354 gdb_listfiles (clientData
, interp
, argc
, argv
)
355 ClientData clientData
;
361 struct objfile
*objfile
;
362 struct partial_symtab
*psymtab
;
364 ALL_PSYMTABS (objfile
, psymtab
)
365 Tcl_AppendElement (interp
, psymtab
->filename
);
371 gdb_stop (clientData
, interp
, argc
, argv
)
372 ClientData clientData
;
377 extern pid_t inferior_process_group
;
379 /* XXX - This is WRONG for remote targets. Probably need a target vector
380 entry to do this right. */
382 kill (-inferior_process_group
, SIGINT
);
387 tk_command (cmd
, from_tty
)
391 Tcl_VarEval (interp
, cmd
, NULL
);
393 gdbtk_fputs (interp
->result
);
398 cleanup_init (ignored
)
401 if (mainWindow
!= NULL
)
402 Tk_DestroyWindow (mainWindow
);
406 Tcl_DeleteInterp (interp
);
410 /* Come here during long calculations to check for GUI events. Usually invoked
411 via the QUIT macro. */
416 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
419 /* Come here when there is activity on the X file descriptor. */
425 /* Process pending events */
427 while (Tk_DoOneEvent (TK_DONT_WAIT
|TK_ALL_EVENTS
) != 0);
431 gdbtk_wait (pid
, ourstatus
)
433 struct target_waitstatus
*ourstatus
;
435 signal (SIGIO
, x_event
);
437 pid
= target_wait (pid
, ourstatus
);
439 signal (SIGIO
, SIG_IGN
);
444 /* This is called from execute_command, and provides a wrapper around
445 various command routines in a place where both protocol messages and
446 user input both flow through. Mostly this is used for indicating whether
447 the target process is running or not.
451 gdbtk_call_command (cmdblk
, arg
, from_tty
)
452 struct cmd_list_element
*cmdblk
;
456 if (cmdblk
->class == class_run
)
458 Tcl_VarEval (interp
, "gdbtk_tcl_busy", NULL
);
459 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
460 Tcl_VarEval (interp
, "gdbtk_tcl_idle", NULL
);
463 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
469 struct cleanup
*old_chain
;
470 char *gdbtk_filename
;
473 old_chain
= make_cleanup (cleanup_init
, 0);
475 /* First init tcl and tk. */
477 interp
= Tcl_CreateInterp ();
480 error ("Tcl_CreateInterp failed");
482 mainWindow
= Tk_CreateMainWindow (interp
, NULL
, "gdb", "Gdb");
485 return; /* DISPLAY probably not set */
487 if (Tcl_Init(interp
) != TCL_OK
)
488 error ("Tcl_Init failed: %s", interp
->result
);
490 if (Tk_Init(interp
) != TCL_OK
)
491 error ("Tk_Init failed: %s", interp
->result
);
493 Tcl_CreateCommand (interp
, "gdb_cmd", gdb_cmd
, NULL
, NULL
);
494 Tcl_CreateCommand (interp
, "gdb_loc", gdb_loc
, NULL
, NULL
);
495 Tcl_CreateCommand (interp
, "gdb_listfiles", gdb_listfiles
, NULL
, NULL
);
496 Tcl_CreateCommand (interp
, "gdb_stop", gdb_stop
, NULL
, NULL
);
498 gdbtk_filename
= getenv ("GDBTK_FILENAME");
500 if (access ("gdbtk.tcl", R_OK
) == 0)
501 gdbtk_filename
= "gdbtk.tcl";
503 gdbtk_filename
= GDBTK_FILENAME
;
505 if (Tcl_EvalFile (interp
, gdbtk_filename
) != TCL_OK
)
506 error ("Failure reading %s: %s", gdbtk_filename
, interp
->result
);
508 /* Get the file descriptor for the X server */
510 x_fd
= ConnectionNumber (Tk_Display (mainWindow
));
512 /* Setup for I/O interrupts */
514 signal (SIGIO
, SIG_IGN
);
516 i
= fcntl (x_fd
, F_GETFL
, 0);
517 fcntl (x_fd
, F_SETFL
, i
|FASYNC
);
518 fcntl (x_fd
, F_SETOWN
, getpid());
520 command_loop_hook
= Tk_MainLoop
;
521 fputs_unfiltered_hook
= gdbtk_fputs
;
522 print_frame_info_listing_hook
= null_routine
;
523 query_hook
= gdbtk_query
;
524 flush_hook
= gdbtk_flush
;
525 create_breakpoint_hook
= gdbtk_create_breakpoint
;
526 delete_breakpoint_hook
= gdbtk_delete_breakpoint
;
527 enable_breakpoint_hook
= gdbtk_enable_breakpoint
;
528 disable_breakpoint_hook
= gdbtk_disable_breakpoint
;
529 interactive_hook
= gdbtk_interactive
;
530 target_wait_hook
= gdbtk_wait
;
531 call_command_hook
= gdbtk_call_command
;
533 discard_cleanups (old_chain
);
535 add_com ("tk", class_obscure
, tk_command
,
536 "Send a command directly into tk.");
539 /* Come here during initialze_all_files () */
546 /* Tell the rest of the world that Gdbtk is now set up. */
548 init_ui_hook
= gdbtk_init
;