* chexp.exp: fix tests that assume >16-bit ints.
[deliverable/binutils-gdb.git] / gdb / gdbtk.c
CommitLineData
4604b34c 1/* Tcl/Tk interface routines.
a5f4fbff 2 Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
4604b34c
SG
3
4 Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
754e5da2
SG
5
6This file is part of GDB.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
6c9638b4 20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
754e5da2
SG
21
22#include "defs.h"
23#include "symtab.h"
24#include "inferior.h"
25#include "command.h"
26#include "bfd.h"
27#include "symfile.h"
28#include "objfiles.h"
29#include "target.h"
018d76dd
KS
30#include "gdbcore.h"
31#include "tracepoint.h"
929db6e5 32#include "demangle.h"
018d76dd
KS
33
34#ifdef _WIN32
35#include <winuser.h>
36#endif
37
e6e9507d
EZ
38#include <sys/stat.h>
39
754e5da2
SG
40#include <tcl.h>
41#include <tk.h>
2476848a
MH
42#include <itcl.h>
43#include <tix.h>
dd3dd918 44#include "guitcl.h"
2476848a
MH
45
46#ifdef IDE
018d76dd 47/* start-sanitize-ide */
2476848a
MH
48#include "event.h"
49#include "idetcl.h"
018d76dd
KS
50#include "ilutk.h"
51/* end-sanitize-ide */
2476848a
MH
52#endif
53
73d3dbd4 54#ifdef ANSI_PROTOTYPES
85c613aa
C
55#include <stdarg.h>
56#else
cd2df226 57#include <varargs.h>
85c613aa 58#endif
cd2df226
SG
59#include <signal.h>
60#include <fcntl.h>
8532893d 61#include <unistd.h>
86db943c
SG
62#include <setjmp.h>
63#include "top.h"
736a82e7 64#include <sys/ioctl.h>
2b576293 65#include "gdb_string.h"
09722039 66#include "dis-asm.h"
6131622e
SG
67#include <stdio.h>
68#include "gdbcmd.h"
736a82e7 69
929db6e5 70#include "annotate.h"
018d76dd 71#include <sys/time.h>
018d76dd 72
8a19b35a
MH
73#ifdef WINNT
74#define GDBTK_PATH_SEP ";"
75#else
76#define GDBTK_PATH_SEP ":"
77#endif
754e5da2 78
8b3f9ed6 79/* Some versions (1.3.79, 1.3.81) of Linux don't support SIOCSPGRP the way
3f37b696 80 gdbtk wants to use it... */
8b3f9ed6
MM
81#ifdef __linux__
82#undef SIOCSPGRP
83#endif
84
94a6f14f
MH
85extern int Tktable_Init PARAMS ((Tcl_Interp *interp));
86
0b7148e4 87static int No_Update = 0;
0776b0b0 88static int load_in_progress = 0;
ed5fa7c3 89static int in_fputs = 0;
0776b0b0 90
018d76dd
KS
91int gdbtk_load_hash PARAMS ((char *, unsigned long));
92int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
11f91b2b
KS
93void (*pre_add_symbol_hook) PARAMS ((char *));
94void (*post_add_symbol_hook) PARAMS ((void));
018d76dd 95
21b3bc77
KS
96#ifdef __CYGWIN32__
97extern void (*ui_loop_hook) PARAMS ((int));
98#endif
99
929db6e5
EZ
100char * get_prompt PARAMS ((void));
101
b607efe7
FF
102static void null_routine PARAMS ((int));
103static void gdbtk_flush PARAMS ((FILE *));
104static void gdbtk_fputs PARAMS ((const char *, FILE *));
105static int gdbtk_query PARAMS ((const char *, va_list));
e6e9507d 106static void gdbtk_warning PARAMS ((const char *, va_list));
cb432079 107static void gdbtk_ignorable_warning PARAMS ((const char *));
b607efe7 108static char *gdbtk_readline PARAMS ((char *));
2476848a 109static void gdbtk_init PARAMS ((char *));
b607efe7
FF
110static void tk_command_loop PARAMS ((void));
111static void gdbtk_call_command PARAMS ((struct cmd_list_element *, char *, int));
112static int gdbtk_wait PARAMS ((int, struct target_waitstatus *));
113static void x_event PARAMS ((int));
114static void gdbtk_interactive PARAMS ((void));
115static void cleanup_init PARAMS ((int));
116static void tk_command PARAMS ((char *, int));
117static int gdb_disassemble PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
118static int compare_lines PARAMS ((const PTR, const PTR));
119static int gdbtk_dis_asm_read_memory PARAMS ((bfd_vma, bfd_byte *, int, disassemble_info *));
8a19b35a 120static int gdb_path_conv PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
b607efe7 121static int gdb_stop PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
018d76dd
KS
122static int gdb_confirm_quit PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
123static int gdb_force_quit PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
0776b0b0 124static int gdb_listfiles PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
99c98415 125static int gdb_listfuncs PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
b607efe7 126static int call_wrapper PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
ff62d310 127static int call_obj_wrapper PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
b607efe7 128static int gdb_cmd PARAMS ((ClientData, Tcl_Interp *, int, char *argv[]));
0422b59e 129static int gdb_immediate_command PARAMS ((ClientData, Tcl_Interp *, int, char *argv[]));
b607efe7
FF
130static int gdb_fetch_registers PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
131static void gdbtk_readline_end PARAMS ((void));
929db6e5 132static void pc_changed PARAMS ((void));
b607efe7
FF
133static int gdb_changed_register_list PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
134static void register_changed_p PARAMS ((int, void *));
135static int gdb_get_breakpoint_list PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
136static int gdb_get_breakpoint_info PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
137static void breakpoint_notify PARAMS ((struct breakpoint *, const char *));
138static void gdbtk_create_breakpoint PARAMS ((struct breakpoint *));
139static void gdbtk_delete_breakpoint PARAMS ((struct breakpoint *));
140static void gdbtk_modify_breakpoint PARAMS ((struct breakpoint *));
141static int gdb_loc PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
142static int gdb_eval PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
b607efe7
FF
143static int map_arg_registers PARAMS ((int, char *[], void (*) (int, void *), void *));
144static void get_register_name PARAMS ((int, void *));
145static int gdb_regnames PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
146static void get_register PARAMS ((int, void *));
41158958 147static int gdb_trace_status PARAMS ((ClientData, Tcl_Interp *, int, char *argv[]));
018d76dd
KS
148static int gdb_target_has_execution_command PARAMS ((ClientData, Tcl_Interp *, int, char *argv[]));
149static int gdb_load_info PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
0776b0b0 150void TclDebug PARAMS ((const char *fmt, ...));
b33b741a
JI
151static int gdb_get_locals_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST
152 objv[]));
153static int gdb_get_args_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST
154 objv[]));
018d76dd
KS
155static int gdb_get_vars_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
156static int gdb_get_function_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
157static int gdb_get_line_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
158static int gdb_get_file_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
159static int gdb_tracepoint_exists_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
160static int gdb_get_tracepoint_info PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
161static int gdb_actions_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
162static int gdb_prompt_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
e0f7db02 163static int gdb_find_file_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
4f17e6eb 164static int gdb_get_tracepoint_list PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
018d76dd
KS
165static void gdbtk_create_tracepoint PARAMS ((struct tracepoint *));
166static void gdbtk_delete_tracepoint PARAMS ((struct tracepoint *));
a5f4fbff 167static void gdbtk_modify_tracepoint PARAMS ((struct tracepoint *));
018d76dd 168static void tracepoint_notify PARAMS ((struct tracepoint *, const char *));
a5f4fbff 169static void gdbtk_print_frame_info PARAMS ((struct symtab *, int, int, int));
11f91b2b
KS
170void gdbtk_pre_add_symbol PARAMS ((char *));
171void gdbtk_post_add_symbol PARAMS ((void));
929db6e5
EZ
172static int get_pc_register PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
173static int gdb_loadfile PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
174static int gdb_set_bp PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
175static struct symtab *full_lookup_symtab PARAMS ((char *file));
176static int gdb_get_mem PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
fed03c01 177static int gdb_get_trace_frame_num PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
b607efe7 178
754e5da2
SG
179/* Handle for TCL interpreter */
180static Tcl_Interp *interp = NULL;
181
0776b0b0 182static int gdbtk_timer_going = 0;
0776b0b0
MH
183static void gdbtk_start_timer PARAMS ((void));
184static void gdbtk_stop_timer PARAMS ((void));
185
fda6fadc
SS
186/* This variable is true when the inferior is running. Although it's
187 possible to disable most input from widgets and thus prevent
188 attempts to do anything while the inferior is running, any commands
189 that get through - even a simple memory read - are Very Bad, and
190 may cause GDB to crash or behave strangely. So, this variable
191 provides an extra layer of defense. */
09722039 192
fda6fadc
SS
193static int running_now;
194
195/* This variable determines where memory used for disassembly is read from.
196 If > 0, then disassembly comes from the exec file rather than the
197 target (which might be at the other end of a slow serial link). If
198 == 0 then disassembly comes from target. If < 0 disassembly is
199 automatically switched to the target if it's an inferior process,
200 otherwise the exec file is used. */
09722039
SG
201
202static int disassemble_from_exec = -1;
203
9b119644
ILT
204#ifndef _WIN32
205
206/* Supply malloc calls for tcl/tk. We do not want to do this on
207 Windows, because Tcl_Alloc is probably in a DLL which will not call
208 the mmalloc routines. */
8c19daa1
SG
209
210char *
a5a6e3bd 211Tcl_Alloc (size)
8c19daa1
SG
212 unsigned int size;
213{
214 return xmalloc (size);
215}
216
217char *
218Tcl_Realloc (ptr, size)
219 char *ptr;
220 unsigned int size;
221{
222 return xrealloc (ptr, size);
223}
224
225void
226Tcl_Free(ptr)
227 char *ptr;
228{
229 free (ptr);
230}
231
018d76dd 232#endif /* ! _WIN32 */
9b119644 233
754e5da2
SG
234static void
235null_routine(arg)
236 int arg;
237{
238}
239
018d76dd
KS
240#ifdef _WIN32
241
242/* On Windows, if we hold a file open, other programs can't write to
243 it. In particular, we don't want to hold the executable open,
244 because it will mean that people have to get out of the debugging
245 session in order to remake their program. So we close it, although
246 this will cost us if and when we need to reopen it. */
247
248static void
249close_bfds ()
250{
251 struct objfile *o;
252
253 ALL_OBJFILES (o)
254 {
255 if (o->obfd != NULL)
256 bfd_cache_close (o->obfd);
257 }
258
259 if (exec_bfd != NULL)
260 bfd_cache_close (exec_bfd);
261}
262
263#endif /* _WIN32 */
264
546b8ca7
SG
265/* The following routines deal with stdout/stderr data, which is created by
266 {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
267 lowest level of these routines and capture all output from the rest of GDB.
268 Normally they present their data to tcl via callbacks to the following tcl
269 routines: gdbtk_tcl_fputs, gdbtk_tcl_fputs_error, and gdbtk_flush. These
270 in turn call tk routines to update the display.
86db943c 271
546b8ca7
SG
272 Under some circumstances, you may want to collect the output so that it can
273 be returned as the value of a tcl procedure. This can be done by
274 surrounding the output routines with calls to start_saving_output and
275 finish_saving_output. The saved data can then be retrieved with
276 get_saved_output (but this must be done before the call to
277 finish_saving_output). */
86db943c 278
018d76dd 279/* Dynamic string for output. */
86db943c 280
6131622e 281static Tcl_DString *result_ptr;
018d76dd
KS
282
283/* Dynamic string for stderr. This is only used if result_ptr is
284 NULL. */
285
286static Tcl_DString *error_string_ptr;
754e5da2 287\f
754e5da2
SG
288static void
289gdbtk_flush (stream)
290 FILE *stream;
291{
6131622e 292#if 0
86db943c
SG
293 /* Force immediate screen update */
294
754e5da2 295 Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
6131622e 296#endif
754e5da2
SG
297}
298
fed03c01
EZ
299/* Print the string PTR, with necessary hair for dealing with the
300 GDB console thingy, etc. To wit:
301
302 Append the string PTR to result_ptr or error_string_ptr, if they
303 are set. Otherwise, call the Tcl function `gdbtk_tcl_fputs', with
304 the string PTR as its only argument. */
8532893d 305static void
86db943c 306gdbtk_fputs (ptr, stream)
8532893d 307 const char *ptr;
86db943c 308 FILE *stream;
8532893d 309{
ed5fa7c3
MH
310 char *merge[2], *command;
311 in_fputs = 1;
312
6131622e 313 if (result_ptr)
ff62d310 314 Tcl_DStringAppend (result_ptr, (char *) ptr, -1);
018d76dd
KS
315 else if (error_string_ptr != NULL && stream == gdb_stderr)
316 Tcl_DStringAppend (error_string_ptr, (char *) ptr, -1);
6131622e 317 else
86db943c 318 {
ed5fa7c3
MH
319 merge[0] = "gdbtk_tcl_fputs";
320 merge[1] = (char *)ptr;
321 command = Tcl_Merge (2, merge);
322 Tcl_Eval (interp, command);
323 Tcl_Free (command);
6131622e 324 }
ed5fa7c3 325 in_fputs = 0;
8532893d
SG
326}
327
e6e9507d
EZ
328static void
329gdbtk_warning (warning, args)
330 const char *warning;
331 va_list args;
332{
333 char buf[200], *merge[2];
334 char *command;
335
336 vsprintf (buf, warning, args);
337 merge[0] = "gdbtk_tcl_warning";
338 merge[1] = buf;
339 command = Tcl_Merge (2, merge);
340 Tcl_Eval (interp, command);
341 Tcl_Free (command);
342}
343
344static void
cb432079 345gdbtk_ignorable_warning (warning)
e6e9507d 346 const char *warning;
e6e9507d
EZ
347{
348 char buf[200], *merge[2];
349 char *command;
350
cb432079 351 sprintf (buf, warning);
e6e9507d
EZ
352 merge[0] = "gdbtk_tcl_ignorable_warning";
353 merge[1] = buf;
354 command = Tcl_Merge (2, merge);
355 Tcl_Eval (interp, command);
356 Tcl_Free (command);
357}
358
754e5da2 359static int
85c613aa 360gdbtk_query (query, args)
b607efe7 361 const char *query;
754e5da2
SG
362 va_list args;
363{
4e327047
TT
364 char buf[200], *merge[2];
365 char *command;
754e5da2
SG
366 long val;
367
6131622e 368 vsprintf (buf, query, args);
4e327047
TT
369 merge[0] = "gdbtk_tcl_query";
370 merge[1] = buf;
371 command = Tcl_Merge (2, merge);
372 Tcl_Eval (interp, command);
018d76dd 373 Tcl_Free (command);
e6e9507d 374
754e5da2
SG
375 val = atol (interp->result);
376 return val;
377}
41756e56
FF
378
379/* VARARGS */
380static void
381#ifdef ANSI_PROTOTYPES
382gdbtk_readline_begin (char *format, ...)
383#else
384gdbtk_readline_begin (va_alist)
385 va_dcl
386#endif
387{
388 va_list args;
389 char buf[200], *merge[2];
390 char *command;
391
392#ifdef ANSI_PROTOTYPES
393 va_start (args, format);
394#else
395 char *format;
396 va_start (args);
397 format = va_arg (args, char *);
398#endif
399
400 vsprintf (buf, format, args);
401 merge[0] = "gdbtk_tcl_readline_begin";
402 merge[1] = buf;
403 command = Tcl_Merge (2, merge);
404 Tcl_Eval (interp, command);
929db6e5 405 Tcl_Free (command);
41756e56
FF
406}
407
408static char *
409gdbtk_readline (prompt)
410 char *prompt;
411{
412 char *merge[2];
413 char *command;
bd45f82f 414 int result;
41756e56 415
018d76dd
KS
416#ifdef _WIN32
417 close_bfds ();
418#endif
419
41756e56
FF
420 merge[0] = "gdbtk_tcl_readline";
421 merge[1] = prompt;
422 command = Tcl_Merge (2, merge);
bd45f82f 423 result = Tcl_Eval (interp, command);
929db6e5 424 Tcl_Free (command);
bd45f82f 425 if (result == TCL_OK)
41756e56
FF
426 {
427 return (strdup (interp -> result));
428 }
429 else
430 {
431 gdbtk_fputs (interp -> result, gdb_stdout);
432 gdbtk_fputs ("\n", gdb_stdout);
433 return (NULL);
434 }
435}
436
437static void
438gdbtk_readline_end ()
439{
440 Tcl_Eval (interp, "gdbtk_tcl_readline_end");
441}
442
929db6e5
EZ
443static void
444pc_changed()
445{
446 Tcl_Eval (interp, "gdbtk_pc_changed");
447}
448
754e5da2 449\f
6131622e 450static void
73d3dbd4 451#ifdef ANSI_PROTOTYPES
85c613aa
C
452dsprintf_append_element (Tcl_DString *dsp, char *format, ...)
453#else
6131622e
SG
454dsprintf_append_element (va_alist)
455 va_dcl
85c613aa 456#endif
6131622e
SG
457{
458 va_list args;
85c613aa
C
459 char buf[1024];
460
73d3dbd4 461#ifdef ANSI_PROTOTYPES
85c613aa
C
462 va_start (args, format);
463#else
6131622e
SG
464 Tcl_DString *dsp;
465 char *format;
6131622e
SG
466
467 va_start (args);
6131622e
SG
468 dsp = va_arg (args, Tcl_DString *);
469 format = va_arg (args, char *);
85c613aa 470#endif
6131622e
SG
471
472 vsprintf (buf, format, args);
473
474 Tcl_DStringAppendElement (dsp, buf);
475}
476
8a19b35a
MH
477static int
478gdb_path_conv (clientData, interp, argc, argv)
479 ClientData clientData;
480 Tcl_Interp *interp;
481 int argc;
482 char *argv[];
483{
484#ifdef WINNT
485 char pathname[256], *ptr;
486 if (argc != 2)
487 error ("wrong # args");
488 cygwin32_conv_to_full_win32_path (argv[1], pathname);
489 for (ptr = pathname; *ptr; ptr++)
490 {
491 if (*ptr == '\\')
492 *ptr = '/';
493 }
494#else
495 char *pathname = argv[1];
496#endif
497 Tcl_DStringAppend (result_ptr, pathname, strlen(pathname));
498 return TCL_OK;
499}
500
6131622e
SG
501static int
502gdb_get_breakpoint_list (clientData, interp, argc, argv)
503 ClientData clientData;
504 Tcl_Interp *interp;
505 int argc;
506 char *argv[];
507{
508 struct breakpoint *b;
509 extern struct breakpoint *breakpoint_chain;
510
511 if (argc != 1)
512 error ("wrong # args");
513
514 for (b = breakpoint_chain; b; b = b->next)
515 if (b->type == bp_breakpoint)
516 dsprintf_append_element (result_ptr, "%d", b->number);
517
518 return TCL_OK;
519}
520
521static int
522gdb_get_breakpoint_info (clientData, interp, argc, argv)
523 ClientData clientData;
524 Tcl_Interp *interp;
525 int argc;
526 char *argv[];
527{
528 struct symtab_and_line sal;
529 static char *bptypes[] = {"breakpoint", "hardware breakpoint", "until",
530 "finish", "watchpoint", "hardware watchpoint",
531 "read watchpoint", "access watchpoint",
532 "longjmp", "longjmp resume", "step resume",
533 "through sigtramp", "watchpoint scope",
534 "call dummy" };
27f1958c 535 static char *bpdisp[] = {"delete", "delstop", "disable", "donttouch"};
6131622e
SG
536 struct command_line *cmd;
537 int bpnum;
538 struct breakpoint *b;
539 extern struct breakpoint *breakpoint_chain;
929db6e5
EZ
540 char *funcname, *fname, *filename;
541
6131622e
SG
542 if (argc != 2)
543 error ("wrong # args");
544
545 bpnum = atoi (argv[1]);
546
547 for (b = breakpoint_chain; b; b = b->next)
548 if (b->number == bpnum)
549 break;
550
9468f8aa 551 if (!b || b->type != bp_breakpoint)
6131622e
SG
552 error ("Breakpoint #%d does not exist", bpnum);
553
6131622e
SG
554 sal = find_pc_line (b->address, 0);
555
6c3908db
KS
556 filename = symtab_to_filename (sal.symtab);
557 if (filename == NULL)
11f91b2b 558 filename = "";
84f71d63 559 Tcl_DStringAppendElement (result_ptr, filename);
929db6e5 560
018d76dd 561 find_pc_partial_function (b->address, &funcname, NULL, NULL);
929db6e5
EZ
562 fname = cplus_demangle (funcname, 0);
563 if (fname)
564 {
565 Tcl_DStringAppendElement (result_ptr, fname);
566 free (fname);
567 }
568 else
569 Tcl_DStringAppendElement (result_ptr, funcname);
570 dsprintf_append_element (result_ptr, "%d", b->line_number);
6131622e
SG
571 dsprintf_append_element (result_ptr, "0x%lx", b->address);
572 Tcl_DStringAppendElement (result_ptr, bptypes[b->type]);
573 Tcl_DStringAppendElement (result_ptr, b->enable == enabled ? "1" : "0");
574 Tcl_DStringAppendElement (result_ptr, bpdisp[b->disposition]);
6131622e
SG
575 dsprintf_append_element (result_ptr, "%d", b->ignore_count);
576
577 Tcl_DStringStartSublist (result_ptr);
578 for (cmd = b->commands; cmd; cmd = cmd->next)
579 Tcl_DStringAppendElement (result_ptr, cmd->line);
580 Tcl_DStringEndSublist (result_ptr);
581
582 Tcl_DStringAppendElement (result_ptr, b->cond_string);
583
584 dsprintf_append_element (result_ptr, "%d", b->thread);
585 dsprintf_append_element (result_ptr, "%d", b->hit_count);
586
587 return TCL_OK;
588}
589
754e5da2
SG
590static void
591breakpoint_notify(b, action)
592 struct breakpoint *b;
593 const char *action;
594{
32707df8 595 char buf[256];
754e5da2 596 int v;
2476848a 597 struct symtab_and_line sal;
6c3908db 598 char *filename;
754e5da2
SG
599
600 if (b->type != bp_breakpoint)
601 return;
602
4e327047
TT
603 /* We ensure that ACTION contains no special Tcl characters, so we
604 can do this. */
2476848a 605 sal = find_pc_line (b->address, 0);
6c3908db
KS
606 filename = symtab_to_filename (sal.symtab);
607 if (filename == NULL)
929db6e5
EZ
608 filename = "";
609
2476848a 610 sprintf (buf, "gdbtk_tcl_breakpoint %s %d 0x%lx %d {%s}", action, b->number,
929db6e5 611 (long)b->address, b->line_number, filename);
754e5da2 612
6131622e 613 v = Tcl_Eval (interp, buf);
754e5da2
SG
614
615 if (v != TCL_OK)
616 {
546b8ca7
SG
617 gdbtk_fputs (interp->result, gdb_stdout);
618 gdbtk_fputs ("\n", gdb_stdout);
754e5da2 619 }
754e5da2
SG
620}
621
622static void
623gdbtk_create_breakpoint(b)
624 struct breakpoint *b;
625{
6131622e 626 breakpoint_notify (b, "create");
754e5da2
SG
627}
628
629static void
630gdbtk_delete_breakpoint(b)
631 struct breakpoint *b;
632{
6131622e 633 breakpoint_notify (b, "delete");
754e5da2
SG
634}
635
636static void
6131622e 637gdbtk_modify_breakpoint(b)
754e5da2
SG
638 struct breakpoint *b;
639{
6131622e 640 breakpoint_notify (b, "modify");
754e5da2
SG
641}
642\f
929db6e5
EZ
643/* This implements the TCL command `gdb_loc', which returns a list */
644/* consisting of the following: */
645/* basename, function name, filename, line number, address, current pc */
754e5da2
SG
646
647static int
648gdb_loc (clientData, interp, argc, argv)
649 ClientData clientData;
650 Tcl_Interp *interp;
651 int argc;
652 char *argv[];
653{
654 char *filename;
754e5da2 655 struct symtab_and_line sal;
929db6e5 656 char *funcname, *fname;
8532893d 657 CORE_ADDR pc;
754e5da2 658
018d76dd
KS
659 if (!have_full_symbols () && !have_partial_symbols ())
660 {
661 Tcl_SetResult (interp, "No symbol table is loaded", TCL_STATIC);
662 return TCL_ERROR;
663 }
929db6e5 664
754e5da2
SG
665 if (argc == 1)
666 {
929db6e5 667 if (selected_frame && (selected_frame->pc != stop_pc))
0776b0b0 668 {
929db6e5
EZ
669 /* Note - this next line is not correct on all architectures. */
670 /* For a graphical debugged we really want to highlight the */
671 /* assembly line that called the next function on the stack. */
672 /* Many architectures have the next instruction saved as the */
673 /* pc on the stack, so what happens is the next instruction is hughlighted. */
674 /* FIXME */
675 pc = selected_frame->pc;
0776b0b0
MH
676 sal = find_pc_line (selected_frame->pc,
677 selected_frame->next != NULL
678 && !selected_frame->next->signal_handler_caller
679 && !frame_in_dummy (selected_frame->next));
680 }
681 else
929db6e5
EZ
682 {
683 pc = stop_pc;
684 sal = find_pc_line (stop_pc, 0);
685 }
754e5da2
SG
686 }
687 else if (argc == 2)
688 {
754e5da2 689 struct symtabs_and_lines sals;
8532893d 690 int nelts;
754e5da2
SG
691
692 sals = decode_line_spec (argv[1], 1);
693
8532893d
SG
694 nelts = sals.nelts;
695 sal = sals.sals[0];
696 free (sals.sals);
697
754e5da2 698 if (sals.nelts != 1)
6131622e 699 error ("Ambiguous line spec");
ed5fa7c3
MH
700
701 pc = sal.pc;
754e5da2
SG
702 }
703 else
6131622e 704 error ("wrong # args");
754e5da2 705
754e5da2 706 if (sal.symtab)
6131622e 707 Tcl_DStringAppendElement (result_ptr, sal.symtab->filename);
754e5da2 708 else
6131622e 709 Tcl_DStringAppendElement (result_ptr, "");
8532893d
SG
710
711 find_pc_partial_function (pc, &funcname, NULL, NULL);
929db6e5
EZ
712 fname = cplus_demangle (funcname, 0);
713 if (fname)
714 {
715 Tcl_DStringAppendElement (result_ptr, fname);
716 free (fname);
717 }
718 else
719 Tcl_DStringAppendElement (result_ptr, funcname);
637b1661 720 filename = symtab_to_filename (sal.symtab);
6c3908db 721 if (filename == NULL)
929db6e5 722 filename = "";
8532893d 723
0776b0b0 724 Tcl_DStringAppendElement (result_ptr, filename);
9468f8aa 725 dsprintf_append_element (result_ptr, "%d", sal.line); /* line number */
2476848a 726 dsprintf_append_element (result_ptr, "0x%s", paddr_nz(pc)); /* PC in current frame */
2476848a 727 dsprintf_append_element (result_ptr, "0x%s", paddr_nz(stop_pc)); /* Real PC */
754e5da2
SG
728 return TCL_OK;
729}
730\f
09722039
SG
731/* This implements the TCL command `gdb_eval'. */
732
733static int
734gdb_eval (clientData, interp, argc, argv)
735 ClientData clientData;
736 Tcl_Interp *interp;
737 int argc;
738 char *argv[];
739{
740 struct expression *expr;
741 struct cleanup *old_chain;
742 value_ptr val;
743
744 if (argc != 2)
6131622e 745 error ("wrong # args");
09722039
SG
746
747 expr = parse_expression (argv[1]);
748
749 old_chain = make_cleanup (free_current_contents, &expr);
750
751 val = evaluate_expression (expr);
752
09722039
SG
753 val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val),
754 gdb_stdout, 0, 0, 0, 0);
09722039
SG
755
756 do_cleanups (old_chain);
757
758 return TCL_OK;
759}
018d76dd
KS
760
761/* gdb_get_mem addr form size num aschar*/
762/* dump a block of memory */
763/* addr: address of data to dump */
764/* form: a char indicating format */
765/* size: size of each element; 1,2,4, or 8 bytes*/
ac3dff67
EZ
766/* num: the number of bytes to read */
767/* acshar: an optional ascii character to use in ASCII dump */
768/* returns a list of elements followed by an optional */
018d76dd 769/* ASCII dump */
ac3dff67 770
018d76dd
KS
771static int
772gdb_get_mem (clientData, interp, argc, argv)
773 ClientData clientData;
774 Tcl_Interp *interp;
775 int argc;
776 char *argv[];
777{
ac3dff67
EZ
778 int size, asize, i, j, bc;
779 CORE_ADDR addr;
780 int nbytes, rnum, bpr;
781 char format, c, *ptr, buff[128], aschar, *mbuf, *mptr, *cptr, *bptr;
018d76dd 782 struct type *val_type;
018d76dd 783
ac3dff67
EZ
784 if (argc < 6 || argc > 7)
785 {
786 interp->result = "addr format size bytes bytes_per_row ?ascii_char?";
787 return TCL_ERROR;
788 }
789
790 size = (int)strtoul(argv[3],(char **)NULL,0);
791 nbytes = (int)strtoul(argv[4],(char **)NULL,0);
792 bpr = (int)strtoul(argv[5],(char **)NULL,0);
793 if (nbytes <= 0 || bpr <= 0 || size <= 0)
794 {
795 interp->result = "Invalid number of bytes.";
796 return TCL_ERROR;
797 }
018d76dd
KS
798
799 addr = (CORE_ADDR)strtoul(argv[1],(char **)NULL,0);
018d76dd 800 format = *argv[2];
ac3dff67
EZ
801 mbuf = (char *)malloc (nbytes+32);
802 if (!mbuf)
803 {
804 interp->result = "Out of memory.";
805 return TCL_ERROR;
806 }
807 memset (mbuf, 0, nbytes+32);
808 mptr = cptr = mbuf;
809
810 rnum = target_read_memory_partial (addr, mbuf, nbytes, NULL);
811
812 if (argv[6])
813 aschar = *argv[6];
814 else
815 aschar = 0;
018d76dd
KS
816
817 switch (size) {
818 case 1:
819 val_type = builtin_type_char;
820 asize = 'b';
821 break;
822 case 2:
823 val_type = builtin_type_short;
824 asize = 'h';
825 break;
826 case 4:
827 val_type = builtin_type_int;
828 asize = 'w';
829 break;
830 case 8:
831 val_type = builtin_type_long_long;
832 asize = 'g';
833 break;
834 default:
835 val_type = builtin_type_char;
836 asize = 'b';
837 }
838
ac3dff67
EZ
839 bc = 0; /* count of bytes in a row */
840 buff[0] = '"'; /* buffer for ascii dump */
841 bptr = &buff[1]; /* pointer for ascii dump */
842
843 for (i=0; i < nbytes; i+= size)
018d76dd 844 {
ac3dff67
EZ
845 if ( i >= rnum)
846 {
847 fputs_unfiltered ("N/A ", gdb_stdout);
848 if (aschar)
849 for ( j = 0; j < size; j++)
850 *bptr++ = 'X';
851 }
852 else
853 {
854 print_scalar_formatted (mptr, val_type, format, asize, gdb_stdout);
855 fputs_unfiltered (" ", gdb_stdout);
856 if (aschar)
857 {
858 for ( j = 0; j < size; j++)
859 {
860 c = *cptr++;
861 if (c < 32 || c > 126)
862 c = aschar;
863 if (c == '"')
864 *bptr++ = '\\';
865 *bptr++ = c;
866 }
867 }
868 }
018d76dd 869
ac3dff67
EZ
870 mptr += size;
871 bc += size;
872
873 if (aschar && (bc >= bpr))
018d76dd 874 {
ac3dff67
EZ
875 /* end of row. print it and reset variables */
876 bc = 0;
877 *bptr++ = '"';
878 *bptr++ = ' ';
879 *bptr = 0;
880 fputs_unfiltered (buff, gdb_stdout);
881 bptr = &buff[1];
018d76dd 882 }
018d76dd 883 }
ac3dff67
EZ
884
885 free (mbuf);
018d76dd
KS
886 return TCL_OK;
887}
888
746d1df4
SG
889static int
890map_arg_registers (argc, argv, func, argp)
891 int argc;
892 char *argv[];
6131622e 893 void (*func) PARAMS ((int regnum, void *argp));
746d1df4
SG
894 void *argp;
895{
896 int regnum;
897
898 /* Note that the test for a valid register must include checking the
899 reg_names array because NUM_REGS may be allocated for the union of the
900 register sets within a family of related processors. In this case, the
901 trailing entries of reg_names will change depending upon the particular
902 processor being debugged. */
903
904 if (argc == 0) /* No args, just do all the regs */
905 {
906 for (regnum = 0;
907 regnum < NUM_REGS
908 && reg_names[regnum] != NULL
909 && *reg_names[regnum] != '\000';
910 regnum++)
911 func (regnum, argp);
912
913 return TCL_OK;
914 }
915
916 /* Else, list of register #s, just do listed regs */
917 for (; argc > 0; argc--, argv++)
918 {
919 regnum = atoi (*argv);
920
921 if (regnum >= 0
922 && regnum < NUM_REGS
923 && reg_names[regnum] != NULL
924 && *reg_names[regnum] != '\000')
925 func (regnum, argp);
926 else
6131622e 927 error ("bad register number");
746d1df4
SG
928 }
929
930 return TCL_OK;
931}
932
6131622e 933static void
746d1df4
SG
934get_register_name (regnum, argp)
935 int regnum;
936 void *argp; /* Ignored */
937{
6131622e 938 Tcl_DStringAppendElement (result_ptr, reg_names[regnum]);
746d1df4
SG
939}
940
5b21fb68
SG
941/* This implements the TCL command `gdb_regnames', which returns a list of
942 all of the register names. */
943
944static int
945gdb_regnames (clientData, interp, argc, argv)
946 ClientData clientData;
947 Tcl_Interp *interp;
948 int argc;
949 char *argv[];
950{
746d1df4
SG
951 argc--;
952 argv++;
953
b607efe7 954 return map_arg_registers (argc, argv, get_register_name, NULL);
746d1df4
SG
955}
956
746d1df4
SG
957#ifndef REGISTER_CONVERTIBLE
958#define REGISTER_CONVERTIBLE(x) (0 != 0)
959#endif
960
961#ifndef REGISTER_CONVERT_TO_VIRTUAL
962#define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a)
963#endif
964
965#ifndef INVALID_FLOAT
966#define INVALID_FLOAT(x, y) (0 != 0)
967#endif
968
6131622e 969static void
746d1df4 970get_register (regnum, fp)
6131622e 971 int regnum;
746d1df4
SG
972 void *fp;
973{
974 char raw_buffer[MAX_REGISTER_RAW_SIZE];
975 char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
976 int format = (int)fp;
977
929db6e5
EZ
978 if (format == 'N')
979 format = 0;
980
746d1df4
SG
981 if (read_relative_register_raw_bytes (regnum, raw_buffer))
982 {
6131622e 983 Tcl_DStringAppendElement (result_ptr, "Optimized out");
746d1df4
SG
984 return;
985 }
986
746d1df4
SG
987 /* Convert raw data to virtual format if necessary. */
988
989 if (REGISTER_CONVERTIBLE (regnum))
990 {
991 REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
992 raw_buffer, virtual_buffer);
993 }
994 else
995 memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
996
3d9f68c0
FF
997 if (format == 'r')
998 {
999 int j;
1000 printf_filtered ("0x");
1001 for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++)
1002 {
1003 register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
1004 : REGISTER_RAW_SIZE (regnum) - 1 - j;
1005 printf_filtered ("%02x", (unsigned char)raw_buffer[idx]);
1006 }
1007 }
1008 else
1009 val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
1010 gdb_stdout, format, 1, 0, Val_pretty_default);
746d1df4 1011
6131622e 1012 Tcl_DStringAppend (result_ptr, " ", -1);
746d1df4
SG
1013}
1014
929db6e5
EZ
1015static int
1016get_pc_register (clientData, interp, argc, argv)
1017 ClientData clientData;
1018 Tcl_Interp *interp;
1019 int argc;
1020 char *argv[];
1021{
1022 sprintf(interp->result,"0x%llx",(long long)read_register(PC_REGNUM));
1023 return TCL_OK;
1024}
1025
746d1df4
SG
1026static int
1027gdb_fetch_registers (clientData, interp, argc, argv)
1028 ClientData clientData;
1029 Tcl_Interp *interp;
1030 int argc;
1031 char *argv[];
1032{
1033 int format;
1034
1035 if (argc < 2)
6131622e 1036 error ("wrong # args");
5b21fb68 1037
929db6e5 1038 argc -= 2;
746d1df4 1039 argv++;
746d1df4 1040 format = **argv++;
929db6e5 1041
b607efe7 1042 return map_arg_registers (argc, argv, get_register, (void *) format);
746d1df4
SG
1043}
1044
1045/* This contains the previous values of the registers, since the last call to
1046 gdb_changed_register_list. */
1047
1048static char old_regs[REGISTER_BYTES];
1049
6131622e 1050static void
746d1df4 1051register_changed_p (regnum, argp)
6131622e 1052 int regnum;
746d1df4
SG
1053 void *argp; /* Ignored */
1054{
1055 char raw_buffer[MAX_REGISTER_RAW_SIZE];
746d1df4
SG
1056
1057 if (read_relative_register_raw_bytes (regnum, raw_buffer))
1058 return;
1059
1060 if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
1061 REGISTER_RAW_SIZE (regnum)) == 0)
1062 return;
1063
fda6fadc 1064 /* Found a changed register. Save new value and return its number. */
746d1df4
SG
1065
1066 memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
1067 REGISTER_RAW_SIZE (regnum));
1068
9468f8aa 1069 dsprintf_append_element (result_ptr, "%d", regnum);
746d1df4
SG
1070}
1071
1072static int
1073gdb_changed_register_list (clientData, interp, argc, argv)
1074 ClientData clientData;
1075 Tcl_Interp *interp;
1076 int argc;
1077 char *argv[];
1078{
746d1df4
SG
1079 argc--;
1080 argv++;
1081
1082 return map_arg_registers (argc, argv, register_changed_p, NULL);
5b21fb68
SG
1083}
1084\f
0422b59e
KS
1085/* This implements the tcl command "gdb_immediate", which does exactly
1086 the same thing as gdb_cmd, except NONE of its outut is buffered. */
4350602f
KS
1087/* This will also ALWAYS cause the busy,update, and idle hooks to be
1088 called, contrasted with gdb_cmd, which NEVER calls them. */
0422b59e
KS
1089static int
1090gdb_immediate_command (clientData, interp, argc, argv)
1091 ClientData clientData;
1092 Tcl_Interp *interp;
1093 int argc;
1094 char *argv[];
1095{
1096 Tcl_DString *save_ptr = NULL;
1097
1098 if (argc != 2)
1099 error ("wrong # args");
1100
ed5fa7c3 1101 if (running_now || load_in_progress)
0422b59e
KS
1102 return TCL_OK;
1103
0b7148e4
KS
1104 No_Update = 0;
1105
0422b59e
KS
1106 Tcl_DStringAppend (result_ptr, "", -1);
1107 save_ptr = result_ptr;
1108 result_ptr = NULL;
1109
1110 execute_command (argv[1], 1);
1111
1112 bpstat_do_actions (&stop_bpstat);
1113
1114 result_ptr = save_ptr;
1115
1116 return TCL_OK;
1117}
1118
fda6fadc 1119/* This implements the TCL command `gdb_cmd', which sends its argument into
754e5da2 1120 the GDB command scanner. */
4350602f
KS
1121/* This command will never cause the update, idle and busy hooks to be called
1122 within the GUI. */
754e5da2
SG
1123static int
1124gdb_cmd (clientData, interp, argc, argv)
1125 ClientData clientData;
1126 Tcl_Interp *interp;
1127 int argc;
1128 char *argv[];
1129{
018d76dd
KS
1130 Tcl_DString *save_ptr = NULL;
1131
0b7148e4 1132 if (argc < 2)
6131622e 1133 error ("wrong # args");
754e5da2 1134
ed5fa7c3 1135 if (running_now || load_in_progress)
fda6fadc
SS
1136 return TCL_OK;
1137
4350602f 1138 No_Update = 1;
0b7148e4 1139
018d76dd
KS
1140 /* for the load instruction (and possibly others later) we
1141 set result_ptr to NULL so gdbtk_fputs() will not buffer
1142 all the data until the command is finished. */
1143
4f17e6eb
KS
1144 if (strncmp ("load ", argv[1], 5) == 0
1145 || strncmp ("while ", argv[1], 6) == 0)
1146 {
1147 Tcl_DStringAppend (result_ptr, "", -1);
1148 save_ptr = result_ptr;
1149 result_ptr = NULL;
0776b0b0 1150 load_in_progress = 1;
0776b0b0 1151 gdbtk_start_timer ();
4f17e6eb 1152 }
018d76dd 1153
86db943c 1154 execute_command (argv[1], 1);
479f0f18 1155
0776b0b0 1156 if (load_in_progress)
7234efcb
KS
1157 {
1158 gdbtk_stop_timer ();
1159 load_in_progress = 0;
1160 }
0776b0b0 1161
754e5da2 1162 bpstat_do_actions (&stop_bpstat);
018d76dd
KS
1163
1164 if (save_ptr)
1165 result_ptr = save_ptr;
754e5da2 1166
754e5da2
SG
1167 return TCL_OK;
1168}
1169
c14cabba
AC
1170/* Client of call_wrapper - this routine performs the actual call to
1171 the client function. */
1172
1173struct wrapped_call_args
1174{
1175 Tcl_Interp *interp;
1176 Tcl_CmdProc *func;
1177 int argc;
1178 char **argv;
1179 int val;
1180};
1181
1182static int
1183wrapped_call (args)
1184 struct wrapped_call_args *args;
1185{
1186 args->val = (*args->func) (args->func, args->interp, args->argc, args->argv);
1187 return 1;
1188}
1189
ff62d310
JI
1190struct wrapped_call_objs
1191{
1192 Tcl_Interp *interp;
fed03c01 1193 Tcl_ObjCmdProc *func;
ff62d310 1194 int objc;
fed03c01 1195 Tcl_Obj * CONST *objv;
ff62d310
JI
1196 int val;
1197};
1198
1199static int
1200wrapped_obj_call (args)
1201 struct wrapped_call_objs *args;
1202{
1203 args->val = (*args->func) (args->func, args->interp, args->objc, args->objv);
1204 return 1;
1205}
1206
86db943c
SG
1207/* This routine acts as a top-level for all GDB code called by tcl/Tk. It
1208 handles cleanups, and calls to return_to_top_level (usually via error).
1209 This is necessary in order to prevent a longjmp out of the bowels of Tk,
1210 possibly leaving things in a bad state. Since this routine can be called
1211 recursively, it needs to save and restore the contents of the jmp_buf as
1212 necessary. */
1213
1214static int
1215call_wrapper (clientData, interp, argc, argv)
1216 ClientData clientData;
1217 Tcl_Interp *interp;
1218 int argc;
1219 char *argv[];
1220{
c14cabba 1221 struct wrapped_call_args wrapped_args;
6131622e 1222 Tcl_DString result, *old_result_ptr;
018d76dd 1223 Tcl_DString error_string, *old_error_string_ptr;
6131622e
SG
1224
1225 Tcl_DStringInit (&result);
1226 old_result_ptr = result_ptr;
1227 result_ptr = &result;
86db943c 1228
018d76dd
KS
1229 Tcl_DStringInit (&error_string);
1230 old_error_string_ptr = error_string_ptr;
1231 error_string_ptr = &error_string;
1232
c14cabba
AC
1233 wrapped_args.func = (Tcl_CmdProc *)clientData;
1234 wrapped_args.interp = interp;
1235 wrapped_args.argc = argc;
1236 wrapped_args.argv = argv;
1237 wrapped_args.val = 0;
86db943c 1238
c14cabba 1239 if (!catch_errors (wrapped_call, &wrapped_args, "", RETURN_MASK_ALL))
86db943c 1240 {
c14cabba 1241 wrapped_args.val = TCL_ERROR; /* Flag an error for TCL */
86db943c 1242
0776b0b0
MH
1243 /* Make sure the timer interrupts are turned off. */
1244 if (gdbtk_timer_going)
7234efcb 1245 gdbtk_stop_timer ();
86db943c 1246
0776b0b0 1247 gdb_flush (gdb_stderr); /* Flush error output */
09722039
SG
1248 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
1249
fda6fadc
SS
1250 /* In case of an error, we may need to force the GUI into idle
1251 mode because gdbtk_call_command may have bombed out while in
1252 the command routine. */
86db943c 1253
40dffa42 1254 running_now = 0;
4e327047 1255 Tcl_Eval (interp, "gdbtk_tcl_idle");
86db943c 1256 }
929db6e5
EZ
1257
1258 /* do not suppress any errors -- a remote target could have errored */
1259 load_in_progress = 0;
0776b0b0 1260
018d76dd
KS
1261 if (Tcl_DStringLength (&error_string) == 0)
1262 {
1263 Tcl_DStringResult (interp, &result);
1264 Tcl_DStringFree (&error_string);
1265 }
1266 else if (Tcl_DStringLength (&result) == 0)
1267 {
1268 Tcl_DStringResult (interp, &error_string);
1269 Tcl_DStringFree (&result);
0776b0b0 1270 Tcl_DStringFree (&error_string);
018d76dd
KS
1271 }
1272 else
1273 {
1274 Tcl_ResetResult (interp);
1275 Tcl_AppendResult (interp, Tcl_DStringValue (&result),
1276 Tcl_DStringValue (&error_string), (char *) NULL);
1277 Tcl_DStringFree (&result);
1278 Tcl_DStringFree (&error_string);
1279 }
1280
6131622e 1281 result_ptr = old_result_ptr;
018d76dd
KS
1282 error_string_ptr = old_error_string_ptr;
1283
ff62d310
JI
1284#ifdef _WIN32
1285 close_bfds ();
1286#endif
1287
1288 return wrapped_args.val;
1289}
1290static int
1291call_obj_wrapper (clientData, interp, objc, objv)
1292 ClientData clientData;
1293 Tcl_Interp *interp;
1294 int objc;
1295 Tcl_Obj *CONST objv[];
1296{
1297 struct wrapped_call_objs wrapped_args;
1298 Tcl_DString result, *old_result_ptr;
1299 Tcl_DString error_string, *old_error_string_ptr;
1300
1301 /* The obj call wrapper works differently from the string wrapper, because
1302 * the obj calls currently insert their results directly into the
1303 * interpreter's result. So there is no need to have a result_ptr...
1304 * FIXME - rewrite all the object commands so they use a result_obj_ptr
1305 * - rewrite all the string commands to be object commands.
1306 */
1307
1308 Tcl_DStringInit (&result);
1309 old_result_ptr = result_ptr;
1310 result_ptr = &result;
1311
1312 Tcl_DStringInit (&error_string);
1313
1314 Tcl_DStringInit (&error_string);
1315 old_error_string_ptr = error_string_ptr;
1316 error_string_ptr = &error_string;
1317
fed03c01 1318 wrapped_args.func = (Tcl_ObjCmdProc *)clientData;
ff62d310
JI
1319 wrapped_args.interp = interp;
1320 wrapped_args.objc = objc;
1321 wrapped_args.objv = objv;
1322 wrapped_args.val = 0;
1323
1324 if (!catch_errors (wrapped_obj_call, &wrapped_args, "", RETURN_MASK_ALL))
1325 {
1326 wrapped_args.val = TCL_ERROR; /* Flag an error for TCL */
1327
1328 /* Make sure the timer interrupts are turned off. */
1329 if (gdbtk_timer_going)
1330 gdbtk_stop_timer ();
1331
1332 gdb_flush (gdb_stderr); /* Flush error output */
1333 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
1334
1335 /* In case of an error, we may need to force the GUI into idle
1336 mode because gdbtk_call_command may have bombed out while in
1337 the command routine. */
1338
1339 running_now = 0;
1340 Tcl_Eval (interp, "gdbtk_tcl_idle");
fed03c01
EZ
1341
1342
1343 /* if the error message is in RESULT instead of ERROR_STRING we copy it
1344 back to ERROR_STRING and free RESULT */
1345
1346 if ((Tcl_DStringLength (&error_string) == 0) && (Tcl_DStringLength (&result) > 0))
1347 {
1348 Tcl_DStringAppend (&error_string, Tcl_DStringValue (&result), Tcl_DStringLength (&result));
1349 Tcl_DStringFree (&result);
1350 }
1351
ff62d310
JI
1352 }
1353
1354 /* do not suppress any errors -- a remote target could have errored */
1355 load_in_progress = 0;
1356
1357 if (Tcl_DStringLength (&error_string) == 0)
1358 {
1359 /* We should insert the result here, but the obj commands now
1360 * do this directly, so we don't need to.
1361 * FIXME - ultimately, all this should be redone so that all the
1362 * commands either manipulate the Tcl result directly, or use a result_ptr.
1363 */
1364
1365 Tcl_DStringFree (&error_string);
1366 }
1367 else if (*(Tcl_GetStringResult (interp)) == '\0')
1368 {
1369 Tcl_DStringResult (interp, &error_string);
1370 Tcl_DStringFree (&error_string);
1371 }
1372 else
1373 {
1374 Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_DStringValue (&error_string),
1375 Tcl_DStringLength (&error_string));
1376 Tcl_DStringFree (&error_string);
1377 }
1378
1379 result_ptr = old_result_ptr;
1380 error_string_ptr = old_error_string_ptr;
1381
018d76dd
KS
1382#ifdef _WIN32
1383 close_bfds ();
1384#endif
6131622e 1385
c14cabba 1386 return wrapped_args.val;
86db943c
SG
1387}
1388
754e5da2 1389static int
0776b0b0
MH
1390comp_files (file1, file2)
1391 const char *file1[], *file2[];
1392{
1393 return strcmp(*file1,*file2);
1394}
1395
0776b0b0
MH
1396static int
1397gdb_listfiles (clientData, interp, objc, objv)
1398 ClientData clientData;
1399 Tcl_Interp *interp;
1400 int objc;
1401 Tcl_Obj *CONST objv[];
754e5da2 1402{
754e5da2
SG
1403 struct objfile *objfile;
1404 struct partial_symtab *psymtab;
546b8ca7 1405 struct symtab *symtab;
6da4c15f
JM
1406 char *lastfile, *pathname, **files;
1407 int files_size;
0776b0b0
MH
1408 int i, numfiles = 0, len = 0;
1409 Tcl_Obj *mylist;
1410
6da4c15f
JM
1411 files_size = 1000;
1412 files = (char **) xmalloc (sizeof (char *) * files_size);
1413
0776b0b0
MH
1414 if (objc > 2)
1415 {
1416 Tcl_WrongNumArgs (interp, 1, objv, "Usage: gdb_listfiles ?pathname?");
1417 return TCL_ERROR;
1418 }
1419 else if (objc == 2)
1420 pathname = Tcl_GetStringFromObj (objv[1], &len);
1421
1422 mylist = Tcl_NewListObj (0, NULL);
754e5da2
SG
1423
1424 ALL_PSYMTABS (objfile, psymtab)
0776b0b0 1425 {
6da4c15f
JM
1426 if (numfiles == files_size)
1427 {
1428 files_size = files_size * 2;
1429 files = (char **) xrealloc (files, sizeof (char *) * files_size);
1430 }
0776b0b0
MH
1431 if (len == 0)
1432 {
1433 if (psymtab->filename)
1434 files[numfiles++] = basename(psymtab->filename);
1435 }
1436 else if (!strcmp(psymtab->filename,basename(psymtab->filename))
1437 || !strncmp(pathname,psymtab->filename,len))
1438 if (psymtab->filename)
1439 files[numfiles++] = basename(psymtab->filename);
1440 }
754e5da2 1441
546b8ca7 1442 ALL_SYMTABS (objfile, symtab)
0776b0b0 1443 {
6da4c15f
JM
1444 if (numfiles == files_size)
1445 {
1446 files_size = files_size * 2;
1447 files = (char **) xrealloc (files, sizeof (char *) * files_size);
1448 }
0776b0b0
MH
1449 if (len == 0)
1450 {
1451 if (symtab->filename)
1452 files[numfiles++] = basename(symtab->filename);
1453 }
1454 else if (!strcmp(symtab->filename,basename(symtab->filename))
1455 || !strncmp(pathname,symtab->filename,len))
1456 if (symtab->filename)
1457 files[numfiles++] = basename(symtab->filename);
1458 }
1459
1460 qsort (files, numfiles, sizeof(char *), comp_files);
546b8ca7 1461
0776b0b0
MH
1462 lastfile = "";
1463 for (i = 0; i < numfiles; i++)
1464 {
1465 if (strcmp(files[i],lastfile))
1466 Tcl_ListObjAppendElement (interp, mylist, Tcl_NewStringObj(files[i], -1));
1467 lastfile = files[i];
1468 }
1469 Tcl_SetObjResult (interp, mylist);
6da4c15f 1470 free (files);
754e5da2
SG
1471 return TCL_OK;
1472}
479f0f18 1473
99c98415
MH
1474static int
1475gdb_listfuncs (clientData, interp, argc, argv)
1476 ClientData clientData;
1477 Tcl_Interp *interp;
1478 int argc;
1479 char *argv[];
1480{
1481 struct symtab *symtab;
1482 struct blockvector *bv;
1483 struct block *b;
1484 struct symbol *sym;
929db6e5 1485 char buf[128];
99c98415 1486 int i,j;
929db6e5 1487
99c98415
MH
1488 if (argc != 2)
1489 error ("wrong # args");
1490
929db6e5 1491 symtab = full_lookup_symtab (argv[1]);
99c98415
MH
1492 if (!symtab)
1493 error ("No such file");
1494
1495 bv = BLOCKVECTOR (symtab);
1496 for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
1497 {
1498 b = BLOCKVECTOR_BLOCK (bv, i);
1499 /* Skip the sort if this block is always sorted. */
1500 if (!BLOCK_SHOULD_SORT (b))
1501 sort_block_syms (b);
1502 for (j = 0; j < BLOCK_NSYMS (b); j++)
1503 {
1504 sym = BLOCK_SYM (b, j);
1505 if (SYMBOL_CLASS (sym) == LOC_BLOCK)
1506 {
929db6e5
EZ
1507
1508 char *name = cplus_demangle (SYMBOL_NAME(sym), 0);
1509 if (name)
1510 {
1511 sprintf (buf,"{%s} 1", name);
1512 }
1513 else
1514 sprintf (buf,"{%s} 0", SYMBOL_NAME(sym));
1515 Tcl_DStringAppendElement (result_ptr, buf);
99c98415
MH
1516 }
1517 }
1518 }
1519 return TCL_OK;
1520}
1521
ed5fa7c3
MH
1522static int
1523target_stop_wrapper (args)
1524 char * args;
1525{
1526 target_stop ();
1527 return 1;
1528}
1529
479f0f18
SG
1530static int
1531gdb_stop (clientData, interp, argc, argv)
1532 ClientData clientData;
1533 Tcl_Interp *interp;
1534 int argc;
1535 char *argv[];
1536{
c14cabba 1537 if (target_stop)
ed5fa7c3
MH
1538 {
1539 catch_errors (target_stop_wrapper, NULL, "",
1540 RETURN_MASK_ALL);
1541 }
c14cabba
AC
1542 else
1543 quit_flag = 1; /* hope something sees this */
546b8ca7
SG
1544
1545 return TCL_OK;
479f0f18 1546}
018d76dd
KS
1547
1548/* Prepare to accept a new executable file. This is called when we
1549 want to clear away everything we know about the old file, without
1550 asking the user. The Tcl code will have already asked the user if
1551 necessary. After this is called, we should be able to run the
1552 `file' command without getting any questions. */
1553
1554static int
1555gdb_clear_file (clientData, interp, argc, argv)
1556 ClientData clientData;
1557 Tcl_Interp *interp;
1558 int argc;
1559 char *argv[];
1560{
1561 if (inferior_pid != 0 && target_has_execution)
1562 {
1563 if (attach_flag)
1564 target_detach (NULL, 0);
1565 else
1566 target_kill ();
1567 }
1568
1569 if (target_has_execution)
1570 pop_target ();
1571
1572 symbol_file_command (NULL, 0);
1573
0776b0b0
MH
1574 /* gdb_loc refers to stop_pc, but nothing seems to clear it, so we
1575 clear it here. FIXME: This seems like an abstraction violation
1576 somewhere. */
1577 stop_pc = 0;
1578
018d76dd
KS
1579 return TCL_OK;
1580}
1581
1582/* Ask the user to confirm an exit request. */
1583
1584static int
1585gdb_confirm_quit (clientData, interp, argc, argv)
1586 ClientData clientData;
1587 Tcl_Interp *interp;
1588 int argc;
1589 char *argv[];
1590{
1591 int ret;
1592
1593 ret = quit_confirm ();
1594 Tcl_DStringAppendElement (result_ptr, ret ? "1" : "0");
1595 return TCL_OK;
1596}
1597
1598/* Quit without asking for confirmation. */
1599
1600static int
1601gdb_force_quit (clientData, interp, argc, argv)
1602 ClientData clientData;
1603 Tcl_Interp *interp;
1604 int argc;
1605 char *argv[];
1606{
1607 quit_force ((char *) NULL, 1);
1608 return TCL_OK;
1609}
09722039
SG
1610\f
1611/* This implements the TCL command `gdb_disassemble'. */
479f0f18 1612
09722039
SG
1613static int
1614gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
1615 bfd_vma memaddr;
1616 bfd_byte *myaddr;
1617 int len;
1618 disassemble_info *info;
1619{
1620 extern struct target_ops exec_ops;
1621 int res;
1622
1623 errno = 0;
1624 res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
1625
1626 if (res == len)
1627 return 0;
1628 else
1629 if (errno == 0)
1630 return EIO;
1631 else
1632 return errno;
1633}
1634
1635/* We need a different sort of line table from the normal one cuz we can't
1636 depend upon implicit line-end pc's for lines. This is because of the
1637 reordering we are about to do. */
1638
1639struct my_line_entry {
1640 int line;
1641 CORE_ADDR start_pc;
1642 CORE_ADDR end_pc;
1643};
1644
1645static int
1646compare_lines (mle1p, mle2p)
1647 const PTR mle1p;
1648 const PTR mle2p;
1649{
1650 struct my_line_entry *mle1, *mle2;
1651 int val;
1652
1653 mle1 = (struct my_line_entry *) mle1p;
1654 mle2 = (struct my_line_entry *) mle2p;
1655
1656 val = mle1->line - mle2->line;
1657
1658 if (val != 0)
1659 return val;
1660
1661 return mle1->start_pc - mle2->start_pc;
1662}
1663
1664static int
1665gdb_disassemble (clientData, interp, argc, argv)
1666 ClientData clientData;
1667 Tcl_Interp *interp;
1668 int argc;
1669 char *argv[];
1670{
1671 CORE_ADDR pc, low, high;
1672 int mixed_source_and_assembly;
fc941258
DE
1673 static disassemble_info di;
1674 static int di_initialized;
1675
1676 if (! di_initialized)
1677 {
91550191
SG
1678 INIT_DISASSEMBLE_INFO_NO_ARCH (di, gdb_stdout,
1679 (fprintf_ftype) fprintf_unfiltered);
caeec767 1680 di.flavour = bfd_target_unknown_flavour;
fc941258
DE
1681 di.memory_error_func = dis_asm_memory_error;
1682 di.print_address_func = dis_asm_print_address;
1683 di_initialized = 1;
1684 }
09722039 1685
91550191
SG
1686 di.mach = tm_print_insn_info.mach;
1687 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
e4bb9027 1688 di.endian = BFD_ENDIAN_BIG;
91550191 1689 else
e4bb9027 1690 di.endian = BFD_ENDIAN_LITTLE;
91550191 1691
09722039 1692 if (argc != 3 && argc != 4)
6131622e 1693 error ("wrong # args");
09722039
SG
1694
1695 if (strcmp (argv[1], "source") == 0)
1696 mixed_source_and_assembly = 1;
1697 else if (strcmp (argv[1], "nosource") == 0)
1698 mixed_source_and_assembly = 0;
1699 else
6131622e 1700 error ("First arg must be 'source' or 'nosource'");
09722039
SG
1701
1702 low = parse_and_eval_address (argv[2]);
1703
1704 if (argc == 3)
1705 {
1706 if (find_pc_partial_function (low, NULL, &low, &high) == 0)
6131622e 1707 error ("No function contains specified address");
09722039
SG
1708 }
1709 else
1710 high = parse_and_eval_address (argv[3]);
1711
1712 /* If disassemble_from_exec == -1, then we use the following heuristic to
1713 determine whether or not to do disassembly from target memory or from the
1714 exec file:
1715
1716 If we're debugging a local process, read target memory, instead of the
1717 exec file. This makes disassembly of functions in shared libs work
1718 correctly.
1719
1720 Else, we're debugging a remote process, and should disassemble from the
fda6fadc 1721 exec file for speed. However, this is no good if the target modifies its
09722039
SG
1722 code (for relocation, or whatever).
1723 */
1724
1725 if (disassemble_from_exec == -1)
1726 if (strcmp (target_shortname, "child") == 0
d7c4766c
SS
1727 || strcmp (target_shortname, "procfs") == 0
1728 || strcmp (target_shortname, "vxprocess") == 0)
09722039
SG
1729 disassemble_from_exec = 0; /* It's a child process, read inferior mem */
1730 else
1731 disassemble_from_exec = 1; /* It's remote, read the exec file */
1732
1733 if (disassemble_from_exec)
a76ef70a
SG
1734 di.read_memory_func = gdbtk_dis_asm_read_memory;
1735 else
1736 di.read_memory_func = dis_asm_read_memory;
09722039
SG
1737
1738 /* If just doing straight assembly, all we need to do is disassemble
1739 everything between low and high. If doing mixed source/assembly, we've
1740 got a totally different path to follow. */
1741
1742 if (mixed_source_and_assembly)
1743 { /* Come here for mixed source/assembly */
1744 /* The idea here is to present a source-O-centric view of a function to
1745 the user. This means that things are presented in source order, with
1746 (possibly) out of order assembly immediately following. */
1747 struct symtab *symtab;
1748 struct linetable_entry *le;
1749 int nlines;
c81a3fa9 1750 int newlines;
09722039
SG
1751 struct my_line_entry *mle;
1752 struct symtab_and_line sal;
1753 int i;
1754 int out_of_order;
c81a3fa9 1755 int next_line;
09722039
SG
1756
1757 symtab = find_pc_symtab (low); /* Assume symtab is valid for whole PC range */
1758
1759 if (!symtab)
1760 goto assembly_only;
1761
1762/* First, convert the linetable to a bunch of my_line_entry's. */
1763
1764 le = symtab->linetable->item;
1765 nlines = symtab->linetable->nitems;
1766
1767 if (nlines <= 0)
1768 goto assembly_only;
1769
1770 mle = (struct my_line_entry *) alloca (nlines * sizeof (struct my_line_entry));
1771
1772 out_of_order = 0;
1773
c81a3fa9
SG
1774/* Copy linetable entries for this function into our data structure, creating
1775 end_pc's and setting out_of_order as appropriate. */
1776
1777/* First, skip all the preceding functions. */
1778
1779 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
1780
1781/* Now, copy all entries before the end of this function. */
1782
1783 newlines = 0;
1784 for (; i < nlines - 1 && le[i].pc < high; i++)
09722039 1785 {
c81a3fa9
SG
1786 if (le[i].line == le[i + 1].line
1787 && le[i].pc == le[i + 1].pc)
1788 continue; /* Ignore duplicates */
1789
1790 mle[newlines].line = le[i].line;
09722039
SG
1791 if (le[i].line > le[i + 1].line)
1792 out_of_order = 1;
c81a3fa9
SG
1793 mle[newlines].start_pc = le[i].pc;
1794 mle[newlines].end_pc = le[i + 1].pc;
1795 newlines++;
09722039
SG
1796 }
1797
c81a3fa9
SG
1798/* If we're on the last line, and it's part of the function, then we need to
1799 get the end pc in a special way. */
1800
1801 if (i == nlines - 1
1802 && le[i].pc < high)
1803 {
1804 mle[newlines].line = le[i].line;
1805 mle[newlines].start_pc = le[i].pc;
1806 sal = find_pc_line (le[i].pc, 0);
1807 mle[newlines].end_pc = sal.end;
1808 newlines++;
1809 }
09722039
SG
1810
1811/* Now, sort mle by line #s (and, then by addresses within lines). */
1812
1813 if (out_of_order)
c81a3fa9 1814 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
09722039
SG
1815
1816/* Now, for each line entry, emit the specified lines (unless they have been
1817 emitted before), followed by the assembly code for that line. */
1818
c81a3fa9
SG
1819 next_line = 0; /* Force out first line */
1820 for (i = 0; i < newlines; i++)
09722039 1821 {
c81a3fa9
SG
1822/* Print out everything from next_line to the current line. */
1823
1824 if (mle[i].line >= next_line)
09722039 1825 {
c81a3fa9
SG
1826 if (next_line != 0)
1827 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
09722039 1828 else
c81a3fa9
SG
1829 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
1830
1831 next_line = mle[i].line + 1;
09722039 1832 }
c81a3fa9 1833
09722039
SG
1834 for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
1835 {
1836 QUIT;
1837 fputs_unfiltered (" ", gdb_stdout);
1838 print_address (pc, gdb_stdout);
1839 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 1840 pc += (*tm_print_insn) (pc, &di);
09722039
SG
1841 fputs_unfiltered ("\n", gdb_stdout);
1842 }
1843 }
1844 }
1845 else
1846 {
1847assembly_only:
1848 for (pc = low; pc < high; )
1849 {
1850 QUIT;
1851 fputs_unfiltered (" ", gdb_stdout);
1852 print_address (pc, gdb_stdout);
1853 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 1854 pc += (*tm_print_insn) (pc, &di);
09722039
SG
1855 fputs_unfiltered ("\n", gdb_stdout);
1856 }
1857 }
1858
09722039
SG
1859 gdb_flush (gdb_stdout);
1860
1861 return TCL_OK;
1862}
754e5da2
SG
1863\f
1864static void
1865tk_command (cmd, from_tty)
1866 char *cmd;
1867 int from_tty;
1868{
546b8ca7
SG
1869 int retval;
1870 char *result;
1871 struct cleanup *old_chain;
1872
572977a5
FF
1873 /* Catch case of no argument, since this will make the tcl interpreter dump core. */
1874 if (cmd == NULL)
1875 error_no_arg ("tcl command to interpret");
1876
546b8ca7
SG
1877 retval = Tcl_Eval (interp, cmd);
1878
1879 result = strdup (interp->result);
754e5da2 1880
546b8ca7
SG
1881 old_chain = make_cleanup (free, result);
1882
1883 if (retval != TCL_OK)
1884 error (result);
1885
1886 printf_unfiltered ("%s\n", result);
1887
1888 do_cleanups (old_chain);
754e5da2
SG
1889}
1890
1891static void
1892cleanup_init (ignored)
1893 int ignored;
1894{
754e5da2
SG
1895 if (interp != NULL)
1896 Tcl_DeleteInterp (interp);
1897 interp = NULL;
1898}
1899
637b1661
SG
1900/* Come here during long calculations to check for GUI events. Usually invoked
1901 via the QUIT macro. */
1902
1903static void
1904gdbtk_interactive ()
1905{
1906 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
1907}
1908
479f0f18
SG
1909/* Come here when there is activity on the X file descriptor. */
1910
1911static void
1912x_event (signo)
1913 int signo;
1914{
ed5fa7c3
MH
1915 static int in_x_event = 0;
1916 static Tcl_Obj *varname = NULL;
ed5fa7c3
MH
1917 if (in_x_event || in_fputs)
1918 return;
1919
1920 in_x_event = 1;
1921
21b3bc77
KS
1922#ifdef __CYGWIN32__
1923 if (signo == -2)
1924 if (gdbtk_timer_going)
1925 gdbtk_stop_timer ();
1926#endif
1927
479f0f18 1928 /* Process pending events */
0776b0b0
MH
1929 while (Tcl_DoOneEvent (TCL_DONT_WAIT|TCL_ALL_EVENTS) != 0)
1930 ;
1931
0776b0b0
MH
1932 if (load_in_progress)
1933 {
ed5fa7c3
MH
1934 int val;
1935 if (varname == NULL)
1936 {
1937 Tcl_Obj *varnamestrobj = Tcl_NewStringObj("download_cancel_ok",-1);
1938 varname = Tcl_ObjGetVar2(interp,varnamestrobj,NULL,TCL_GLOBAL_ONLY);
1939 }
1940 if ((Tcl_GetIntFromObj(interp,varname,&val) == TCL_OK) && val)
0776b0b0
MH
1941 {
1942 quit_flag = 1;
1943#ifdef REQUEST_QUIT
1944 REQUEST_QUIT;
1945#else
1946 if (immediate_quit)
1947 quit ();
1948#endif
1949 }
1950 }
ed5fa7c3 1951 in_x_event = 0;
479f0f18
SG
1952}
1953
018d76dd
KS
1954/* For Cygwin32, we use a timer to periodically check for Windows
1955 messages. FIXME: It would be better to not poll, but to instead
1956 rewrite the target_wait routines to serve as input sources.
1957 Unfortunately, that will be a lot of work. */
ed5fa7c3
MH
1958static sigset_t nullsigmask;
1959static struct sigaction act1, act2;
1960static struct itimerval it_on, it_off;
018d76dd
KS
1961
1962static void
1963gdbtk_start_timer ()
1964{
ed5fa7c3
MH
1965 static int first = 1;
1966 /*TclDebug ("Starting timer....");*/
1967 if (first)
1968 {
1969 /* first time called, set up all the structs */
1970 first = 0;
1971 sigemptyset (&nullsigmask);
018d76dd 1972
ed5fa7c3
MH
1973 act1.sa_handler = x_event;
1974 act1.sa_mask = nullsigmask;
1975 act1.sa_flags = 0;
018d76dd 1976
ed5fa7c3
MH
1977 act2.sa_handler = SIG_IGN;
1978 act2.sa_mask = nullsigmask;
1979 act2.sa_flags = 0;
018d76dd 1980
ed5fa7c3 1981 it_on.it_interval.tv_sec = 0;
7234efcb 1982 it_on.it_interval.tv_usec = 250000; /* .25 sec */
ed5fa7c3 1983 it_on.it_value.tv_sec = 0;
7234efcb 1984 it_on.it_value.tv_usec = 250000;
0776b0b0 1985
ed5fa7c3
MH
1986 it_off.it_interval.tv_sec = 0;
1987 it_off.it_interval.tv_usec = 0;
1988 it_off.it_value.tv_sec = 0;
1989 it_off.it_value.tv_usec = 0;
1990 }
7234efcb
KS
1991
1992 if (!gdbtk_timer_going)
1993 {
1994 sigaction (SIGALRM, &act1, NULL);
1995 setitimer (ITIMER_REAL, &it_on, NULL);
1996 gdbtk_timer_going = 1;
1997 }
018d76dd
KS
1998}
1999
2000static void
2001gdbtk_stop_timer ()
2002{
7234efcb
KS
2003 if (gdbtk_timer_going)
2004 {
2005 gdbtk_timer_going = 0;
2006 /*TclDebug ("Stopping timer.");*/
2007 setitimer (ITIMER_REAL, &it_off, NULL);
2008 sigaction (SIGALRM, &act2, NULL);
2009 }
018d76dd
KS
2010}
2011
018d76dd
KS
2012/* This hook function is called whenever we want to wait for the
2013 target. */
2014
479f0f18
SG
2015static int
2016gdbtk_wait (pid, ourstatus)
2017 int pid;
2018 struct target_waitstatus *ourstatus;
2019{
7234efcb 2020 gdbtk_start_timer ();
479f0f18 2021 pid = target_wait (pid, ourstatus);
7234efcb 2022 gdbtk_stop_timer ();
479f0f18
SG
2023 return pid;
2024}
2025
2026/* This is called from execute_command, and provides a wrapper around
2027 various command routines in a place where both protocol messages and
2028 user input both flow through. Mostly this is used for indicating whether
2029 the target process is running or not.
2030*/
2031
2032static void
2033gdbtk_call_command (cmdblk, arg, from_tty)
2034 struct cmd_list_element *cmdblk;
2035 char *arg;
2036 int from_tty;
2037{
fda6fadc 2038 running_now = 0;
018d76dd 2039 if (cmdblk->class == class_run || cmdblk->class == class_trace)
479f0f18 2040 {
ff62d310
JI
2041
2042/* HACK! HACK! This is to get the gui to update the tstart/tstop
2043 button only incase of tstart/tstop commands issued from the console
fed03c01 2044 We don't want to update the src window, so we need to have specific
ff62d310 2045 procedures to do tstart and tstop
fed03c01
EZ
2046 Unfortunately this will not display errors from tstart or tstop in the
2047 console window itself, but as dialogs.*/
2048
ff62d310 2049 if (!strcmp(cmdblk->name, "tstart") && !No_Update)
fed03c01 2050 {
ff62d310 2051 Tcl_Eval (interp, "gdbtk_tcl_tstart");
fed03c01
EZ
2052 (*cmdblk->function.cfunc)(arg, from_tty);
2053 }
ff62d310 2054 else if (!strcmp(cmdblk->name, "tstop") && !No_Update)
fed03c01 2055 {
ff62d310 2056 Tcl_Eval (interp, "gdbtk_tcl_tstop");
fed03c01
EZ
2057 (*cmdblk->function.cfunc)(arg, from_tty);
2058 }
ff62d310
JI
2059/* end of hack */
2060 else
2061 {
2062 running_now = 1;
2063 if (!No_Update)
2064 Tcl_Eval (interp, "gdbtk_tcl_busy");
2065 (*cmdblk->function.cfunc)(arg, from_tty);
2066 running_now = 0;
2067 if (!No_Update)
2068 Tcl_Eval (interp, "gdbtk_tcl_idle");
2069 }
479f0f18
SG
2070 }
2071 else
2072 (*cmdblk->function.cfunc)(arg, from_tty);
2073}
2074
5bac2b50
FF
2075/* This function is called instead of gdb's internal command loop. This is the
2076 last chance to do anything before entering the main Tk event loop. */
2077
2078static void
2079tk_command_loop ()
2080{
41756e56
FF
2081 extern GDB_FILE *instream;
2082
2083 /* We no longer want to use stdin as the command input stream */
2084 instream = NULL;
018d76dd
KS
2085
2086 if (Tcl_Eval (interp, "gdbtk_tcl_preloop") != TCL_OK)
2087 {
2088 char *msg;
2089
2090 /* Force errorInfo to be set up propertly. */
2091 Tcl_AddErrorInfo (interp, "");
2092
2093 msg = Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY);
2094#ifdef _WIN32
2095 MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
2096#else
2097 fputs_unfiltered (msg, gdb_stderr);
2098#endif
2099 }
2100
2101#ifdef _WIN32
2102 close_bfds ();
2103#endif
2104
5bac2b50
FF
2105 Tk_MainLoop ();
2106}
2107
9a2f9219
ILT
2108/* gdbtk_init installs this function as a final cleanup. */
2109
2110static void
2111gdbtk_cleanup (dummy)
2112 PTR dummy;
2113{
929db6e5
EZ
2114#ifdef IDE
2115 struct ide_event_handle *h = (struct ide_event_handle *) dummy;
2116
2117 ide_interface_deregister_all (h);
2118#endif
9a2f9219
ILT
2119 Tcl_Finalize ();
2120}
2121
2122/* Initialize gdbtk. */
2123
754e5da2 2124static void
2476848a
MH
2125gdbtk_init ( argv0 )
2126 char *argv0;
754e5da2
SG
2127{
2128 struct cleanup *old_chain;
74089546 2129 char *lib, *gdbtk_lib, *gdbtk_lib_tmp, *gdbtk_file;
8a19b35a 2130 int i, found_main;
018d76dd 2131#ifndef WINNT
736a82e7
SG
2132 struct sigaction action;
2133 static sigset_t nullsigmask = {0};
018d76dd 2134#endif
2476848a 2135#ifdef IDE
018d76dd 2136 /* start-sanitize-ide */
2476848a
MH
2137 struct ide_event_handle *h;
2138 const char *errmsg;
2139 char *libexecdir;
018d76dd 2140 /* end-sanitize-ide */
2476848a 2141#endif
754e5da2 2142
fe58c81f
FF
2143 /* If there is no DISPLAY environment variable, Tk_Init below will fail,
2144 causing gdb to abort. If instead we simply return here, gdb will
2145 gracefully degrade to using the command line interface. */
2146
8a19b35a 2147#ifndef WINNT
fe58c81f
FF
2148 if (getenv ("DISPLAY") == NULL)
2149 return;
8a19b35a 2150#endif
fe58c81f 2151
754e5da2
SG
2152 old_chain = make_cleanup (cleanup_init, 0);
2153
2154 /* First init tcl and tk. */
2476848a 2155 Tcl_FindExecutable (argv0);
754e5da2
SG
2156 interp = Tcl_CreateInterp ();
2157
ed5fa7c3
MH
2158#ifdef TCL_MEM_DEBUG
2159 Tcl_InitMemory (interp);
2160#endif
2161
754e5da2
SG
2162 if (!interp)
2163 error ("Tcl_CreateInterp failed");
2164
754e5da2
SG
2165 if (Tcl_Init(interp) != TCL_OK)
2166 error ("Tcl_Init failed: %s", interp->result);
2167
929db6e5
EZ
2168#ifndef IDE
2169 /* For the IDE we register the cleanup later, after we've
2170 initialized events. */
2171 make_final_cleanup (gdbtk_cleanup, NULL);
2172#endif
2476848a 2173
9a2f9219 2174 /* Initialize the Paths variable. */
74089546 2175 if (ide_initialize_paths (interp, "gdbtcl") != TCL_OK)
9a2f9219
ILT
2176 error ("ide_initialize_paths failed: %s", interp->result);
2177
dd3dd918 2178#ifdef IDE
018d76dd 2179 /* start-sanitize-ide */
2476848a
MH
2180 /* Find the directory where we expect to find idemanager. We ignore
2181 errors since it doesn't really matter if this fails. */
2182 libexecdir = Tcl_GetVar2 (interp, "Paths", "libexecdir", TCL_GLOBAL_ONLY);
2183
2184 IluTk_Init ();
2185
7b94b2ea 2186 h = ide_event_init_from_environment (&errmsg, libexecdir);
929db6e5 2187 make_final_cleanup (gdbtk_cleanup, h);
2476848a
MH
2188 if (h == NULL)
2189 {
2190 Tcl_AppendResult (interp, "can't initialize event system: ", errmsg,
2191 (char *) NULL);
2192 fprintf(stderr, "WARNING: ide_event_init_client failed: %s\n", interp->result);
9a2f9219
ILT
2193
2194 Tcl_SetVar (interp, "GDBTK_IDE", "0", 0);
2476848a
MH
2195 }
2196 else
2197 {
2198 if (ide_create_tclevent_command (interp, h) != TCL_OK)
2199 error ("ide_create_tclevent_command failed: %s", interp->result);
018d76dd 2200
2476848a
MH
2201 if (ide_create_edit_command (interp, h) != TCL_OK)
2202 error ("ide_create_edit_command failed: %s", interp->result);
2203
2204 if (ide_create_property_command (interp, h) != TCL_OK)
2205 error ("ide_create_property_command failed: %s", interp->result);
018d76dd
KS
2206
2207 if (ide_create_build_command (interp, h) != TCL_OK)
2208 error ("ide_create_build_command failed: %s", interp->result);
2209
2210 if (ide_create_window_register_command (interp, h, "gdb-restore")
2211 != TCL_OK)
9a2f9219
ILT
2212 error ("ide_create_window_register_command failed: %s",
2213 interp->result);
2214
2215 if (ide_create_window_command (interp, h) != TCL_OK)
2216 error ("ide_create_window_command failed: %s", interp->result);
2217
018d76dd
KS
2218 if (ide_create_exit_command (interp, h) != TCL_OK)
2219 error ("ide_create_exit_command failed: %s", interp->result);
2220
2221 if (ide_create_help_command (interp) != TCL_OK)
2222 error ("ide_create_help_command failed: %s", interp->result);
2223
2476848a
MH
2224 /*
2225 if (ide_initialize (interp, "gdb") != TCL_OK)
2226 error ("ide_initialize failed: %s", interp->result);
2227 */
9a2f9219
ILT
2228
2229 Tcl_SetVar (interp, "GDBTK_IDE", "1", 0);
2476848a 2230 }
018d76dd 2231 /* end-sanitize-ide */
2476848a
MH
2232#else
2233 Tcl_SetVar (interp, "GDBTK_IDE", "0", 0);
2234#endif /* IDE */
2235
9a2f9219
ILT
2236 /* We don't want to open the X connection until we've done all the
2237 IDE initialization. Otherwise, goofy looking unfinished windows
2238 pop up when ILU drops into the TCL event loop. */
2239
2240 if (Tk_Init(interp) != TCL_OK)
2241 error ("Tk_Init failed: %s", interp->result);
2242
2243 if (Itcl_Init(interp) == TCL_ERROR)
2244 error ("Itcl_Init failed: %s", interp->result);
2245
2246 if (Tix_Init(interp) != TCL_OK)
2247 error ("Tix_Init failed: %s", interp->result);
2248
94a6f14f
MH
2249 if (Tktable_Init(interp) != TCL_OK)
2250 error ("Tktable_Init failed: %s", interp->result);
2251 Tcl_StaticPackage(interp, "Tktable", Tktable_Init,
2252 (Tcl_PackageInitProc *) NULL);
2253
018d76dd 2254#ifdef __CYGWIN32__
929db6e5
EZ
2255 if (ide_create_messagebox_command (interp) != TCL_OK)
2256 error ("messagebox command initialization failed");
018d76dd
KS
2257 /* On Windows, create a sizebox widget command */
2258 if (ide_create_sizebox_command (interp) != TCL_OK)
2259 error ("sizebox creation failed");
2260 if (ide_create_winprint_command (interp) != TCL_OK)
2261 error ("windows print code initialization failed");
2262 /* start-sanitize-ide */
2263 /* An interface to ShellExecute. */
2264 if (ide_create_shell_execute_command (interp) != TCL_OK)
2265 error ("shell execute command initialization failed");
06434f5f 2266 /* end-sanitize-ide */
929db6e5
EZ
2267 if (ide_create_win_grab_command (interp) != TCL_OK)
2268 error ("grab support command initialization failed");
2269 /* Path conversion functions. */
2270 if (ide_create_cygwin_path_command (interp) != TCL_OK)
2271 error ("cygwin path command initialization failed");
018d76dd
KS
2272#endif
2273
86db943c 2274 Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
0422b59e
KS
2275 Tcl_CreateCommand (interp, "gdb_immediate", call_wrapper,
2276 gdb_immediate_command, NULL);
86db943c 2277 Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
8a19b35a 2278 Tcl_CreateCommand (interp, "gdb_path_conv", call_wrapper, gdb_path_conv, NULL);
ff62d310 2279 Tcl_CreateObjCommand (interp, "gdb_listfiles", call_obj_wrapper, gdb_listfiles, NULL);
99c98415
MH
2280 Tcl_CreateCommand (interp, "gdb_listfuncs", call_wrapper, gdb_listfuncs,
2281 NULL);
018d76dd
KS
2282 Tcl_CreateCommand (interp, "gdb_get_mem", call_wrapper, gdb_get_mem,
2283 NULL);
86db943c
SG
2284 Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
2285 Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
2286 Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
2287 gdb_fetch_registers, NULL);
2288 Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
2289 gdb_changed_register_list, NULL);
09722039
SG
2290 Tcl_CreateCommand (interp, "gdb_disassemble", call_wrapper,
2291 gdb_disassemble, NULL);
2292 Tcl_CreateCommand (interp, "gdb_eval", call_wrapper, gdb_eval, NULL);
6131622e
SG
2293 Tcl_CreateCommand (interp, "gdb_get_breakpoint_list", call_wrapper,
2294 gdb_get_breakpoint_list, NULL);
2295 Tcl_CreateCommand (interp, "gdb_get_breakpoint_info", call_wrapper,
2296 gdb_get_breakpoint_info, NULL);
018d76dd
KS
2297 Tcl_CreateCommand (interp, "gdb_clear_file", call_wrapper,
2298 gdb_clear_file, NULL);
2299 Tcl_CreateCommand (interp, "gdb_confirm_quit", call_wrapper,
2300 gdb_confirm_quit, NULL);
2301 Tcl_CreateCommand (interp, "gdb_force_quit", call_wrapper,
2302 gdb_force_quit, NULL);
2303 Tcl_CreateCommand (interp, "gdb_target_has_execution",
2304 gdb_target_has_execution_command,
2305 NULL, NULL);
41158958
EZ
2306 Tcl_CreateCommand (interp, "gdb_is_tracing",
2307 gdb_trace_status,
2308 NULL, NULL);
ff62d310 2309 Tcl_CreateObjCommand (interp, "gdb_load_info", call_obj_wrapper, gdb_load_info, NULL);
b33b741a 2310 Tcl_CreateObjCommand (interp, "gdb_get_locals", call_obj_wrapper, gdb_get_locals_command,
ff62d310 2311 NULL);
b33b741a 2312 Tcl_CreateObjCommand (interp, "gdb_get_args", call_obj_wrapper, gdb_get_args_command,
ff62d310
JI
2313 NULL);
2314 Tcl_CreateObjCommand (interp, "gdb_get_function", call_obj_wrapper, gdb_get_function_command,
2315 NULL);
2316 Tcl_CreateObjCommand (interp, "gdb_get_line", call_obj_wrapper, gdb_get_line_command,
2317 NULL);
2318 Tcl_CreateObjCommand (interp, "gdb_get_file", call_obj_wrapper, gdb_get_file_command,
2319 NULL);
018d76dd 2320 Tcl_CreateObjCommand (interp, "gdb_tracepoint_exists",
ff62d310 2321 call_obj_wrapper, gdb_tracepoint_exists_command, NULL);
018d76dd 2322 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_info",
ff62d310 2323 call_obj_wrapper, gdb_get_tracepoint_info, NULL);
018d76dd 2324 Tcl_CreateObjCommand (interp, "gdb_actions",
ff62d310 2325 call_obj_wrapper, gdb_actions_command, NULL);
018d76dd 2326 Tcl_CreateObjCommand (interp, "gdb_prompt",
ff62d310 2327 call_obj_wrapper, gdb_prompt_command, NULL);
e0f7db02 2328 Tcl_CreateObjCommand (interp, "gdb_find_file",
ff62d310 2329 call_obj_wrapper, gdb_find_file_command, NULL);
4f17e6eb 2330 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_list",
ff62d310 2331 call_obj_wrapper, gdb_get_tracepoint_list, NULL);
929db6e5 2332 Tcl_CreateCommand (interp, "gdb_pc_reg", get_pc_register, NULL, NULL);
ff62d310
JI
2333 Tcl_CreateObjCommand (interp, "gdb_loadfile", call_obj_wrapper, gdb_loadfile, NULL);
2334 Tcl_CreateObjCommand (interp, "gdb_set_bp", call_obj_wrapper, gdb_set_bp, NULL);
fed03c01
EZ
2335 Tcl_CreateObjCommand (interp, "gdb_get_trace_frame_num",
2336 call_obj_wrapper, gdb_get_trace_frame_num, NULL);
929db6e5 2337
5bac2b50 2338 command_loop_hook = tk_command_loop;
a5f4fbff 2339 print_frame_info_listing_hook = gdbtk_print_frame_info;
09722039 2340 query_hook = gdbtk_query;
e6e9507d 2341 warning_hook = gdbtk_warning;
09722039
SG
2342 flush_hook = gdbtk_flush;
2343 create_breakpoint_hook = gdbtk_create_breakpoint;
2344 delete_breakpoint_hook = gdbtk_delete_breakpoint;
6131622e 2345 modify_breakpoint_hook = gdbtk_modify_breakpoint;
09722039
SG
2346 interactive_hook = gdbtk_interactive;
2347 target_wait_hook = gdbtk_wait;
2348 call_command_hook = gdbtk_call_command;
41756e56
FF
2349 readline_begin_hook = gdbtk_readline_begin;
2350 readline_hook = gdbtk_readline;
2351 readline_end_hook = gdbtk_readline_end;
018d76dd 2352 ui_load_progress_hook = gdbtk_load_hash;
21b3bc77
KS
2353#ifdef __CYGWIN32__
2354 ui_loop_hook = x_event;
2355#endif
11f91b2b
KS
2356 pre_add_symbol_hook = gdbtk_pre_add_symbol;
2357 post_add_symbol_hook = gdbtk_post_add_symbol;
018d76dd
KS
2358 create_tracepoint_hook = gdbtk_create_tracepoint;
2359 delete_tracepoint_hook = gdbtk_delete_tracepoint;
a5f4fbff 2360 modify_tracepoint_hook = gdbtk_modify_tracepoint;
929db6e5 2361 pc_changed_hook = pc_changed;
479f0f18 2362
754e5da2
SG
2363 add_com ("tk", class_obscure, tk_command,
2364 "Send a command directly into tk.");
09722039 2365
09722039
SG
2366 Tcl_LinkVar (interp, "disassemble-from-exec", (char *)&disassemble_from_exec,
2367 TCL_LINK_INT);
2368
8a19b35a 2369 /* find the gdb tcl library and source main.tcl */
09722039 2370
8a19b35a
MH
2371 gdbtk_lib = getenv ("GDBTK_LIBRARY");
2372 if (!gdbtk_lib)
2373 if (access ("gdbtcl/main.tcl", R_OK) == 0)
2374 gdbtk_lib = "gdbtcl";
09722039 2375 else
8a19b35a
MH
2376 gdbtk_lib = GDBTK_LIBRARY;
2377
74089546
ILT
2378 gdbtk_lib_tmp = xstrdup (gdbtk_lib);
2379
8a19b35a
MH
2380 found_main = 0;
2381 /* see if GDBTK_LIBRARY is a path list */
2382 lib = strtok (gdbtk_lib_tmp, GDBTK_PATH_SEP);
2383 do
2384 {
2385 if (Tcl_VarEval (interp, "lappend auto_path ", lib, NULL) != TCL_OK)
2386 {
2387 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
2388 error ("");
2389 }
2390 if (!found_main)
2391 {
74089546 2392 gdbtk_file = concat (lib, "/main.tcl", (char *) NULL);
8a19b35a
MH
2393 if (access (gdbtk_file, R_OK) == 0)
2394 {
2395 found_main++;
2396 Tcl_SetVar (interp, "GDBTK_LIBRARY", lib, 0);
2397 }
2398 }
2399 }
56e327b3 2400 while ((lib = strtok (NULL, ":")) != NULL);
74089546
ILT
2401
2402 free (gdbtk_lib_tmp);
2403
74089546
ILT
2404 if (!found_main)
2405 {
2406 /* Try finding it with the auto path. */
2407
2408 static const char script[] ="\
2409proc gdbtk_find_main {} {\n\
2410 global auto_path GDBTK_LIBRARY\n\
2411 foreach dir $auto_path {\n\
2412 set f [file join $dir main.tcl]\n\
2413 if {[file exists $f]} then {\n\
2414 set GDBTK_LIBRARY $dir\n\
2415 return $f\n\
2416 }\n\
2417 }\n\
2418 return ""\n\
2419}\n\
2420gdbtk_find_main";
2421
2422 if (Tcl_GlobalEval (interp, (char *) script) != TCL_OK)
2423 {
2424 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
2425 error ("");
2426 }
2427
2428 if (interp->result[0] != '\0')
2429 {
2430 gdbtk_file = xstrdup (interp->result);
2431 found_main++;
2432 }
2433 }
74089546 2434
8a19b35a
MH
2435 if (!found_main)
2436 {
2437 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
2438 if (getenv("GDBTK_LIBRARY"))
2439 {
2440 fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n",getenv("GDBTK_LIBRARY"));
2441 fprintf_unfiltered (stderr,
2442 "Please set GDBTK_LIBRARY to a path that includes the GDB tcl files.\n");
2443 }
2444 else
2445 {
2446 fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n", GDBTK_LIBRARY);
2447 fprintf_unfiltered (stderr, "You might want to set GDBTK_LIBRARY\n");
2448 }
2449 error("");
2450 }
09722039 2451
724498fd
SG
2452/* Defer setup of fputs_unfiltered_hook to near the end so that error messages
2453 prior to this point go to stdout/stderr. */
2454
2455 fputs_unfiltered_hook = gdbtk_fputs;
2456
8a19b35a 2457 if (Tcl_EvalFile (interp, gdbtk_file) != TCL_OK)
724498fd 2458 {
018d76dd
KS
2459 char *msg;
2460
2461 /* Force errorInfo to be set up propertly. */
2462 Tcl_AddErrorInfo (interp, "");
2463
2464 msg = Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY);
2465
724498fd
SG
2466 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
2467
018d76dd
KS
2468#ifdef _WIN32
2469 MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
2470#else
2471 fputs_unfiltered (msg, gdb_stderr);
2472#endif
b66051ec 2473
b66051ec 2474 error ("");
724498fd 2475 }
09722039 2476
018d76dd
KS
2477#ifdef IDE
2478 /* start-sanitize-ide */
2479 /* Don't do this until we have initialized. Otherwise, we may get a
2480 run command before we are ready for one. */
2481 if (ide_run_server_init (interp, h) != TCL_OK)
2482 error ("ide_run_server_init failed: %s", interp->result);
2483 /* end-sanitize-ide */
2484#endif
2485
74089546
ILT
2486 free (gdbtk_file);
2487
09722039 2488 discard_cleanups (old_chain);
754e5da2
SG
2489}
2490
018d76dd
KS
2491static int
2492gdb_target_has_execution_command (clientData, interp, argc, argv)
2493 ClientData clientData;
2494 Tcl_Interp *interp;
2495 int argc;
2496 char *argv[];
2497{
2498 int result = 0;
2499
2500 if (target_has_execution && inferior_pid != 0)
2501 result = 1;
2502
2503 Tcl_SetIntObj (Tcl_GetObjResult (interp), result);
2504 return TCL_OK;
2505}
2506
41158958
EZ
2507static int
2508gdb_trace_status (clientData, interp, argc, argv)
2509 ClientData clientData;
2510 Tcl_Interp *interp;
2511 int argc;
2512 char *argv[];
2513{
2514 int result = 0;
2515
2516 if (trace_running_p)
2517 result = 1;
2518
2519 Tcl_SetIntObj (Tcl_GetObjResult (interp), result);
2520 return TCL_OK;
2521}
2522
018d76dd
KS
2523/* gdb_load_info - returns information about the file about to be downloaded */
2524
2525static int
2526gdb_load_info (clientData, interp, objc, objv)
2527 ClientData clientData;
2528 Tcl_Interp *interp;
2529 int objc;
2530 Tcl_Obj *CONST objv[];
2531{
2532 bfd *loadfile_bfd;
2533 struct cleanup *old_cleanups;
2534 asection *s;
2535 Tcl_Obj *ob[2];
2536 Tcl_Obj *res[16];
2537 int i = 0;
2538
2539 char *filename = Tcl_GetStringFromObj (objv[1], NULL);
2540
2541 loadfile_bfd = bfd_openr (filename, gnutarget);
2542 if (loadfile_bfd == NULL)
2543 {
2544 Tcl_SetObjResult (interp, Tcl_NewStringObj ("Open failed", -1));
2545 return TCL_ERROR;
2546 }
2547 old_cleanups = make_cleanup (bfd_close, loadfile_bfd);
2548
2549 if (!bfd_check_format (loadfile_bfd, bfd_object))
2550 {
2551 Tcl_SetObjResult (interp, Tcl_NewStringObj ("Bad Object File", -1));
2552 return TCL_ERROR;
2553 }
2554
2555 for (s = loadfile_bfd->sections; s; s = s->next)
2556 {
2557 if (s->flags & SEC_LOAD)
2558 {
2559 bfd_size_type size = bfd_get_section_size_before_reloc (s);
2560 if (size > 0)
2561 {
2562 ob[0] = Tcl_NewStringObj((char *)bfd_get_section_name(loadfile_bfd, s), -1);
2563 ob[1] = Tcl_NewLongObj ((long)size);
2564 res[i++] = Tcl_NewListObj (2, ob);
2565 }
2566 }
2567 }
2568
2569 Tcl_SetObjResult (interp, Tcl_NewListObj (i, res));
2570 do_cleanups (old_cleanups);
2571 return TCL_OK;
2572}
2573
2574
2575int
2576gdbtk_load_hash (section, num)
2577 char *section;
2578 unsigned long num;
2579{
018d76dd
KS
2580 char buf[128];
2581 sprintf (buf, "download_hash %s %ld", section, num);
0776b0b0
MH
2582 Tcl_Eval (interp, buf);
2583 return atoi (interp->result);
018d76dd
KS
2584}
2585
ff62d310
JI
2586/* gdb_get_locals -
2587 * This and gdb_get_locals just call gdb_get_vars_command with the right
2588 * value of clientData. We can't use the client data in the definition
2589 * of the command, because the call wrapper uses this instead...
2590 */
2591
2592static int
b33b741a 2593gdb_get_locals_command (clientData, interp, objc, objv)
ff62d310
JI
2594 ClientData clientData;
2595 Tcl_Interp *interp;
2596 int objc;
2597 Tcl_Obj *CONST objv[];
2598{
2599
2600 return gdb_get_vars_command((ClientData) 0, interp, objc, objv);
2601
2602}
2603
2604static int
b33b741a 2605gdb_get_args_command (clientData, interp, objc, objv)
ff62d310
JI
2606 ClientData clientData;
2607 Tcl_Interp *interp;
2608 int objc;
2609 Tcl_Obj *CONST objv[];
2610{
2611
2612 return gdb_get_vars_command((ClientData) 1, interp, objc, objv);
2613
2614}
2615
018d76dd
KS
2616/* gdb_get_vars_command -
2617 *
2618 * Implements the "gdb_get_locals" and "gdb_get_args" tcl commands. This
2619 * function sets the Tcl interpreter's result to a list of variable names
2620 * depending on clientData. If clientData is one, the result is a list of
2621 * arguments; zero returns a list of locals -- all relative to the block
2622 * specified as an argument to the command. Valid commands include
2623 * anything decode_line_1 can handle (like "main.c:2", "*0x02020202",
2624 * and "main").
2625 */
2626static int
2627gdb_get_vars_command (clientData, interp, objc, objv)
2628 ClientData clientData;
2629 Tcl_Interp *interp;
2630 int objc;
2631 Tcl_Obj *CONST objv[];
2632{
2633 Tcl_Obj *result;
2634 struct symtabs_and_lines sals;
2635 struct symbol *sym;
2636 struct block *block;
2637 char **canonical, *args;
2638 int i, nsyms, arguments;
2639
2640 if (objc != 2)
2641 {
2642 Tcl_AppendResult (interp,
2643 "wrong # of args: should be \"",
2644 Tcl_GetStringFromObj (objv[0], NULL),
2645 " function:line|function|line|*addr\"");
2646 return TCL_ERROR;
2647 }
2648
2649 arguments = (int) clientData;
2650 args = Tcl_GetStringFromObj (objv[1], NULL);
2651 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2652 if (sals.nelts == 0)
2653 {
2654 Tcl_AppendResult (interp,
2655 "error decoding line", NULL);
2656 return TCL_ERROR;
2657 }
2658
2659 /* Initialize a list that will hold the results */
2660 result = Tcl_NewListObj (0, NULL);
2661
2662 /* Resolve all line numbers to PC's */
2663 for (i = 0; i < sals.nelts; i++)
2664 resolve_sal_pc (&sals.sals[i]);
2665
2666 block = block_for_pc (sals.sals[0].pc);
2667 while (block != 0)
2668 {
2669 nsyms = BLOCK_NSYMS (block);
2670 for (i = 0; i < nsyms; i++)
2671 {
2672 sym = BLOCK_SYM (block, i);
2673 switch (SYMBOL_CLASS (sym)) {
2674 default:
2675 case LOC_UNDEF: /* catches errors */
2676 case LOC_CONST: /* constant */
2677 case LOC_STATIC: /* static */
2678 case LOC_REGISTER: /* register */
2679 case LOC_TYPEDEF: /* local typedef */
2680 case LOC_LABEL: /* local label */
2681 case LOC_BLOCK: /* local function */
2682 case LOC_CONST_BYTES: /* loc. byte seq. */
2683 case LOC_UNRESOLVED: /* unresolved static */
2684 case LOC_OPTIMIZED_OUT: /* optimized out */
2685 break;
2686 case LOC_ARG: /* argument */
2687 case LOC_REF_ARG: /* reference arg */
2688 case LOC_REGPARM: /* register arg */
2689 case LOC_REGPARM_ADDR: /* indirect register arg */
2690 case LOC_LOCAL_ARG: /* stack arg */
2691 case LOC_BASEREG_ARG: /* basereg arg */
2692 if (arguments)
2693 Tcl_ListObjAppendElement (interp, result,
2694 Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
2695 break;
2696 case LOC_LOCAL: /* stack local */
2697 case LOC_BASEREG: /* basereg local */
2698 if (!arguments)
2699 Tcl_ListObjAppendElement (interp, result,
2700 Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
2701 break;
2702 }
2703 }
2704 if (BLOCK_FUNCTION (block))
2705 break;
2706 else
2707 block = BLOCK_SUPERBLOCK (block);
2708 }
2709
2710 Tcl_SetObjResult (interp, result);
2711 return TCL_OK;
2712}
2713
2714static int
2715gdb_get_line_command (clientData, interp, objc, objv)
2716 ClientData clientData;
2717 Tcl_Interp *interp;
2718 int objc;
2719 Tcl_Obj *CONST objv[];
2720{
2721 Tcl_Obj *result;
2722 struct symtabs_and_lines sals;
2723 char *args, **canonical;
2724
2725 if (objc != 2)
2726 {
2727 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2728 Tcl_GetStringFromObj (objv[0], NULL),
2729 " linespec\"");
2730 return TCL_ERROR;
2731 }
2732
2733 args = Tcl_GetStringFromObj (objv[1], NULL);
2734 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2735 if (sals.nelts == 1)
2736 {
2737 Tcl_SetObjResult (interp, Tcl_NewIntObj (sals.sals[0].line));
2738 return TCL_OK;
2739 }
2740
2741 Tcl_SetResult (interp, "N/A", TCL_STATIC);
2742 return TCL_OK;
2743}
2744
fed03c01
EZ
2745
2746static int
2747gdb_get_trace_frame_num (clientData, interp, objc, objv)
2748 ClientData clientData;
2749 Tcl_Interp *interp;
2750 int objc;
2751 Tcl_Obj *CONST objv[];
2752{
2753 if (objc != 1)
2754 {
2755 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2756 Tcl_GetStringFromObj (objv[0], NULL),
2757 " linespec\"");
2758 return TCL_ERROR;
2759 }
2760
2761 Tcl_SetObjResult (interp, Tcl_NewIntObj (get_traceframe_number ()));
2762 return TCL_OK;
2763}
2764
2765
2766
018d76dd
KS
2767static int
2768gdb_get_file_command (clientData, interp, objc, objv)
2769 ClientData clientData;
2770 Tcl_Interp *interp;
2771 int objc;
2772 Tcl_Obj *CONST objv[];
2773{
2774 Tcl_Obj *result;
2775 struct symtabs_and_lines sals;
2776 char *args, **canonical;
2777
2778 if (objc != 2)
2779 {
2780 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2781 Tcl_GetStringFromObj (objv[0], NULL),
2782 " linespec\"");
2783 return TCL_ERROR;
2784 }
2785
2786 args = Tcl_GetStringFromObj (objv[1], NULL);
2787 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2788 if (sals.nelts == 1)
2789 {
2790 Tcl_SetResult (interp, sals.sals[0].symtab->filename, TCL_VOLATILE);
2791 return TCL_OK;
2792 }
2793
2794 Tcl_SetResult (interp, "N/A", TCL_STATIC);
2795 return TCL_OK;
2796}
2797
2798static int
2799gdb_get_function_command (clientData, interp, objc, objv)
2800 ClientData clientData;
2801 Tcl_Interp *interp;
2802 int objc;
2803 Tcl_Obj *CONST objv[];
2804{
2805 Tcl_Obj *result;
2806 char *function;
2807 struct symtabs_and_lines sals;
2808 char *args, **canonical;
2809
2810 if (objc != 2)
2811 {
2812 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2813 Tcl_GetStringFromObj (objv[0], NULL),
2814 " linespec\"");
2815 return TCL_ERROR;
2816 }
2817
2818 args = Tcl_GetStringFromObj (objv[1], NULL);
2819 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2820 if (sals.nelts == 1)
2821 {
2822 resolve_sal_pc (&sals.sals[0]);
2823 find_pc_partial_function (sals.sals[0].pc, &function, NULL, NULL);
2824 if (function != NULL)
2825 {
2826 Tcl_SetResult (interp, function, TCL_VOLATILE);
2827 return TCL_OK;
2828 }
2829 }
2830
2831 Tcl_SetResult (interp, "N/A", TCL_STATIC);
2832 return TCL_OK;
2833}
2834
2835static int
2836gdb_get_tracepoint_info (clientData, interp, objc, objv)
2837 ClientData clientData;
2838 Tcl_Interp *interp;
2839 int objc;
2840 Tcl_Obj *CONST objv[];
2841{
2842 struct symtab_and_line sal;
018d76dd
KS
2843 int tpnum;
2844 struct tracepoint *tp;
2845 struct action_line *al;
2846 Tcl_Obj *list, *action_list;
09e4fde2 2847 char *filename, *funcname;
018d76dd
KS
2848 char tmp[19];
2849
2850 if (objc != 2)
2851 error ("wrong # args");
2852
2853 Tcl_GetIntFromObj (NULL, objv[1], &tpnum);
2854
2855 ALL_TRACEPOINTS (tp)
2856 if (tp->number == tpnum)
2857 break;
2858
2859 if (tp == NULL)
2860 error ("Tracepoint #%d does not exist", tpnum);
2861
2862 list = Tcl_NewListObj (0, NULL);
09e4fde2
KS
2863 sal = find_pc_line (tp->address, 0);
2864 filename = symtab_to_filename (sal.symtab);
2865 if (filename == NULL)
2866 filename = "N/A";
2867 Tcl_ListObjAppendElement (interp, list,
2868 Tcl_NewStringObj (filename, -1));
09e4fde2
KS
2869 find_pc_partial_function (tp->address, &funcname, NULL, NULL);
2870 Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj (funcname, -1));
4f17e6eb 2871 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (sal.line));
c62a71b6 2872 sprintf (tmp, "0x%lx", tp->address);
018d76dd
KS
2873 Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj (tmp, -1));
2874 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->enabled));
2875 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->pass_count));
2876 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->step_count));
2877 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->thread));
2878 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->hit_count));
2879
2880 /* Append a list of actions */
2881 action_list = Tcl_NewListObj (0, NULL);
2882 for (al = tp->actions; al != NULL; al = al->next)
2883 {
2884 Tcl_ListObjAppendElement (interp, action_list,
2885 Tcl_NewStringObj (al->action, -1));
2886 }
2887 Tcl_ListObjAppendElement (interp, list, action_list);
2888
2889 Tcl_SetObjResult (interp, list);
2890 return TCL_OK;
2891}
2892
929db6e5
EZ
2893
2894/* TclDebug (const char *fmt, ...) works just like printf() but */
2895/* sends the output to the GDB TK debug window. */
2896/* Not for normal use; just a convenient tool for debugging */
2897void
2898#ifdef ANSI_PROTOTYPES
2899TclDebug (const char *fmt, ...)
2900#else
2901TclDebug (va_alist)
2902 va_dcl
2903#endif
2904{
2905 va_list args;
2906 char buf[512], *v[2], *merge;
2907
2908#ifdef ANSI_PROTOTYPES
2909 va_start (args, fmt);
2910#else
2911 char *fmt;
2912 va_start (args);
2913 fmt = va_arg (args, char *);
2914#endif
2915
2916 v[0] = "debug";
2917 v[1] = buf;
2918
2919 vsprintf (buf, fmt, args);
2920 va_end (args);
2921
2922 merge = Tcl_Merge (2, v);
2923 Tcl_Eval (interp, merge);
2924 Tcl_Free (merge);
2925}
2926
2927
2928/* Find the full pathname to a file, searching the symbol tables */
2929
2930static int
2931gdb_find_file_command (clientData, interp, objc, objv)
2932 ClientData clientData;
2933 Tcl_Interp *interp;
2934 int objc;
2935 Tcl_Obj *CONST objv[];
2936{
2937 char *filename = NULL;
2938 struct symtab *st;
2939
2940 if (objc != 2)
2941 {
2942 Tcl_WrongNumArgs(interp, 1, objv, "filename");
2943 return TCL_ERROR;
2944 }
2945
2946 st = full_lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
2947 if (st)
2948 filename = st->fullname;
2949
2950 if (filename == NULL)
2951 Tcl_SetObjResult (interp, Tcl_NewStringObj ("", 0));
2952 else
2953 Tcl_SetObjResult (interp, Tcl_NewStringObj (filename, -1));
2954
2955 return TCL_OK;
2956}
2957
018d76dd
KS
2958static void
2959gdbtk_create_tracepoint (tp)
2960 struct tracepoint *tp;
2961{
2962 tracepoint_notify (tp, "create");
2963}
2964
2965static void
2966gdbtk_delete_tracepoint (tp)
2967 struct tracepoint *tp;
2968{
2969 tracepoint_notify (tp, "delete");
2970}
2971
a5f4fbff
KS
2972static void
2973gdbtk_modify_tracepoint (tp)
2974 struct tracepoint *tp;
2975{
2976 tracepoint_notify (tp, "modify");
2977}
2978
018d76dd
KS
2979static void
2980tracepoint_notify(tp, action)
2981 struct tracepoint *tp;
2982 const char *action;
2983{
2984 char buf[256];
018d76dd 2985 int v;
09e4fde2
KS
2986 struct symtab_and_line sal;
2987 char *filename;
018d76dd
KS
2988
2989 /* We ensure that ACTION contains no special Tcl characters, so we
2990 can do this. */
09e4fde2
KS
2991 sal = find_pc_line (tp->address, 0);
2992
2993 filename = symtab_to_filename (sal.symtab);
2994 if (filename == NULL)
2995 filename = "N/A";
018d76dd 2996 sprintf (buf, "gdbtk_tcl_tracepoint %s %d 0x%lx %d {%s}", action, tp->number,
41158958 2997 (long)tp->address, sal.line, filename, tp->pass_count);
018d76dd
KS
2998
2999 v = Tcl_Eval (interp, buf);
3000
3001 if (v != TCL_OK)
3002 {
3003 gdbtk_fputs (interp->result, gdb_stdout);
3004 gdbtk_fputs ("\n", gdb_stdout);
3005 }
3006}
3007
3008/* returns -1 if not found, tracepoint # if found */
3009int
3010tracepoint_exists (char * args)
3011{
3012 struct tracepoint *tp;
3013 char **canonical;
3014 struct symtabs_and_lines sals;
3015 char *file = NULL;
3016 int result = -1;
3017
3018 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
3019 if (sals.nelts == 1)
3020 {
3021 resolve_sal_pc (&sals.sals[0]);
3022 file = xmalloc (strlen (sals.sals[0].symtab->dirname)
3023 + strlen (sals.sals[0].symtab->filename) + 1);
3024 if (file != NULL)
3025 {
3026 strcpy (file, sals.sals[0].symtab->dirname);
3027 strcat (file, sals.sals[0].symtab->filename);
3028
3029 ALL_TRACEPOINTS (tp)
3030 {
3031 if (tp->address == sals.sals[0].pc)
3032 result = tp->number;
c62a71b6
KS
3033#if 0
3034 /* Why is this here? This messes up assembly traces */
018d76dd
KS
3035 else if (tp->source_file != NULL
3036 && strcmp (tp->source_file, file) == 0
3037 && sals.sals[0].line == tp->line_number)
018d76dd 3038 result = tp->number;
c62a71b6 3039#endif
018d76dd
KS
3040 }
3041 }
3042 }
3043 if (file != NULL)
3044 free (file);
3045 return result;
3046}
3047
3048static int
3049gdb_actions_command (clientData, interp, objc, objv)
3050 ClientData clientData;
3051 Tcl_Interp *interp;
3052 int objc;
3053 Tcl_Obj *CONST objv[];
3054{
3055 struct tracepoint *tp;
3056 Tcl_Obj **actions;
3057 int nactions, i, len;
3058 char *number, *args, *action;
43b043cf 3059 long step_count;
018d76dd 3060 struct action_line *next = NULL, *temp;
fed03c01 3061 enum actionline_type linetype;
018d76dd
KS
3062
3063 if (objc != 3)
3064 {
3065 Tcl_AppendResult (interp, "wrong # args: should be: \"",
3066 Tcl_GetStringFromObj (objv[0], NULL),
3067 " number actions\"");
3068 return TCL_ERROR;
3069 }
3070
3071 args = number = Tcl_GetStringFromObj (objv[1], NULL);
3072 tp = get_tracepoint_by_number (&args);
3073 if (tp == NULL)
3074 {
3075 Tcl_AppendResult (interp, "Tracepoint \"", number, "\" does not exist");
3076 return TCL_ERROR;
3077 }
3078
3079 /* Free any existing actions */
a5f4fbff
KS
3080 if (tp->actions != NULL)
3081 free_actions (tp);
3082
43b043cf 3083 step_count = 0;
018d76dd
KS
3084
3085 Tcl_ListObjGetElements (interp, objv[2], &nactions, &actions);
fed03c01
EZ
3086
3087 /* Add the actions to the tracepoint */
018d76dd
KS
3088 for (i = 0; i < nactions; i++)
3089 {
3090 temp = xmalloc (sizeof (struct action_line));
3091 temp->next = NULL;
3092 action = Tcl_GetStringFromObj (actions[i], &len);
3093 temp->action = savestring (action, len);
fed03c01
EZ
3094
3095 linetype = validate_actionline (&(temp->action), tp);
3096
3097 if (linetype == BADLINE)
3098 {
3099 free (temp);
3100 continue;
3101 }
3102
018d76dd
KS
3103 if (next == NULL)
3104 {
3105 tp->actions = temp;
3106 next = temp;
3107 }
3108 else
3109 {
3110 next->next = temp;
3111 next = temp;
3112 }
3113 }
3114
3115 return TCL_OK;
3116}
3117
3118static int
3119gdb_tracepoint_exists_command (clientData, interp, objc, objv)
3120 ClientData clientData;
3121 Tcl_Interp *interp;
3122 int objc;
3123 Tcl_Obj *CONST objv[];
3124{
3125 char * args;
3126
3127 if (objc != 2)
3128 {
3129 Tcl_AppendResult (interp, "wrong # of args: should be \"",
3130 Tcl_GetStringFromObj (objv[0], NULL),
3131 " function:line|function|line|*addr\"");
3132 return TCL_ERROR;
3133 }
3134
3135 args = Tcl_GetStringFromObj (objv[1], NULL);
3136
3137 Tcl_SetObjResult (interp, Tcl_NewIntObj (tracepoint_exists (args)));
3138 return TCL_OK;
3139}
3140
3141/* Return the prompt to the interpreter */
3142static int
3143gdb_prompt_command (clientData, interp, objc, objv)
3144 ClientData clientData;
3145 Tcl_Interp *interp;
3146 int objc;
3147 Tcl_Obj *CONST objv[];
3148{
3149 Tcl_SetResult (interp, get_prompt (), TCL_VOLATILE);
3150 return TCL_OK;
3151}
3152
4f17e6eb
KS
3153/* return a list of all tracepoint numbers in interpreter */
3154static int
3155gdb_get_tracepoint_list (clientData, interp, objc, objv)
3156 ClientData clientData;
3157 Tcl_Interp *interp;
3158 int objc;
3159 Tcl_Obj *CONST objv[];
3160{
3161 Tcl_Obj *list;
3162 struct tracepoint *tp;
3163
3164 list = Tcl_NewListObj (0, NULL);
3165
3166 ALL_TRACEPOINTS (tp)
3167 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->number));
3168
3169 Tcl_SetObjResult (interp, list);
3170 return TCL_OK;
3171}
e0f7db02 3172
e0f7db02 3173
929db6e5
EZ
3174/* This hook is called whenever we are ready to load a symbol file so that
3175 the UI can notify the user... */
3176void
3177gdbtk_pre_add_symbol (name)
3178 char *name;
3179{
e924e162 3180 char *merge, *v[2];
e0f7db02 3181
e924e162
EZ
3182 v[0] = "gdbtk_tcl_pre_add_symbol";
3183 v[1] = name;
3184 merge = Tcl_Merge (2, v);
3185 Tcl_Eval (interp, merge);
3186 Tcl_Free (merge);
929db6e5 3187}
e0f7db02 3188
929db6e5
EZ
3189/* This hook is called whenever we finish loading a symbol file. */
3190void
3191gdbtk_post_add_symbol ()
3192{
3193 Tcl_Eval (interp, "gdbtk_tcl_post_add_symbol");
3194}
e0f7db02 3195
e0f7db02 3196
e0f7db02 3197
929db6e5
EZ
3198static void
3199gdbtk_print_frame_info (s, line, stopline, noerror)
3200 struct symtab *s;
3201 int line;
3202 int stopline;
3203 int noerror;
3204{
3205 current_source_symtab = s;
3206 current_source_line = line;
3207}
3208
3209
3210/* The lookup_symtab() in symtab.c doesn't work correctly */
3211/* It will not work will full pathnames and if multiple */
3212/* source files have the same basename, it will return */
3213/* the first one instead of the correct one. This version */
3214/* also always makes sure symtab->fullname is set. */
3215
3216static struct symtab *
3217full_lookup_symtab(file)
3218 char *file;
3219{
3220 struct symtab *st;
3221 struct objfile *objfile;
3222 char *bfile, *fullname;
3223 struct partial_symtab *pt;
3224
3225 if (!file)
3226 return NULL;
3227
3228 /* first try a direct lookup */
3229 st = lookup_symtab (file);
3230 if (st)
3231 {
3232 if (!st->fullname)
3233 symtab_to_filename(st);
3234 return st;
3235 }
3236
3237 /* if the direct approach failed, try */
3238 /* looking up the basename and checking */
3239 /* all matches with the fullname */
3240 bfile = basename (file);
3241 ALL_SYMTABS (objfile, st)
3242 {
3243 if (!strcmp (bfile, basename(st->filename)))
3244 {
3245 if (!st->fullname)
3246 fullname = symtab_to_filename (st);
3247 else
3248 fullname = st->fullname;
3249
3250 if (!strcmp (file, fullname))
3251 return st;
3252 }
3253 }
3254
3255 /* still no luck? look at psymtabs */
3256 ALL_PSYMTABS (objfile, pt)
3257 {
3258 if (!strcmp (bfile, basename(pt->filename)))
3259 {
3260 st = PSYMTAB_TO_SYMTAB (pt);
3261 if (st)
3262 {
3263 fullname = symtab_to_filename (st);
3264 if (!strcmp (file, fullname))
3265 return st;
3266 }
3267 }
3268 }
3269 return NULL;
3270}
3271
e6e9507d
EZ
3272static int
3273perror_with_name_wrapper (args)
3274 char * args;
3275{
3276 perror_with_name (args);
3277 return 1;
3278}
929db6e5
EZ
3279
3280/* gdb_loadfile loads a c source file into a text widget. */
3281
3282/* LTABLE_SIZE is the number of bytes to allocate for the */
3283/* line table. Its size limits the maximum number of lines */
3284/* in a file to 8 * LTABLE_SIZE. This memory is freed after */
3285/* the file is loaded, so it is OK to make this very large. */
3286/* Additional memory will be allocated if needed. */
3287#define LTABLE_SIZE 20000
e0f7db02 3288
e0f7db02 3289static int
929db6e5 3290gdb_loadfile (clientData, interp, objc, objv)
e0f7db02
KS
3291 ClientData clientData;
3292 Tcl_Interp *interp;
3293 int objc;
3294 Tcl_Obj *CONST objv[];
3295{
929db6e5
EZ
3296 char *file, *widget, *line, *buf, msg[128];
3297 int linenumbers, ln, anum, lnum, ltable_size;
3298 Tcl_Obj *a[2], *b[2], *cmd;
3299 FILE *fp;
3300 char *ltable;
3301 struct symtab *symtab;
3302 struct linetable_entry *le;
e6e9507d
EZ
3303 long mtime = 0;
3304 struct stat st;
3305
929db6e5
EZ
3306
3307 if (objc != 4)
3308 {
3309 Tcl_WrongNumArgs(interp, 1, objv, "widget filename linenumbers");
3310 return TCL_ERROR;
3311 }
e0f7db02 3312
929db6e5
EZ
3313 widget = Tcl_GetStringFromObj (objv[1], NULL);
3314 file = Tcl_GetStringFromObj (objv[2], NULL);
3315 Tcl_GetBooleanFromObj (interp, objv[3], &linenumbers);
3316
3317 if ((fp = fopen ( file, "r" )) == NULL)
3318 return TCL_ERROR;
3319
3320 symtab = full_lookup_symtab (file);
3321 if (!symtab)
e0f7db02 3322 {
ed5fa7c3
MH
3323 sprintf(msg, "File not found");
3324 Tcl_SetStringObj ( Tcl_GetObjResult (interp), msg, -1);
929db6e5 3325 fclose (fp);
e0f7db02
KS
3326 return TCL_ERROR;
3327 }
3328
d2a3ee23 3329 if (stat (file, &st) < 0)
e6e9507d
EZ
3330 {
3331 catch_errors (perror_with_name_wrapper, "gdbtk: get time stamp", "",
3332 RETURN_MASK_ALL);
3333 return TCL_ERROR;
3334 }
3335
3336 if (symtab && symtab->objfile && symtab->objfile->obfd)
3337 mtime = bfd_get_mtime(symtab->objfile->obfd);
3338 else if (exec_bfd)
3339 mtime = bfd_get_mtime(exec_bfd);
3340
3341 if (mtime && mtime < st.st_mtime)
cb432079 3342 gdbtk_ignorable_warning("Source file is more recent than executable.\n");
e6e9507d
EZ
3343
3344
929db6e5
EZ
3345 /* Source linenumbers don't appear to be in order, and a sort is */
3346 /* too slow so the fastest solution is just to allocate a huge */
3347 /* array and set the array entry for each linenumber */
3348
3349 ltable_size = LTABLE_SIZE;
3350 ltable = (char *)malloc (LTABLE_SIZE);
3351 if (ltable == NULL)
3352 {
3353 sprintf(msg, "Out of memory.");
3354 Tcl_SetStringObj ( Tcl_GetObjResult (interp), msg, -1);
3355 fclose (fp);
3356 return TCL_ERROR;
3357 }
3358
3359 memset (ltable, 0, LTABLE_SIZE);
3360
3361 if (symtab->linetable && symtab->linetable->nitems)
3362 {
3363 le = symtab->linetable->item;
3364 for (ln = symtab->linetable->nitems ;ln > 0; ln--, le++)
3365 {
3366 lnum = le->line >> 3;
3367 if (lnum >= ltable_size)
3368 {
3369 char *new_ltable;
3370 new_ltable = (char *)realloc (ltable, ltable_size*2);
3371 memset (new_ltable + ltable_size, 0, ltable_size);
3372 ltable_size *= 2;
3373 if (new_ltable == NULL)
3374 {
3375 sprintf(msg, "Out of memory.");
3376 Tcl_SetStringObj ( Tcl_GetObjResult (interp), msg, -1);
3377 free (ltable);
3378 fclose (fp);
3379 return TCL_ERROR;
3380 }
3381 ltable = new_ltable;
3382 }
3383 ltable[lnum] |= 1 << (le->line % 8);
3384 }
3385 }
11f91b2b 3386
929db6e5
EZ
3387 /* create an object with enough space, then grab its */
3388 /* buffer and sprintf directly into it. */
3389 a[0] = Tcl_NewStringObj (ltable, 1024);
3390 a[1] = Tcl_NewListObj(0,NULL);
3391 buf = a[0]->bytes;
3392 b[0] = Tcl_NewStringObj (ltable,1024);
3393 b[1] = Tcl_NewStringObj ("source_tag", -1);
3394 Tcl_IncrRefCount (b[0]);
3395 Tcl_IncrRefCount (b[1]);
3396 line = b[0]->bytes + 1;
3397 strcpy(b[0]->bytes,"\t");
3398
3399 ln = 1;
3400 while (fgets (line, 980, fp))
3401 {
3402 if (linenumbers)
3403 {
3404 if (ltable[ln >> 3] & (1 << (ln % 8)))
390ca26a
KS
3405 {
3406 sprintf (buf,"%s insert end {-\t%d} break_tag", widget, ln);
3407 a[0]->length = strlen (buf);
3408 }
929db6e5 3409 else
390ca26a
KS
3410 {
3411 sprintf (buf,"%s insert end { \t%d} \"\"", widget, ln);
3412 a[0]->length = strlen (buf);
3413 }
929db6e5
EZ
3414 }
3415 else
3416 {
3417 if (ltable[ln >> 3] & (1 << (ln % 8)))
390ca26a
KS
3418 {
3419 sprintf (buf,"%s insert end {-\t} break_tag", widget);
3420 a[0]->length = strlen (buf);
3421 }
929db6e5 3422 else
390ca26a
KS
3423 {
3424 sprintf (buf,"%s insert end { \t} \"\"", widget);
3425 a[0]->length = strlen (buf);
3426 }
929db6e5
EZ
3427 }
3428 b[0]->length = strlen(b[0]->bytes);
3429 Tcl_SetListObj(a[1],2,b);
3430 cmd = Tcl_ConcatObj(2,a);
3431 Tcl_EvalObj (interp, cmd);
3432 Tcl_DecrRefCount (cmd);
3433 ln++;
3434 }
3435 Tcl_DecrRefCount (b[0]);
3436 Tcl_DecrRefCount (b[0]);
3437 Tcl_DecrRefCount (b[1]);
3438 Tcl_DecrRefCount (b[1]);
3439 free (ltable);
3440 fclose (fp);
11f91b2b
KS
3441 return TCL_OK;
3442}
3443
929db6e5
EZ
3444/* at some point make these static in breakpoint.c and move GUI code there */
3445extern struct breakpoint *set_raw_breakpoint (struct symtab_and_line sal);
3446extern void set_breakpoint_count (int);
3447extern int breakpoint_count;
3448
3449/* set a breakpoint by source file and line number */
3450/* flags are as follows: */
3451/* least significant 2 bits are disposition, rest is */
3452/* type (normally 0).
3453
3454enum bptype {
3455 bp_breakpoint, Normal breakpoint
3456 bp_hardware_breakpoint, Hardware assisted breakpoint
3457}
3458
3459Disposition of breakpoint. Ie: what to do after hitting it.
3460enum bpdisp {
3461 del, Delete it
3462 del_at_next_stop, Delete at next stop, whether hit or not
3463 disable, Disable it
3464 donttouch Leave it alone
3465 };
3466*/
3467
3468static int
3469gdb_set_bp (clientData, interp, objc, objv)
3470 ClientData clientData;
3471 Tcl_Interp *interp;
3472 int objc;
3473 Tcl_Obj *CONST objv[];
3474
11f91b2b 3475{
929db6e5
EZ
3476 struct symtab_and_line sal;
3477 int line, flags, ret;
3478 struct breakpoint *b;
3479 char buf[64];
3480 Tcl_Obj *a[5], *cmd;
e0f7db02 3481
929db6e5 3482 if (objc != 4)
e0f7db02 3483 {
929db6e5
EZ
3484 Tcl_WrongNumArgs(interp, 1, objv, "filename line type");
3485 return TCL_ERROR;
e0f7db02 3486 }
11f91b2b 3487
929db6e5
EZ
3488 sal.symtab = full_lookup_symtab (Tcl_GetStringFromObj( objv[1], NULL));
3489 if (sal.symtab == NULL)
3490 return TCL_ERROR;
3491
3492 if (Tcl_GetIntFromObj( interp, objv[2], &line) == TCL_ERROR)
3493 return TCL_ERROR;
3494
3495 if (Tcl_GetIntFromObj( interp, objv[3], &flags) == TCL_ERROR)
3496 return TCL_ERROR;
3497
3498 sal.line = line;
3499 sal.pc = find_line_pc (sal.symtab, sal.line);
3500 if (sal.pc == 0)
3501 return TCL_ERROR;
3502
3503 sal.section = find_pc_overlay (sal.pc);
3504 b = set_raw_breakpoint (sal);
3505 set_breakpoint_count (breakpoint_count + 1);
3506 b->number = breakpoint_count;
3507 b->type = flags >> 2;
3508 b->disposition = flags & 3;
3509
3510 /* FIXME: this won't work for duplicate basenames! */
3511 sprintf (buf, "%s:%d", basename(Tcl_GetStringFromObj( objv[1], NULL)), line);
3512 b->addr_string = strsave (buf);
3513
3514 /* now send notification command back to GUI */
3515 sprintf (buf, "0x%x", sal.pc);
3516 a[0] = Tcl_NewStringObj ("gdbtk_tcl_breakpoint create", -1);
3517 a[1] = Tcl_NewIntObj (b->number);
3518 a[2] = Tcl_NewStringObj (buf, -1);
3519 a[3] = objv[2];
3520 a[4] = Tcl_NewListObj (1,&objv[1]);
3521 cmd = Tcl_ConcatObj(5,a);
3522 ret = Tcl_EvalObj (interp, cmd);
3523 Tcl_DecrRefCount (cmd);
3524 return ret;
11f91b2b 3525}
4f17e6eb 3526
3f37b696 3527/* Come here during initialize_all_files () */
754e5da2
SG
3528
3529void
3530_initialize_gdbtk ()
3531{
c5197511
SG
3532 if (use_windows)
3533 {
3534 /* Tell the rest of the world that Gdbtk is now set up. */
754e5da2 3535
c5197511 3536 init_ui_hook = gdbtk_init;
47792960
KS
3537#ifdef __CYGWIN32__
3538 (void) FreeConsole ();
3539#endif
c5197511 3540 }
cb432079
EZ
3541#ifdef __CYGWIN32__
3542 else
3543 {
3544 DWORD ft = GetFileType (GetStdHandle (STD_INPUT_HANDLE));
3545 void cygwin32_attach_handle_to_fd (char *, int, HANDLE, int, int);
3546
3547 switch (ft)
3548 {
3549 case FILE_TYPE_DISK:
3550 case FILE_TYPE_CHAR:
3551 case FILE_TYPE_PIPE:
3552 break;
3553 default:
3554 AllocConsole();
3555 cygwin32_attach_handle_to_fd ("/dev/conin", 0,
3556 GetStdHandle (STD_INPUT_HANDLE),
3557 1, GENERIC_READ);
3558 cygwin32_attach_handle_to_fd ("/dev/conout", 1,
3559 GetStdHandle (STD_OUTPUT_HANDLE),
3560 0, GENERIC_WRITE);
3561 cygwin32_attach_handle_to_fd ("/dev/conout", 2,
3562 GetStdHandle (STD_ERROR_HANDLE),
3563 0, GENERIC_WRITE);
3564 break;
3565 }
3566 }
3567#endif
754e5da2 3568}
This page took 0.343144 seconds and 4 git commands to generate.