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;
64 /* This routine redirects the output of fputs_unfiltered so that
65 the user can see what's going on in his debugger window. */
67 static char holdbuf[200];
68 static char *holdbufp = holdbuf;
69 static int holdfree = sizeof (holdbuf);
74 if (holdbufp == holdbuf)
77 Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", holdbuf, "}", NULL);
79 holdfree = sizeof (holdbuf);
88 Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
97 len = strlen (ptr) + 1;
103 if (len > sizeof (holdbuf))
105 Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", ptr, "}", NULL);
110 strncpy (holdbufp, ptr, len);
123 query = va_arg (args, char *);
125 vsprintf(buf, query, args);
126 Tcl_VarEval (interp, "gdbtk_tcl_query ", "{", buf, "}", NULL);
128 val = atol (interp->result);
134 full_filename(symtab)
135 struct symtab *symtab;
143 if (symtab->fullname)
144 return savestring(symtab->fullname, strlen(symtab->fullname));
146 if (symtab->filename[0] == '/')
147 return savestring(symtab->filename, strlen(symtab->filename));
150 pathlen = strlen(symtab->dirname);
153 if (symtab->filename)
154 pathlen += strlen(symtab->filename);
156 filename = xmalloc(pathlen+1);
159 strcpy(filename, symtab->dirname);
162 if (symtab->filename)
163 strcat(filename, symtab->filename);
170 breakpoint_notify(b, action)
171 struct breakpoint *b;
175 char bpnum[50], line[50], pc[50];
176 struct symtab_and_line sal;
180 if (b->type != bp_breakpoint)
183 sal = find_pc_line (b->address, 0);
185 filename = symtab_to_filename (sal.symtab);
187 sprintf (bpnum, "%d", b->number);
188 sprintf (line, "%d", sal.line);
189 sprintf (pc, "0x%x", b->address);
191 v = Tcl_VarEval (interp,
192 "gdbtk_tcl_breakpoint ",
202 gdbtk_fputs (interp->result);
208 gdbtk_create_breakpoint(b)
209 struct breakpoint *b;
211 breakpoint_notify(b, "create");
215 gdbtk_delete_breakpoint(b)
216 struct breakpoint *b;
218 breakpoint_notify(b, "delete");
222 gdbtk_enable_breakpoint(b)
223 struct breakpoint *b;
225 breakpoint_notify(b, "enable");
229 gdbtk_disable_breakpoint(b)
230 struct breakpoint *b;
232 breakpoint_notify(b, "disable");
235 /* This implements the TCL command `gdb_loc', which returns a list consisting
236 of the source and line number associated with the current pc. */
239 gdb_loc (clientData, interp, argc, argv)
240 ClientData clientData;
247 struct symtab_and_line sal;
253 struct frame_info *frame;
256 frame = get_frame_info (selected_frame);
258 pc = frame ? frame->pc : stop_pc;
260 sal = find_pc_line (pc, 0);
264 struct symtabs_and_lines sals;
267 sals = decode_line_spec (argv[1], 1);
275 Tcl_SetResult (interp, "Ambiguous line spec", TCL_STATIC);
283 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
288 Tcl_AppendElement (interp, sal.symtab->filename);
290 Tcl_AppendElement (interp, "");
292 find_pc_partial_function (pc, &funcname, NULL, NULL);
293 Tcl_AppendElement (interp, funcname);
295 filename = symtab_to_filename (sal.symtab);
296 Tcl_AppendElement (interp, filename);
298 sprintf (buf, "%d", sal.line);
299 Tcl_AppendElement (interp, buf); /* line number */
301 sprintf (buf, "0x%x", pc);
302 Tcl_AppendElement (interp, buf); /* PC */
311 execute_command (cmd, 1);
313 return 1; /* Indicate success */
316 /* This implements the TCL command `gdb_cmd', which sends it's argument into
317 the GDB command scanner. */
320 gdb_cmd (clientData, interp, argc, argv)
321 ClientData clientData;
327 struct cleanup *old_chain;
331 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
335 old_chain = make_cleanup (null_routine, 0);
337 val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR);
339 bpstat_do_actions (&stop_bpstat);
340 do_cleanups (old_chain);
342 /* Drain all buffered command output */
344 gdb_flush (gdb_stderr);
345 gdb_flush (gdb_stdout);
347 /* We could base the return value on val, but that would require most users
348 to use catch. Since GDB errors are already being handled elsewhere, I
349 see no reason to pass them up to the caller. */
355 gdb_listfiles (clientData, interp, argc, argv)
356 ClientData clientData;
362 struct objfile *objfile;
363 struct partial_symtab *psymtab;
365 ALL_PSYMTABS (objfile, psymtab)
366 Tcl_AppendElement (interp, psymtab->filename);
372 tk_command (cmd, from_tty)
376 Tcl_VarEval (interp, cmd, NULL);
378 gdbtk_fputs (interp->result);
383 cleanup_init (ignored)
386 if (mainWindow != NULL)
387 Tk_DestroyWindow (mainWindow);
391 Tcl_DeleteInterp (interp);
395 /* Come here during long calculations to check for GUI events. Usually invoked
396 via the QUIT macro. */
401 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
407 struct cleanup *old_chain;
408 char *gdbtk_filename;
410 old_chain = make_cleanup (cleanup_init, 0);
412 /* First init tcl and tk. */
414 interp = Tcl_CreateInterp ();
417 error ("Tcl_CreateInterp failed");
419 mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb");
422 return; /* DISPLAY probably not set */
424 if (Tcl_Init(interp) != TCL_OK)
425 error ("Tcl_Init failed: %s", interp->result);
427 if (Tk_Init(interp) != TCL_OK)
428 error ("Tk_Init failed: %s", interp->result);
430 Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
431 Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
432 Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
434 gdbtk_filename = getenv ("GDBTK_FILENAME");
436 if (access ("gdbtk.tcl", R_OK) == 0)
437 gdbtk_filename = "gdbtk.tcl";
439 gdbtk_filename = GDBTK_FILENAME;
441 if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
442 error ("Failure reading %s: %s", gdbtk_filename, interp->result);
444 command_loop_hook = Tk_MainLoop;
445 fputs_unfiltered_hook = gdbtk_fputs;
446 print_frame_info_listing_hook = null_routine;
447 query_hook = gdbtk_query;
448 flush_hook = gdbtk_flush;
449 create_breakpoint_hook = gdbtk_create_breakpoint;
450 delete_breakpoint_hook = gdbtk_delete_breakpoint;
451 enable_breakpoint_hook = gdbtk_enable_breakpoint;
452 disable_breakpoint_hook = gdbtk_disable_breakpoint;
453 interactive_hook = gdbtk_interactive;
455 discard_cleanups (old_chain);
457 add_com ("tk", class_obscure, tk_command,
458 "Send a command directly into tk.");
461 /* Come here during initialze_all_files () */
469 /* Tell the rest of the world that Gdbtk is now set up. */
471 init_ui_hook = gdbtk_init;