* valprint.c (print_longest): Fix a syntax error in #ifdef
[deliverable/binutils-gdb.git] / gdb / gdbtk.c
CommitLineData
4604b34c
SG
1/* Tcl/Tk interface routines.
2 Copyright 1994, 1995 Free Software Foundation, Inc.
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
20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
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>
cd2df226
SG
32#include <varargs.h>
33#include <signal.h>
34#include <fcntl.h>
8532893d 35#include <unistd.h>
86db943c
SG
36#include <setjmp.h>
37#include "top.h"
736a82e7
SG
38#include <sys/ioctl.h>
39#include <string.h>
09722039 40#include "dis-asm.h"
6131622e
SG
41#include <stdio.h>
42#include "gdbcmd.h"
736a82e7
SG
43
44#ifndef FIOASYNC
546b8ca7
SG
45#include <sys/stropts.h>
46#endif
754e5da2 47
754e5da2
SG
48/* Handle for TCL interpreter */
49static Tcl_Interp *interp = NULL;
50
51/* Handle for TK main window */
52static Tk_Window mainWindow = NULL;
53
479f0f18
SG
54static int x_fd; /* X network socket */
55
09722039
SG
56/* This variable determines where memory used for disassembly is read from.
57
58 If > 0, then disassembly comes from the exec file rather than the target
59 (which might be at the other end of a slow serial link). If == 0 then
60 disassembly comes from target. If < 0 disassembly is automatically switched
61 to the target if it's an inferior process, otherwise the exec file is
62 used.
63 */
64
65static int disassemble_from_exec = -1;
66
754e5da2
SG
67static void
68null_routine(arg)
69 int arg;
70{
71}
72
546b8ca7
SG
73/* The following routines deal with stdout/stderr data, which is created by
74 {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
75 lowest level of these routines and capture all output from the rest of GDB.
76 Normally they present their data to tcl via callbacks to the following tcl
77 routines: gdbtk_tcl_fputs, gdbtk_tcl_fputs_error, and gdbtk_flush. These
78 in turn call tk routines to update the display.
86db943c 79
546b8ca7
SG
80 Under some circumstances, you may want to collect the output so that it can
81 be returned as the value of a tcl procedure. This can be done by
82 surrounding the output routines with calls to start_saving_output and
83 finish_saving_output. The saved data can then be retrieved with
84 get_saved_output (but this must be done before the call to
85 finish_saving_output). */
86db943c 86
546b8ca7 87/* Dynamic string header for stdout. */
86db943c 88
6131622e 89static Tcl_DString *result_ptr;
754e5da2 90\f
754e5da2
SG
91static void
92gdbtk_flush (stream)
93 FILE *stream;
94{
6131622e 95#if 0
86db943c
SG
96 /* Force immediate screen update */
97
754e5da2 98 Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
6131622e 99#endif
754e5da2
SG
100}
101
8532893d 102static void
86db943c 103gdbtk_fputs (ptr, stream)
8532893d 104 const char *ptr;
86db943c 105 FILE *stream;
8532893d 106{
6131622e
SG
107 if (result_ptr)
108 Tcl_DStringAppend (result_ptr, ptr, -1);
109 else
86db943c 110 {
6131622e 111 Tcl_DString str;
86db943c 112
6131622e 113 Tcl_DStringInit (&str);
8532893d 114
6131622e
SG
115 Tcl_DStringAppend (&str, "gdbtk_tcl_fputs", -1);
116 Tcl_DStringAppendElement (&str, ptr);
8532893d 117
6131622e
SG
118 Tcl_Eval (interp, Tcl_DStringValue (&str));
119 Tcl_DStringFree (&str);
120 }
8532893d
SG
121}
122
754e5da2
SG
123static int
124gdbtk_query (args)
125 va_list args;
126{
127 char *query;
128 char buf[200];
129 long val;
130
131 query = va_arg (args, char *);
132
6131622e 133 vsprintf (buf, query, args);
754e5da2
SG
134 Tcl_VarEval (interp, "gdbtk_tcl_query ", "{", buf, "}", NULL);
135
136 val = atol (interp->result);
137 return val;
138}
139\f
6131622e
SG
140static void
141dsprintf_append_element (va_alist)
142 va_dcl
143{
144 va_list args;
145 Tcl_DString *dsp;
146 char *format;
147 char buf[1024];
148
149 va_start (args);
150
151 dsp = va_arg (args, Tcl_DString *);
152 format = va_arg (args, char *);
153
154 vsprintf (buf, format, args);
155
156 Tcl_DStringAppendElement (dsp, buf);
157}
158
159static int
160gdb_get_breakpoint_list (clientData, interp, argc, argv)
161 ClientData clientData;
162 Tcl_Interp *interp;
163 int argc;
164 char *argv[];
165{
166 struct breakpoint *b;
167 extern struct breakpoint *breakpoint_chain;
168
169 if (argc != 1)
170 error ("wrong # args");
171
172 for (b = breakpoint_chain; b; b = b->next)
173 if (b->type == bp_breakpoint)
174 dsprintf_append_element (result_ptr, "%d", b->number);
175
176 return TCL_OK;
177}
178
179static int
180gdb_get_breakpoint_info (clientData, interp, argc, argv)
181 ClientData clientData;
182 Tcl_Interp *interp;
183 int argc;
184 char *argv[];
185{
186 struct symtab_and_line sal;
187 static char *bptypes[] = {"breakpoint", "hardware breakpoint", "until",
188 "finish", "watchpoint", "hardware watchpoint",
189 "read watchpoint", "access watchpoint",
190 "longjmp", "longjmp resume", "step resume",
191 "through sigtramp", "watchpoint scope",
192 "call dummy" };
193 static char *bpdisp[] = {"delete", "disable", "donttouch"};
194 struct command_line *cmd;
195 int bpnum;
196 struct breakpoint *b;
197 extern struct breakpoint *breakpoint_chain;
198
199 if (argc != 2)
200 error ("wrong # args");
201
202 bpnum = atoi (argv[1]);
203
204 for (b = breakpoint_chain; b; b = b->next)
205 if (b->number == bpnum)
206 break;
207
9468f8aa 208 if (!b || b->type != bp_breakpoint)
6131622e
SG
209 error ("Breakpoint #%d does not exist", bpnum);
210
6131622e
SG
211 sal = find_pc_line (b->address, 0);
212
213 Tcl_DStringAppendElement (result_ptr, symtab_to_filename (sal.symtab));
214 dsprintf_append_element (result_ptr, "%d", sal.line);
215 dsprintf_append_element (result_ptr, "0x%lx", b->address);
216 Tcl_DStringAppendElement (result_ptr, bptypes[b->type]);
217 Tcl_DStringAppendElement (result_ptr, b->enable == enabled ? "1" : "0");
218 Tcl_DStringAppendElement (result_ptr, bpdisp[b->disposition]);
219 dsprintf_append_element (result_ptr, "%d", b->silent);
220 dsprintf_append_element (result_ptr, "%d", b->ignore_count);
221
222 Tcl_DStringStartSublist (result_ptr);
223 for (cmd = b->commands; cmd; cmd = cmd->next)
224 Tcl_DStringAppendElement (result_ptr, cmd->line);
225 Tcl_DStringEndSublist (result_ptr);
226
227 Tcl_DStringAppendElement (result_ptr, b->cond_string);
228
229 dsprintf_append_element (result_ptr, "%d", b->thread);
230 dsprintf_append_element (result_ptr, "%d", b->hit_count);
231
232 return TCL_OK;
233}
234
754e5da2
SG
235static void
236breakpoint_notify(b, action)
237 struct breakpoint *b;
238 const char *action;
239{
6131622e 240 char buf[100];
754e5da2
SG
241 int v;
242
243 if (b->type != bp_breakpoint)
244 return;
245
6131622e 246 sprintf (buf, "gdbtk_tcl_breakpoint %s %d", action, b->number);
754e5da2 247
6131622e 248 v = Tcl_Eval (interp, buf);
754e5da2
SG
249
250 if (v != TCL_OK)
251 {
546b8ca7
SG
252 gdbtk_fputs (interp->result, gdb_stdout);
253 gdbtk_fputs ("\n", gdb_stdout);
754e5da2 254 }
754e5da2
SG
255}
256
257static void
258gdbtk_create_breakpoint(b)
259 struct breakpoint *b;
260{
6131622e 261 breakpoint_notify (b, "create");
754e5da2
SG
262}
263
264static void
265gdbtk_delete_breakpoint(b)
266 struct breakpoint *b;
267{
6131622e 268 breakpoint_notify (b, "delete");
754e5da2
SG
269}
270
271static void
6131622e 272gdbtk_modify_breakpoint(b)
754e5da2
SG
273 struct breakpoint *b;
274{
6131622e 275 breakpoint_notify (b, "modify");
754e5da2
SG
276}
277\f
278/* This implements the TCL command `gdb_loc', which returns a list consisting
279 of the source and line number associated with the current pc. */
280
281static int
282gdb_loc (clientData, interp, argc, argv)
283 ClientData clientData;
284 Tcl_Interp *interp;
285 int argc;
286 char *argv[];
287{
288 char *filename;
754e5da2
SG
289 struct symtab_and_line sal;
290 char *funcname;
8532893d 291 CORE_ADDR pc;
754e5da2
SG
292
293 if (argc == 1)
294 {
1dfc8dfb 295 pc = selected_frame ? selected_frame->pc : stop_pc;
754e5da2
SG
296 sal = find_pc_line (pc, 0);
297 }
298 else if (argc == 2)
299 {
754e5da2 300 struct symtabs_and_lines sals;
8532893d 301 int nelts;
754e5da2
SG
302
303 sals = decode_line_spec (argv[1], 1);
304
8532893d
SG
305 nelts = sals.nelts;
306 sal = sals.sals[0];
307 free (sals.sals);
308
754e5da2 309 if (sals.nelts != 1)
6131622e 310 error ("Ambiguous line spec");
754e5da2 311
8532893d 312 pc = sal.pc;
754e5da2
SG
313 }
314 else
6131622e 315 error ("wrong # args");
754e5da2 316
754e5da2 317 if (sal.symtab)
6131622e 318 Tcl_DStringAppendElement (result_ptr, sal.symtab->filename);
754e5da2 319 else
6131622e 320 Tcl_DStringAppendElement (result_ptr, "");
8532893d
SG
321
322 find_pc_partial_function (pc, &funcname, NULL, NULL);
6131622e 323 Tcl_DStringAppendElement (result_ptr, funcname);
8532893d 324
637b1661 325 filename = symtab_to_filename (sal.symtab);
6131622e 326 Tcl_DStringAppendElement (result_ptr, filename);
8532893d 327
9468f8aa 328 dsprintf_append_element (result_ptr, "%d", sal.line); /* line number */
754e5da2 329
9468f8aa 330 dsprintf_append_element (result_ptr, "0x%lx", pc); /* PC */
8532893d 331
754e5da2
SG
332 return TCL_OK;
333}
334\f
09722039
SG
335/* This implements the TCL command `gdb_eval'. */
336
337static int
338gdb_eval (clientData, interp, argc, argv)
339 ClientData clientData;
340 Tcl_Interp *interp;
341 int argc;
342 char *argv[];
343{
344 struct expression *expr;
345 struct cleanup *old_chain;
346 value_ptr val;
347
348 if (argc != 2)
6131622e 349 error ("wrong # args");
09722039
SG
350
351 expr = parse_expression (argv[1]);
352
353 old_chain = make_cleanup (free_current_contents, &expr);
354
355 val = evaluate_expression (expr);
356
09722039
SG
357 val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val),
358 gdb_stdout, 0, 0, 0, 0);
09722039
SG
359
360 do_cleanups (old_chain);
361
362 return TCL_OK;
363}
364\f
5b21fb68
SG
365/* This implements the TCL command `gdb_sourcelines', which returns a list of
366 all of the lines containing executable code for the specified source file
367 (ie: lines where you can put breakpoints). */
368
369static int
370gdb_sourcelines (clientData, interp, argc, argv)
371 ClientData clientData;
372 Tcl_Interp *interp;
373 int argc;
374 char *argv[];
375{
376 struct symtab *symtab;
377 struct linetable_entry *le;
378 int nlines;
5b21fb68
SG
379
380 if (argc != 2)
6131622e 381 error ("wrong # args");
5b21fb68
SG
382
383 symtab = lookup_symtab (argv[1]);
384
385 if (!symtab)
6131622e 386 error ("No such file");
5b21fb68
SG
387
388 /* If there's no linetable, or no entries, then we are done. */
389
390 if (!symtab->linetable
391 || symtab->linetable->nitems == 0)
392 {
6131622e 393 Tcl_DStringAppendElement (result_ptr, "");
5b21fb68
SG
394 return TCL_OK;
395 }
396
397 le = symtab->linetable->item;
398 nlines = symtab->linetable->nitems;
399
400 for (;nlines > 0; nlines--, le++)
401 {
402 /* If the pc of this line is the same as the pc of the next line, then
403 just skip it. */
404 if (nlines > 1
405 && le->pc == (le + 1)->pc)
406 continue;
407
9468f8aa 408 dsprintf_append_element (result_ptr, "%d", le->line);
5b21fb68
SG
409 }
410
411 return TCL_OK;
412}
413\f
746d1df4
SG
414static int
415map_arg_registers (argc, argv, func, argp)
416 int argc;
417 char *argv[];
6131622e 418 void (*func) PARAMS ((int regnum, void *argp));
746d1df4
SG
419 void *argp;
420{
421 int regnum;
422
423 /* Note that the test for a valid register must include checking the
424 reg_names array because NUM_REGS may be allocated for the union of the
425 register sets within a family of related processors. In this case, the
426 trailing entries of reg_names will change depending upon the particular
427 processor being debugged. */
428
429 if (argc == 0) /* No args, just do all the regs */
430 {
431 for (regnum = 0;
432 regnum < NUM_REGS
433 && reg_names[regnum] != NULL
434 && *reg_names[regnum] != '\000';
435 regnum++)
436 func (regnum, argp);
437
438 return TCL_OK;
439 }
440
441 /* Else, list of register #s, just do listed regs */
442 for (; argc > 0; argc--, argv++)
443 {
444 regnum = atoi (*argv);
445
446 if (regnum >= 0
447 && regnum < NUM_REGS
448 && reg_names[regnum] != NULL
449 && *reg_names[regnum] != '\000')
450 func (regnum, argp);
451 else
6131622e 452 error ("bad register number");
746d1df4
SG
453 }
454
455 return TCL_OK;
456}
457
6131622e 458static void
746d1df4
SG
459get_register_name (regnum, argp)
460 int regnum;
461 void *argp; /* Ignored */
462{
6131622e 463 Tcl_DStringAppendElement (result_ptr, reg_names[regnum]);
746d1df4
SG
464}
465
5b21fb68
SG
466/* This implements the TCL command `gdb_regnames', which returns a list of
467 all of the register names. */
468
469static int
470gdb_regnames (clientData, interp, argc, argv)
471 ClientData clientData;
472 Tcl_Interp *interp;
473 int argc;
474 char *argv[];
475{
746d1df4
SG
476 argc--;
477 argv++;
478
479 return map_arg_registers (argc, argv, get_register_name, 0);
480}
481
746d1df4
SG
482#ifndef REGISTER_CONVERTIBLE
483#define REGISTER_CONVERTIBLE(x) (0 != 0)
484#endif
485
486#ifndef REGISTER_CONVERT_TO_VIRTUAL
487#define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a)
488#endif
489
490#ifndef INVALID_FLOAT
491#define INVALID_FLOAT(x, y) (0 != 0)
492#endif
493
6131622e 494static void
746d1df4 495get_register (regnum, fp)
6131622e 496 int regnum;
746d1df4
SG
497 void *fp;
498{
499 char raw_buffer[MAX_REGISTER_RAW_SIZE];
500 char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
501 int format = (int)fp;
502
503 if (read_relative_register_raw_bytes (regnum, raw_buffer))
504 {
6131622e 505 Tcl_DStringAppendElement (result_ptr, "Optimized out");
746d1df4
SG
506 return;
507 }
508
746d1df4
SG
509 /* Convert raw data to virtual format if necessary. */
510
511 if (REGISTER_CONVERTIBLE (regnum))
512 {
513 REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
514 raw_buffer, virtual_buffer);
515 }
516 else
517 memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
518
519 val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
520 gdb_stdout, format, 1, 0, Val_pretty_default);
521
6131622e 522 Tcl_DStringAppend (result_ptr, " ", -1);
746d1df4
SG
523}
524
525static int
526gdb_fetch_registers (clientData, interp, argc, argv)
527 ClientData clientData;
528 Tcl_Interp *interp;
529 int argc;
530 char *argv[];
531{
532 int format;
533
534 if (argc < 2)
6131622e 535 error ("wrong # args");
5b21fb68 536
746d1df4
SG
537 argc--;
538 argv++;
5b21fb68 539
746d1df4
SG
540 argc--;
541 format = **argv++;
542
543 return map_arg_registers (argc, argv, get_register, format);
544}
545
546/* This contains the previous values of the registers, since the last call to
547 gdb_changed_register_list. */
548
549static char old_regs[REGISTER_BYTES];
550
6131622e 551static void
746d1df4 552register_changed_p (regnum, argp)
6131622e 553 int regnum;
746d1df4
SG
554 void *argp; /* Ignored */
555{
556 char raw_buffer[MAX_REGISTER_RAW_SIZE];
557 char buf[100];
558
559 if (read_relative_register_raw_bytes (regnum, raw_buffer))
560 return;
561
562 if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
563 REGISTER_RAW_SIZE (regnum)) == 0)
564 return;
565
566 /* Found a changed register. Save new value and return it's number. */
567
568 memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
569 REGISTER_RAW_SIZE (regnum));
570
9468f8aa 571 dsprintf_append_element (result_ptr, "%d", regnum);
746d1df4
SG
572}
573
574static int
575gdb_changed_register_list (clientData, interp, argc, argv)
576 ClientData clientData;
577 Tcl_Interp *interp;
578 int argc;
579 char *argv[];
580{
746d1df4
SG
581 argc--;
582 argv++;
583
584 return map_arg_registers (argc, argv, register_changed_p, NULL);
5b21fb68
SG
585}
586\f
754e5da2
SG
587/* This implements the TCL command `gdb_cmd', which sends it's argument into
588 the GDB command scanner. */
589
590static int
591gdb_cmd (clientData, interp, argc, argv)
592 ClientData clientData;
593 Tcl_Interp *interp;
594 int argc;
595 char *argv[];
596{
754e5da2 597 if (argc != 2)
6131622e 598 error ("wrong # args");
754e5da2 599
86db943c 600 execute_command (argv[1], 1);
479f0f18 601
754e5da2 602 bpstat_do_actions (&stop_bpstat);
754e5da2 603
754e5da2
SG
604 return TCL_OK;
605}
606
86db943c
SG
607/* This routine acts as a top-level for all GDB code called by tcl/Tk. It
608 handles cleanups, and calls to return_to_top_level (usually via error).
609 This is necessary in order to prevent a longjmp out of the bowels of Tk,
610 possibly leaving things in a bad state. Since this routine can be called
611 recursively, it needs to save and restore the contents of the jmp_buf as
612 necessary. */
613
614static int
615call_wrapper (clientData, interp, argc, argv)
616 ClientData clientData;
617 Tcl_Interp *interp;
618 int argc;
619 char *argv[];
620{
621 int val;
622 struct cleanup *saved_cleanup_chain;
623 Tcl_CmdProc *func;
624 jmp_buf saved_error_return;
6131622e
SG
625 Tcl_DString result, *old_result_ptr;
626
627 Tcl_DStringInit (&result);
628 old_result_ptr = result_ptr;
629 result_ptr = &result;
86db943c
SG
630
631 func = (Tcl_CmdProc *)clientData;
632 memcpy (saved_error_return, error_return, sizeof (jmp_buf));
633
634 saved_cleanup_chain = save_cleanups ();
635
636 if (!setjmp (error_return))
637 val = func (clientData, interp, argc, argv);
638 else
639 {
640 val = TCL_ERROR; /* Flag an error for TCL */
641
86db943c
SG
642 gdb_flush (gdb_stderr); /* Flush error output */
643
09722039
SG
644 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
645
86db943c
SG
646/* In case of an error, we may need to force the GUI into idle mode because
647 gdbtk_call_command may have bombed out while in the command routine. */
648
649 Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
650 }
651
652 do_cleanups (ALL_CLEANUPS);
653
654 restore_cleanups (saved_cleanup_chain);
655
656 memcpy (error_return, saved_error_return, sizeof (jmp_buf));
657
6131622e
SG
658 Tcl_DStringResult (interp, &result);
659 result_ptr = old_result_ptr;
660
86db943c
SG
661 return val;
662}
663
754e5da2
SG
664static int
665gdb_listfiles (clientData, interp, argc, argv)
666 ClientData clientData;
667 Tcl_Interp *interp;
668 int argc;
669 char *argv[];
670{
754e5da2
SG
671 struct objfile *objfile;
672 struct partial_symtab *psymtab;
546b8ca7 673 struct symtab *symtab;
754e5da2
SG
674
675 ALL_PSYMTABS (objfile, psymtab)
6131622e 676 Tcl_DStringAppendElement (result_ptr, psymtab->filename);
754e5da2 677
546b8ca7 678 ALL_SYMTABS (objfile, symtab)
6131622e 679 Tcl_DStringAppendElement (result_ptr, symtab->filename);
546b8ca7 680
754e5da2
SG
681 return TCL_OK;
682}
479f0f18
SG
683
684static int
685gdb_stop (clientData, interp, argc, argv)
686 ClientData clientData;
687 Tcl_Interp *interp;
688 int argc;
689 char *argv[];
690{
6c27841f 691 target_stop ();
546b8ca7
SG
692
693 return TCL_OK;
479f0f18 694}
09722039
SG
695\f
696/* This implements the TCL command `gdb_disassemble'. */
479f0f18 697
09722039
SG
698static int
699gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
700 bfd_vma memaddr;
701 bfd_byte *myaddr;
702 int len;
703 disassemble_info *info;
704{
705 extern struct target_ops exec_ops;
706 int res;
707
708 errno = 0;
709 res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
710
711 if (res == len)
712 return 0;
713 else
714 if (errno == 0)
715 return EIO;
716 else
717 return errno;
718}
719
720/* We need a different sort of line table from the normal one cuz we can't
721 depend upon implicit line-end pc's for lines. This is because of the
722 reordering we are about to do. */
723
724struct my_line_entry {
725 int line;
726 CORE_ADDR start_pc;
727 CORE_ADDR end_pc;
728};
729
730static int
731compare_lines (mle1p, mle2p)
732 const PTR mle1p;
733 const PTR mle2p;
734{
735 struct my_line_entry *mle1, *mle2;
736 int val;
737
738 mle1 = (struct my_line_entry *) mle1p;
739 mle2 = (struct my_line_entry *) mle2p;
740
741 val = mle1->line - mle2->line;
742
743 if (val != 0)
744 return val;
745
746 return mle1->start_pc - mle2->start_pc;
747}
748
749static int
750gdb_disassemble (clientData, interp, argc, argv)
751 ClientData clientData;
752 Tcl_Interp *interp;
753 int argc;
754 char *argv[];
755{
756 CORE_ADDR pc, low, high;
757 int mixed_source_and_assembly;
a76ef70a
SG
758 static disassemble_info di = {
759 (fprintf_ftype) fprintf_filtered, /* fprintf_func */
760 gdb_stdout, /* stream */
761 NULL, /* application_data */
762 0, /* flags */
763 NULL, /* private_data */
764 NULL, /* read_memory_func */
765 dis_asm_memory_error, /* memory_error_func */
766 dis_asm_print_address /* print_address_func */
767 };
09722039
SG
768
769 if (argc != 3 && argc != 4)
6131622e 770 error ("wrong # args");
09722039
SG
771
772 if (strcmp (argv[1], "source") == 0)
773 mixed_source_and_assembly = 1;
774 else if (strcmp (argv[1], "nosource") == 0)
775 mixed_source_and_assembly = 0;
776 else
6131622e 777 error ("First arg must be 'source' or 'nosource'");
09722039
SG
778
779 low = parse_and_eval_address (argv[2]);
780
781 if (argc == 3)
782 {
783 if (find_pc_partial_function (low, NULL, &low, &high) == 0)
6131622e 784 error ("No function contains specified address");
09722039
SG
785 }
786 else
787 high = parse_and_eval_address (argv[3]);
788
789 /* If disassemble_from_exec == -1, then we use the following heuristic to
790 determine whether or not to do disassembly from target memory or from the
791 exec file:
792
793 If we're debugging a local process, read target memory, instead of the
794 exec file. This makes disassembly of functions in shared libs work
795 correctly.
796
797 Else, we're debugging a remote process, and should disassemble from the
798 exec file for speed. However, this is no good if the target modifies it's
799 code (for relocation, or whatever).
800 */
801
802 if (disassemble_from_exec == -1)
803 if (strcmp (target_shortname, "child") == 0
804 || strcmp (target_shortname, "procfs") == 0)
805 disassemble_from_exec = 0; /* It's a child process, read inferior mem */
806 else
807 disassemble_from_exec = 1; /* It's remote, read the exec file */
808
809 if (disassemble_from_exec)
a76ef70a
SG
810 di.read_memory_func = gdbtk_dis_asm_read_memory;
811 else
812 di.read_memory_func = dis_asm_read_memory;
09722039
SG
813
814 /* If just doing straight assembly, all we need to do is disassemble
815 everything between low and high. If doing mixed source/assembly, we've
816 got a totally different path to follow. */
817
818 if (mixed_source_and_assembly)
819 { /* Come here for mixed source/assembly */
820 /* The idea here is to present a source-O-centric view of a function to
821 the user. This means that things are presented in source order, with
822 (possibly) out of order assembly immediately following. */
823 struct symtab *symtab;
824 struct linetable_entry *le;
825 int nlines;
c81a3fa9 826 int newlines;
09722039
SG
827 struct my_line_entry *mle;
828 struct symtab_and_line sal;
829 int i;
830 int out_of_order;
c81a3fa9 831 int next_line;
09722039
SG
832
833 symtab = find_pc_symtab (low); /* Assume symtab is valid for whole PC range */
834
835 if (!symtab)
836 goto assembly_only;
837
838/* First, convert the linetable to a bunch of my_line_entry's. */
839
840 le = symtab->linetable->item;
841 nlines = symtab->linetable->nitems;
842
843 if (nlines <= 0)
844 goto assembly_only;
845
846 mle = (struct my_line_entry *) alloca (nlines * sizeof (struct my_line_entry));
847
848 out_of_order = 0;
849
c81a3fa9
SG
850/* Copy linetable entries for this function into our data structure, creating
851 end_pc's and setting out_of_order as appropriate. */
852
853/* First, skip all the preceding functions. */
854
855 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
856
857/* Now, copy all entries before the end of this function. */
858
859 newlines = 0;
860 for (; i < nlines - 1 && le[i].pc < high; i++)
09722039 861 {
c81a3fa9
SG
862 if (le[i].line == le[i + 1].line
863 && le[i].pc == le[i + 1].pc)
864 continue; /* Ignore duplicates */
865
866 mle[newlines].line = le[i].line;
09722039
SG
867 if (le[i].line > le[i + 1].line)
868 out_of_order = 1;
c81a3fa9
SG
869 mle[newlines].start_pc = le[i].pc;
870 mle[newlines].end_pc = le[i + 1].pc;
871 newlines++;
09722039
SG
872 }
873
c81a3fa9
SG
874/* If we're on the last line, and it's part of the function, then we need to
875 get the end pc in a special way. */
876
877 if (i == nlines - 1
878 && le[i].pc < high)
879 {
880 mle[newlines].line = le[i].line;
881 mle[newlines].start_pc = le[i].pc;
882 sal = find_pc_line (le[i].pc, 0);
883 mle[newlines].end_pc = sal.end;
884 newlines++;
885 }
09722039
SG
886
887/* Now, sort mle by line #s (and, then by addresses within lines). */
888
889 if (out_of_order)
c81a3fa9 890 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
09722039
SG
891
892/* Now, for each line entry, emit the specified lines (unless they have been
893 emitted before), followed by the assembly code for that line. */
894
c81a3fa9
SG
895 next_line = 0; /* Force out first line */
896 for (i = 0; i < newlines; i++)
09722039 897 {
c81a3fa9
SG
898/* Print out everything from next_line to the current line. */
899
900 if (mle[i].line >= next_line)
09722039 901 {
c81a3fa9
SG
902 if (next_line != 0)
903 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
09722039 904 else
c81a3fa9
SG
905 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
906
907 next_line = mle[i].line + 1;
09722039 908 }
c81a3fa9 909
09722039
SG
910 for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
911 {
912 QUIT;
913 fputs_unfiltered (" ", gdb_stdout);
914 print_address (pc, gdb_stdout);
915 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 916 pc += (*tm_print_insn) (pc, &di);
09722039
SG
917 fputs_unfiltered ("\n", gdb_stdout);
918 }
919 }
920 }
921 else
922 {
923assembly_only:
924 for (pc = low; pc < high; )
925 {
926 QUIT;
927 fputs_unfiltered (" ", gdb_stdout);
928 print_address (pc, gdb_stdout);
929 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 930 pc += (*tm_print_insn) (pc, &di);
09722039
SG
931 fputs_unfiltered ("\n", gdb_stdout);
932 }
933 }
934
09722039
SG
935 gdb_flush (gdb_stdout);
936
937 return TCL_OK;
938}
754e5da2
SG
939\f
940static void
941tk_command (cmd, from_tty)
942 char *cmd;
943 int from_tty;
944{
546b8ca7
SG
945 int retval;
946 char *result;
947 struct cleanup *old_chain;
948
949 retval = Tcl_Eval (interp, cmd);
950
951 result = strdup (interp->result);
754e5da2 952
546b8ca7
SG
953 old_chain = make_cleanup (free, result);
954
955 if (retval != TCL_OK)
956 error (result);
957
958 printf_unfiltered ("%s\n", result);
959
960 do_cleanups (old_chain);
754e5da2
SG
961}
962
963static void
964cleanup_init (ignored)
965 int ignored;
966{
967 if (mainWindow != NULL)
968 Tk_DestroyWindow (mainWindow);
969 mainWindow = NULL;
970
971 if (interp != NULL)
972 Tcl_DeleteInterp (interp);
973 interp = NULL;
974}
975
637b1661
SG
976/* Come here during long calculations to check for GUI events. Usually invoked
977 via the QUIT macro. */
978
979static void
980gdbtk_interactive ()
981{
982 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
983}
984
479f0f18
SG
985/* Come here when there is activity on the X file descriptor. */
986
987static void
988x_event (signo)
989 int signo;
990{
991 /* Process pending events */
992
993 while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
994}
995
996static int
997gdbtk_wait (pid, ourstatus)
998 int pid;
999 struct target_waitstatus *ourstatus;
1000{
736a82e7
SG
1001 struct sigaction action;
1002 static sigset_t nullsigmask = {0};
1003
1004#ifndef SA_RESTART
1005 /* Needed for SunOS 4.1.x */
1006#define SA_RESTART 0
546b8ca7 1007#endif
479f0f18 1008
736a82e7
SG
1009 action.sa_handler = x_event;
1010 action.sa_mask = nullsigmask;
1011 action.sa_flags = SA_RESTART;
1012 sigaction(SIGIO, &action, NULL);
1013
479f0f18
SG
1014 pid = target_wait (pid, ourstatus);
1015
736a82e7
SG
1016 action.sa_handler = SIG_IGN;
1017 sigaction(SIGIO, &action, NULL);
479f0f18
SG
1018
1019 return pid;
1020}
1021
1022/* This is called from execute_command, and provides a wrapper around
1023 various command routines in a place where both protocol messages and
1024 user input both flow through. Mostly this is used for indicating whether
1025 the target process is running or not.
1026*/
1027
1028static void
1029gdbtk_call_command (cmdblk, arg, from_tty)
1030 struct cmd_list_element *cmdblk;
1031 char *arg;
1032 int from_tty;
1033{
1034 if (cmdblk->class == class_run)
1035 {
1036 Tcl_VarEval (interp, "gdbtk_tcl_busy", NULL);
1037 (*cmdblk->function.cfunc)(arg, from_tty);
1038 Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
1039 }
1040 else
1041 (*cmdblk->function.cfunc)(arg, from_tty);
1042}
1043
754e5da2
SG
1044static void
1045gdbtk_init ()
1046{
1047 struct cleanup *old_chain;
1048 char *gdbtk_filename;
479f0f18 1049 int i;
736a82e7
SG
1050 struct sigaction action;
1051 static sigset_t nullsigmask = {0};
754e5da2
SG
1052
1053 old_chain = make_cleanup (cleanup_init, 0);
1054
1055 /* First init tcl and tk. */
1056
1057 interp = Tcl_CreateInterp ();
1058
1059 if (!interp)
1060 error ("Tcl_CreateInterp failed");
1061
1062 mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb");
1063
1064 if (!mainWindow)
1065 return; /* DISPLAY probably not set */
1066
1067 if (Tcl_Init(interp) != TCL_OK)
1068 error ("Tcl_Init failed: %s", interp->result);
1069
1070 if (Tk_Init(interp) != TCL_OK)
1071 error ("Tk_Init failed: %s", interp->result);
1072
86db943c
SG
1073 Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
1074 Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
1075 Tcl_CreateCommand (interp, "gdb_sourcelines", call_wrapper, gdb_sourcelines,
1076 NULL);
1077 Tcl_CreateCommand (interp, "gdb_listfiles", call_wrapper, gdb_listfiles,
746d1df4 1078 NULL);
86db943c
SG
1079 Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
1080 Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
1081 Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
1082 gdb_fetch_registers, NULL);
1083 Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
1084 gdb_changed_register_list, NULL);
09722039
SG
1085 Tcl_CreateCommand (interp, "gdb_disassemble", call_wrapper,
1086 gdb_disassemble, NULL);
1087 Tcl_CreateCommand (interp, "gdb_eval", call_wrapper, gdb_eval, NULL);
6131622e
SG
1088 Tcl_CreateCommand (interp, "gdb_get_breakpoint_list", call_wrapper,
1089 gdb_get_breakpoint_list, NULL);
1090 Tcl_CreateCommand (interp, "gdb_get_breakpoint_info", call_wrapper,
1091 gdb_get_breakpoint_info, NULL);
754e5da2 1092
09722039 1093 command_loop_hook = Tk_MainLoop;
09722039
SG
1094 print_frame_info_listing_hook = null_routine;
1095 query_hook = gdbtk_query;
1096 flush_hook = gdbtk_flush;
1097 create_breakpoint_hook = gdbtk_create_breakpoint;
1098 delete_breakpoint_hook = gdbtk_delete_breakpoint;
6131622e 1099 modify_breakpoint_hook = gdbtk_modify_breakpoint;
09722039
SG
1100 interactive_hook = gdbtk_interactive;
1101 target_wait_hook = gdbtk_wait;
1102 call_command_hook = gdbtk_call_command;
754e5da2 1103
cd2df226 1104 /* Get the file descriptor for the X server */
479f0f18 1105
cd2df226 1106 x_fd = ConnectionNumber (Tk_Display (mainWindow));
479f0f18
SG
1107
1108 /* Setup for I/O interrupts */
1109
736a82e7
SG
1110 action.sa_mask = nullsigmask;
1111 action.sa_flags = 0;
1112 action.sa_handler = SIG_IGN;
1113 sigaction(SIGIO, &action, NULL);
1114
1115#ifdef FIOASYNC
1116 i = 1;
1117 if (ioctl (x_fd, FIOASYNC, &i))
1118 perror_with_name ("gdbtk_init: ioctl FIOASYNC failed");
479f0f18 1119
77a89957 1120#ifdef SIOCSPGRP
736a82e7
SG
1121 i = getpid();
1122 if (ioctl (x_fd, SIOCSPGRP, &i))
1123 perror_with_name ("gdbtk_init: ioctl SIOCSPGRP failed");
77a89957 1124#endif
546b8ca7
SG
1125#else
1126 if (ioctl (x_fd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
736a82e7
SG
1127 perror_with_name ("gdbtk_init: ioctl I_SETSIG failed");
1128#endif /* ifndef FIOASYNC */
479f0f18 1129
754e5da2
SG
1130 add_com ("tk", class_obscure, tk_command,
1131 "Send a command directly into tk.");
09722039 1132
09722039
SG
1133 Tcl_LinkVar (interp, "disassemble-from-exec", (char *)&disassemble_from_exec,
1134 TCL_LINK_INT);
1135
1136 /* Load up gdbtk.tcl after all the environment stuff has been setup. */
1137
1138 gdbtk_filename = getenv ("GDBTK_FILENAME");
1139 if (!gdbtk_filename)
1140 if (access ("gdbtk.tcl", R_OK) == 0)
1141 gdbtk_filename = "gdbtk.tcl";
1142 else
1143 gdbtk_filename = GDBTK_FILENAME;
1144
724498fd
SG
1145/* Defer setup of fputs_unfiltered_hook to near the end so that error messages
1146 prior to this point go to stdout/stderr. */
1147
1148 fputs_unfiltered_hook = gdbtk_fputs;
1149
09722039 1150 if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
724498fd
SG
1151 {
1152 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
1153
1154 fprintf_unfiltered (stderr, "%s:%d: %s\n", gdbtk_filename,
1155 interp->errorLine, interp->result);
b66051ec
SG
1156
1157 fputs_unfiltered ("Stack trace:\n", gdb_stderr);
1158 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
1159 error ("");
724498fd 1160 }
09722039
SG
1161
1162 discard_cleanups (old_chain);
754e5da2
SG
1163}
1164
1165/* Come here during initialze_all_files () */
1166
1167void
1168_initialize_gdbtk ()
1169{
c5197511
SG
1170 if (use_windows)
1171 {
1172 /* Tell the rest of the world that Gdbtk is now set up. */
754e5da2 1173
c5197511
SG
1174 init_ui_hook = gdbtk_init;
1175 }
754e5da2 1176}
This page took 0.10001 seconds and 4 git commands to generate.