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. */
28 #include <sys/types.h>
30 #include <sys/param.h>
34 #include <sys/filio.h>
37 #include <sys/errno.h>
44 /* Non-zero means that we're doing the gdbtk interface. */
47 /* Non-zero means we are reloading breakpoints, etc from the
48 Gdbtk kernel, and we should suppress various messages */
49 static int gdbtk_reloading = 0;
51 /* Handle for TCL interpreter */
52 static Tcl_Interp *interp = NULL;
54 /* Handle for TK main window */
55 static Tk_Window mainWindow = NULL;
57 static int x_fd; /* X network socket */
66 /* This routine redirects the output of fputs_unfiltered so that
67 the user can see what's going on in his debugger window. */
69 static char holdbuf[200];
70 static char *holdbufp = holdbuf;
71 static int holdfree = sizeof (holdbuf);
76 if (holdbufp == holdbuf)
79 Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", holdbuf, "}", NULL);
81 holdfree = sizeof (holdbuf);
90 Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
99 len = strlen (ptr) + 1;
105 if (len > sizeof (holdbuf))
107 Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", ptr, "}", NULL);
112 strncpy (holdbufp, ptr, len);
125 query = va_arg (args, char *);
127 vsprintf(buf, query, args);
128 Tcl_VarEval (interp, "gdbtk_tcl_query ", "{", buf, "}", NULL);
130 val = atol (interp->result);
136 full_filename(symtab)
137 struct symtab *symtab;
145 if (symtab->fullname)
146 return savestring(symtab->fullname, strlen(symtab->fullname));
148 if (symtab->filename[0] == '/')
149 return savestring(symtab->filename, strlen(symtab->filename));
152 pathlen = strlen(symtab->dirname);
155 if (symtab->filename)
156 pathlen += strlen(symtab->filename);
158 filename = xmalloc(pathlen+1);
161 strcpy(filename, symtab->dirname);
164 if (symtab->filename)
165 strcat(filename, symtab->filename);
172 breakpoint_notify(b, action)
173 struct breakpoint *b;
177 char bpnum[50], line[50], pc[50];
178 struct symtab_and_line sal;
182 if (b->type != bp_breakpoint)
185 sal = find_pc_line (b->address, 0);
187 filename = symtab_to_filename (sal.symtab);
189 sprintf (bpnum, "%d", b->number);
190 sprintf (line, "%d", sal.line);
191 sprintf (pc, "0x%x", b->address);
193 v = Tcl_VarEval (interp,
194 "gdbtk_tcl_breakpoint ",
204 gdbtk_fputs (interp->result);
210 gdbtk_create_breakpoint(b)
211 struct breakpoint *b;
213 breakpoint_notify(b, "create");
217 gdbtk_delete_breakpoint(b)
218 struct breakpoint *b;
220 breakpoint_notify(b, "delete");
224 gdbtk_enable_breakpoint(b)
225 struct breakpoint *b;
227 breakpoint_notify(b, "enable");
231 gdbtk_disable_breakpoint(b)
232 struct breakpoint *b;
234 breakpoint_notify(b, "disable");
237 /* This implements the TCL command `gdb_loc', which returns a list consisting
238 of the source and line number associated with the current pc. */
241 gdb_loc (clientData, interp, argc, argv)
242 ClientData clientData;
249 struct symtab_and_line sal;
255 struct frame_info *frame;
258 frame = get_frame_info (selected_frame);
260 pc = frame ? frame->pc : stop_pc;
262 sal = find_pc_line (pc, 0);
266 struct symtabs_and_lines sals;
269 sals = decode_line_spec (argv[1], 1);
277 Tcl_SetResult (interp, "Ambiguous line spec", TCL_STATIC);
285 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
290 Tcl_AppendElement (interp, sal.symtab->filename);
292 Tcl_AppendElement (interp, "");
294 find_pc_partial_function (pc, &funcname, NULL, NULL);
295 Tcl_AppendElement (interp, funcname);
297 filename = symtab_to_filename (sal.symtab);
298 Tcl_AppendElement (interp, filename);
300 sprintf (buf, "%d", sal.line);
301 Tcl_AppendElement (interp, buf); /* line number */
303 sprintf (buf, "0x%x", pc);
304 Tcl_AppendElement (interp, buf); /* PC */
313 execute_command (cmd, 1);
315 return 1; /* Indicate success */
318 /* This implements the TCL command `gdb_cmd', which sends it's argument into
319 the GDB command scanner. */
322 gdb_cmd (clientData, interp, argc, argv)
323 ClientData clientData;
329 struct cleanup *old_chain;
333 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
337 old_chain = make_cleanup (null_routine, 0);
339 val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR);
341 /* In case of an error, we may need to force the GUI into idle mode because
342 gdbtk_call_command may have bombed out while in the command routine. */
345 Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
347 bpstat_do_actions (&stop_bpstat);
348 do_cleanups (old_chain);
350 /* Drain all buffered command output */
352 gdb_flush (gdb_stderr);
353 gdb_flush (gdb_stdout);
355 /* We could base the return value on val, but that would require most users
356 to use catch. Since GDB errors are already being handled elsewhere, I
357 see no reason to pass them up to the caller. */
363 gdb_listfiles (clientData, interp, argc, argv)
364 ClientData clientData;
370 struct objfile *objfile;
371 struct partial_symtab *psymtab;
373 ALL_PSYMTABS (objfile, psymtab)
374 Tcl_AppendElement (interp, psymtab->filename);
380 gdb_stop (clientData, interp, argc, argv)
381 ClientData clientData;
386 extern pid_t inferior_process_group;
388 /* XXX - This is WRONG for remote targets. Probably need a target vector
389 entry to do this right. */
391 kill (-inferior_process_group, SIGINT);
396 tk_command (cmd, from_tty)
400 Tcl_VarEval (interp, cmd, NULL);
402 gdbtk_fputs (interp->result);
407 cleanup_init (ignored)
410 if (mainWindow != NULL)
411 Tk_DestroyWindow (mainWindow);
415 Tcl_DeleteInterp (interp);
419 /* Come here during long calculations to check for GUI events. Usually invoked
420 via the QUIT macro. */
425 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
428 /* Come here when there is activity on the X file descriptor. */
434 /* Process pending events */
436 while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
440 gdbtk_wait (pid, ourstatus)
442 struct target_waitstatus *ourstatus;
444 signal (SIGIO, x_event);
446 pid = target_wait (pid, ourstatus);
448 signal (SIGIO, SIG_IGN);
453 /* This is called from execute_command, and provides a wrapper around
454 various command routines in a place where both protocol messages and
455 user input both flow through. Mostly this is used for indicating whether
456 the target process is running or not.
460 gdbtk_call_command (cmdblk, arg, from_tty)
461 struct cmd_list_element *cmdblk;
465 if (cmdblk->class == class_run)
467 Tcl_VarEval (interp, "gdbtk_tcl_busy", NULL);
468 (*cmdblk->function.cfunc)(arg, from_tty);
469 Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
472 (*cmdblk->function.cfunc)(arg, from_tty);
478 struct cleanup *old_chain;
479 char *gdbtk_filename;
482 old_chain = make_cleanup (cleanup_init, 0);
484 /* First init tcl and tk. */
486 interp = Tcl_CreateInterp ();
489 error ("Tcl_CreateInterp failed");
491 mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb");
494 return; /* DISPLAY probably not set */
496 if (Tcl_Init(interp) != TCL_OK)
497 error ("Tcl_Init failed: %s", interp->result);
499 if (Tk_Init(interp) != TCL_OK)
500 error ("Tk_Init failed: %s", interp->result);
502 Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
503 Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
504 Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
505 Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
507 gdbtk_filename = getenv ("GDBTK_FILENAME");
509 if (access ("gdbtk.tcl", R_OK) == 0)
510 gdbtk_filename = "gdbtk.tcl";
512 gdbtk_filename = GDBTK_FILENAME;
514 if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
515 error ("Failure reading %s: %s", gdbtk_filename, interp->result);
517 /* XXX - Get the file descriptor for the network socket. This is not Kosher
518 as it involves looking at data private to Xlib. */
520 x_fd = Tk_Display (mainWindow) -> fd;
522 /* Setup for I/O interrupts */
524 signal (SIGIO, SIG_IGN);
526 i = fcntl (x_fd, F_GETFL, 0);
527 fcntl (x_fd, F_SETFL, i|FASYNC);
528 fcntl (x_fd, F_SETOWN, getpid());
530 command_loop_hook = Tk_MainLoop;
531 fputs_unfiltered_hook = gdbtk_fputs;
532 print_frame_info_listing_hook = null_routine;
533 query_hook = gdbtk_query;
534 flush_hook = gdbtk_flush;
535 create_breakpoint_hook = gdbtk_create_breakpoint;
536 delete_breakpoint_hook = gdbtk_delete_breakpoint;
537 enable_breakpoint_hook = gdbtk_enable_breakpoint;
538 disable_breakpoint_hook = gdbtk_disable_breakpoint;
539 interactive_hook = gdbtk_interactive;
540 target_wait_hook = gdbtk_wait;
541 call_command_hook = gdbtk_call_command;
543 discard_cleanups (old_chain);
545 add_com ("tk", class_obscure, tk_command,
546 "Send a command directly into tk.");
549 /* Come here during initialze_all_files () */
557 /* Tell the rest of the world that Gdbtk is now set up. */
559 init_ui_hook = gdbtk_init;