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 pc = selected_frame ? selected_frame->pc : stop_pc;
247 sal = find_pc_line (pc, 0);
251 struct symtabs_and_lines sals;
254 sals = decode_line_spec (argv[1], 1);
262 Tcl_SetResult (interp, "Ambiguous line spec", TCL_STATIC);
270 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
275 Tcl_AppendElement (interp, sal.symtab->filename);
277 Tcl_AppendElement (interp, "");
279 find_pc_partial_function (pc, &funcname, NULL, NULL);
280 Tcl_AppendElement (interp, funcname);
282 filename = symtab_to_filename (sal.symtab);
283 Tcl_AppendElement (interp, filename);
285 sprintf (buf, "%d", sal.line);
286 Tcl_AppendElement (interp, buf); /* line number */
288 sprintf (buf, "0x%x", pc);
289 Tcl_AppendElement (interp, buf); /* PC */
294 /* This implements the TCL command `gdb_sourcelines', which returns a list of
295 all of the lines containing executable code for the specified source file
296 (ie: lines where you can put breakpoints). */
299 gdb_sourcelines (clientData, interp, argc, argv)
300 ClientData clientData;
305 struct symtab *symtab;
306 struct linetable_entry *le;
312 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
316 symtab = lookup_symtab (argv[1]);
320 Tcl_SetResult (interp, "No such file", TCL_STATIC);
324 /* If there's no linetable, or no entries, then we are done. */
326 if (!symtab->linetable
327 || symtab->linetable->nitems == 0)
329 Tcl_AppendElement (interp, "");
333 le = symtab->linetable->item;
334 nlines = symtab->linetable->nitems;
336 for (;nlines > 0; nlines--, le++)
338 /* If the pc of this line is the same as the pc of the next line, then
341 && le->pc == (le + 1)->pc)
344 sprintf (buf, "%d", le->line);
345 Tcl_AppendElement (interp, buf);
351 /* This implements the TCL command `gdb_regnames', which returns a list of
352 all of the register names. */
355 gdb_regnames (clientData, interp, argc, argv)
356 ClientData clientData;
365 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
369 for (i = 0; i < NUM_REGS; i++)
370 Tcl_AppendElement (interp, reg_names[i]);
379 execute_command (cmd, 1);
381 return 1; /* Indicate success */
384 /* This implements the TCL command `gdb_cmd', which sends it's argument into
385 the GDB command scanner. */
388 gdb_cmd (clientData, interp, argc, argv)
389 ClientData clientData;
395 struct cleanup *old_chain;
399 Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
403 old_chain = make_cleanup (null_routine, 0);
405 val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR);
407 /* In case of an error, we may need to force the GUI into idle mode because
408 gdbtk_call_command may have bombed out while in the command routine. */
411 Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
413 bpstat_do_actions (&stop_bpstat);
414 do_cleanups (old_chain);
416 /* Drain all buffered command output */
418 gdb_flush (gdb_stderr);
419 gdb_flush (gdb_stdout);
421 /* We could base the return value on val, but that would require most users
422 to use catch. Since GDB errors are already being handled elsewhere, I
423 see no reason to pass them up to the caller. */
429 gdb_listfiles (clientData, interp, argc, argv)
430 ClientData clientData;
436 struct objfile *objfile;
437 struct partial_symtab *psymtab;
439 ALL_PSYMTABS (objfile, psymtab)
440 Tcl_AppendElement (interp, psymtab->filename);
446 gdb_stop (clientData, interp, argc, argv)
447 ClientData clientData;
457 tk_command (cmd, from_tty)
461 Tcl_VarEval (interp, cmd, NULL);
463 gdbtk_fputs (interp->result);
468 cleanup_init (ignored)
471 if (mainWindow != NULL)
472 Tk_DestroyWindow (mainWindow);
476 Tcl_DeleteInterp (interp);
480 /* Come here during long calculations to check for GUI events. Usually invoked
481 via the QUIT macro. */
486 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
489 /* Come here when there is activity on the X file descriptor. */
495 /* Process pending events */
497 while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
501 gdbtk_wait (pid, ourstatus)
503 struct target_waitstatus *ourstatus;
505 signal (SIGIO, x_event);
507 pid = target_wait (pid, ourstatus);
509 signal (SIGIO, SIG_IGN);
514 /* This is called from execute_command, and provides a wrapper around
515 various command routines in a place where both protocol messages and
516 user input both flow through. Mostly this is used for indicating whether
517 the target process is running or not.
521 gdbtk_call_command (cmdblk, arg, from_tty)
522 struct cmd_list_element *cmdblk;
526 if (cmdblk->class == class_run)
528 Tcl_VarEval (interp, "gdbtk_tcl_busy", NULL);
529 (*cmdblk->function.cfunc)(arg, from_tty);
530 Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
533 (*cmdblk->function.cfunc)(arg, from_tty);
539 struct cleanup *old_chain;
540 char *gdbtk_filename;
543 old_chain = make_cleanup (cleanup_init, 0);
545 /* First init tcl and tk. */
547 interp = Tcl_CreateInterp ();
550 error ("Tcl_CreateInterp failed");
552 mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb");
555 return; /* DISPLAY probably not set */
557 if (Tcl_Init(interp) != TCL_OK)
558 error ("Tcl_Init failed: %s", interp->result);
560 if (Tk_Init(interp) != TCL_OK)
561 error ("Tk_Init failed: %s", interp->result);
563 Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
564 Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
565 Tcl_CreateCommand (interp, "gdb_sourcelines", gdb_sourcelines, NULL, NULL);
566 Tcl_CreateCommand (interp, "gdb_regnames", gdb_regnames, NULL, NULL);
567 Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
568 Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
570 gdbtk_filename = getenv ("GDBTK_FILENAME");
572 if (access ("gdbtk.tcl", R_OK) == 0)
573 gdbtk_filename = "gdbtk.tcl";
575 gdbtk_filename = GDBTK_FILENAME;
577 if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
578 error ("Failure reading %s: %s", gdbtk_filename, interp->result);
580 /* Get the file descriptor for the X server */
582 x_fd = ConnectionNumber (Tk_Display (mainWindow));
584 /* Setup for I/O interrupts */
586 signal (SIGIO, SIG_IGN);
588 i = fcntl (x_fd, F_GETFL, 0);
589 fcntl (x_fd, F_SETFL, i|FASYNC);
590 fcntl (x_fd, F_SETOWN, getpid());
592 command_loop_hook = Tk_MainLoop;
593 fputs_unfiltered_hook = gdbtk_fputs;
594 print_frame_info_listing_hook = null_routine;
595 query_hook = gdbtk_query;
596 flush_hook = gdbtk_flush;
597 create_breakpoint_hook = gdbtk_create_breakpoint;
598 delete_breakpoint_hook = gdbtk_delete_breakpoint;
599 enable_breakpoint_hook = gdbtk_enable_breakpoint;
600 disable_breakpoint_hook = gdbtk_disable_breakpoint;
601 interactive_hook = gdbtk_interactive;
602 target_wait_hook = gdbtk_wait;
603 call_command_hook = gdbtk_call_command;
605 discard_cleanups (old_chain);
607 add_com ("tk", class_obscure, tk_command,
608 "Send a command directly into tk.");
611 /* Come here during initialze_all_files () */
618 /* Tell the rest of the world that Gdbtk is now set up. */
620 init_ui_hook = gdbtk_init;