Add alignment option.
[deliverable/binutils-gdb.git] / gdb / gdbtk.c
CommitLineData
4604b34c 1/* Tcl/Tk interface routines.
8a19b35a 2 Copyright 1994, 1995, 1996, 1997 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"
754e5da2
SG
30#include <tcl.h>
31#include <tk.h>
2476848a
MH
32#include <itcl.h>
33#include <tix.h>
34
35#ifdef IDE
36#include "event.h"
37#include "idetcl.h"
38#endif
39
73d3dbd4 40#ifdef ANSI_PROTOTYPES
85c613aa
C
41#include <stdarg.h>
42#else
cd2df226 43#include <varargs.h>
85c613aa 44#endif
cd2df226
SG
45#include <signal.h>
46#include <fcntl.h>
8532893d 47#include <unistd.h>
86db943c
SG
48#include <setjmp.h>
49#include "top.h"
736a82e7 50#include <sys/ioctl.h>
2b576293 51#include "gdb_string.h"
09722039 52#include "dis-asm.h"
6131622e
SG
53#include <stdio.h>
54#include "gdbcmd.h"
736a82e7 55
8a19b35a 56#ifndef WINNT
736a82e7 57#ifndef FIOASYNC
546b8ca7
SG
58#include <sys/stropts.h>
59#endif
8a19b35a
MH
60#endif
61
62#ifdef WINNT
63#define GDBTK_PATH_SEP ";"
64#else
65#define GDBTK_PATH_SEP ":"
66#endif
754e5da2 67
8b3f9ed6 68/* Some versions (1.3.79, 1.3.81) of Linux don't support SIOCSPGRP the way
3f37b696 69 gdbtk wants to use it... */
8b3f9ed6
MM
70#ifdef __linux__
71#undef SIOCSPGRP
72#endif
73
b607efe7
FF
74static void null_routine PARAMS ((int));
75static void gdbtk_flush PARAMS ((FILE *));
76static void gdbtk_fputs PARAMS ((const char *, FILE *));
77static int gdbtk_query PARAMS ((const char *, va_list));
78static char *gdbtk_readline PARAMS ((char *));
2476848a 79static void gdbtk_init PARAMS ((char *));
b607efe7
FF
80static void tk_command_loop PARAMS ((void));
81static void gdbtk_call_command PARAMS ((struct cmd_list_element *, char *, int));
82static int gdbtk_wait PARAMS ((int, struct target_waitstatus *));
83static void x_event PARAMS ((int));
84static void gdbtk_interactive PARAMS ((void));
85static void cleanup_init PARAMS ((int));
86static void tk_command PARAMS ((char *, int));
87static int gdb_disassemble PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
88static int compare_lines PARAMS ((const PTR, const PTR));
89static int gdbtk_dis_asm_read_memory PARAMS ((bfd_vma, bfd_byte *, int, disassemble_info *));
8a19b35a 90static int gdb_path_conv PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
b607efe7
FF
91static int gdb_stop PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
92static int gdb_listfiles PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
99c98415 93static int gdb_listfuncs PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
b607efe7
FF
94static int call_wrapper PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
95static int gdb_cmd PARAMS ((ClientData, Tcl_Interp *, int, char *argv[]));
96static int gdb_fetch_registers PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
97static void gdbtk_readline_end PARAMS ((void));
98static int gdb_changed_register_list PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
99static void register_changed_p PARAMS ((int, void *));
100static int gdb_get_breakpoint_list PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
101static int gdb_get_breakpoint_info PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
102static void breakpoint_notify PARAMS ((struct breakpoint *, const char *));
103static void gdbtk_create_breakpoint PARAMS ((struct breakpoint *));
104static void gdbtk_delete_breakpoint PARAMS ((struct breakpoint *));
105static void gdbtk_modify_breakpoint PARAMS ((struct breakpoint *));
106static int gdb_loc PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
107static int gdb_eval PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
108static int gdb_sourcelines PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
109static int map_arg_registers PARAMS ((int, char *[], void (*) (int, void *), void *));
110static void get_register_name PARAMS ((int, void *));
111static int gdb_regnames PARAMS ((ClientData, Tcl_Interp *, int, char *[]));
112static void get_register PARAMS ((int, void *));
113
754e5da2 114/* Handle for TCL interpreter */
fda6fadc 115
754e5da2
SG
116static Tcl_Interp *interp = NULL;
117
479f0f18
SG
118static int x_fd; /* X network socket */
119
fda6fadc
SS
120/* This variable is true when the inferior is running. Although it's
121 possible to disable most input from widgets and thus prevent
122 attempts to do anything while the inferior is running, any commands
123 that get through - even a simple memory read - are Very Bad, and
124 may cause GDB to crash or behave strangely. So, this variable
125 provides an extra layer of defense. */
09722039 126
fda6fadc
SS
127static int running_now;
128
129/* This variable determines where memory used for disassembly is read from.
130 If > 0, then disassembly comes from the exec file rather than the
131 target (which might be at the other end of a slow serial link). If
132 == 0 then disassembly comes from target. If < 0 disassembly is
133 automatically switched to the target if it's an inferior process,
134 otherwise the exec file is used. */
09722039
SG
135
136static int disassemble_from_exec = -1;
137
9b119644
ILT
138#ifndef _WIN32
139
140/* Supply malloc calls for tcl/tk. We do not want to do this on
141 Windows, because Tcl_Alloc is probably in a DLL which will not call
142 the mmalloc routines. */
8c19daa1
SG
143
144char *
a5a6e3bd 145Tcl_Alloc (size)
8c19daa1
SG
146 unsigned int size;
147{
148 return xmalloc (size);
149}
150
151char *
152Tcl_Realloc (ptr, size)
153 char *ptr;
154 unsigned int size;
155{
156 return xrealloc (ptr, size);
157}
158
159void
160Tcl_Free(ptr)
161 char *ptr;
162{
163 free (ptr);
164}
165
9b119644
ILT
166#endif /* _WIN32 */
167
754e5da2
SG
168static void
169null_routine(arg)
170 int arg;
171{
172}
173
546b8ca7
SG
174/* The following routines deal with stdout/stderr data, which is created by
175 {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
176 lowest level of these routines and capture all output from the rest of GDB.
177 Normally they present their data to tcl via callbacks to the following tcl
178 routines: gdbtk_tcl_fputs, gdbtk_tcl_fputs_error, and gdbtk_flush. These
179 in turn call tk routines to update the display.
86db943c 180
546b8ca7
SG
181 Under some circumstances, you may want to collect the output so that it can
182 be returned as the value of a tcl procedure. This can be done by
183 surrounding the output routines with calls to start_saving_output and
184 finish_saving_output. The saved data can then be retrieved with
185 get_saved_output (but this must be done before the call to
186 finish_saving_output). */
86db943c 187
546b8ca7 188/* Dynamic string header for stdout. */
86db943c 189
6131622e 190static Tcl_DString *result_ptr;
754e5da2 191\f
754e5da2
SG
192static void
193gdbtk_flush (stream)
194 FILE *stream;
195{
6131622e 196#if 0
86db943c
SG
197 /* Force immediate screen update */
198
754e5da2 199 Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
6131622e 200#endif
754e5da2
SG
201}
202
8532893d 203static void
86db943c 204gdbtk_fputs (ptr, stream)
8532893d 205 const char *ptr;
86db943c 206 FILE *stream;
8532893d 207{
6131622e 208 if (result_ptr)
45f90c50 209 Tcl_DStringAppend (result_ptr, (char *)ptr, -1);
6131622e 210 else
86db943c 211 {
6131622e 212 Tcl_DString str;
86db943c 213
6131622e 214 Tcl_DStringInit (&str);
8532893d 215
6131622e 216 Tcl_DStringAppend (&str, "gdbtk_tcl_fputs", -1);
45f90c50 217 Tcl_DStringAppendElement (&str, (char *)ptr);
8532893d 218
2476848a 219 Tcl_Eval (interp, Tcl_DStringValue (&str));
6131622e
SG
220 Tcl_DStringFree (&str);
221 }
8532893d
SG
222}
223
754e5da2 224static int
85c613aa 225gdbtk_query (query, args)
b607efe7 226 const char *query;
754e5da2
SG
227 va_list args;
228{
4e327047
TT
229 char buf[200], *merge[2];
230 char *command;
754e5da2
SG
231 long val;
232
6131622e 233 vsprintf (buf, query, args);
4e327047
TT
234 merge[0] = "gdbtk_tcl_query";
235 merge[1] = buf;
236 command = Tcl_Merge (2, merge);
237 Tcl_Eval (interp, command);
238 free (command);
754e5da2
SG
239
240 val = atol (interp->result);
241 return val;
242}
41756e56
FF
243
244/* VARARGS */
245static void
246#ifdef ANSI_PROTOTYPES
247gdbtk_readline_begin (char *format, ...)
248#else
249gdbtk_readline_begin (va_alist)
250 va_dcl
251#endif
252{
253 va_list args;
254 char buf[200], *merge[2];
255 char *command;
256
257#ifdef ANSI_PROTOTYPES
258 va_start (args, format);
259#else
260 char *format;
261 va_start (args);
262 format = va_arg (args, char *);
263#endif
264
265 vsprintf (buf, format, args);
266 merge[0] = "gdbtk_tcl_readline_begin";
267 merge[1] = buf;
268 command = Tcl_Merge (2, merge);
269 Tcl_Eval (interp, command);
270 free (command);
271}
272
273static char *
274gdbtk_readline (prompt)
275 char *prompt;
276{
277 char *merge[2];
278 char *command;
bd45f82f 279 int result;
41756e56
FF
280
281 merge[0] = "gdbtk_tcl_readline";
282 merge[1] = prompt;
283 command = Tcl_Merge (2, merge);
bd45f82f
TT
284 result = Tcl_Eval (interp, command);
285 free (command);
286 if (result == TCL_OK)
41756e56
FF
287 {
288 return (strdup (interp -> result));
289 }
290 else
291 {
292 gdbtk_fputs (interp -> result, gdb_stdout);
293 gdbtk_fputs ("\n", gdb_stdout);
294 return (NULL);
295 }
296}
297
298static void
299gdbtk_readline_end ()
300{
301 Tcl_Eval (interp, "gdbtk_tcl_readline_end");
302}
303
754e5da2 304\f
6131622e 305static void
73d3dbd4 306#ifdef ANSI_PROTOTYPES
85c613aa
C
307dsprintf_append_element (Tcl_DString *dsp, char *format, ...)
308#else
6131622e
SG
309dsprintf_append_element (va_alist)
310 va_dcl
85c613aa 311#endif
6131622e
SG
312{
313 va_list args;
85c613aa
C
314 char buf[1024];
315
73d3dbd4 316#ifdef ANSI_PROTOTYPES
85c613aa
C
317 va_start (args, format);
318#else
6131622e
SG
319 Tcl_DString *dsp;
320 char *format;
6131622e
SG
321
322 va_start (args);
6131622e
SG
323 dsp = va_arg (args, Tcl_DString *);
324 format = va_arg (args, char *);
85c613aa 325#endif
6131622e
SG
326
327 vsprintf (buf, format, args);
328
329 Tcl_DStringAppendElement (dsp, buf);
330}
331
8a19b35a
MH
332static int
333gdb_path_conv (clientData, interp, argc, argv)
334 ClientData clientData;
335 Tcl_Interp *interp;
336 int argc;
337 char *argv[];
338{
339#ifdef WINNT
340 char pathname[256], *ptr;
341 if (argc != 2)
342 error ("wrong # args");
343 cygwin32_conv_to_full_win32_path (argv[1], pathname);
344 for (ptr = pathname; *ptr; ptr++)
345 {
346 if (*ptr == '\\')
347 *ptr = '/';
348 }
349#else
350 char *pathname = argv[1];
351#endif
352 Tcl_DStringAppend (result_ptr, pathname, strlen(pathname));
353 return TCL_OK;
354}
355
6131622e
SG
356static int
357gdb_get_breakpoint_list (clientData, interp, argc, argv)
358 ClientData clientData;
359 Tcl_Interp *interp;
360 int argc;
361 char *argv[];
362{
363 struct breakpoint *b;
364 extern struct breakpoint *breakpoint_chain;
365
366 if (argc != 1)
367 error ("wrong # args");
368
369 for (b = breakpoint_chain; b; b = b->next)
370 if (b->type == bp_breakpoint)
371 dsprintf_append_element (result_ptr, "%d", b->number);
372
373 return TCL_OK;
374}
375
376static int
377gdb_get_breakpoint_info (clientData, interp, argc, argv)
378 ClientData clientData;
379 Tcl_Interp *interp;
380 int argc;
381 char *argv[];
382{
383 struct symtab_and_line sal;
384 static char *bptypes[] = {"breakpoint", "hardware breakpoint", "until",
385 "finish", "watchpoint", "hardware watchpoint",
386 "read watchpoint", "access watchpoint",
387 "longjmp", "longjmp resume", "step resume",
388 "through sigtramp", "watchpoint scope",
389 "call dummy" };
27f1958c 390 static char *bpdisp[] = {"delete", "delstop", "disable", "donttouch"};
6131622e
SG
391 struct command_line *cmd;
392 int bpnum;
393 struct breakpoint *b;
394 extern struct breakpoint *breakpoint_chain;
395
396 if (argc != 2)
397 error ("wrong # args");
398
399 bpnum = atoi (argv[1]);
400
401 for (b = breakpoint_chain; b; b = b->next)
402 if (b->number == bpnum)
403 break;
404
9468f8aa 405 if (!b || b->type != bp_breakpoint)
6131622e
SG
406 error ("Breakpoint #%d does not exist", bpnum);
407
6131622e
SG
408 sal = find_pc_line (b->address, 0);
409
410 Tcl_DStringAppendElement (result_ptr, symtab_to_filename (sal.symtab));
411 dsprintf_append_element (result_ptr, "%d", sal.line);
412 dsprintf_append_element (result_ptr, "0x%lx", b->address);
413 Tcl_DStringAppendElement (result_ptr, bptypes[b->type]);
414 Tcl_DStringAppendElement (result_ptr, b->enable == enabled ? "1" : "0");
415 Tcl_DStringAppendElement (result_ptr, bpdisp[b->disposition]);
416 dsprintf_append_element (result_ptr, "%d", b->silent);
417 dsprintf_append_element (result_ptr, "%d", b->ignore_count);
418
419 Tcl_DStringStartSublist (result_ptr);
420 for (cmd = b->commands; cmd; cmd = cmd->next)
421 Tcl_DStringAppendElement (result_ptr, cmd->line);
422 Tcl_DStringEndSublist (result_ptr);
423
424 Tcl_DStringAppendElement (result_ptr, b->cond_string);
425
426 dsprintf_append_element (result_ptr, "%d", b->thread);
427 dsprintf_append_element (result_ptr, "%d", b->hit_count);
428
429 return TCL_OK;
430}
431
754e5da2
SG
432static void
433breakpoint_notify(b, action)
434 struct breakpoint *b;
435 const char *action;
436{
32707df8 437 char buf[256];
754e5da2 438 int v;
2476848a 439 struct symtab_and_line sal;
754e5da2
SG
440
441 if (b->type != bp_breakpoint)
442 return;
443
4e327047
TT
444 /* We ensure that ACTION contains no special Tcl characters, so we
445 can do this. */
2476848a
MH
446 sal = find_pc_line (b->address, 0);
447 sprintf (buf, "gdbtk_tcl_breakpoint %s %d 0x%lx %d {%s}", action, b->number,
448 (long)b->address, sal.line, symtab_to_filename (sal.symtab));
754e5da2 449
6131622e 450 v = Tcl_Eval (interp, buf);
754e5da2
SG
451
452 if (v != TCL_OK)
453 {
546b8ca7
SG
454 gdbtk_fputs (interp->result, gdb_stdout);
455 gdbtk_fputs ("\n", gdb_stdout);
754e5da2 456 }
754e5da2
SG
457}
458
459static void
460gdbtk_create_breakpoint(b)
461 struct breakpoint *b;
462{
6131622e 463 breakpoint_notify (b, "create");
754e5da2
SG
464}
465
466static void
467gdbtk_delete_breakpoint(b)
468 struct breakpoint *b;
469{
6131622e 470 breakpoint_notify (b, "delete");
754e5da2
SG
471}
472
473static void
6131622e 474gdbtk_modify_breakpoint(b)
754e5da2
SG
475 struct breakpoint *b;
476{
6131622e 477 breakpoint_notify (b, "modify");
754e5da2
SG
478}
479\f
480/* This implements the TCL command `gdb_loc', which returns a list consisting
481 of the source and line number associated with the current pc. */
482
483static int
484gdb_loc (clientData, interp, argc, argv)
485 ClientData clientData;
486 Tcl_Interp *interp;
487 int argc;
488 char *argv[];
489{
490 char *filename;
754e5da2
SG
491 struct symtab_and_line sal;
492 char *funcname;
8532893d 493 CORE_ADDR pc;
754e5da2
SG
494
495 if (argc == 1)
496 {
1dfc8dfb 497 pc = selected_frame ? selected_frame->pc : stop_pc;
754e5da2
SG
498 sal = find_pc_line (pc, 0);
499 }
500 else if (argc == 2)
501 {
754e5da2 502 struct symtabs_and_lines sals;
8532893d 503 int nelts;
754e5da2
SG
504
505 sals = decode_line_spec (argv[1], 1);
506
8532893d
SG
507 nelts = sals.nelts;
508 sal = sals.sals[0];
509 free (sals.sals);
510
754e5da2 511 if (sals.nelts != 1)
6131622e 512 error ("Ambiguous line spec");
754e5da2 513
8532893d 514 pc = sal.pc;
754e5da2
SG
515 }
516 else
6131622e 517 error ("wrong # args");
754e5da2 518
754e5da2 519 if (sal.symtab)
6131622e 520 Tcl_DStringAppendElement (result_ptr, sal.symtab->filename);
754e5da2 521 else
6131622e 522 Tcl_DStringAppendElement (result_ptr, "");
8532893d
SG
523
524 find_pc_partial_function (pc, &funcname, NULL, NULL);
6131622e 525 Tcl_DStringAppendElement (result_ptr, funcname);
8532893d 526
637b1661 527 filename = symtab_to_filename (sal.symtab);
6131622e 528 Tcl_DStringAppendElement (result_ptr, filename);
8532893d 529
9468f8aa 530 dsprintf_append_element (result_ptr, "%d", sal.line); /* line number */
754e5da2 531
2476848a
MH
532 dsprintf_append_element (result_ptr, "0x%s", paddr_nz(pc)); /* PC in current frame */
533
534 dsprintf_append_element (result_ptr, "0x%s", paddr_nz(stop_pc)); /* Real PC */
8532893d 535
754e5da2
SG
536 return TCL_OK;
537}
538\f
09722039
SG
539/* This implements the TCL command `gdb_eval'. */
540
541static int
542gdb_eval (clientData, interp, argc, argv)
543 ClientData clientData;
544 Tcl_Interp *interp;
545 int argc;
546 char *argv[];
547{
548 struct expression *expr;
549 struct cleanup *old_chain;
550 value_ptr val;
551
552 if (argc != 2)
6131622e 553 error ("wrong # args");
09722039
SG
554
555 expr = parse_expression (argv[1]);
556
557 old_chain = make_cleanup (free_current_contents, &expr);
558
559 val = evaluate_expression (expr);
560
09722039
SG
561 val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val),
562 gdb_stdout, 0, 0, 0, 0);
09722039
SG
563
564 do_cleanups (old_chain);
565
566 return TCL_OK;
567}
568\f
5b21fb68
SG
569/* This implements the TCL command `gdb_sourcelines', which returns a list of
570 all of the lines containing executable code for the specified source file
571 (ie: lines where you can put breakpoints). */
572
573static int
574gdb_sourcelines (clientData, interp, argc, argv)
575 ClientData clientData;
576 Tcl_Interp *interp;
577 int argc;
578 char *argv[];
579{
580 struct symtab *symtab;
581 struct linetable_entry *le;
582 int nlines;
5b21fb68
SG
583
584 if (argc != 2)
6131622e 585 error ("wrong # args");
5b21fb68
SG
586
587 symtab = lookup_symtab (argv[1]);
588
589 if (!symtab)
6131622e 590 error ("No such file");
5b21fb68
SG
591
592 /* If there's no linetable, or no entries, then we are done. */
593
594 if (!symtab->linetable
595 || symtab->linetable->nitems == 0)
596 {
6131622e 597 Tcl_DStringAppendElement (result_ptr, "");
5b21fb68
SG
598 return TCL_OK;
599 }
600
601 le = symtab->linetable->item;
602 nlines = symtab->linetable->nitems;
603
604 for (;nlines > 0; nlines--, le++)
605 {
606 /* If the pc of this line is the same as the pc of the next line, then
607 just skip it. */
608 if (nlines > 1
609 && le->pc == (le + 1)->pc)
610 continue;
611
9468f8aa 612 dsprintf_append_element (result_ptr, "%d", le->line);
5b21fb68
SG
613 }
614
615 return TCL_OK;
616}
617\f
746d1df4
SG
618static int
619map_arg_registers (argc, argv, func, argp)
620 int argc;
621 char *argv[];
6131622e 622 void (*func) PARAMS ((int regnum, void *argp));
746d1df4
SG
623 void *argp;
624{
625 int regnum;
626
627 /* Note that the test for a valid register must include checking the
628 reg_names array because NUM_REGS may be allocated for the union of the
629 register sets within a family of related processors. In this case, the
630 trailing entries of reg_names will change depending upon the particular
631 processor being debugged. */
632
633 if (argc == 0) /* No args, just do all the regs */
634 {
635 for (regnum = 0;
636 regnum < NUM_REGS
637 && reg_names[regnum] != NULL
638 && *reg_names[regnum] != '\000';
639 regnum++)
640 func (regnum, argp);
641
642 return TCL_OK;
643 }
644
645 /* Else, list of register #s, just do listed regs */
646 for (; argc > 0; argc--, argv++)
647 {
648 regnum = atoi (*argv);
649
650 if (regnum >= 0
651 && regnum < NUM_REGS
652 && reg_names[regnum] != NULL
653 && *reg_names[regnum] != '\000')
654 func (regnum, argp);
655 else
6131622e 656 error ("bad register number");
746d1df4
SG
657 }
658
659 return TCL_OK;
660}
661
6131622e 662static void
746d1df4
SG
663get_register_name (regnum, argp)
664 int regnum;
665 void *argp; /* Ignored */
666{
6131622e 667 Tcl_DStringAppendElement (result_ptr, reg_names[regnum]);
746d1df4
SG
668}
669
5b21fb68
SG
670/* This implements the TCL command `gdb_regnames', which returns a list of
671 all of the register names. */
672
673static int
674gdb_regnames (clientData, interp, argc, argv)
675 ClientData clientData;
676 Tcl_Interp *interp;
677 int argc;
678 char *argv[];
679{
746d1df4
SG
680 argc--;
681 argv++;
682
b607efe7 683 return map_arg_registers (argc, argv, get_register_name, NULL);
746d1df4
SG
684}
685
746d1df4
SG
686#ifndef REGISTER_CONVERTIBLE
687#define REGISTER_CONVERTIBLE(x) (0 != 0)
688#endif
689
690#ifndef REGISTER_CONVERT_TO_VIRTUAL
691#define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a)
692#endif
693
694#ifndef INVALID_FLOAT
695#define INVALID_FLOAT(x, y) (0 != 0)
696#endif
697
6131622e 698static void
746d1df4 699get_register (regnum, fp)
6131622e 700 int regnum;
746d1df4
SG
701 void *fp;
702{
703 char raw_buffer[MAX_REGISTER_RAW_SIZE];
704 char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
705 int format = (int)fp;
706
707 if (read_relative_register_raw_bytes (regnum, raw_buffer))
708 {
6131622e 709 Tcl_DStringAppendElement (result_ptr, "Optimized out");
746d1df4
SG
710 return;
711 }
712
746d1df4
SG
713 /* Convert raw data to virtual format if necessary. */
714
715 if (REGISTER_CONVERTIBLE (regnum))
716 {
717 REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
718 raw_buffer, virtual_buffer);
719 }
720 else
721 memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
722
3d9f68c0
FF
723 if (format == 'r')
724 {
725 int j;
726 printf_filtered ("0x");
727 for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++)
728 {
729 register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
730 : REGISTER_RAW_SIZE (regnum) - 1 - j;
731 printf_filtered ("%02x", (unsigned char)raw_buffer[idx]);
732 }
733 }
734 else
735 val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
736 gdb_stdout, format, 1, 0, Val_pretty_default);
746d1df4 737
6131622e 738 Tcl_DStringAppend (result_ptr, " ", -1);
746d1df4
SG
739}
740
741static int
742gdb_fetch_registers (clientData, interp, argc, argv)
743 ClientData clientData;
744 Tcl_Interp *interp;
745 int argc;
746 char *argv[];
747{
748 int format;
749
750 if (argc < 2)
6131622e 751 error ("wrong # args");
5b21fb68 752
746d1df4
SG
753 argc--;
754 argv++;
5b21fb68 755
746d1df4
SG
756 argc--;
757 format = **argv++;
758
b607efe7 759 return map_arg_registers (argc, argv, get_register, (void *) format);
746d1df4
SG
760}
761
762/* This contains the previous values of the registers, since the last call to
763 gdb_changed_register_list. */
764
765static char old_regs[REGISTER_BYTES];
766
6131622e 767static void
746d1df4 768register_changed_p (regnum, argp)
6131622e 769 int regnum;
746d1df4
SG
770 void *argp; /* Ignored */
771{
772 char raw_buffer[MAX_REGISTER_RAW_SIZE];
746d1df4
SG
773
774 if (read_relative_register_raw_bytes (regnum, raw_buffer))
775 return;
776
777 if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
778 REGISTER_RAW_SIZE (regnum)) == 0)
779 return;
780
fda6fadc 781 /* Found a changed register. Save new value and return its number. */
746d1df4
SG
782
783 memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
784 REGISTER_RAW_SIZE (regnum));
785
9468f8aa 786 dsprintf_append_element (result_ptr, "%d", regnum);
746d1df4
SG
787}
788
789static int
790gdb_changed_register_list (clientData, interp, argc, argv)
791 ClientData clientData;
792 Tcl_Interp *interp;
793 int argc;
794 char *argv[];
795{
746d1df4
SG
796 argc--;
797 argv++;
798
799 return map_arg_registers (argc, argv, register_changed_p, NULL);
5b21fb68
SG
800}
801\f
fda6fadc 802/* This implements the TCL command `gdb_cmd', which sends its argument into
754e5da2
SG
803 the GDB command scanner. */
804
805static int
806gdb_cmd (clientData, interp, argc, argv)
807 ClientData clientData;
808 Tcl_Interp *interp;
809 int argc;
810 char *argv[];
811{
754e5da2 812 if (argc != 2)
6131622e 813 error ("wrong # args");
754e5da2 814
fda6fadc
SS
815 if (running_now)
816 return TCL_OK;
817
86db943c 818 execute_command (argv[1], 1);
479f0f18 819
754e5da2 820 bpstat_do_actions (&stop_bpstat);
754e5da2 821
754e5da2
SG
822 return TCL_OK;
823}
824
c14cabba
AC
825/* Client of call_wrapper - this routine performs the actual call to
826 the client function. */
827
828struct wrapped_call_args
829{
830 Tcl_Interp *interp;
831 Tcl_CmdProc *func;
832 int argc;
833 char **argv;
834 int val;
835};
836
837static int
838wrapped_call (args)
839 struct wrapped_call_args *args;
840{
841 args->val = (*args->func) (args->func, args->interp, args->argc, args->argv);
842 return 1;
843}
844
86db943c
SG
845/* This routine acts as a top-level for all GDB code called by tcl/Tk. It
846 handles cleanups, and calls to return_to_top_level (usually via error).
847 This is necessary in order to prevent a longjmp out of the bowels of Tk,
848 possibly leaving things in a bad state. Since this routine can be called
849 recursively, it needs to save and restore the contents of the jmp_buf as
850 necessary. */
851
852static int
853call_wrapper (clientData, interp, argc, argv)
854 ClientData clientData;
855 Tcl_Interp *interp;
856 int argc;
857 char *argv[];
858{
c14cabba 859 struct wrapped_call_args wrapped_args;
6131622e
SG
860 Tcl_DString result, *old_result_ptr;
861
862 Tcl_DStringInit (&result);
863 old_result_ptr = result_ptr;
864 result_ptr = &result;
86db943c 865
c14cabba
AC
866 wrapped_args.func = (Tcl_CmdProc *)clientData;
867 wrapped_args.interp = interp;
868 wrapped_args.argc = argc;
869 wrapped_args.argv = argv;
870 wrapped_args.val = 0;
86db943c 871
c14cabba 872 if (!catch_errors (wrapped_call, &wrapped_args, "", RETURN_MASK_ALL))
86db943c 873 {
c14cabba 874 wrapped_args.val = TCL_ERROR; /* Flag an error for TCL */
86db943c 875
86db943c
SG
876 gdb_flush (gdb_stderr); /* Flush error output */
877
09722039
SG
878 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
879
fda6fadc
SS
880 /* In case of an error, we may need to force the GUI into idle
881 mode because gdbtk_call_command may have bombed out while in
882 the command routine. */
86db943c 883
40dffa42 884 running_now = 0;
4e327047 885 Tcl_Eval (interp, "gdbtk_tcl_idle");
86db943c
SG
886 }
887
6131622e
SG
888 Tcl_DStringResult (interp, &result);
889 result_ptr = old_result_ptr;
890
c14cabba 891 return wrapped_args.val;
86db943c
SG
892}
893
754e5da2
SG
894static int
895gdb_listfiles (clientData, interp, argc, argv)
896 ClientData clientData;
897 Tcl_Interp *interp;
898 int argc;
899 char *argv[];
900{
754e5da2
SG
901 struct objfile *objfile;
902 struct partial_symtab *psymtab;
546b8ca7 903 struct symtab *symtab;
754e5da2
SG
904
905 ALL_PSYMTABS (objfile, psymtab)
6131622e 906 Tcl_DStringAppendElement (result_ptr, psymtab->filename);
754e5da2 907
546b8ca7 908 ALL_SYMTABS (objfile, symtab)
6131622e 909 Tcl_DStringAppendElement (result_ptr, symtab->filename);
546b8ca7 910
754e5da2
SG
911 return TCL_OK;
912}
479f0f18 913
99c98415
MH
914static int
915gdb_listfuncs (clientData, interp, argc, argv)
916 ClientData clientData;
917 Tcl_Interp *interp;
918 int argc;
919 char *argv[];
920{
921 struct symtab *symtab;
922 struct blockvector *bv;
923 struct block *b;
924 struct symbol *sym;
925 int i,j;
926
927 if (argc != 2)
928 error ("wrong # args");
929
930 symtab = lookup_symtab (argv[1]);
931
932 if (!symtab)
933 error ("No such file");
934
935 bv = BLOCKVECTOR (symtab);
936 for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
937 {
938 b = BLOCKVECTOR_BLOCK (bv, i);
939 /* Skip the sort if this block is always sorted. */
940 if (!BLOCK_SHOULD_SORT (b))
941 sort_block_syms (b);
942 for (j = 0; j < BLOCK_NSYMS (b); j++)
943 {
944 sym = BLOCK_SYM (b, j);
945 if (SYMBOL_CLASS (sym) == LOC_BLOCK)
946 {
947 Tcl_DStringAppendElement (result_ptr, SYMBOL_NAME(sym));
948 }
949 }
950 }
951 return TCL_OK;
952}
953
479f0f18
SG
954static int
955gdb_stop (clientData, interp, argc, argv)
956 ClientData clientData;
957 Tcl_Interp *interp;
958 int argc;
959 char *argv[];
960{
c14cabba
AC
961 if (target_stop)
962 target_stop ();
963 else
964 quit_flag = 1; /* hope something sees this */
546b8ca7
SG
965
966 return TCL_OK;
479f0f18 967}
09722039
SG
968\f
969/* This implements the TCL command `gdb_disassemble'. */
479f0f18 970
09722039
SG
971static int
972gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
973 bfd_vma memaddr;
974 bfd_byte *myaddr;
975 int len;
976 disassemble_info *info;
977{
978 extern struct target_ops exec_ops;
979 int res;
980
981 errno = 0;
982 res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
983
984 if (res == len)
985 return 0;
986 else
987 if (errno == 0)
988 return EIO;
989 else
990 return errno;
991}
992
993/* We need a different sort of line table from the normal one cuz we can't
994 depend upon implicit line-end pc's for lines. This is because of the
995 reordering we are about to do. */
996
997struct my_line_entry {
998 int line;
999 CORE_ADDR start_pc;
1000 CORE_ADDR end_pc;
1001};
1002
1003static int
1004compare_lines (mle1p, mle2p)
1005 const PTR mle1p;
1006 const PTR mle2p;
1007{
1008 struct my_line_entry *mle1, *mle2;
1009 int val;
1010
1011 mle1 = (struct my_line_entry *) mle1p;
1012 mle2 = (struct my_line_entry *) mle2p;
1013
1014 val = mle1->line - mle2->line;
1015
1016 if (val != 0)
1017 return val;
1018
1019 return mle1->start_pc - mle2->start_pc;
1020}
1021
1022static int
1023gdb_disassemble (clientData, interp, argc, argv)
1024 ClientData clientData;
1025 Tcl_Interp *interp;
1026 int argc;
1027 char *argv[];
1028{
1029 CORE_ADDR pc, low, high;
1030 int mixed_source_and_assembly;
fc941258
DE
1031 static disassemble_info di;
1032 static int di_initialized;
1033
1034 if (! di_initialized)
1035 {
91550191
SG
1036 INIT_DISASSEMBLE_INFO_NO_ARCH (di, gdb_stdout,
1037 (fprintf_ftype) fprintf_unfiltered);
caeec767 1038 di.flavour = bfd_target_unknown_flavour;
fc941258
DE
1039 di.memory_error_func = dis_asm_memory_error;
1040 di.print_address_func = dis_asm_print_address;
1041 di_initialized = 1;
1042 }
09722039 1043
91550191
SG
1044 di.mach = tm_print_insn_info.mach;
1045 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
e4bb9027 1046 di.endian = BFD_ENDIAN_BIG;
91550191 1047 else
e4bb9027 1048 di.endian = BFD_ENDIAN_LITTLE;
91550191 1049
09722039 1050 if (argc != 3 && argc != 4)
6131622e 1051 error ("wrong # args");
09722039
SG
1052
1053 if (strcmp (argv[1], "source") == 0)
1054 mixed_source_and_assembly = 1;
1055 else if (strcmp (argv[1], "nosource") == 0)
1056 mixed_source_and_assembly = 0;
1057 else
6131622e 1058 error ("First arg must be 'source' or 'nosource'");
09722039
SG
1059
1060 low = parse_and_eval_address (argv[2]);
1061
1062 if (argc == 3)
1063 {
1064 if (find_pc_partial_function (low, NULL, &low, &high) == 0)
6131622e 1065 error ("No function contains specified address");
09722039
SG
1066 }
1067 else
1068 high = parse_and_eval_address (argv[3]);
1069
1070 /* If disassemble_from_exec == -1, then we use the following heuristic to
1071 determine whether or not to do disassembly from target memory or from the
1072 exec file:
1073
1074 If we're debugging a local process, read target memory, instead of the
1075 exec file. This makes disassembly of functions in shared libs work
1076 correctly.
1077
1078 Else, we're debugging a remote process, and should disassemble from the
fda6fadc 1079 exec file for speed. However, this is no good if the target modifies its
09722039
SG
1080 code (for relocation, or whatever).
1081 */
1082
1083 if (disassemble_from_exec == -1)
1084 if (strcmp (target_shortname, "child") == 0
d7c4766c
SS
1085 || strcmp (target_shortname, "procfs") == 0
1086 || strcmp (target_shortname, "vxprocess") == 0)
09722039
SG
1087 disassemble_from_exec = 0; /* It's a child process, read inferior mem */
1088 else
1089 disassemble_from_exec = 1; /* It's remote, read the exec file */
1090
1091 if (disassemble_from_exec)
a76ef70a
SG
1092 di.read_memory_func = gdbtk_dis_asm_read_memory;
1093 else
1094 di.read_memory_func = dis_asm_read_memory;
09722039
SG
1095
1096 /* If just doing straight assembly, all we need to do is disassemble
1097 everything between low and high. If doing mixed source/assembly, we've
1098 got a totally different path to follow. */
1099
1100 if (mixed_source_and_assembly)
1101 { /* Come here for mixed source/assembly */
1102 /* The idea here is to present a source-O-centric view of a function to
1103 the user. This means that things are presented in source order, with
1104 (possibly) out of order assembly immediately following. */
1105 struct symtab *symtab;
1106 struct linetable_entry *le;
1107 int nlines;
c81a3fa9 1108 int newlines;
09722039
SG
1109 struct my_line_entry *mle;
1110 struct symtab_and_line sal;
1111 int i;
1112 int out_of_order;
c81a3fa9 1113 int next_line;
09722039
SG
1114
1115 symtab = find_pc_symtab (low); /* Assume symtab is valid for whole PC range */
1116
1117 if (!symtab)
1118 goto assembly_only;
1119
1120/* First, convert the linetable to a bunch of my_line_entry's. */
1121
1122 le = symtab->linetable->item;
1123 nlines = symtab->linetable->nitems;
1124
1125 if (nlines <= 0)
1126 goto assembly_only;
1127
1128 mle = (struct my_line_entry *) alloca (nlines * sizeof (struct my_line_entry));
1129
1130 out_of_order = 0;
1131
c81a3fa9
SG
1132/* Copy linetable entries for this function into our data structure, creating
1133 end_pc's and setting out_of_order as appropriate. */
1134
1135/* First, skip all the preceding functions. */
1136
1137 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
1138
1139/* Now, copy all entries before the end of this function. */
1140
1141 newlines = 0;
1142 for (; i < nlines - 1 && le[i].pc < high; i++)
09722039 1143 {
c81a3fa9
SG
1144 if (le[i].line == le[i + 1].line
1145 && le[i].pc == le[i + 1].pc)
1146 continue; /* Ignore duplicates */
1147
1148 mle[newlines].line = le[i].line;
09722039
SG
1149 if (le[i].line > le[i + 1].line)
1150 out_of_order = 1;
c81a3fa9
SG
1151 mle[newlines].start_pc = le[i].pc;
1152 mle[newlines].end_pc = le[i + 1].pc;
1153 newlines++;
09722039
SG
1154 }
1155
c81a3fa9
SG
1156/* If we're on the last line, and it's part of the function, then we need to
1157 get the end pc in a special way. */
1158
1159 if (i == nlines - 1
1160 && le[i].pc < high)
1161 {
1162 mle[newlines].line = le[i].line;
1163 mle[newlines].start_pc = le[i].pc;
1164 sal = find_pc_line (le[i].pc, 0);
1165 mle[newlines].end_pc = sal.end;
1166 newlines++;
1167 }
09722039
SG
1168
1169/* Now, sort mle by line #s (and, then by addresses within lines). */
1170
1171 if (out_of_order)
c81a3fa9 1172 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
09722039
SG
1173
1174/* Now, for each line entry, emit the specified lines (unless they have been
1175 emitted before), followed by the assembly code for that line. */
1176
c81a3fa9
SG
1177 next_line = 0; /* Force out first line */
1178 for (i = 0; i < newlines; i++)
09722039 1179 {
c81a3fa9
SG
1180/* Print out everything from next_line to the current line. */
1181
1182 if (mle[i].line >= next_line)
09722039 1183 {
c81a3fa9
SG
1184 if (next_line != 0)
1185 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
09722039 1186 else
c81a3fa9
SG
1187 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
1188
1189 next_line = mle[i].line + 1;
09722039 1190 }
c81a3fa9 1191
09722039
SG
1192 for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
1193 {
1194 QUIT;
1195 fputs_unfiltered (" ", gdb_stdout);
1196 print_address (pc, gdb_stdout);
1197 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 1198 pc += (*tm_print_insn) (pc, &di);
09722039
SG
1199 fputs_unfiltered ("\n", gdb_stdout);
1200 }
1201 }
1202 }
1203 else
1204 {
1205assembly_only:
1206 for (pc = low; pc < high; )
1207 {
1208 QUIT;
1209 fputs_unfiltered (" ", gdb_stdout);
1210 print_address (pc, gdb_stdout);
1211 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 1212 pc += (*tm_print_insn) (pc, &di);
09722039
SG
1213 fputs_unfiltered ("\n", gdb_stdout);
1214 }
1215 }
1216
09722039
SG
1217 gdb_flush (gdb_stdout);
1218
1219 return TCL_OK;
1220}
754e5da2
SG
1221\f
1222static void
1223tk_command (cmd, from_tty)
1224 char *cmd;
1225 int from_tty;
1226{
546b8ca7
SG
1227 int retval;
1228 char *result;
1229 struct cleanup *old_chain;
1230
572977a5
FF
1231 /* Catch case of no argument, since this will make the tcl interpreter dump core. */
1232 if (cmd == NULL)
1233 error_no_arg ("tcl command to interpret");
1234
546b8ca7
SG
1235 retval = Tcl_Eval (interp, cmd);
1236
1237 result = strdup (interp->result);
754e5da2 1238
546b8ca7
SG
1239 old_chain = make_cleanup (free, result);
1240
1241 if (retval != TCL_OK)
1242 error (result);
1243
1244 printf_unfiltered ("%s\n", result);
1245
1246 do_cleanups (old_chain);
754e5da2
SG
1247}
1248
1249static void
1250cleanup_init (ignored)
1251 int ignored;
1252{
754e5da2
SG
1253 if (interp != NULL)
1254 Tcl_DeleteInterp (interp);
1255 interp = NULL;
1256}
1257
637b1661
SG
1258/* Come here during long calculations to check for GUI events. Usually invoked
1259 via the QUIT macro. */
1260
1261static void
1262gdbtk_interactive ()
1263{
1264 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
1265}
1266
479f0f18
SG
1267/* Come here when there is activity on the X file descriptor. */
1268
1269static void
1270x_event (signo)
1271 int signo;
1272{
1273 /* Process pending events */
1274
f02156cf 1275 while (Tcl_DoOneEvent (TCL_DONT_WAIT|TCL_ALL_EVENTS) != 0);
479f0f18
SG
1276}
1277
1278static int
1279gdbtk_wait (pid, ourstatus)
1280 int pid;
1281 struct target_waitstatus *ourstatus;
1282{
736a82e7
SG
1283 struct sigaction action;
1284 static sigset_t nullsigmask = {0};
1285
1286#ifndef SA_RESTART
1287 /* Needed for SunOS 4.1.x */
1288#define SA_RESTART 0
546b8ca7 1289#endif
479f0f18 1290
736a82e7
SG
1291 action.sa_handler = x_event;
1292 action.sa_mask = nullsigmask;
1293 action.sa_flags = SA_RESTART;
8a19b35a 1294#ifndef WINNT
736a82e7 1295 sigaction(SIGIO, &action, NULL);
8a19b35a 1296#endif
736a82e7 1297
479f0f18
SG
1298 pid = target_wait (pid, ourstatus);
1299
736a82e7 1300 action.sa_handler = SIG_IGN;
8a19b35a
MH
1301#ifndef WINNT
1302 sigaction(SIGIO, &action, NULL);
1303#endif
479f0f18
SG
1304
1305 return pid;
1306}
1307
1308/* This is called from execute_command, and provides a wrapper around
1309 various command routines in a place where both protocol messages and
1310 user input both flow through. Mostly this is used for indicating whether
1311 the target process is running or not.
1312*/
1313
1314static void
1315gdbtk_call_command (cmdblk, arg, from_tty)
1316 struct cmd_list_element *cmdblk;
1317 char *arg;
1318 int from_tty;
1319{
fda6fadc 1320 running_now = 0;
479f0f18
SG
1321 if (cmdblk->class == class_run)
1322 {
fda6fadc 1323 running_now = 1;
4e327047 1324 Tcl_Eval (interp, "gdbtk_tcl_busy");
479f0f18 1325 (*cmdblk->function.cfunc)(arg, from_tty);
fda6fadc 1326 running_now = 0;
2476848a 1327 Tcl_Eval (interp, "gdbtk_tcl_idle");
479f0f18
SG
1328 }
1329 else
1330 (*cmdblk->function.cfunc)(arg, from_tty);
1331}
1332
5bac2b50
FF
1333/* This function is called instead of gdb's internal command loop. This is the
1334 last chance to do anything before entering the main Tk event loop. */
1335
1336static void
1337tk_command_loop ()
1338{
41756e56
FF
1339 extern GDB_FILE *instream;
1340
1341 /* We no longer want to use stdin as the command input stream */
1342 instream = NULL;
5bac2b50
FF
1343 Tcl_Eval (interp, "gdbtk_tcl_preloop");
1344 Tk_MainLoop ();
1345}
1346
9a2f9219
ILT
1347/* gdbtk_init installs this function as a final cleanup. */
1348
1349static void
1350gdbtk_cleanup (dummy)
1351 PTR dummy;
1352{
1353 Tcl_Finalize ();
1354}
1355
1356/* Initialize gdbtk. */
1357
754e5da2 1358static void
2476848a
MH
1359gdbtk_init ( argv0 )
1360 char *argv0;
754e5da2
SG
1361{
1362 struct cleanup *old_chain;
74089546 1363 char *lib, *gdbtk_lib, *gdbtk_lib_tmp, *gdbtk_file;
8a19b35a 1364 int i, found_main;
736a82e7
SG
1365 struct sigaction action;
1366 static sigset_t nullsigmask = {0};
2476848a
MH
1367#ifdef IDE
1368 struct ide_event_handle *h;
1369 const char *errmsg;
1370 char *libexecdir;
1371#endif
754e5da2 1372
fe58c81f
FF
1373 /* If there is no DISPLAY environment variable, Tk_Init below will fail,
1374 causing gdb to abort. If instead we simply return here, gdb will
1375 gracefully degrade to using the command line interface. */
1376
8a19b35a 1377#ifndef WINNT
fe58c81f
FF
1378 if (getenv ("DISPLAY") == NULL)
1379 return;
8a19b35a 1380#endif
fe58c81f 1381
754e5da2
SG
1382 old_chain = make_cleanup (cleanup_init, 0);
1383
1384 /* First init tcl and tk. */
2476848a 1385 Tcl_FindExecutable (argv0);
754e5da2
SG
1386 interp = Tcl_CreateInterp ();
1387
1388 if (!interp)
1389 error ("Tcl_CreateInterp failed");
1390
754e5da2
SG
1391 if (Tcl_Init(interp) != TCL_OK)
1392 error ("Tcl_Init failed: %s", interp->result);
1393
9a2f9219 1394 make_final_cleanup (gdbtk_cleanup, NULL);
2476848a
MH
1395
1396#ifdef IDE
9a2f9219 1397 /* Initialize the Paths variable. */
74089546 1398 if (ide_initialize_paths (interp, "gdbtcl") != TCL_OK)
9a2f9219
ILT
1399 error ("ide_initialize_paths failed: %s", interp->result);
1400
2476848a
MH
1401 /* Find the directory where we expect to find idemanager. We ignore
1402 errors since it doesn't really matter if this fails. */
1403 libexecdir = Tcl_GetVar2 (interp, "Paths", "libexecdir", TCL_GLOBAL_ONLY);
1404
1405 IluTk_Init ();
1406
7b94b2ea 1407 h = ide_event_init_from_environment (&errmsg, libexecdir);
2476848a
MH
1408 if (h == NULL)
1409 {
1410 Tcl_AppendResult (interp, "can't initialize event system: ", errmsg,
1411 (char *) NULL);
1412 fprintf(stderr, "WARNING: ide_event_init_client failed: %s\n", interp->result);
9a2f9219
ILT
1413
1414 Tcl_SetVar (interp, "GDBTK_IDE", "0", 0);
2476848a
MH
1415 }
1416 else
1417 {
1418 if (ide_create_tclevent_command (interp, h) != TCL_OK)
1419 error ("ide_create_tclevent_command failed: %s", interp->result);
1420 if (ide_create_edit_command (interp, h) != TCL_OK)
1421 error ("ide_create_edit_command failed: %s", interp->result);
1422
1423 if (ide_create_property_command (interp, h) != TCL_OK)
1424 error ("ide_create_property_command failed: %s", interp->result);
1425
9a2f9219
ILT
1426 if (ide_create_window_register_command (interp, h) != TCL_OK)
1427 error ("ide_create_window_register_command failed: %s",
1428 interp->result);
1429
1430 if (ide_create_window_command (interp, h) != TCL_OK)
1431 error ("ide_create_window_command failed: %s", interp->result);
1432
2476848a
MH
1433 /*
1434 if (ide_initialize (interp, "gdb") != TCL_OK)
1435 error ("ide_initialize failed: %s", interp->result);
1436 */
9a2f9219
ILT
1437
1438 Tcl_SetVar (interp, "GDBTK_IDE", "1", 0);
2476848a 1439 }
2476848a
MH
1440#else
1441 Tcl_SetVar (interp, "GDBTK_IDE", "0", 0);
1442#endif /* IDE */
1443
9a2f9219
ILT
1444 /* We don't want to open the X connection until we've done all the
1445 IDE initialization. Otherwise, goofy looking unfinished windows
1446 pop up when ILU drops into the TCL event loop. */
1447
1448 if (Tk_Init(interp) != TCL_OK)
1449 error ("Tk_Init failed: %s", interp->result);
1450
1451 if (Itcl_Init(interp) == TCL_ERROR)
1452 error ("Itcl_Init failed: %s", interp->result);
1453
1454 if (Tix_Init(interp) != TCL_OK)
1455 error ("Tix_Init failed: %s", interp->result);
1456
86db943c
SG
1457 Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
1458 Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
8a19b35a 1459 Tcl_CreateCommand (interp, "gdb_path_conv", call_wrapper, gdb_path_conv, NULL);
86db943c
SG
1460 Tcl_CreateCommand (interp, "gdb_sourcelines", call_wrapper, gdb_sourcelines,
1461 NULL);
1462 Tcl_CreateCommand (interp, "gdb_listfiles", call_wrapper, gdb_listfiles,
746d1df4 1463 NULL);
99c98415
MH
1464 Tcl_CreateCommand (interp, "gdb_listfuncs", call_wrapper, gdb_listfuncs,
1465 NULL);
86db943c
SG
1466 Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
1467 Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
1468 Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
1469 gdb_fetch_registers, NULL);
1470 Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
1471 gdb_changed_register_list, NULL);
09722039
SG
1472 Tcl_CreateCommand (interp, "gdb_disassemble", call_wrapper,
1473 gdb_disassemble, NULL);
1474 Tcl_CreateCommand (interp, "gdb_eval", call_wrapper, gdb_eval, NULL);
6131622e
SG
1475 Tcl_CreateCommand (interp, "gdb_get_breakpoint_list", call_wrapper,
1476 gdb_get_breakpoint_list, NULL);
1477 Tcl_CreateCommand (interp, "gdb_get_breakpoint_info", call_wrapper,
1478 gdb_get_breakpoint_info, NULL);
754e5da2 1479
5bac2b50 1480 command_loop_hook = tk_command_loop;
b607efe7
FF
1481 print_frame_info_listing_hook =
1482 (void (*) PARAMS ((struct symtab *, int, int, int))) null_routine;
09722039
SG
1483 query_hook = gdbtk_query;
1484 flush_hook = gdbtk_flush;
1485 create_breakpoint_hook = gdbtk_create_breakpoint;
1486 delete_breakpoint_hook = gdbtk_delete_breakpoint;
6131622e 1487 modify_breakpoint_hook = gdbtk_modify_breakpoint;
09722039
SG
1488 interactive_hook = gdbtk_interactive;
1489 target_wait_hook = gdbtk_wait;
1490 call_command_hook = gdbtk_call_command;
41756e56
FF
1491 readline_begin_hook = gdbtk_readline_begin;
1492 readline_hook = gdbtk_readline;
1493 readline_end_hook = gdbtk_readline_end;
754e5da2 1494
cd2df226 1495 /* Get the file descriptor for the X server */
479f0f18 1496
047465fd 1497 x_fd = ConnectionNumber (Tk_Display (Tk_MainWindow (interp)));
479f0f18
SG
1498
1499 /* Setup for I/O interrupts */
1500
736a82e7
SG
1501 action.sa_mask = nullsigmask;
1502 action.sa_flags = 0;
1503 action.sa_handler = SIG_IGN;
8a19b35a 1504#ifndef WINNT
736a82e7 1505 sigaction(SIGIO, &action, NULL);
8a19b35a 1506#endif
736a82e7
SG
1507
1508#ifdef FIOASYNC
1509 i = 1;
1510 if (ioctl (x_fd, FIOASYNC, &i))
1511 perror_with_name ("gdbtk_init: ioctl FIOASYNC failed");
479f0f18 1512
77a89957 1513#ifdef SIOCSPGRP
736a82e7
SG
1514 i = getpid();
1515 if (ioctl (x_fd, SIOCSPGRP, &i))
1516 perror_with_name ("gdbtk_init: ioctl SIOCSPGRP failed");
45f90c50
MM
1517
1518#else
1519#ifdef F_SETOWN
1520 i = getpid();
1521 if (fcntl (x_fd, F_SETOWN, i))
1522 perror_with_name ("gdbtk_init: fcntl F_SETOWN failed");
1523#endif /* F_SETOWN */
1524#endif /* !SIOCSPGRP */
546b8ca7 1525#else
8a19b35a 1526#ifndef WINNT
546b8ca7 1527 if (ioctl (x_fd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
736a82e7 1528 perror_with_name ("gdbtk_init: ioctl I_SETSIG failed");
8a19b35a
MH
1529#endif
1530
736a82e7 1531#endif /* ifndef FIOASYNC */
479f0f18 1532
754e5da2
SG
1533 add_com ("tk", class_obscure, tk_command,
1534 "Send a command directly into tk.");
09722039 1535
09722039
SG
1536 Tcl_LinkVar (interp, "disassemble-from-exec", (char *)&disassemble_from_exec,
1537 TCL_LINK_INT);
1538
8a19b35a 1539 /* find the gdb tcl library and source main.tcl */
09722039 1540
8a19b35a
MH
1541 gdbtk_lib = getenv ("GDBTK_LIBRARY");
1542 if (!gdbtk_lib)
1543 if (access ("gdbtcl/main.tcl", R_OK) == 0)
1544 gdbtk_lib = "gdbtcl";
09722039 1545 else
8a19b35a
MH
1546 gdbtk_lib = GDBTK_LIBRARY;
1547
74089546
ILT
1548 gdbtk_lib_tmp = xstrdup (gdbtk_lib);
1549
8a19b35a
MH
1550 found_main = 0;
1551 /* see if GDBTK_LIBRARY is a path list */
1552 lib = strtok (gdbtk_lib_tmp, GDBTK_PATH_SEP);
1553 do
1554 {
1555 if (Tcl_VarEval (interp, "lappend auto_path ", lib, NULL) != TCL_OK)
1556 {
1557 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
1558 error ("");
1559 }
1560 if (!found_main)
1561 {
74089546 1562 gdbtk_file = concat (lib, "/main.tcl", (char *) NULL);
8a19b35a
MH
1563 if (access (gdbtk_file, R_OK) == 0)
1564 {
1565 found_main++;
1566 Tcl_SetVar (interp, "GDBTK_LIBRARY", lib, 0);
1567 }
1568 }
1569 }
56e327b3 1570 while ((lib = strtok (NULL, ":")) != NULL);
74089546
ILT
1571
1572 free (gdbtk_lib_tmp);
1573
1574#ifdef IDE
1575 if (!found_main)
1576 {
1577 /* Try finding it with the auto path. */
1578
1579 static const char script[] ="\
1580proc gdbtk_find_main {} {\n\
1581 global auto_path GDBTK_LIBRARY\n\
1582 foreach dir $auto_path {\n\
1583 set f [file join $dir main.tcl]\n\
1584 if {[file exists $f]} then {\n\
1585 set GDBTK_LIBRARY $dir\n\
1586 return $f\n\
1587 }\n\
1588 }\n\
1589 return ""\n\
1590}\n\
1591gdbtk_find_main";
1592
1593 if (Tcl_GlobalEval (interp, (char *) script) != TCL_OK)
1594 {
1595 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
1596 error ("");
1597 }
1598
1599 if (interp->result[0] != '\0')
1600 {
1601 gdbtk_file = xstrdup (interp->result);
1602 found_main++;
1603 }
1604 }
1605#endif
1606
8a19b35a
MH
1607 if (!found_main)
1608 {
1609 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
1610 if (getenv("GDBTK_LIBRARY"))
1611 {
1612 fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n",getenv("GDBTK_LIBRARY"));
1613 fprintf_unfiltered (stderr,
1614 "Please set GDBTK_LIBRARY to a path that includes the GDB tcl files.\n");
1615 }
1616 else
1617 {
1618 fprintf_unfiltered (stderr, "Unable to find main.tcl in %s\n", GDBTK_LIBRARY);
1619 fprintf_unfiltered (stderr, "You might want to set GDBTK_LIBRARY\n");
1620 }
1621 error("");
1622 }
09722039 1623
724498fd
SG
1624/* Defer setup of fputs_unfiltered_hook to near the end so that error messages
1625 prior to this point go to stdout/stderr. */
1626
1627 fputs_unfiltered_hook = gdbtk_fputs;
1628
8a19b35a 1629 if (Tcl_EvalFile (interp, gdbtk_file) != TCL_OK)
724498fd
SG
1630 {
1631 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
1632
8a19b35a 1633 fprintf_unfiltered (stderr, "%s:%d: %s\n", gdbtk_file,
724498fd 1634 interp->errorLine, interp->result);
b66051ec
SG
1635
1636 fputs_unfiltered ("Stack trace:\n", gdb_stderr);
1637 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
1638 error ("");
724498fd 1639 }
09722039 1640
74089546
ILT
1641 free (gdbtk_file);
1642
09722039 1643 discard_cleanups (old_chain);
754e5da2
SG
1644}
1645
3f37b696 1646/* Come here during initialize_all_files () */
754e5da2
SG
1647
1648void
1649_initialize_gdbtk ()
1650{
c5197511
SG
1651 if (use_windows)
1652 {
1653 /* Tell the rest of the world that Gdbtk is now set up. */
754e5da2 1654
c5197511
SG
1655 init_ui_hook = gdbtk_init;
1656 }
754e5da2 1657}
This page took 0.215828 seconds and 4 git commands to generate.