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