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>
43 /* Non-zero means that we're doing the gdbtk interface. */
46 /* Non-zero means we are reloading breakpoints, etc from the
47 Gdbtk kernel, and we should suppress various messages */
48 static int gdbtk_reloading
= 0;
50 /* Handle for TCL interpreter */
51 static Tcl_Interp
*interp
= NULL
;
53 /* Handle for TK main window */
54 static Tk_Window mainWindow
= NULL
;
63 /* This routine redirects the output of fputs_unfiltered so that
64 the user can see what's going on in his debugger window. */
70 Tcl_VarEval (interp
, "gdbtk_tcl_fputs ", "{", ptr
, "}", NULL
);
77 Tcl_VarEval (interp
, "gdbtk_tcl_flush", NULL
);
88 query
= va_arg (args
, char *);
90 vsprintf(buf
, query
, args
);
91 Tcl_VarEval (interp
, "gdbtk_tcl_query ", "{", buf
, "}", NULL
);
93 val
= atol (interp
->result
);
99 struct symtab
*symtab
;
107 if (symtab
->fullname
)
108 return savestring(symtab
->fullname
, strlen(symtab
->fullname
));
110 if (symtab
->filename
[0] == '/')
111 return savestring(symtab
->filename
, strlen(symtab
->filename
));
114 pathlen
= strlen(symtab
->dirname
);
117 if (symtab
->filename
)
118 pathlen
+= strlen(symtab
->filename
);
120 filename
= xmalloc(pathlen
+1);
123 strcpy(filename
, symtab
->dirname
);
126 if (symtab
->filename
)
127 strcat(filename
, symtab
->filename
);
133 breakpoint_notify(b
, action
)
134 struct breakpoint
*b
;
138 char bpnum
[50], line
[50];
139 struct symtab_and_line sal
;
143 if (b
->type
!= bp_breakpoint
)
146 sal
= find_pc_line (b
->address
, 0);
148 filename
= full_filename (sal
.symtab
);
150 sprintf (bpnum
, "%d", b
->number
);
151 sprintf (line
, "%d", sal
.line
);
153 v
= Tcl_VarEval (interp
,
154 "gdbtk_tcl_breakpoint ",
163 gdbtk_fputs (interp
->result
);
172 gdbtk_create_breakpoint(b
)
173 struct breakpoint
*b
;
175 breakpoint_notify(b
, "create");
179 gdbtk_delete_breakpoint(b
)
180 struct breakpoint
*b
;
182 breakpoint_notify(b
, "delete");
186 gdbtk_enable_breakpoint(b
)
187 struct breakpoint
*b
;
189 breakpoint_notify(b
, "enable");
193 gdbtk_disable_breakpoint(b
)
194 struct breakpoint
*b
;
196 breakpoint_notify(b
, "disable");
199 /* This implements the TCL command `gdb_loc', which returns a list consisting
200 of the source and line number associated with the current pc. */
203 gdb_loc (clientData
, interp
, argc
, argv
)
204 ClientData clientData
;
211 struct symtab_and_line sal
;
216 struct frame_info
*frame
;
220 frame
= get_frame_info (selected_frame
);
221 pc
= frame
? frame
->pc
: stop_pc
;
222 func
= find_pc_function (pc
);
223 funcname
= func
? SYMBOL_NAME (func
) : "";
224 sal
= find_pc_line (pc
, 0);
228 struct cleanup
*old_chain
;
229 struct symtabs_and_lines sals
;
231 sals
= decode_line_spec (argv
[1], 1);
235 Tcl_SetResult (interp
, "Ambiguous line spec", TCL_STATIC
);
246 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
250 filename
= full_filename (sal
.symtab
);
252 sprintf (buf
, "%d", sal
.line
);
255 Tcl_AppendElement (interp
, sal
.symtab
->filename
);
257 Tcl_AppendElement (interp
, "");
258 Tcl_AppendElement (interp
, funcname
);
259 Tcl_AppendElement (interp
, filename
);
260 Tcl_AppendElement (interp
, buf
); /* line number */
272 execute_command (cmd
, 1);
274 return 1; /* Indicate success */
277 /* This implements the TCL command `gdb_cmd', which sends it's argument into
278 the GDB command scanner. */
281 gdb_cmd (clientData
, interp
, argc
, argv
)
282 ClientData clientData
;
288 struct cleanup
*old_chain
;
292 Tcl_SetResult (interp
, "wrong # args", TCL_STATIC
);
296 old_chain
= make_cleanup (null_routine
, 0);
298 val
= catch_errors (gdb_cmd_stub
, argv
[1], "", RETURN_MASK_ERROR
);
300 bpstat_do_actions (&stop_bpstat
);
301 do_cleanups (old_chain
);
303 /* We could base the return value on val, but that would require most users
304 to use catch. Since GDB errors are already being handled elsewhere, I
305 see no reason to pass them up to the caller. */
311 gdb_listfiles (clientData
, interp
, argc
, argv
)
312 ClientData clientData
;
318 struct objfile
*objfile
;
319 struct partial_symtab
*psymtab
;
321 ALL_PSYMTABS (objfile
, psymtab
)
322 Tcl_AppendElement (interp
, psymtab
->filename
);
328 tk_command (cmd
, from_tty
)
332 Tcl_VarEval (interp
, cmd
, NULL
);
334 gdbtk_fputs (interp
->result
);
339 cleanup_init (ignored
)
342 if (mainWindow
!= NULL
)
343 Tk_DestroyWindow (mainWindow
);
347 Tcl_DeleteInterp (interp
);
354 struct cleanup
*old_chain
;
355 char *gdbtk_filename
;
357 old_chain
= make_cleanup (cleanup_init
, 0);
359 /* First init tcl and tk. */
361 interp
= Tcl_CreateInterp ();
364 error ("Tcl_CreateInterp failed");
366 mainWindow
= Tk_CreateMainWindow (interp
, NULL
, "gdb", "Gdb");
369 return; /* DISPLAY probably not set */
371 if (Tcl_Init(interp
) != TCL_OK
)
372 error ("Tcl_Init failed: %s", interp
->result
);
374 if (Tk_Init(interp
) != TCL_OK
)
375 error ("Tk_Init failed: %s", interp
->result
);
377 Tcl_CreateCommand (interp
, "gdb_cmd", gdb_cmd
, NULL
, NULL
);
378 Tcl_CreateCommand (interp
, "gdb_loc", gdb_loc
, NULL
, NULL
);
379 Tcl_CreateCommand (interp
, "gdb_listfiles", gdb_listfiles
, NULL
, NULL
);
381 gdbtk_filename
= getenv ("GDBTK_FILENAME");
384 if (Tcl_EvalFile (interp
, gdbtk_filename
) != TCL_OK
)
385 error ("Failure reading %s: %s", gdbtk_filename
, interp
->result
);
389 if (Tcl_EvalFile (interp
, "gdbtk.tcl") != TCL_OK
)
391 Tcl_ResetResult (interp
);
392 if (Tcl_EvalFile (interp
, GDBTK_FILENAME
) != TCL_OK
)
393 error ("Failure reading %s: %s", GDBTK_FILENAME
, interp
->result
);
397 command_loop_hook
= Tk_MainLoop
;
398 fputs_unfiltered_hook
= gdbtk_fputs
;
399 print_frame_info_listing_hook
= null_routine
;
400 query_hook
= gdbtk_query
;
401 flush_hook
= gdbtk_flush
;
402 create_breakpoint_hook
= gdbtk_create_breakpoint
;
403 delete_breakpoint_hook
= gdbtk_delete_breakpoint
;
404 enable_breakpoint_hook
= gdbtk_enable_breakpoint
;
405 disable_breakpoint_hook
= gdbtk_disable_breakpoint
;
407 discard_cleanups (old_chain
);
409 add_com ("tk", class_obscure
, tk_command
,
410 "Send a command directly into tk.");
413 /* Come here during initialze_all_files () */
421 /* Tell the rest of the world that Gdbtk is now set up. */
423 init_ui_hook
= gdbtk_init
;