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