New function hw_strdup() - use memory tied to hw device.
[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;
d7363521
JM
1220 char *lastfile, *pathname, **files;
1221 int files_size;
0776b0b0
MH
1222 int i, numfiles = 0, len = 0;
1223 Tcl_Obj *mylist;
1224
d7363521 1225 files_size = 1000;
94ec3e76 1226 files = (char **) xmalloc (sizeof (char *) * files_size);
d7363521 1227
0776b0b0
MH
1228 if (objc > 2)
1229 {
1230 Tcl_WrongNumArgs (interp, 1, objv, "Usage: gdb_listfiles ?pathname?");
1231 return TCL_ERROR;
1232 }
1233 else if (objc == 2)
1234 pathname = Tcl_GetStringFromObj (objv[1], &len);
1235
1236 mylist = Tcl_NewListObj (0, NULL);
754e5da2
SG
1237
1238 ALL_PSYMTABS (objfile, psymtab)
0776b0b0 1239 {
d7363521
JM
1240 if (numfiles == files_size)
1241 {
1242 files_size = files_size * 2;
94ec3e76 1243 files = (char **) xrealloc (files, sizeof (char *) * files_size);
d7363521 1244 }
0776b0b0
MH
1245 if (len == 0)
1246 {
1247 if (psymtab->filename)
1248 files[numfiles++] = basename(psymtab->filename);
1249 }
1250 else if (!strcmp(psymtab->filename,basename(psymtab->filename))
1251 || !strncmp(pathname,psymtab->filename,len))
1252 if (psymtab->filename)
1253 files[numfiles++] = basename(psymtab->filename);
1254 }
754e5da2 1255
546b8ca7 1256 ALL_SYMTABS (objfile, symtab)
0776b0b0 1257 {
d7363521
JM
1258 if (numfiles == files_size)
1259 {
1260 files_size = files_size * 2;
94ec3e76 1261 files = (char **) xrealloc (files, sizeof (char *) * files_size);
d7363521 1262 }
0776b0b0
MH
1263 if (len == 0)
1264 {
1265 if (symtab->filename)
1266 files[numfiles++] = basename(symtab->filename);
1267 }
1268 else if (!strcmp(symtab->filename,basename(symtab->filename))
1269 || !strncmp(pathname,symtab->filename,len))
1270 if (symtab->filename)
1271 files[numfiles++] = basename(symtab->filename);
1272 }
1273
1274 qsort (files, numfiles, sizeof(char *), comp_files);
546b8ca7 1275
0776b0b0
MH
1276 lastfile = "";
1277 for (i = 0; i < numfiles; i++)
1278 {
1279 if (strcmp(files[i],lastfile))
1280 Tcl_ListObjAppendElement (interp, mylist, Tcl_NewStringObj(files[i], -1));
1281 lastfile = files[i];
1282 }
1283 Tcl_SetObjResult (interp, mylist);
d7363521 1284 free (files);
754e5da2
SG
1285 return TCL_OK;
1286}
479f0f18 1287
99c98415
MH
1288static int
1289gdb_listfuncs (clientData, interp, argc, argv)
1290 ClientData clientData;
1291 Tcl_Interp *interp;
1292 int argc;
1293 char *argv[];
1294{
1295 struct symtab *symtab;
1296 struct blockvector *bv;
1297 struct block *b;
1298 struct symbol *sym;
1299 int i,j;
1300
1301 if (argc != 2)
1302 error ("wrong # args");
1303
1304 symtab = lookup_symtab (argv[1]);
1305
1306 if (!symtab)
1307 error ("No such file");
1308
1309 bv = BLOCKVECTOR (symtab);
1310 for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
1311 {
1312 b = BLOCKVECTOR_BLOCK (bv, i);
1313 /* Skip the sort if this block is always sorted. */
1314 if (!BLOCK_SHOULD_SORT (b))
1315 sort_block_syms (b);
1316 for (j = 0; j < BLOCK_NSYMS (b); j++)
1317 {
1318 sym = BLOCK_SYM (b, j);
1319 if (SYMBOL_CLASS (sym) == LOC_BLOCK)
1320 {
1321 Tcl_DStringAppendElement (result_ptr, SYMBOL_NAME(sym));
1322 }
1323 }
1324 }
1325 return TCL_OK;
1326}
1327
479f0f18
SG
1328static int
1329gdb_stop (clientData, interp, argc, argv)
1330 ClientData clientData;
1331 Tcl_Interp *interp;
1332 int argc;
1333 char *argv[];
1334{
c14cabba
AC
1335 if (target_stop)
1336 target_stop ();
1337 else
1338 quit_flag = 1; /* hope something sees this */
546b8ca7
SG
1339
1340 return TCL_OK;
479f0f18 1341}
018d76dd
KS
1342
1343/* Prepare to accept a new executable file. This is called when we
1344 want to clear away everything we know about the old file, without
1345 asking the user. The Tcl code will have already asked the user if
1346 necessary. After this is called, we should be able to run the
1347 `file' command without getting any questions. */
1348
1349static int
1350gdb_clear_file (clientData, interp, argc, argv)
1351 ClientData clientData;
1352 Tcl_Interp *interp;
1353 int argc;
1354 char *argv[];
1355{
1356 if (inferior_pid != 0 && target_has_execution)
1357 {
1358 if (attach_flag)
1359 target_detach (NULL, 0);
1360 else
1361 target_kill ();
1362 }
1363
1364 if (target_has_execution)
1365 pop_target ();
1366
1367 symbol_file_command (NULL, 0);
1368
0776b0b0
MH
1369 /* gdb_loc refers to stop_pc, but nothing seems to clear it, so we
1370 clear it here. FIXME: This seems like an abstraction violation
1371 somewhere. */
1372 stop_pc = 0;
1373
018d76dd
KS
1374 return TCL_OK;
1375}
1376
1377/* Ask the user to confirm an exit request. */
1378
1379static int
1380gdb_confirm_quit (clientData, interp, argc, argv)
1381 ClientData clientData;
1382 Tcl_Interp *interp;
1383 int argc;
1384 char *argv[];
1385{
1386 int ret;
1387
1388 ret = quit_confirm ();
1389 Tcl_DStringAppendElement (result_ptr, ret ? "1" : "0");
1390 return TCL_OK;
1391}
1392
1393/* Quit without asking for confirmation. */
1394
1395static int
1396gdb_force_quit (clientData, interp, argc, argv)
1397 ClientData clientData;
1398 Tcl_Interp *interp;
1399 int argc;
1400 char *argv[];
1401{
1402 quit_force ((char *) NULL, 1);
1403 return TCL_OK;
1404}
09722039
SG
1405\f
1406/* This implements the TCL command `gdb_disassemble'. */
479f0f18 1407
09722039
SG
1408static int
1409gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
1410 bfd_vma memaddr;
1411 bfd_byte *myaddr;
1412 int len;
1413 disassemble_info *info;
1414{
1415 extern struct target_ops exec_ops;
1416 int res;
1417
1418 errno = 0;
1419 res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
1420
1421 if (res == len)
1422 return 0;
1423 else
1424 if (errno == 0)
1425 return EIO;
1426 else
1427 return errno;
1428}
1429
1430/* We need a different sort of line table from the normal one cuz we can't
1431 depend upon implicit line-end pc's for lines. This is because of the
1432 reordering we are about to do. */
1433
1434struct my_line_entry {
1435 int line;
1436 CORE_ADDR start_pc;
1437 CORE_ADDR end_pc;
1438};
1439
1440static int
1441compare_lines (mle1p, mle2p)
1442 const PTR mle1p;
1443 const PTR mle2p;
1444{
1445 struct my_line_entry *mle1, *mle2;
1446 int val;
1447
1448 mle1 = (struct my_line_entry *) mle1p;
1449 mle2 = (struct my_line_entry *) mle2p;
1450
1451 val = mle1->line - mle2->line;
1452
1453 if (val != 0)
1454 return val;
1455
1456 return mle1->start_pc - mle2->start_pc;
1457}
1458
1459static int
1460gdb_disassemble (clientData, interp, argc, argv)
1461 ClientData clientData;
1462 Tcl_Interp *interp;
1463 int argc;
1464 char *argv[];
1465{
1466 CORE_ADDR pc, low, high;
1467 int mixed_source_and_assembly;
fc941258
DE
1468 static disassemble_info di;
1469 static int di_initialized;
1470
1471 if (! di_initialized)
1472 {
91550191
SG
1473 INIT_DISASSEMBLE_INFO_NO_ARCH (di, gdb_stdout,
1474 (fprintf_ftype) fprintf_unfiltered);
caeec767 1475 di.flavour = bfd_target_unknown_flavour;
fc941258
DE
1476 di.memory_error_func = dis_asm_memory_error;
1477 di.print_address_func = dis_asm_print_address;
1478 di_initialized = 1;
1479 }
09722039 1480
91550191
SG
1481 di.mach = tm_print_insn_info.mach;
1482 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
e4bb9027 1483 di.endian = BFD_ENDIAN_BIG;
91550191 1484 else
e4bb9027 1485 di.endian = BFD_ENDIAN_LITTLE;
91550191 1486
09722039 1487 if (argc != 3 && argc != 4)
6131622e 1488 error ("wrong # args");
09722039
SG
1489
1490 if (strcmp (argv[1], "source") == 0)
1491 mixed_source_and_assembly = 1;
1492 else if (strcmp (argv[1], "nosource") == 0)
1493 mixed_source_and_assembly = 0;
1494 else
6131622e 1495 error ("First arg must be 'source' or 'nosource'");
09722039
SG
1496
1497 low = parse_and_eval_address (argv[2]);
1498
1499 if (argc == 3)
1500 {
1501 if (find_pc_partial_function (low, NULL, &low, &high) == 0)
6131622e 1502 error ("No function contains specified address");
09722039
SG
1503 }
1504 else
1505 high = parse_and_eval_address (argv[3]);
1506
1507 /* If disassemble_from_exec == -1, then we use the following heuristic to
1508 determine whether or not to do disassembly from target memory or from the
1509 exec file:
1510
1511 If we're debugging a local process, read target memory, instead of the
1512 exec file. This makes disassembly of functions in shared libs work
1513 correctly.
1514
1515 Else, we're debugging a remote process, and should disassemble from the
fda6fadc 1516 exec file for speed. However, this is no good if the target modifies its
09722039
SG
1517 code (for relocation, or whatever).
1518 */
1519
1520 if (disassemble_from_exec == -1)
1521 if (strcmp (target_shortname, "child") == 0
d7c4766c
SS
1522 || strcmp (target_shortname, "procfs") == 0
1523 || strcmp (target_shortname, "vxprocess") == 0)
09722039
SG
1524 disassemble_from_exec = 0; /* It's a child process, read inferior mem */
1525 else
1526 disassemble_from_exec = 1; /* It's remote, read the exec file */
1527
1528 if (disassemble_from_exec)
a76ef70a
SG
1529 di.read_memory_func = gdbtk_dis_asm_read_memory;
1530 else
1531 di.read_memory_func = dis_asm_read_memory;
09722039
SG
1532
1533 /* If just doing straight assembly, all we need to do is disassemble
1534 everything between low and high. If doing mixed source/assembly, we've
1535 got a totally different path to follow. */
1536
1537 if (mixed_source_and_assembly)
1538 { /* Come here for mixed source/assembly */
1539 /* The idea here is to present a source-O-centric view of a function to
1540 the user. This means that things are presented in source order, with
1541 (possibly) out of order assembly immediately following. */
1542 struct symtab *symtab;
1543 struct linetable_entry *le;
1544 int nlines;
c81a3fa9 1545 int newlines;
09722039
SG
1546 struct my_line_entry *mle;
1547 struct symtab_and_line sal;
1548 int i;
1549 int out_of_order;
c81a3fa9 1550 int next_line;
09722039
SG
1551
1552 symtab = find_pc_symtab (low); /* Assume symtab is valid for whole PC range */
1553
1554 if (!symtab)
1555 goto assembly_only;
1556
1557/* First, convert the linetable to a bunch of my_line_entry's. */
1558
1559 le = symtab->linetable->item;
1560 nlines = symtab->linetable->nitems;
1561
1562 if (nlines <= 0)
1563 goto assembly_only;
1564
1565 mle = (struct my_line_entry *) alloca (nlines * sizeof (struct my_line_entry));
1566
1567 out_of_order = 0;
1568
c81a3fa9
SG
1569/* Copy linetable entries for this function into our data structure, creating
1570 end_pc's and setting out_of_order as appropriate. */
1571
1572/* First, skip all the preceding functions. */
1573
1574 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
1575
1576/* Now, copy all entries before the end of this function. */
1577
1578 newlines = 0;
1579 for (; i < nlines - 1 && le[i].pc < high; i++)
09722039 1580 {
c81a3fa9
SG
1581 if (le[i].line == le[i + 1].line
1582 && le[i].pc == le[i + 1].pc)
1583 continue; /* Ignore duplicates */
1584
1585 mle[newlines].line = le[i].line;
09722039
SG
1586 if (le[i].line > le[i + 1].line)
1587 out_of_order = 1;
c81a3fa9
SG
1588 mle[newlines].start_pc = le[i].pc;
1589 mle[newlines].end_pc = le[i + 1].pc;
1590 newlines++;
09722039
SG
1591 }
1592
c81a3fa9
SG
1593/* If we're on the last line, and it's part of the function, then we need to
1594 get the end pc in a special way. */
1595
1596 if (i == nlines - 1
1597 && le[i].pc < high)
1598 {
1599 mle[newlines].line = le[i].line;
1600 mle[newlines].start_pc = le[i].pc;
1601 sal = find_pc_line (le[i].pc, 0);
1602 mle[newlines].end_pc = sal.end;
1603 newlines++;
1604 }
09722039
SG
1605
1606/* Now, sort mle by line #s (and, then by addresses within lines). */
1607
1608 if (out_of_order)
c81a3fa9 1609 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
09722039
SG
1610
1611/* Now, for each line entry, emit the specified lines (unless they have been
1612 emitted before), followed by the assembly code for that line. */
1613
c81a3fa9
SG
1614 next_line = 0; /* Force out first line */
1615 for (i = 0; i < newlines; i++)
09722039 1616 {
c81a3fa9
SG
1617/* Print out everything from next_line to the current line. */
1618
1619 if (mle[i].line >= next_line)
09722039 1620 {
c81a3fa9
SG
1621 if (next_line != 0)
1622 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
09722039 1623 else
c81a3fa9
SG
1624 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
1625
1626 next_line = mle[i].line + 1;
09722039 1627 }
c81a3fa9 1628
09722039
SG
1629 for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
1630 {
1631 QUIT;
1632 fputs_unfiltered (" ", gdb_stdout);
1633 print_address (pc, gdb_stdout);
1634 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 1635 pc += (*tm_print_insn) (pc, &di);
09722039
SG
1636 fputs_unfiltered ("\n", gdb_stdout);
1637 }
1638 }
1639 }
1640 else
1641 {
1642assembly_only:
1643 for (pc = low; pc < high; )
1644 {
1645 QUIT;
1646 fputs_unfiltered (" ", gdb_stdout);
1647 print_address (pc, gdb_stdout);
1648 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 1649 pc += (*tm_print_insn) (pc, &di);
09722039
SG
1650 fputs_unfiltered ("\n", gdb_stdout);
1651 }
1652 }
1653
09722039
SG
1654 gdb_flush (gdb_stdout);
1655
1656 return TCL_OK;
1657}
754e5da2
SG
1658\f
1659static void
1660tk_command (cmd, from_tty)
1661 char *cmd;
1662 int from_tty;
1663{
546b8ca7
SG
1664 int retval;
1665 char *result;
1666 struct cleanup *old_chain;
1667
572977a5
FF
1668 /* Catch case of no argument, since this will make the tcl interpreter dump core. */
1669 if (cmd == NULL)
1670 error_no_arg ("tcl command to interpret");
1671
546b8ca7
SG
1672 retval = Tcl_Eval (interp, cmd);
1673
1674 result = strdup (interp->result);
754e5da2 1675
546b8ca7
SG
1676 old_chain = make_cleanup (free, result);
1677
1678 if (retval != TCL_OK)
1679 error (result);
1680
1681 printf_unfiltered ("%s\n", result);
1682
1683 do_cleanups (old_chain);
754e5da2
SG
1684}
1685
1686static void
1687cleanup_init (ignored)
1688 int ignored;
1689{
754e5da2
SG
1690 if (interp != NULL)
1691 Tcl_DeleteInterp (interp);
1692 interp = NULL;
1693}
1694
637b1661
SG
1695/* Come here during long calculations to check for GUI events. Usually invoked
1696 via the QUIT macro. */
1697
1698static void
1699gdbtk_interactive ()
1700{
1701 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
1702}
1703
479f0f18
SG
1704/* Come here when there is activity on the X file descriptor. */
1705
1706static void
1707x_event (signo)
1708 int signo;
1709{
1710 /* Process pending events */
1711
0776b0b0
MH
1712 while (Tcl_DoOneEvent (TCL_DONT_WAIT|TCL_ALL_EVENTS) != 0)
1713 ;
1714
1715 /* If we are doing a download, see if the download should be
1716 cancelled. FIXME: We should use a better variable name. */
1717 if (load_in_progress)
1718 {
1719 char *val;
1720
1721 val = Tcl_GetVar (interp, "download_cancel_ok", TCL_GLOBAL_ONLY);
1722 if (val != NULL && atoi (val))
1723 {
1724 quit_flag = 1;
1725#ifdef REQUEST_QUIT
1726 REQUEST_QUIT;
1727#else
1728 if (immediate_quit)
1729 quit ();
1730#endif
1731 }
1732 }
479f0f18
SG
1733}
1734
018d76dd
KS
1735#ifdef __CYGWIN32__
1736
1737/* For Cygwin32, we use a timer to periodically check for Windows
1738 messages. FIXME: It would be better to not poll, but to instead
1739 rewrite the target_wait routines to serve as input sources.
1740 Unfortunately, that will be a lot of work. */
1741
1742static void
1743gdbtk_start_timer ()
1744{
1745 sigset_t nullsigmask;
1746 struct sigaction action;
1747 struct itimerval it;
1748
1749 sigemptyset (&nullsigmask);
1750
1751 action.sa_handler = x_event;
1752 action.sa_mask = nullsigmask;
1753 action.sa_flags = 0;
1754 sigaction (SIGALRM, &action, NULL);
1755
1756 it.it_interval.tv_sec = 0;
1757 /* Check for messages twice a second. */
1758 it.it_interval.tv_usec = 500 * 1000;
1759 it.it_value.tv_sec = 0;
1760 it.it_value.tv_usec = 500 * 1000;
1761
1762 setitimer (ITIMER_REAL, &it, NULL);
0776b0b0
MH
1763
1764 gdbtk_timer_going = 1;
018d76dd
KS
1765}
1766
1767static void
1768gdbtk_stop_timer ()
1769{
1770 sigset_t nullsigmask;
1771 struct sigaction action;
1772 struct itimerval it;
1773
0776b0b0
MH
1774 gdbtk_timer_going = 0;
1775
018d76dd
KS
1776 sigemptyset (&nullsigmask);
1777
1778 action.sa_handler = SIG_IGN;
1779 action.sa_mask = nullsigmask;
1780 action.sa_flags = 0;
1781 sigaction (SIGALRM, &action, NULL);
1782
1783 it.it_interval.tv_sec = 0;
1784 it.it_interval.tv_usec = 0;
1785 it.it_value.tv_sec = 0;
1786 it.it_value.tv_usec = 0;
1787 setitimer (ITIMER_REAL, &it, NULL);
1788}
1789
1790#endif
1791
1792/* This hook function is called whenever we want to wait for the
1793 target. */
1794
479f0f18
SG
1795static int
1796gdbtk_wait (pid, ourstatus)
1797 int pid;
1798 struct target_waitstatus *ourstatus;
1799{
018d76dd 1800#ifndef WINNT
736a82e7
SG
1801 struct sigaction action;
1802 static sigset_t nullsigmask = {0};
1803
018d76dd 1804
736a82e7
SG
1805#ifndef SA_RESTART
1806 /* Needed for SunOS 4.1.x */
1807#define SA_RESTART 0
546b8ca7 1808#endif
479f0f18 1809
736a82e7
SG
1810 action.sa_handler = x_event;
1811 action.sa_mask = nullsigmask;
1812 action.sa_flags = SA_RESTART;
1813 sigaction(SIGIO, &action, NULL);
018d76dd
KS
1814#endif /* WINNT */
1815
1816#ifdef __CYGWIN32__
0776b0b0
MH
1817 /* Call x_event ourselves now, as well as starting the timer;
1818 otherwise, if single stepping, we may never wait long enough for
1819 the timer to trigger. */
1820 x_event (SIGALRM);
1821
018d76dd 1822 gdbtk_start_timer ();
8a19b35a 1823#endif
736a82e7 1824
479f0f18
SG
1825 pid = target_wait (pid, ourstatus);
1826
018d76dd
KS
1827#ifdef __CYGWIN32__
1828 gdbtk_stop_timer ();
1829#endif
1830
8a19b35a 1831#ifndef WINNT
018d76dd 1832 action.sa_handler = SIG_IGN;
8a19b35a
MH
1833 sigaction(SIGIO, &action, NULL);
1834#endif
479f0f18
SG
1835
1836 return pid;
1837}
1838
1839/* This is called from execute_command, and provides a wrapper around
1840 various command routines in a place where both protocol messages and
1841 user input both flow through. Mostly this is used for indicating whether
1842 the target process is running or not.
1843*/
1844
1845static void
1846gdbtk_call_command (cmdblk, arg, from_tty)
1847 struct cmd_list_element *cmdblk;
1848 char *arg;
1849 int from_tty;
1850{
fda6fadc 1851 running_now = 0;
018d76dd 1852 if (cmdblk->class == class_run || cmdblk->class == class_trace)
479f0f18 1853 {
fda6fadc 1854 running_now = 1;
4e327047 1855 Tcl_Eval (interp, "gdbtk_tcl_busy");
479f0f18 1856 (*cmdblk->function.cfunc)(arg, from_tty);
fda6fadc 1857 running_now = 0;
2476848a 1858 Tcl_Eval (interp, "gdbtk_tcl_idle");
479f0f18
SG
1859 }
1860 else
1861 (*cmdblk->function.cfunc)(arg, from_tty);
1862}
1863
5bac2b50
FF
1864/* This function is called instead of gdb's internal command loop. This is the
1865 last chance to do anything before entering the main Tk event loop. */
1866
1867static void
1868tk_command_loop ()
1869{
41756e56
FF
1870 extern GDB_FILE *instream;
1871
1872 /* We no longer want to use stdin as the command input stream */
1873 instream = NULL;
018d76dd
KS
1874
1875 if (Tcl_Eval (interp, "gdbtk_tcl_preloop") != TCL_OK)
1876 {
1877 char *msg;
1878
1879 /* Force errorInfo to be set up propertly. */
1880 Tcl_AddErrorInfo (interp, "");
1881
1882 msg = Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY);
1883#ifdef _WIN32
1884 MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
1885#else
1886 fputs_unfiltered (msg, gdb_stderr);
1887#endif
1888 }
1889
1890#ifdef _WIN32
1891 close_bfds ();
1892#endif
1893
5bac2b50
FF
1894 Tk_MainLoop ();
1895}
1896
9a2f9219
ILT
1897/* gdbtk_init installs this function as a final cleanup. */
1898
1899static void
1900gdbtk_cleanup (dummy)
1901 PTR dummy;
1902{
1903 Tcl_Finalize ();
1904}
1905
1906/* Initialize gdbtk. */
1907
754e5da2 1908static void
2476848a
MH
1909gdbtk_init ( argv0 )
1910 char *argv0;
754e5da2
SG
1911{
1912 struct cleanup *old_chain;
74089546 1913 char *lib, *gdbtk_lib, *gdbtk_lib_tmp, *gdbtk_file;
8a19b35a 1914 int i, found_main;
018d76dd 1915#ifndef WINNT
736a82e7
SG
1916 struct sigaction action;
1917 static sigset_t nullsigmask = {0};
018d76dd 1918#endif
2476848a 1919#ifdef IDE
018d76dd 1920 /* start-sanitize-ide */
2476848a
MH
1921 struct ide_event_handle *h;
1922 const char *errmsg;
1923 char *libexecdir;
018d76dd 1924 /* end-sanitize-ide */
2476848a 1925#endif
754e5da2 1926
fe58c81f
FF
1927 /* If there is no DISPLAY environment variable, Tk_Init below will fail,
1928 causing gdb to abort. If instead we simply return here, gdb will
1929 gracefully degrade to using the command line interface. */
1930
8a19b35a 1931#ifndef WINNT
fe58c81f
FF
1932 if (getenv ("DISPLAY") == NULL)
1933 return;
8a19b35a 1934#endif
fe58c81f 1935
754e5da2
SG
1936 old_chain = make_cleanup (cleanup_init, 0);
1937
1938 /* First init tcl and tk. */
2476848a 1939 Tcl_FindExecutable (argv0);
754e5da2
SG
1940 interp = Tcl_CreateInterp ();
1941
1942 if (!interp)
1943 error ("Tcl_CreateInterp failed");
1944
754e5da2
SG
1945 if (Tcl_Init(interp) != TCL_OK)
1946 error ("Tcl_Init failed: %s", interp->result);
1947
9a2f9219 1948 make_final_cleanup (gdbtk_cleanup, NULL);
2476848a 1949
9a2f9219 1950 /* Initialize the Paths variable. */
74089546 1951 if (ide_initialize_paths (interp, "gdbtcl") != TCL_OK)
9a2f9219
ILT
1952 error ("ide_initialize_paths failed: %s", interp->result);
1953
dd3dd918 1954#ifdef IDE
018d76dd 1955 /* start-sanitize-ide */
2476848a
MH
1956 /* Find the directory where we expect to find idemanager. We ignore
1957 errors since it doesn't really matter if this fails. */
1958 libexecdir = Tcl_GetVar2 (interp, "Paths", "libexecdir", TCL_GLOBAL_ONLY);
1959
1960 IluTk_Init ();
1961
7b94b2ea 1962 h = ide_event_init_from_environment (&errmsg, libexecdir);
2476848a
MH
1963 if (h == NULL)
1964 {
1965 Tcl_AppendResult (interp, "can't initialize event system: ", errmsg,
1966 (char *) NULL);
1967 fprintf(stderr, "WARNING: ide_event_init_client failed: %s\n", interp->result);
9a2f9219
ILT
1968
1969 Tcl_SetVar (interp, "GDBTK_IDE", "0", 0);
2476848a
MH
1970 }
1971 else
1972 {
1973 if (ide_create_tclevent_command (interp, h) != TCL_OK)
1974 error ("ide_create_tclevent_command failed: %s", interp->result);
018d76dd 1975
2476848a
MH
1976 if (ide_create_edit_command (interp, h) != TCL_OK)
1977 error ("ide_create_edit_command failed: %s", interp->result);
1978
1979 if (ide_create_property_command (interp, h) != TCL_OK)
1980 error ("ide_create_property_command failed: %s", interp->result);
018d76dd
KS
1981
1982 if (ide_create_build_command (interp, h) != TCL_OK)
1983 error ("ide_create_build_command failed: %s", interp->result);
1984
1985 if (ide_create_window_register_command (interp, h, "gdb-restore")
1986 != TCL_OK)
9a2f9219
ILT
1987 error ("ide_create_window_register_command failed: %s",
1988 interp->result);
1989
1990 if (ide_create_window_command (interp, h) != TCL_OK)
1991 error ("ide_create_window_command failed: %s", interp->result);
1992
018d76dd
KS
1993 if (ide_create_exit_command (interp, h) != TCL_OK)
1994 error ("ide_create_exit_command failed: %s", interp->result);
1995
1996 if (ide_create_help_command (interp) != TCL_OK)
1997 error ("ide_create_help_command failed: %s", interp->result);
1998
2476848a
MH
1999 /*
2000 if (ide_initialize (interp, "gdb") != TCL_OK)
2001 error ("ide_initialize failed: %s", interp->result);
2002 */
9a2f9219
ILT
2003
2004 Tcl_SetVar (interp, "GDBTK_IDE", "1", 0);
018d76dd 2005 Tcl_SetVar (interp, "IDE", "1", TCL_GLOBAL_ONLY);
2476848a 2006 }
018d76dd 2007 /* end-sanitize-ide */
2476848a
MH
2008#else
2009 Tcl_SetVar (interp, "GDBTK_IDE", "0", 0);
2010#endif /* IDE */
2011
9a2f9219
ILT
2012 /* We don't want to open the X connection until we've done all the
2013 IDE initialization. Otherwise, goofy looking unfinished windows
2014 pop up when ILU drops into the TCL event loop. */
2015
2016 if (Tk_Init(interp) != TCL_OK)
2017 error ("Tk_Init failed: %s", interp->result);
2018
2019 if (Itcl_Init(interp) == TCL_ERROR)
2020 error ("Itcl_Init failed: %s", interp->result);
2021
2022 if (Tix_Init(interp) != TCL_OK)
2023 error ("Tix_Init failed: %s", interp->result);
2024
018d76dd
KS
2025#ifdef __CYGWIN32__
2026 /* On Windows, create a sizebox widget command */
2027 if (ide_create_sizebox_command (interp) != TCL_OK)
2028 error ("sizebox creation failed");
2029 if (ide_create_winprint_command (interp) != TCL_OK)
2030 error ("windows print code initialization failed");
2031 /* start-sanitize-ide */
2032 /* An interface to ShellExecute. */
2033 if (ide_create_shell_execute_command (interp) != TCL_OK)
2034 error ("shell execute command initialization failed");
06434f5f 2035 /* end-sanitize-ide */
018d76dd
KS
2036#endif
2037
86db943c 2038 Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
0422b59e
KS
2039 Tcl_CreateCommand (interp, "gdb_immediate", call_wrapper,
2040 gdb_immediate_command, NULL);
86db943c 2041 Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
8a19b35a 2042 Tcl_CreateCommand (interp, "gdb_path_conv", call_wrapper, gdb_path_conv, NULL);
86db943c
SG
2043 Tcl_CreateCommand (interp, "gdb_sourcelines", call_wrapper, gdb_sourcelines,
2044 NULL);
0776b0b0 2045 Tcl_CreateObjCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
99c98415
MH
2046 Tcl_CreateCommand (interp, "gdb_listfuncs", call_wrapper, gdb_listfuncs,
2047 NULL);
018d76dd
KS
2048 Tcl_CreateCommand (interp, "gdb_get_mem", call_wrapper, gdb_get_mem,
2049 NULL);
86db943c
SG
2050 Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
2051 Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
2052 Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
2053 gdb_fetch_registers, NULL);
2054 Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
2055 gdb_changed_register_list, NULL);
09722039
SG
2056 Tcl_CreateCommand (interp, "gdb_disassemble", call_wrapper,
2057 gdb_disassemble, NULL);
2058 Tcl_CreateCommand (interp, "gdb_eval", call_wrapper, gdb_eval, NULL);
6131622e
SG
2059 Tcl_CreateCommand (interp, "gdb_get_breakpoint_list", call_wrapper,
2060 gdb_get_breakpoint_list, NULL);
2061 Tcl_CreateCommand (interp, "gdb_get_breakpoint_info", call_wrapper,
2062 gdb_get_breakpoint_info, NULL);
018d76dd
KS
2063 Tcl_CreateCommand (interp, "gdb_clear_file", call_wrapper,
2064 gdb_clear_file, NULL);
2065 Tcl_CreateCommand (interp, "gdb_confirm_quit", call_wrapper,
2066 gdb_confirm_quit, NULL);
2067 Tcl_CreateCommand (interp, "gdb_force_quit", call_wrapper,
2068 gdb_force_quit, NULL);
2069 Tcl_CreateCommand (interp, "gdb_target_has_execution",
2070 gdb_target_has_execution_command,
2071 NULL, NULL);
2072 Tcl_CreateObjCommand (interp, "gdb_load_info", gdb_load_info, NULL, NULL);
2073 Tcl_CreateObjCommand (interp, "gdb_get_locals", gdb_get_vars_command,
2074 (ClientData) 0, NULL);
2075 Tcl_CreateObjCommand (interp, "gdb_get_args", gdb_get_vars_command,
2076 (ClientData) 1, NULL);
2077 Tcl_CreateObjCommand (interp, "gdb_get_function", gdb_get_function_command,
2078 NULL, NULL);
2079 Tcl_CreateObjCommand (interp, "gdb_get_line", gdb_get_line_command,
2080 NULL, NULL);
2081 Tcl_CreateObjCommand (interp, "gdb_get_file", gdb_get_file_command,
2082 NULL, NULL);
2083 Tcl_CreateObjCommand (interp, "gdb_tracepoint_exists",
2084 gdb_tracepoint_exists_command, NULL, NULL);
2085 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_info",
2086 gdb_get_tracepoint_info, NULL, NULL);
2087 Tcl_CreateObjCommand (interp, "gdb_actions",
2088 gdb_actions_command, NULL, NULL);
2089 Tcl_CreateObjCommand (interp, "gdb_prompt",
2090 gdb_prompt_command, NULL, NULL);
e0f7db02
KS
2091 Tcl_CreateObjCommand (interp, "gdb_find_file",
2092 gdb_find_file_command, NULL, NULL);
4f17e6eb
KS
2093 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_list",
2094 gdb_get_tracepoint_list, NULL, NULL);
018d76dd 2095
5bac2b50 2096 command_loop_hook = tk_command_loop;
a5f4fbff 2097 print_frame_info_listing_hook = gdbtk_print_frame_info;
09722039
SG
2098 query_hook = gdbtk_query;
2099 flush_hook = gdbtk_flush;
2100 create_breakpoint_hook = gdbtk_create_breakpoint;
2101 delete_breakpoint_hook = gdbtk_delete_breakpoint;
6131622e 2102 modify_breakpoint_hook = gdbtk_modify_breakpoint;
09722039
SG
2103 interactive_hook = gdbtk_interactive;
2104 target_wait_hook = gdbtk_wait;
2105 call_command_hook = gdbtk_call_command;
41756e56
FF
2106 readline_begin_hook = gdbtk_readline_begin;
2107 readline_hook = gdbtk_readline;
2108 readline_end_hook = gdbtk_readline_end;
018d76dd 2109 ui_load_progress_hook = gdbtk_load_hash;
11f91b2b
KS
2110 pre_add_symbol_hook = gdbtk_pre_add_symbol;
2111 post_add_symbol_hook = gdbtk_post_add_symbol;
018d76dd
KS
2112 create_tracepoint_hook = gdbtk_create_tracepoint;
2113 delete_tracepoint_hook = gdbtk_delete_tracepoint;
a5f4fbff 2114 modify_tracepoint_hook = gdbtk_modify_tracepoint;
754e5da2 2115
018d76dd 2116#ifndef WINNT
cd2df226 2117 /* Get the file descriptor for the X server */
479f0f18 2118
047465fd 2119 x_fd = ConnectionNumber (Tk_Display (Tk_MainWindow (interp)));
479f0f18
SG
2120
2121 /* Setup for I/O interrupts */
2122
736a82e7
SG
2123 action.sa_mask = nullsigmask;
2124 action.sa_flags = 0;
2125 action.sa_handler = SIG_IGN;
2126 sigaction(SIGIO, &action, NULL);
2127
2128#ifdef FIOASYNC
2129 i = 1;
2130 if (ioctl (x_fd, FIOASYNC, &i))
2131 perror_with_name ("gdbtk_init: ioctl FIOASYNC failed");
479f0f18 2132
77a89957 2133#ifdef SIOCSPGRP
736a82e7
SG
2134 i = getpid();
2135 if (ioctl (x_fd, SIOCSPGRP, &i))
2136 perror_with_name ("gdbtk_init: ioctl SIOCSPGRP failed");
45f90c50
MM
2137
2138#else
2139#ifdef F_SETOWN
2140 i = getpid();
2141 if (fcntl (x_fd, F_SETOWN, i))
2142 perror_with_name ("gdbtk_init: fcntl F_SETOWN failed");
2143#endif /* F_SETOWN */
2144#endif /* !SIOCSPGRP */
546b8ca7 2145#else
8a19b35a 2146#ifndef WINNT
546b8ca7 2147 if (ioctl (x_fd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
736a82e7 2148 perror_with_name ("gdbtk_init: ioctl I_SETSIG failed");
8a19b35a
MH
2149#endif
2150
736a82e7 2151#endif /* ifndef FIOASYNC */
018d76dd 2152#endif /* WINNT */
479f0f18 2153
754e5da2
SG
2154 add_com ("tk", class_obscure, tk_command,
2155 "Send a command directly into tk.");
09722039 2156
09722039
SG
2157 Tcl_LinkVar (interp, "disassemble-from-exec", (char *)&disassemble_from_exec,
2158 TCL_LINK_INT);
2159
8a19b35a 2160 /* find the gdb tcl library and source main.tcl */
09722039 2161
8a19b35a
MH
2162 gdbtk_lib = getenv ("GDBTK_LIBRARY");
2163 if (!gdbtk_lib)
2164 if (access ("gdbtcl/main.tcl", R_OK) == 0)
2165 gdbtk_lib = "gdbtcl";
09722039 2166 else
8a19b35a
MH
2167 gdbtk_lib = GDBTK_LIBRARY;
2168
74089546
ILT
2169 gdbtk_lib_tmp = xstrdup (gdbtk_lib);
2170
8a19b35a
MH
2171 found_main = 0;
2172 /* see if GDBTK_LIBRARY is a path list */
2173 lib = strtok (gdbtk_lib_tmp, GDBTK_PATH_SEP);
2174 do
2175 {
2176 if (Tcl_VarEval (interp, "lappend auto_path ", lib, NULL) != TCL_OK)
2177 {
2178 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
2179 error ("");
2180 }
2181 if (!found_main)
2182 {
74089546 2183 gdbtk_file = concat (lib, "/main.tcl", (char *) NULL);
8a19b35a
MH
2184 if (access (gdbtk_file, R_OK) == 0)
2185 {
2186 found_main++;
2187 Tcl_SetVar (interp, "GDBTK_LIBRARY", lib, 0);
2188 }
2189 }
2190 }
56e327b3 2191 while ((lib = strtok (NULL, ":")) != NULL);
74089546
ILT
2192
2193 free (gdbtk_lib_tmp);
2194
74089546
ILT
2195 if (!found_main)
2196 {
2197 /* Try finding it with the auto path. */
2198
2199 static const char script[] ="\
2200proc gdbtk_find_main {} {\n\
2201 global auto_path GDBTK_LIBRARY\n\
2202 foreach dir $auto_path {\n\
2203 set f [file join $dir main.tcl]\n\
2204 if {[file exists $f]} then {\n\
2205 set GDBTK_LIBRARY $dir\n\
2206 return $f\n\
2207 }\n\
2208 }\n\
2209 return ""\n\
2210}\n\
2211gdbtk_find_main";
2212
2213 if (Tcl_GlobalEval (interp, (char *) script) != TCL_OK)
2214 {
2215 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
2216 error ("");
2217 }
2218
2219 if (interp->result[0] != '\0')
2220 {
2221 gdbtk_file = xstrdup (interp->result);
2222 found_main++;
2223 }
2224 }
74089546 2225
8a19b35a
MH
2226 if (!found_main)
2227 {
2228 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
2229 if (getenv("GDBTK_LIBRARY"))
2230 {
2231 fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n",getenv("GDBTK_LIBRARY"));
2232 fprintf_unfiltered (stderr,
2233 "Please set GDBTK_LIBRARY to a path that includes the GDB tcl files.\n");
2234 }
2235 else
2236 {
2237 fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n", GDBTK_LIBRARY);
2238 fprintf_unfiltered (stderr, "You might want to set GDBTK_LIBRARY\n");
2239 }
2240 error("");
2241 }
09722039 2242
724498fd
SG
2243/* Defer setup of fputs_unfiltered_hook to near the end so that error messages
2244 prior to this point go to stdout/stderr. */
2245
2246 fputs_unfiltered_hook = gdbtk_fputs;
2247
8a19b35a 2248 if (Tcl_EvalFile (interp, gdbtk_file) != TCL_OK)
724498fd 2249 {
018d76dd
KS
2250 char *msg;
2251
2252 /* Force errorInfo to be set up propertly. */
2253 Tcl_AddErrorInfo (interp, "");
2254
2255 msg = Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY);
2256
724498fd
SG
2257 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
2258
018d76dd
KS
2259#ifdef _WIN32
2260 MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
2261#else
2262 fputs_unfiltered (msg, gdb_stderr);
2263#endif
b66051ec 2264
b66051ec 2265 error ("");
724498fd 2266 }
09722039 2267
018d76dd
KS
2268#ifdef IDE
2269 /* start-sanitize-ide */
2270 /* Don't do this until we have initialized. Otherwise, we may get a
2271 run command before we are ready for one. */
2272 if (ide_run_server_init (interp, h) != TCL_OK)
2273 error ("ide_run_server_init failed: %s", interp->result);
2274 /* end-sanitize-ide */
2275#endif
2276
74089546
ILT
2277 free (gdbtk_file);
2278
09722039 2279 discard_cleanups (old_chain);
754e5da2
SG
2280}
2281
018d76dd
KS
2282static int
2283gdb_target_has_execution_command (clientData, interp, argc, argv)
2284 ClientData clientData;
2285 Tcl_Interp *interp;
2286 int argc;
2287 char *argv[];
2288{
2289 int result = 0;
2290
2291 if (target_has_execution && inferior_pid != 0)
2292 result = 1;
2293
2294 Tcl_SetIntObj (Tcl_GetObjResult (interp), result);
2295 return TCL_OK;
2296}
2297
2298/* gdb_load_info - returns information about the file about to be downloaded */
2299
2300static int
2301gdb_load_info (clientData, interp, objc, objv)
2302 ClientData clientData;
2303 Tcl_Interp *interp;
2304 int objc;
2305 Tcl_Obj *CONST objv[];
2306{
2307 bfd *loadfile_bfd;
2308 struct cleanup *old_cleanups;
2309 asection *s;
2310 Tcl_Obj *ob[2];
2311 Tcl_Obj *res[16];
2312 int i = 0;
2313
2314 char *filename = Tcl_GetStringFromObj (objv[1], NULL);
2315
2316 loadfile_bfd = bfd_openr (filename, gnutarget);
2317 if (loadfile_bfd == NULL)
2318 {
2319 Tcl_SetObjResult (interp, Tcl_NewStringObj ("Open failed", -1));
2320 return TCL_ERROR;
2321 }
2322 old_cleanups = make_cleanup (bfd_close, loadfile_bfd);
2323
2324 if (!bfd_check_format (loadfile_bfd, bfd_object))
2325 {
2326 Tcl_SetObjResult (interp, Tcl_NewStringObj ("Bad Object File", -1));
2327 return TCL_ERROR;
2328 }
2329
2330 for (s = loadfile_bfd->sections; s; s = s->next)
2331 {
2332 if (s->flags & SEC_LOAD)
2333 {
2334 bfd_size_type size = bfd_get_section_size_before_reloc (s);
2335 if (size > 0)
2336 {
2337 ob[0] = Tcl_NewStringObj((char *)bfd_get_section_name(loadfile_bfd, s), -1);
2338 ob[1] = Tcl_NewLongObj ((long)size);
2339 res[i++] = Tcl_NewListObj (2, ob);
2340 }
2341 }
2342 }
2343
2344 Tcl_SetObjResult (interp, Tcl_NewListObj (i, res));
2345 do_cleanups (old_cleanups);
2346 return TCL_OK;
2347}
2348
2349
2350int
2351gdbtk_load_hash (section, num)
2352 char *section;
2353 unsigned long num;
2354{
018d76dd
KS
2355 char buf[128];
2356 sprintf (buf, "download_hash %s %ld", section, num);
0776b0b0
MH
2357 Tcl_Eval (interp, buf);
2358 return atoi (interp->result);
018d76dd
KS
2359}
2360
2361/* gdb_get_vars_command -
2362 *
2363 * Implements the "gdb_get_locals" and "gdb_get_args" tcl commands. This
2364 * function sets the Tcl interpreter's result to a list of variable names
2365 * depending on clientData. If clientData is one, the result is a list of
2366 * arguments; zero returns a list of locals -- all relative to the block
2367 * specified as an argument to the command. Valid commands include
2368 * anything decode_line_1 can handle (like "main.c:2", "*0x02020202",
2369 * and "main").
2370 */
2371static int
2372gdb_get_vars_command (clientData, interp, objc, objv)
2373 ClientData clientData;
2374 Tcl_Interp *interp;
2375 int objc;
2376 Tcl_Obj *CONST objv[];
2377{
2378 Tcl_Obj *result;
2379 struct symtabs_and_lines sals;
2380 struct symbol *sym;
2381 struct block *block;
2382 char **canonical, *args;
2383 int i, nsyms, arguments;
2384
2385 if (objc != 2)
2386 {
2387 Tcl_AppendResult (interp,
2388 "wrong # of args: should be \"",
2389 Tcl_GetStringFromObj (objv[0], NULL),
2390 " function:line|function|line|*addr\"");
2391 return TCL_ERROR;
2392 }
2393
2394 arguments = (int) clientData;
2395 args = Tcl_GetStringFromObj (objv[1], NULL);
2396 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2397 if (sals.nelts == 0)
2398 {
2399 Tcl_AppendResult (interp,
2400 "error decoding line", NULL);
2401 return TCL_ERROR;
2402 }
2403
2404 /* Initialize a list that will hold the results */
2405 result = Tcl_NewListObj (0, NULL);
2406
2407 /* Resolve all line numbers to PC's */
2408 for (i = 0; i < sals.nelts; i++)
2409 resolve_sal_pc (&sals.sals[i]);
2410
2411 block = block_for_pc (sals.sals[0].pc);
2412 while (block != 0)
2413 {
2414 nsyms = BLOCK_NSYMS (block);
2415 for (i = 0; i < nsyms; i++)
2416 {
2417 sym = BLOCK_SYM (block, i);
2418 switch (SYMBOL_CLASS (sym)) {
2419 default:
2420 case LOC_UNDEF: /* catches errors */
2421 case LOC_CONST: /* constant */
2422 case LOC_STATIC: /* static */
2423 case LOC_REGISTER: /* register */
2424 case LOC_TYPEDEF: /* local typedef */
2425 case LOC_LABEL: /* local label */
2426 case LOC_BLOCK: /* local function */
2427 case LOC_CONST_BYTES: /* loc. byte seq. */
2428 case LOC_UNRESOLVED: /* unresolved static */
2429 case LOC_OPTIMIZED_OUT: /* optimized out */
2430 break;
2431 case LOC_ARG: /* argument */
2432 case LOC_REF_ARG: /* reference arg */
2433 case LOC_REGPARM: /* register arg */
2434 case LOC_REGPARM_ADDR: /* indirect register arg */
2435 case LOC_LOCAL_ARG: /* stack arg */
2436 case LOC_BASEREG_ARG: /* basereg arg */
2437 if (arguments)
2438 Tcl_ListObjAppendElement (interp, result,
2439 Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
2440 break;
2441 case LOC_LOCAL: /* stack local */
2442 case LOC_BASEREG: /* basereg local */
2443 if (!arguments)
2444 Tcl_ListObjAppendElement (interp, result,
2445 Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
2446 break;
2447 }
2448 }
2449 if (BLOCK_FUNCTION (block))
2450 break;
2451 else
2452 block = BLOCK_SUPERBLOCK (block);
2453 }
2454
2455 Tcl_SetObjResult (interp, result);
2456 return TCL_OK;
2457}
2458
2459static int
2460gdb_get_line_command (clientData, interp, objc, objv)
2461 ClientData clientData;
2462 Tcl_Interp *interp;
2463 int objc;
2464 Tcl_Obj *CONST objv[];
2465{
2466 Tcl_Obj *result;
2467 struct symtabs_and_lines sals;
2468 char *args, **canonical;
2469
2470 if (objc != 2)
2471 {
2472 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2473 Tcl_GetStringFromObj (objv[0], NULL),
2474 " linespec\"");
2475 return TCL_ERROR;
2476 }
2477
2478 args = Tcl_GetStringFromObj (objv[1], NULL);
2479 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2480 if (sals.nelts == 1)
2481 {
2482 Tcl_SetObjResult (interp, Tcl_NewIntObj (sals.sals[0].line));
2483 return TCL_OK;
2484 }
2485
2486 Tcl_SetResult (interp, "N/A", TCL_STATIC);
2487 return TCL_OK;
2488}
2489
2490static int
2491gdb_get_file_command (clientData, interp, objc, objv)
2492 ClientData clientData;
2493 Tcl_Interp *interp;
2494 int objc;
2495 Tcl_Obj *CONST objv[];
2496{
2497 Tcl_Obj *result;
2498 struct symtabs_and_lines sals;
2499 char *args, **canonical;
2500
2501 if (objc != 2)
2502 {
2503 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2504 Tcl_GetStringFromObj (objv[0], NULL),
2505 " linespec\"");
2506 return TCL_ERROR;
2507 }
2508
2509 args = Tcl_GetStringFromObj (objv[1], NULL);
2510 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2511 if (sals.nelts == 1)
2512 {
2513 Tcl_SetResult (interp, sals.sals[0].symtab->filename, TCL_VOLATILE);
2514 return TCL_OK;
2515 }
2516
2517 Tcl_SetResult (interp, "N/A", TCL_STATIC);
2518 return TCL_OK;
2519}
2520
2521static int
2522gdb_get_function_command (clientData, interp, objc, objv)
2523 ClientData clientData;
2524 Tcl_Interp *interp;
2525 int objc;
2526 Tcl_Obj *CONST objv[];
2527{
2528 Tcl_Obj *result;
2529 char *function;
2530 struct symtabs_and_lines sals;
2531 char *args, **canonical;
2532
2533 if (objc != 2)
2534 {
2535 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2536 Tcl_GetStringFromObj (objv[0], NULL),
2537 " linespec\"");
2538 return TCL_ERROR;
2539 }
2540
2541 args = Tcl_GetStringFromObj (objv[1], NULL);
2542 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2543 if (sals.nelts == 1)
2544 {
2545 resolve_sal_pc (&sals.sals[0]);
2546 find_pc_partial_function (sals.sals[0].pc, &function, NULL, NULL);
2547 if (function != NULL)
2548 {
2549 Tcl_SetResult (interp, function, TCL_VOLATILE);
2550 return TCL_OK;
2551 }
2552 }
2553
2554 Tcl_SetResult (interp, "N/A", TCL_STATIC);
2555 return TCL_OK;
2556}
2557
2558static int
2559gdb_get_tracepoint_info (clientData, interp, objc, objv)
2560 ClientData clientData;
2561 Tcl_Interp *interp;
2562 int objc;
2563 Tcl_Obj *CONST objv[];
2564{
2565 struct symtab_and_line sal;
018d76dd
KS
2566 int tpnum;
2567 struct tracepoint *tp;
2568 struct action_line *al;
2569 Tcl_Obj *list, *action_list;
09e4fde2 2570 char *filename, *funcname;
018d76dd
KS
2571 char tmp[19];
2572
2573 if (objc != 2)
2574 error ("wrong # args");
2575
2576 Tcl_GetIntFromObj (NULL, objv[1], &tpnum);
2577
2578 ALL_TRACEPOINTS (tp)
2579 if (tp->number == tpnum)
2580 break;
2581
2582 if (tp == NULL)
2583 error ("Tracepoint #%d does not exist", tpnum);
2584
2585 list = Tcl_NewListObj (0, NULL);
09e4fde2
KS
2586 sal = find_pc_line (tp->address, 0);
2587 filename = symtab_to_filename (sal.symtab);
2588 if (filename == NULL)
2589 filename = "N/A";
2590 Tcl_ListObjAppendElement (interp, list,
2591 Tcl_NewStringObj (filename, -1));
09e4fde2
KS
2592 find_pc_partial_function (tp->address, &funcname, NULL, NULL);
2593 Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj (funcname, -1));
4f17e6eb 2594 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (sal.line));
018d76dd
KS
2595 sprintf (tmp, "0x%08x", tp->address);
2596 Tcl_ListObjAppendElement (interp, list, Tcl_NewStringObj (tmp, -1));
2597 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->enabled));
2598 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->pass_count));
2599 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->step_count));
2600 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->thread));
2601 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->hit_count));
2602
2603 /* Append a list of actions */
2604 action_list = Tcl_NewListObj (0, NULL);
2605 for (al = tp->actions; al != NULL; al = al->next)
2606 {
2607 Tcl_ListObjAppendElement (interp, action_list,
2608 Tcl_NewStringObj (al->action, -1));
2609 }
2610 Tcl_ListObjAppendElement (interp, list, action_list);
2611
2612 Tcl_SetObjResult (interp, list);
2613 return TCL_OK;
2614}
2615
2616static void
2617gdbtk_create_tracepoint (tp)
2618 struct tracepoint *tp;
2619{
2620 tracepoint_notify (tp, "create");
2621}
2622
2623static void
2624gdbtk_delete_tracepoint (tp)
2625 struct tracepoint *tp;
2626{
2627 tracepoint_notify (tp, "delete");
2628}
2629
a5f4fbff
KS
2630static void
2631gdbtk_modify_tracepoint (tp)
2632 struct tracepoint *tp;
2633{
2634 tracepoint_notify (tp, "modify");
2635}
2636
018d76dd
KS
2637static void
2638tracepoint_notify(tp, action)
2639 struct tracepoint *tp;
2640 const char *action;
2641{
2642 char buf[256];
018d76dd 2643 int v;
09e4fde2
KS
2644 struct symtab_and_line sal;
2645 char *filename;
018d76dd
KS
2646
2647 /* We ensure that ACTION contains no special Tcl characters, so we
2648 can do this. */
09e4fde2
KS
2649 sal = find_pc_line (tp->address, 0);
2650
2651 filename = symtab_to_filename (sal.symtab);
2652 if (filename == NULL)
2653 filename = "N/A";
018d76dd 2654 sprintf (buf, "gdbtk_tcl_tracepoint %s %d 0x%lx %d {%s}", action, tp->number,
09e4fde2 2655 (long)tp->address, sal.line, filename);
018d76dd
KS
2656
2657 v = Tcl_Eval (interp, buf);
2658
2659 if (v != TCL_OK)
2660 {
2661 gdbtk_fputs (interp->result, gdb_stdout);
2662 gdbtk_fputs ("\n", gdb_stdout);
2663 }
2664}
2665
2666/* returns -1 if not found, tracepoint # if found */
2667int
2668tracepoint_exists (char * args)
2669{
2670 struct tracepoint *tp;
2671 char **canonical;
2672 struct symtabs_and_lines sals;
2673 char *file = NULL;
2674 int result = -1;
2675
2676 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2677 if (sals.nelts == 1)
2678 {
2679 resolve_sal_pc (&sals.sals[0]);
2680 file = xmalloc (strlen (sals.sals[0].symtab->dirname)
2681 + strlen (sals.sals[0].symtab->filename) + 1);
2682 if (file != NULL)
2683 {
2684 strcpy (file, sals.sals[0].symtab->dirname);
2685 strcat (file, sals.sals[0].symtab->filename);
2686
2687 ALL_TRACEPOINTS (tp)
2688 {
2689 if (tp->address == sals.sals[0].pc)
2690 result = tp->number;
2691 else if (tp->source_file != NULL
2692 && strcmp (tp->source_file, file) == 0
2693 && sals.sals[0].line == tp->line_number)
2694
2695 result = tp->number;
2696 }
2697 }
2698 }
2699 if (file != NULL)
2700 free (file);
2701 return result;
2702}
2703
2704static int
2705gdb_actions_command (clientData, interp, objc, objv)
2706 ClientData clientData;
2707 Tcl_Interp *interp;
2708 int objc;
2709 Tcl_Obj *CONST objv[];
2710{
2711 struct tracepoint *tp;
2712 Tcl_Obj **actions;
2713 int nactions, i, len;
2714 char *number, *args, *action;
43b043cf 2715 long step_count;
018d76dd
KS
2716 struct action_line *next = NULL, *temp;
2717
2718 if (objc != 3)
2719 {
2720 Tcl_AppendResult (interp, "wrong # args: should be: \"",
2721 Tcl_GetStringFromObj (objv[0], NULL),
2722 " number actions\"");
2723 return TCL_ERROR;
2724 }
2725
2726 args = number = Tcl_GetStringFromObj (objv[1], NULL);
2727 tp = get_tracepoint_by_number (&args);
2728 if (tp == NULL)
2729 {
2730 Tcl_AppendResult (interp, "Tracepoint \"", number, "\" does not exist");
2731 return TCL_ERROR;
2732 }
2733
2734 /* Free any existing actions */
a5f4fbff
KS
2735 if (tp->actions != NULL)
2736 free_actions (tp);
2737
43b043cf 2738 step_count = 0;
018d76dd
KS
2739
2740 Tcl_ListObjGetElements (interp, objv[2], &nactions, &actions);
2741 for (i = 0; i < nactions; i++)
2742 {
2743 temp = xmalloc (sizeof (struct action_line));
2744 temp->next = NULL;
2745 action = Tcl_GetStringFromObj (actions[i], &len);
2746 temp->action = savestring (action, len);
43b043cf
MS
2747 if (sscanf (temp->action, "while-stepping %d", &step_count) !=0)
2748 tp->step_count = step_count;
018d76dd
KS
2749 if (next == NULL)
2750 {
2751 tp->actions = temp;
2752 next = temp;
2753 }
2754 else
2755 {
2756 next->next = temp;
2757 next = temp;
2758 }
2759 }
2760
2761 return TCL_OK;
2762}
2763
2764static int
2765gdb_tracepoint_exists_command (clientData, interp, objc, objv)
2766 ClientData clientData;
2767 Tcl_Interp *interp;
2768 int objc;
2769 Tcl_Obj *CONST objv[];
2770{
2771 char * args;
2772
2773 if (objc != 2)
2774 {
2775 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2776 Tcl_GetStringFromObj (objv[0], NULL),
2777 " function:line|function|line|*addr\"");
2778 return TCL_ERROR;
2779 }
2780
2781 args = Tcl_GetStringFromObj (objv[1], NULL);
2782
2783 Tcl_SetObjResult (interp, Tcl_NewIntObj (tracepoint_exists (args)));
2784 return TCL_OK;
2785}
2786
2787/* Return the prompt to the interpreter */
2788static int
2789gdb_prompt_command (clientData, interp, objc, objv)
2790 ClientData clientData;
2791 Tcl_Interp *interp;
2792 int objc;
2793 Tcl_Obj *CONST objv[];
2794{
2795 Tcl_SetResult (interp, get_prompt (), TCL_VOLATILE);
2796 return TCL_OK;
2797}
2798
4f17e6eb
KS
2799/* return a list of all tracepoint numbers in interpreter */
2800static int
2801gdb_get_tracepoint_list (clientData, interp, objc, objv)
2802 ClientData clientData;
2803 Tcl_Interp *interp;
2804 int objc;
2805 Tcl_Obj *CONST objv[];
2806{
2807 Tcl_Obj *list;
2808 struct tracepoint *tp;
2809
2810 list = Tcl_NewListObj (0, NULL);
2811
2812 ALL_TRACEPOINTS (tp)
2813 Tcl_ListObjAppendElement (interp, list, Tcl_NewIntObj (tp->number));
2814
2815 Tcl_SetObjResult (interp, list);
2816 return TCL_OK;
2817}
e0f7db02
KS
2818
2819/* This is stolen from source.c */
2820#ifdef CRLF_SOURCE_FILES
2821
2822/* Define CRLF_SOURCE_FILES in an xm-*.h file if source files on the
2823 host use \r\n rather than just \n. Defining CRLF_SOURCE_FILES is
2824 much faster than defining LSEEK_NOT_LINEAR. */
2825
2826#ifndef O_BINARY
2827#define O_BINARY 0
2828#endif
2829
2830#define OPEN_MODE (O_RDONLY | O_BINARY)
2831
2832#else /* ! defined (CRLF_SOURCE_FILES) */
2833
2834#define OPEN_MODE O_RDONLY
2835
2836#endif /* ! defined (CRLF_SOURCE_FILES) */
2837
2838/* Find the pathname to a file, searching the source_dir */
2839/* we may actually need to use openp to find the the full pathname
2840 so we don't have any "../" et al in it. */
2841static int
2842gdb_find_file_command (clientData, interp, objc, objv)
2843 ClientData clientData;
2844 Tcl_Interp *interp;
2845 int objc;
2846 Tcl_Obj *CONST objv[];
2847{
2848 char *file, *filename;
e0f7db02
KS
2849
2850 if (objc != 2)
2851 {
2852 Tcl_AppendResult (interp, "wrong # of args: should be \"",
2853 Tcl_GetStringFromObj (objv[0], NULL),
2854 " filename\"");
2855 return TCL_ERROR;
2856 }
2857
e0f7db02 2858 file = Tcl_GetStringFromObj (objv[1], NULL);
11f91b2b
KS
2859 filename = find_file_in_dir (file);
2860
2861 if (filename == NULL)
2862 Tcl_SetResult (interp, "", TCL_STATIC);
2863 else
2864 Tcl_SetObjResult (interp, Tcl_NewStringObj (filename, -1));
2865
2866 return TCL_OK;
2867}
2868
2869static char *
2870find_file_in_dir (file)
2871 char *file;
2872{
2873 struct symtab *st = NULL;
e0f7db02 2874
11f91b2b 2875 if (file != NULL)
e0f7db02 2876 {
11f91b2b
KS
2877 /* try something simple first */
2878 if (access (file, R_OK) == 0)
2879 return file;
2880
2881 /* We really need a symtab for this to work... */
2882 st = lookup_symtab (file);
2883 if (st != NULL)
4f17e6eb 2884 {
11f91b2b
KS
2885 file = symtab_to_filename (st);
2886 if (file != NULL)
2887 return file;
4f17e6eb 2888 }
e0f7db02 2889 }
11f91b2b
KS
2890
2891 return NULL;
2892}
4f17e6eb 2893
11f91b2b
KS
2894/* This hook is called whenever we are ready to load a symbol file so that
2895 the UI can notify the user... */
2896void
2897gdbtk_pre_add_symbol (name)
2898 char *name;
2899{
2900 char command[256];
2901
2902 sprintf (command, "gdbtk_tcl_pre_add_symbol %s", name);
2903 Tcl_Eval (interp, command);
2904}
2905
2906/* This hook is called whenever we finish loading a symbol file. */
2907void
2908gdbtk_post_add_symbol ()
2909{
2910 Tcl_Eval (interp, "gdbtk_tcl_post_add_symbol");
e0f7db02
KS
2911}
2912
0776b0b0
MH
2913
2914/* TclDebug (const char *fmt, ...) works just like printf() but */
2915/* sends the output to the GDB TK debug window. */
2916/* Not for normal use; just a convenient tool for debugging */
2917void
2918#ifdef ANSI_PROTOTYPES
2919TclDebug (const char *fmt, ...)
2920#else
2921TclDebug (va_alist)
2922 va_dcl
2923#endif
2924{
2925 va_list args;
2926 char buf[512];
2927
2928#ifdef ANSI_PROTOTYPES
2929 va_start (args, fmt);
2930#else
2931 char *fmt;
2932 va_start (args);
2933 fmt = va_arg (args, char *);
2934#endif
2935
2936 strcpy (buf, "debug \"");
2937 vsprintf (&buf[7], fmt, args);
2938 va_end (args);
2939 strcat (buf, "\"");
2940 Tcl_Eval (interp, buf);
2941}
2942
a5f4fbff
KS
2943static void
2944gdbtk_print_frame_info (s, line, stopline, noerror)
2945 struct symtab *s;
2946 int line;
2947 int stopline;
2948 int noerror;
2949{
2950 current_source_symtab = s;
2951 current_source_line = line;
2952}
0776b0b0 2953
3f37b696 2954/* Come here during initialize_all_files () */
754e5da2
SG
2955
2956void
2957_initialize_gdbtk ()
2958{
c5197511
SG
2959 if (use_windows)
2960 {
2961 /* Tell the rest of the world that Gdbtk is now set up. */
754e5da2 2962
c5197511
SG
2963 init_ui_hook = gdbtk_init;
2964 }
754e5da2 2965}
This page took 0.313547 seconds and 4 git commands to generate.