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