1 /* Startup code for gdbtk.
2 Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
4 Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
31 #include "tracepoint.h"
48 /* start-sanitize-ide */
52 /* end-sanitize-ide */
55 #ifdef ANSI_PROTOTYPES
65 #include <sys/ioctl.h>
66 #include "gdb_string.h"
76 extern int (*ui_load_progress_hook
) PARAMS ((char *, unsigned long));
77 extern void (*pre_add_symbol_hook
) PARAMS ((char *));
78 extern void (*post_add_symbol_hook
) PARAMS ((void));
79 extern void (*selected_frame_level_changed_hook
) PARAMS ((int));
81 extern void (*ui_loop_hook
) PARAMS ((int));
84 static void gdbtk_create_tracepoint
PARAMS ((struct tracepoint
*));
85 static void gdbtk_delete_tracepoint
PARAMS ((struct tracepoint
*));
86 static void gdbtk_modify_tracepoint
PARAMS ((struct tracepoint
*));
87 static void gdbtk_trace_find
PARAMS ((char *arg
, int from_tty
));
88 static void gdbtk_create_breakpoint
PARAMS ((struct breakpoint
*));
89 static void gdbtk_delete_breakpoint
PARAMS ((struct breakpoint
*));
90 static void gdbtk_modify_breakpoint
PARAMS ((struct breakpoint
*));
91 static void gdbtk_file_changed
PARAMS ((char *));
92 static void gdbtk_exec_file_display
PARAMS ((char *));
93 static void tk_command_loop
PARAMS ((void));
94 static void gdbtk_call_command
PARAMS ((struct cmd_list_element
*, char *, int));
95 static int gdbtk_wait
PARAMS ((int, struct target_waitstatus
*));
96 void x_event
PARAMS ((int));
97 static int gdbtk_query
PARAMS ((const char *, va_list));
98 static void gdbtk_warning
PARAMS ((const char *, va_list));
99 void gdbtk_ignorable_warning
PARAMS ((const char *));
100 static char* gdbtk_readline
PARAMS ((char *));
102 #ifdef ANSI_PROTOTYPES
103 gdbtk_readline_begin (char *format
, ...);
105 gdbtk_readline_begin ();
107 static void gdbtk_readline_end
PARAMS ((void));
108 static void gdbtk_flush
PARAMS ((FILE *));
109 static void gdbtk_pre_add_symbol
PARAMS ((char *));
110 static void gdbtk_print_frame_info
PARAMS ((struct symtab
*, int, int, int));
111 static void gdbtk_post_add_symbol
PARAMS ((void));
112 static void pc_changed
PARAMS ((void));
113 static void tracepoint_notify
PARAMS ((struct tracepoint
*, const char *));
114 static void gdbtk_selected_frame_changed
PARAMS ((int));
115 static void gdbtk_context_change
PARAMS ((int));
118 * gdbtk_fputs can't be static, because we need to call it in gdbtk.c.
119 * See note there for details.
122 void gdbtk_fputs
PARAMS ((const char *, FILE *));
123 int gdbtk_load_hash
PARAMS ((char *, unsigned long));
124 static void breakpoint_notify
PARAMS ((struct breakpoint
*, const char *));
127 * gdbtk_add_hooks - add all the hooks to gdb. This will get called by the
128 * startup code to fill in the hooks needed by core gdb.
132 gdbtk_add_hooks(void)
134 command_loop_hook
= tk_command_loop
;
135 call_command_hook
= gdbtk_call_command
;
136 readline_begin_hook
= gdbtk_readline_begin
;
137 readline_hook
= gdbtk_readline
;
138 readline_end_hook
= gdbtk_readline_end
;
140 print_frame_info_listing_hook
= gdbtk_print_frame_info
;
141 query_hook
= gdbtk_query
;
142 warning_hook
= gdbtk_warning
;
143 flush_hook
= gdbtk_flush
;
145 create_breakpoint_hook
= gdbtk_create_breakpoint
;
146 delete_breakpoint_hook
= gdbtk_delete_breakpoint
;
147 modify_breakpoint_hook
= gdbtk_modify_breakpoint
;
149 interactive_hook
= gdbtk_interactive
;
150 target_wait_hook
= gdbtk_wait
;
151 ui_load_progress_hook
= gdbtk_load_hash
;
154 ui_loop_hook
= x_event
;
156 pre_add_symbol_hook
= gdbtk_pre_add_symbol
;
157 post_add_symbol_hook
= gdbtk_post_add_symbol
;
158 file_changed_hook
= gdbtk_file_changed
;
159 exec_file_display_hook
= gdbtk_exec_file_display
;
161 create_tracepoint_hook
= gdbtk_create_tracepoint
;
162 delete_tracepoint_hook
= gdbtk_delete_tracepoint
;
163 modify_tracepoint_hook
= gdbtk_modify_tracepoint
;
164 trace_find_hook
= gdbtk_trace_find
;
166 pc_changed_hook
= pc_changed
;
167 selected_frame_level_changed_hook
= gdbtk_selected_frame_changed
;
168 context_hook
= gdbtk_context_change
;
171 /* These control where to put the gdb output which is created by
172 {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
173 lowest level of these routines and capture all output from the rest of GDB.
175 The reason to use the result_ptr rather than the gdbtk_interp's result
176 directly is so that a call_wrapper invoked function can preserve its result
177 across calls into Tcl which might be made in the course of the function's
180 * result_ptr->obj_ptr is where to accumulate the result.
181 * GDBTK_TO_RESULT flag means the output goes to the gdbtk_tcl_fputs proc
182 instead of to the result_ptr.
183 * GDBTK_MAKES_LIST flag means add to the result as a list element.
187 gdbtk_result
*result_ptr
= NULL
;
190 /* This allows you to Tcl_Eval a tcl command which takes
191 a command word, and then a single argument. */
193 int gdbtk_two_elem_cmd (cmd_name
, argv1
)
198 int result
, flags_ptr
, arg_len
, cmd_len
;
200 arg_len
= Tcl_ScanElement (argv1
, &flags_ptr
);
201 cmd_len
= strlen (cmd_name
);
202 command
= malloc(arg_len
+ cmd_len
+ 2);
203 strcpy (command
, cmd_name
);
204 strcat (command
, " ");
206 Tcl_ConvertElement (argv1
, command
+ cmd_len
+ 1, flags_ptr
);
208 result
= Tcl_Eval (gdbtk_interp
, command
);
219 /* Force immediate screen update */
221 Tcl_VarEval (gdbtk_interp
, "gdbtk_tcl_flush", NULL
);
225 /* This handles all the output from gdb. All the gdb printf_xxx functions
226 * eventually end up here. The output is either passed to the result_ptr
227 * where it will go to the result of some gdbtk command, or passed to the
228 * Tcl proc gdbtk_tcl_fputs (where it is usually just dumped to the console
233 * 1) result_ptr == NULL - This happens when some output comes from gdb which
234 * is not generated by a command in gdbtk-cmds, usually startup stuff.
235 * In this case we just route the data to gdbtk_tcl_fputs.
236 * 2) The GDBTK_TO_RESULT flag is set - The result is supposed to go to Tcl.
237 * We place the data into the result_ptr, either as a string,
238 * or a list, depending whether the GDBTK_MAKES_LIST bit is set.
239 * 3) The GDBTK_TO_RESULT flag is unset - We route the data to gdbtk_tcl_fputs
240 * UNLESS it was coming to stderr. Then we place it in the result_ptr
241 * anyway, so it can be dealt with.
246 gdbtk_fputs (ptr
, stream
)
252 if (result_ptr
!= NULL
)
254 if (result_ptr
->flags
& GDBTK_TO_RESULT
)
256 if (result_ptr
->flags
& GDBTK_MAKES_LIST
)
257 Tcl_ListObjAppendElement(NULL
, result_ptr
->obj_ptr
,
258 Tcl_NewStringObj((char *) ptr
, -1));
260 Tcl_AppendToObj (result_ptr
->obj_ptr
, (char *) ptr
, -1);
262 else if (stream
== gdb_stderr
)
264 if (result_ptr
->flags
& GDBTK_ERROR_STARTED
)
265 Tcl_AppendToObj (result_ptr
->obj_ptr
, (char *) ptr
, -1);
268 Tcl_SetStringObj (result_ptr
->obj_ptr
, (char *) ptr
, -1);
269 result_ptr
->flags
|= GDBTK_ERROR_STARTED
;
274 gdbtk_two_elem_cmd ("gdbtk_tcl_fputs", (char *) ptr
);
275 if (result_ptr
->flags
& GDBTK_MAKES_LIST
)
276 gdbtk_two_elem_cmd ("gdbtk_tcl_fputs", " ");
281 gdbtk_two_elem_cmd ("gdbtk_tcl_fputs", (char *) ptr
);
288 * This routes all warnings to the Tcl function "gdbtk_tcl_warning".
292 gdbtk_warning (warning
, args
)
298 vsprintf (buf
, warning
, args
);
299 gdbtk_two_elem_cmd ("gdbtk_tcl_warning", buf
);
304 * This routes all ignorable warnings to the Tcl function
305 * "gdbtk_tcl_ignorable_warning".
309 gdbtk_ignorable_warning (warning
)
313 sprintf (buf
, warning
);
314 gdbtk_two_elem_cmd ("gdbtk_tcl_ignorable_warning", buf
);
320 Tcl_Eval (gdbtk_interp
, "gdbtk_pc_changed");
324 /* This function is called instead of gdb's internal command loop. This is the
325 last chance to do anything before entering the main Tk event loop.
326 At the end of the command, we enter the main loop. */
331 extern GDB_FILE
*instream
;
333 /* We no longer want to use stdin as the command input stream */
336 if (Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_preloop") != TCL_OK
)
340 /* Force errorInfo to be set up propertly. */
341 Tcl_AddErrorInfo (gdbtk_interp
, "");
343 msg
= Tcl_GetVar (gdbtk_interp
, "errorInfo", TCL_GLOBAL_ONLY
);
345 MessageBox (NULL
, msg
, NULL
, MB_OK
| MB_ICONERROR
| MB_TASKMODAL
);
347 fputs_unfiltered (msg
, gdb_stderr
);
358 /* Come here when there is activity on the X file descriptor. */
364 static int in_x_event
= 0;
365 static Tcl_Obj
*varname
= NULL
;
366 if (in_x_event
|| in_fputs
)
376 /* Process pending events */
377 while (Tcl_DoOneEvent (TCL_DONT_WAIT
|TCL_ALL_EVENTS
) != 0)
380 if (load_in_progress
)
385 Tcl_Obj
*varnamestrobj
= Tcl_NewStringObj("download_cancel_ok",-1);
386 varname
= Tcl_ObjGetVar2(gdbtk_interp
,varnamestrobj
,NULL
,TCL_GLOBAL_ONLY
);
388 if ((Tcl_GetIntFromObj(gdbtk_interp
,varname
,&val
) == TCL_OK
) && val
)
404 #ifdef ANSI_PROTOTYPES
405 gdbtk_readline_begin (char *format
, ...)
407 gdbtk_readline_begin (va_alist
)
414 #ifdef ANSI_PROTOTYPES
415 va_start (args
, format
);
419 format
= va_arg (args
, char *);
422 vsprintf (buf
, format
, args
);
423 gdbtk_two_elem_cmd ("gdbtk_tcl_readline_begin", buf
);
428 gdbtk_readline (prompt
)
437 result
= gdbtk_two_elem_cmd ("gdbtk_tcl_readline", prompt
);
439 if (result
== TCL_OK
)
441 return (strdup (gdbtk_interp
-> result
));
445 gdbtk_fputs (gdbtk_interp
-> result
, gdb_stdout
);
446 gdbtk_fputs ("\n", gdb_stdout
);
452 gdbtk_readline_end ()
454 Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_readline_end");
458 gdbtk_call_command (cmdblk
, arg
, from_tty
)
459 struct cmd_list_element
*cmdblk
;
464 if (cmdblk
->class == class_run
|| cmdblk
->class == class_trace
)
467 /* HACK! HACK! This is to get the gui to update the tstart/tstop
468 button only incase of tstart/tstop commands issued from the console
469 We don't want to update the src window, so we need to have specific
470 procedures to do tstart and tstop
471 Unfortunately this will not display errors from tstart or tstop in the
472 console window itself, but as dialogs.*/
474 if (!strcmp(cmdblk
->name
, "tstart") && !No_Update
)
476 Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_tstart");
477 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
479 else if (!strcmp(cmdblk
->name
, "tstop") && !No_Update
)
481 Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_tstop");
482 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
489 Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_busy");
490 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
493 Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_idle");
497 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
500 /* The next three functions use breakpoint_notify to allow the GUI
501 * to handle creating, deleting and modifying breakpoints. These three
502 * functions are put into the appropriate gdb hooks in gdbtk_init.
506 gdbtk_create_breakpoint(b
)
507 struct breakpoint
*b
;
509 breakpoint_notify (b
, "create");
513 gdbtk_delete_breakpoint(b
)
514 struct breakpoint
*b
;
516 breakpoint_notify (b
, "delete");
520 gdbtk_modify_breakpoint(b
)
521 struct breakpoint
*b
;
523 breakpoint_notify (b
, "modify");
526 /* This is the generic function for handling changes in
527 * a breakpoint. It routes the information to the Tcl
528 * command "gdbtk_tcl_breakpoint" in the form:
529 * gdbtk_tcl_breakpoint action b_number b_address b_line b_file
530 * On error, the error string is written to gdb_stdout.
534 breakpoint_notify(b
, action
)
535 struct breakpoint
*b
;
540 struct symtab_and_line sal
;
543 if (b
->type
!= bp_breakpoint
)
546 /* We ensure that ACTION contains no special Tcl characters, so we
548 sal
= find_pc_line (b
->address
, 0);
549 filename
= symtab_to_filename (sal
.symtab
);
550 if (filename
== NULL
)
553 sprintf (buf
, "gdbtk_tcl_breakpoint %s %d 0x%lx %d {%s} {%s} %d %d",
554 action
, b
->number
, (long)b
->address
, b
->line_number
, filename
,
555 bpdisp
[b
->disposition
], b
->enable
, b
->thread
);
557 v
= Tcl_Eval (gdbtk_interp
, buf
);
561 gdbtk_fputs (Tcl_GetStringResult (gdbtk_interp
), gdb_stdout
);
562 gdbtk_fputs ("\n", gdb_stdout
);
567 gdbtk_load_hash (section
, num
)
572 sprintf (buf
, "download_hash %s %ld", section
, num
);
573 Tcl_Eval (gdbtk_interp
, buf
);
574 return atoi (gdbtk_interp
->result
);
578 /* This hook is called whenever we are ready to load a symbol file so that
579 the UI can notify the user... */
581 gdbtk_pre_add_symbol (name
)
585 gdbtk_two_elem_cmd("gdbtk_tcl_pre_add_symbol", name
);
589 /* This hook is called whenever we finish loading a symbol file. */
591 gdbtk_post_add_symbol ()
593 Tcl_Eval (gdbtk_interp
, "gdbtk_tcl_post_add_symbol");
596 /* This hook function is called whenever we want to wait for the
600 gdbtk_wait (pid
, ourstatus
)
602 struct target_waitstatus
*ourstatus
;
604 /* Don't run the timer on various targets... */
605 if (!STREQ (target_shortname
, "ice"))
606 gdbtk_start_timer ();
607 pid
= target_wait (pid
, ourstatus
);
613 * This handles all queries from gdb.
614 * The first argument is a printf style format statement, the rest are its
615 * arguments. The resultant formatted string is passed to the Tcl function
617 * It returns the users response to the query, as well as putting the value
618 * in the result field of the Tcl interpreter.
622 gdbtk_query (query
, args
)
629 vsprintf (buf
, query
, args
);
630 gdbtk_two_elem_cmd ("gdbtk_tcl_query", buf
);
632 val
= atol (gdbtk_interp
->result
);
638 gdbtk_print_frame_info (s
, line
, stopline
, noerror
)
644 current_source_symtab
= s
;
645 current_source_line
= line
;
649 gdbtk_create_tracepoint (tp
)
650 struct tracepoint
*tp
;
652 tracepoint_notify (tp
, "create");
656 gdbtk_delete_tracepoint (tp
)
657 struct tracepoint
*tp
;
659 tracepoint_notify (tp
, "delete");
663 gdbtk_modify_tracepoint (tp
)
664 struct tracepoint
*tp
;
666 tracepoint_notify (tp
, "modify");
670 tracepoint_notify(tp
, action
)
671 struct tracepoint
*tp
;
676 struct symtab_and_line sal
;
679 /* We ensure that ACTION contains no special Tcl characters, so we
681 sal
= find_pc_line (tp
->address
, 0);
683 filename
= symtab_to_filename (sal
.symtab
);
684 if (filename
== NULL
)
686 sprintf (buf
, "gdbtk_tcl_tracepoint %s %d 0x%lx %d {%s} %d", action
, tp
->number
,
687 (long)tp
->address
, sal
.line
, filename
, tp
->pass_count
);
689 v
= Tcl_Eval (gdbtk_interp
, buf
);
693 gdbtk_fputs (gdbtk_interp
->result
, gdb_stdout
);
694 gdbtk_fputs ("\n", gdb_stdout
);
701 * This is run by the trace_find_command. arg is the argument that was passed
702 * to that command, from_tty is 1 if the command was run from a tty, 0 if it
703 * was run from a script. It runs gdbtk_tcl_tfind_hook passing on these two
709 gdbtk_trace_find (arg
, from_tty
)
715 Tcl_GlobalEval (gdbtk_interp
, "debug {***In gdbtk_trace_find...}");
716 cmdObj
= Tcl_NewListObj (0, NULL
);
717 Tcl_ListObjAppendElement (gdbtk_interp
, cmdObj
,
718 Tcl_NewStringObj ("gdbtk_tcl_trace_find_hook", -1));
719 Tcl_ListObjAppendElement (gdbtk_interp
, cmdObj
, Tcl_NewStringObj (arg
, -1));
720 Tcl_ListObjAppendElement (gdbtk_interp
, cmdObj
, Tcl_NewIntObj(from_tty
));
721 Tcl_GlobalEvalObj (gdbtk_interp
, cmdObj
);
726 gdbtk_selected_frame_changed (level
)
729 Tcl_UpdateLinkedVar (gdbtk_interp
, "gdb_selected_frame_level");
732 /* Called when the current thread changes. */
733 /* gdb_context is linked to the tcl variable "gdb_context_id" */
735 gdbtk_context_change (num
)
741 /* Called from file_command */
743 gdbtk_file_changed (filename
)
746 gdbtk_two_elem_cmd ("gdbtk_tcl_file_changed", filename
);
749 /* Called from exec_file_command */
751 gdbtk_exec_file_display (filename
)
754 gdbtk_two_elem_cmd ("gdbtk_tcl_exec_file_display", filename
);