OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [gdbtk/] [generic/] [gdbtk-hooks.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Startup code for Insight.
2
   Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001
3
   Free Software Foundation, Inc.
4
 
5
   Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 2 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 59 Temple Place - Suite 330,
22
   Boston, MA 02111-1307, USA.  */
23
 
24
#include "defs.h"
25
#include "symtab.h"
26
#include "inferior.h"
27
#include "command.h"
28
#include "bfd.h"
29
#include "symfile.h"
30
#include "objfiles.h"
31
#include "target.h"
32
#include "gdbcore.h"
33
#include "tracepoint.h"
34
#include "demangle.h"
35
#include "gdb-events.h"
36
 
37
#ifdef _WIN32
38
#define WIN32_LEAN_AND_MEAN
39
#include <windows.h>
40
#endif
41
 
42
#include <sys/stat.h>
43
 
44
#include <tcl.h>
45
#include <tk.h>
46
#include <itcl.h>
47
#include <tix.h>
48
#include "guitcl.h"
49
#include "gdbtk.h"
50
 
51
#include <stdarg.h>
52
#include <signal.h>
53
#include <fcntl.h>
54
#include "top.h"
55
#include <sys/ioctl.h>
56
#include "gdb_string.h"
57
#include "dis-asm.h"
58
#include <stdio.h>
59
#include "gdbcmd.h"
60
 
61
#include "annotate.h"
62
#include <sys/time.h>
63
 
64
volatile int in_fputs = 0;
65
 
66
/* Set by gdb_stop, this flag informs x_event to tell its caller
67
   that it should forcibly detach from the target. */
68
int gdbtk_force_detach = 0;
69
 
70
/* From gdbtk-bp.c */
71
extern void gdbtk_create_breakpoint (int);
72
extern void gdbtk_delete_breakpoint (int);
73
extern void gdbtk_modify_breakpoint (int);
74
extern void gdbtk_create_tracepoint (int);
75
extern void gdbtk_delete_tracepoint (int);
76
extern void gdbtk_modify_tracepoint (int);
77
 
78
extern void (*pre_add_symbol_hook) (char *);
79
extern void (*post_add_symbol_hook) (void);
80
extern void (*selected_frame_level_changed_hook) (int);
81
extern int (*ui_loop_hook) (int);
82
 
83
static void gdbtk_trace_find (char *arg, int from_tty);
84
static void gdbtk_trace_start_stop (int, int);
85
static void gdbtk_attach (void);
86
static void gdbtk_detach (void);
87
static void gdbtk_file_changed (char *);
88
static void gdbtk_exec_file_display (char *);
89
static void tk_command_loop (void);
90
static void gdbtk_call_command (struct cmd_list_element *, char *, int);
91
static ptid_t gdbtk_wait (ptid_t, struct target_waitstatus *);
92
int x_event (int);
93
static int gdbtk_query (const char *, va_list);
94
static void gdbtk_warning (const char *, va_list);
95
static char *gdbtk_readline (char *);
96
static void gdbtk_readline_begin (char *format,...);
97
static void gdbtk_readline_end (void);
98
static void gdbtk_pre_add_symbol (char *);
99
static void gdbtk_print_frame_info (struct symtab *, int, int, int);
100
static void gdbtk_post_add_symbol (void);
101
static void gdbtk_register_changed (int regno);
102
static void gdbtk_memory_changed (CORE_ADDR addr, int len);
103
static void gdbtk_selected_frame_changed (int);
104
static void gdbtk_context_change (int);
105
static void gdbtk_error_begin (void);
106
void report_error (void);
107
static void gdbtk_annotate_signal (void);
108
static void gdbtk_set_hook (struct cmd_list_element *cmdblk);
109
 
110
/*
111
 * gdbtk_fputs can't be static, because we need to call it in gdbtk.c.
112
 * See note there for details.
113
 */
114
 
115
void gdbtk_fputs (const char *, struct ui_file *);
116
static int gdbtk_load_hash (const char *, unsigned long);
117
 
118
/*
119
 * gdbtk_add_hooks - add all the hooks to gdb.  This will get called by the
120
 * startup code to fill in the hooks needed by core gdb.
121
 */
122
 
123
void
124
gdbtk_add_hooks (void)
125
{
126
  static struct gdb_events handlers;
127
 
128
  /* Gdb event handlers */
129
  handlers.breakpoint_create = gdbtk_create_breakpoint;
130
  handlers.breakpoint_modify = gdbtk_modify_breakpoint;
131
  handlers.breakpoint_delete = gdbtk_delete_breakpoint;
132
  handlers.tracepoint_create = gdbtk_create_tracepoint;
133
  handlers.tracepoint_modify = gdbtk_modify_tracepoint;
134
  handlers.tracepoint_delete = gdbtk_delete_tracepoint;
135
  set_gdb_event_hooks (&handlers);
136
 
137
  /* Hooks */
138
  command_loop_hook = tk_command_loop;
139
  call_command_hook = gdbtk_call_command;
140
  set_hook = gdbtk_set_hook;
141
  readline_begin_hook = gdbtk_readline_begin;
142
  readline_hook = gdbtk_readline;
143
  readline_end_hook = gdbtk_readline_end;
144
 
145
  print_frame_info_listing_hook = gdbtk_print_frame_info;
146
  query_hook = gdbtk_query;
147
  warning_hook = gdbtk_warning;
148
 
149
  interactive_hook = gdbtk_interactive;
150
  target_wait_hook = gdbtk_wait;
151
  ui_load_progress_hook = gdbtk_load_hash;
152
 
153
  ui_loop_hook = x_event;
154
  pre_add_symbol_hook = gdbtk_pre_add_symbol;
155
  post_add_symbol_hook = gdbtk_post_add_symbol;
156
  file_changed_hook = gdbtk_file_changed;
157
  specify_exec_file_hook (gdbtk_exec_file_display);
158
 
159
  trace_find_hook = gdbtk_trace_find;
160
  trace_start_stop_hook = gdbtk_trace_start_stop;
161
 
162
  attach_hook            = gdbtk_attach;
163
  detach_hook            = gdbtk_detach;
164
 
165
  register_changed_hook = gdbtk_register_changed;
166
  memory_changed_hook = gdbtk_memory_changed;
167
  selected_frame_level_changed_hook = gdbtk_selected_frame_changed;
168
  context_hook = gdbtk_context_change;
169
 
170
  error_begin_hook = gdbtk_error_begin;
171
 
172
  annotate_signal_hook = gdbtk_annotate_signal;
173
}
174
 
175
/* These control where to put the gdb output which is created by
176
   {f}printf_{un}filtered and friends.  gdbtk_fputs is the lowest
177
   level of these routines and capture all output from the rest of
178
   GDB.
179
 
180
   The reason to use the result_ptr rather than the gdbtk_interp's result
181
   directly is so that a call_wrapper invoked function can preserve its result
182
   across calls into Tcl which might be made in the course of the function's
183
   execution.
184
 
185
   * result_ptr->obj_ptr is where to accumulate the result.
186
   * GDBTK_TO_RESULT flag means the output goes to the gdbtk_tcl_fputs proc
187
   instead of to the result_ptr.
188
   * GDBTK_MAKES_LIST flag means add to the result as a list element.
189
 
190
 */
191
 
192
gdbtk_result *result_ptr = NULL;
193
 
194
/* If you want to restore an old value of result_ptr whenever cleanups
195
   are run, pass this function to make_cleanup, along with the value
196
   of result_ptr you'd like to reinstate.  */
197
void
198
gdbtk_restore_result_ptr (void *old_result_ptr)
199
{
200
  result_ptr = (gdbtk_result *) old_result_ptr;
201
}
202
 
203
/* This allows you to Tcl_Eval a tcl command which takes
204
   a command word, and then a single argument. */
205
int
206
gdbtk_two_elem_cmd (cmd_name, argv1)
207
     char *cmd_name;
208
     char *argv1;
209
{
210
  char *command;
211
  int result, flags_ptr, arg_len, cmd_len;
212
 
213
  arg_len = Tcl_ScanElement (argv1, &flags_ptr);
214
  cmd_len = strlen (cmd_name);
215
  command = malloc (arg_len + cmd_len + 2);
216
  strcpy (command, cmd_name);
217
  strcat (command, " ");
218
 
219
  Tcl_ConvertElement (argv1, command + cmd_len + 1, flags_ptr);
220
 
221
  result = Tcl_Eval (gdbtk_interp, command);
222
  if (result != TCL_OK)
223
    report_error ();
224
  free (command);
225
  return result;
226
}
227
 
228
struct ui_file *
229
gdbtk_fileopen (void)
230
{
231
  struct ui_file *file = ui_file_new ();
232
  set_ui_file_fputs (file, gdbtk_fputs);
233
  return file;
234
}
235
 
236
/* This handles all the output from gdb.  All the gdb printf_xxx functions
237
 * eventually end up here.  The output is either passed to the result_ptr
238
 * where it will go to the result of some gdbtk command, or passed to the
239
 * Tcl proc gdbtk_tcl_fputs (where it is usually just dumped to the console
240
 * window.
241
 *
242
 * The cases are:
243
 *
244
 * 1) result_ptr == NULL - This happens when some output comes from gdb which
245
 *    is not generated by a command in gdbtk-cmds, usually startup stuff.
246
 *    In this case we just route the data to gdbtk_tcl_fputs.
247
 * 2) The GDBTK_TO_RESULT flag is set - The result is supposed to go to Tcl.
248
 *    We place the data into the result_ptr, either as a string,
249
 *    or a list, depending whether the GDBTK_MAKES_LIST bit is set.
250
 * 3) The GDBTK_TO_RESULT flag is unset - We route the data to gdbtk_tcl_fputs
251
 *    UNLESS it was coming to gdb_stderr.  Then we place it in the result_ptr
252
 *    anyway, so it can be dealt with.
253
 *
254
 */
255
 
256
void
257
gdbtk_fputs (const char *ptr, struct ui_file *stream)
258
{
259
  if (gdbtk_disable_fputs)
260
    return;
261
 
262
  in_fputs = 1;
263
 
264
  if (stream == gdb_stdlog)
265
    gdbtk_two_elem_cmd ("gdbtk_tcl_fputs_log", (char *) ptr);
266
  else if (stream == gdb_stdtarg)
267
    gdbtk_two_elem_cmd ("gdbtk_tcl_fputs_target", (char *) ptr);
268
  else if (result_ptr != NULL)
269
    {
270
      if (result_ptr->flags & GDBTK_TO_RESULT)
271
        {
272
          if (result_ptr->flags & GDBTK_MAKES_LIST)
273
            Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
274
                                      Tcl_NewStringObj ((char *) ptr, -1));
275
          else
276
            Tcl_AppendToObj (result_ptr->obj_ptr, (char *) ptr, -1);
277
        }
278
      else if (stream == gdb_stderr || result_ptr->flags & GDBTK_ERROR_ONLY)
279
        {
280
          if (result_ptr->flags & GDBTK_ERROR_STARTED)
281
            Tcl_AppendToObj (result_ptr->obj_ptr, (char *) ptr, -1);
282
          else
283
            {
284
              Tcl_SetStringObj (result_ptr->obj_ptr, (char *) ptr, -1);
285
              result_ptr->flags |= GDBTK_ERROR_STARTED;
286
            }
287
        }
288
      else
289
        {
290
          gdbtk_two_elem_cmd ("gdbtk_tcl_fputs", (char *) ptr);
291
          if (result_ptr->flags & GDBTK_MAKES_LIST)
292
            gdbtk_two_elem_cmd ("gdbtk_tcl_fputs", " ");
293
        }
294
    }
295
  else
296
    {
297
      gdbtk_two_elem_cmd ("gdbtk_tcl_fputs", (char *) ptr);
298
    }
299
 
300
  in_fputs = 0;
301
}
302
 
303
/*
304
 * This routes all warnings to the Tcl function "gdbtk_tcl_warning".
305
 */
306
 
307
static void
308
gdbtk_warning (warning, args)
309
     const char *warning;
310
     va_list args;
311
{
312
  char *buf;
313
 
314
  xvasprintf (&buf, warning, args);
315
  gdbtk_two_elem_cmd ("gdbtk_tcl_warning", buf);
316
 
317
  free(buf);
318
}
319
 
320
 
321
/* Error-handling function for all hooks */
322
/* Hooks are not like tcl functions, they do not simply return */
323
/* TCL_OK or TCL_ERROR.  Also, the calling function typically */
324
/* doesn't care about errors in the hook functions.  Therefore */
325
/* after every hook function, report_error should be called. */
326
/* report_error can just call Tcl_BackgroundError() which will */
327
/* pop up a messagebox, or it can silently log the errors through */
328
/* the gdbtk dbug command.  */
329
 
330
void
331
report_error ()
332
{
333
  TclDebug ('E', Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY));
334
  /*  Tcl_BackgroundError(gdbtk_interp); */
335
}
336
 
337
/*
338
 * This routes all ignorable warnings to the Tcl function
339
 * "gdbtk_tcl_ignorable_warning".
340
 */
341
 
342
void
343
gdbtk_ignorable_warning (class, warning)
344
     const char *class;
345
     const char *warning;
346
{
347
  char *buf;
348
  xasprintf (&buf, "gdbtk_tcl_ignorable_warning {%s} {%s}", class, warning);
349
  if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)
350
    report_error ();
351
  free(buf);
352
}
353
 
354
static void
355
gdbtk_register_changed (regno)
356
     int regno;
357
{
358
  if (Tcl_Eval (gdbtk_interp, "gdbtk_register_changed") != TCL_OK)
359
    report_error ();
360
}
361
 
362
static void
363
gdbtk_memory_changed (addr, len)
364
     CORE_ADDR addr;
365
     int len;
366
{
367
  if (Tcl_Eval (gdbtk_interp, "gdbtk_memory_changed") != TCL_OK)
368
    report_error ();
369
}
370
 
371
 
372
/* This function is called instead of gdb's internal command loop.  This is the
373
   last chance to do anything before entering the main Tk event loop.
374
   At the end of the command, we enter the main loop. */
375
 
376
static void
377
tk_command_loop ()
378
{
379
  extern FILE *instream;
380
 
381
  /* We no longer want to use stdin as the command input stream */
382
  instream = NULL;
383
 
384
  if (Tcl_Eval (gdbtk_interp, "gdbtk_tcl_preloop") != TCL_OK)
385
    {
386
      char *msg;
387
 
388
      /* Force errorInfo to be set up propertly.  */
389
      Tcl_AddErrorInfo (gdbtk_interp, "");
390
 
391
      msg = Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY);
392
#ifdef _WIN32
393
      MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
394
#else
395
      fputs_unfiltered (msg, gdb_stderr);
396
#endif
397
    }
398
 
399
#ifdef _WIN32
400
  close_bfds ();
401
#endif
402
 
403
  Tk_MainLoop ();
404
}
405
 
406
/* This hook is installed as the ui_loop_hook, which is used in several
407
 * places to keep the gui alive (x_event runs gdbtk's event loop). Users
408
 * include:
409
 * - ser-tcp.c in socket reading code
410
 * - ser-unix.c in serial port reading code
411
 * - built-in simulators while executing
412
 *
413
 * x_event used to be called on SIGIO on the socket to the X server
414
 * for unix. Unfortunately, Linux does not deliver SIGIO, so we resort
415
 * to an elaborate scheme to keep the gui alive.
416
 *
417
 * For simulators and socket or serial connections on all hosts, we
418
 * rely on ui_loop_hook (x_event) to keep us going. If the user
419
 * requests a detach (as a result of pressing the stop button -- see
420
 * comments before gdb_stop in gdbtk-cmds.c), it sets the global
421
 * GDBTK_FORCE_DETACH, which is the value that x_event returns to
422
 * it's caller. It is up to the caller of x_event to act on this
423
 * information.
424
 *
425
 * For native unix, we simply set an interval timer which calls
426
 * x_event to allow the debugger to run through the Tcl event
427
 * loop. See comments before gdbtk_start_timer and gdb_stop_timer
428
 * in gdbtk.c.
429
 *
430
 * For native windows (and a few other targets, like the v850 ICE),
431
 * we rely on the target_wait loops to call ui_loop_hook to keep us alive. */
432
int
433
x_event (signo)
434
     int signo;
435
{
436
  static volatile int in_x_event = 0;
437
  static Tcl_Obj *varname = NULL;
438
 
439
  /* Do nor re-enter this code or enter it while collecting gdb output. */
440
  if (in_x_event || in_fputs)
441
    return 0;
442
 
443
  /* Also, only do things while the target is running (stops and redraws).
444
     FIXME: We wold like to at least redraw at other times but this is bundled
445
     together in the TCL_WINDOW_EVENTS group and we would also process user
446
     input.  We will have to prevent (unwanted)  user input to be generated
447
     in order to be able to redraw (removing this test here). */
448
  if (!running_now)
449
    return 0;
450
 
451
  in_x_event = 1;
452
  gdbtk_force_detach = 0;
453
 
454
  /* Process pending events */
455
  while (Tcl_DoOneEvent (TCL_DONT_WAIT | TCL_ALL_EVENTS) != 0)
456
    ;
457
 
458
  if (load_in_progress)
459
    {
460
      int val;
461
      if (varname == NULL)
462
        {
463
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 1
464
          Tcl_Obj *varnamestrobj = Tcl_NewStringObj ("download_cancel_ok", -1);
465
          varname = Tcl_ObjGetVar2 (gdbtk_interp, varnamestrobj, NULL, TCL_GLOBAL_ONLY);
466
#else
467
          varname = Tcl_GetObjVar2 (gdbtk_interp, "download_cancel_ok", NULL, TCL_GLOBAL_ONLY);
468
#endif
469
        }
470
      if ((Tcl_GetIntFromObj (gdbtk_interp, varname, &val) == TCL_OK) && val)
471
        {
472
          quit_flag = 1;
473
#ifdef REQUEST_QUIT
474
          REQUEST_QUIT;
475
#else
476
          if (immediate_quit)
477
            quit ();
478
#endif
479
        }
480
    }
481
  in_x_event = 0;
482
 
483
  return gdbtk_force_detach;
484
}
485
 
486
/* VARARGS */
487
static void
488
gdbtk_readline_begin (char *format,...)
489
{
490
  va_list args;
491
  char *buf;
492
 
493
  va_start (args, format);
494
  xvasprintf (&buf, format, args);
495
  gdbtk_two_elem_cmd ("gdbtk_tcl_readline_begin", buf);
496
  free(buf);
497
}
498
 
499
static char *
500
gdbtk_readline (prompt)
501
     char *prompt;
502
{
503
  int result;
504
 
505
#ifdef _WIN32
506
  close_bfds ();
507
#endif
508
 
509
  result = gdbtk_two_elem_cmd ("gdbtk_tcl_readline", prompt);
510
 
511
  if (result == TCL_OK)
512
    {
513
      return (xstrdup (gdbtk_interp->result));
514
    }
515
  else
516
    {
517
      gdbtk_fputs (gdbtk_interp->result, gdb_stdout);
518
      gdbtk_fputs ("\n", gdb_stdout);
519
      return (NULL);
520
    }
521
}
522
 
523
static void
524
gdbtk_readline_end ()
525
{
526
  if (Tcl_Eval (gdbtk_interp, "gdbtk_tcl_readline_end") != TCL_OK)
527
    report_error ();
528
}
529
 
530
static void
531
gdbtk_call_command (cmdblk, arg, from_tty)
532
     struct cmd_list_element *cmdblk;
533
     char *arg;
534
     int from_tty;
535
{
536
  running_now = 0;
537
  if (cmdblk->class == class_run || cmdblk->class == class_trace)
538
    {
539
 
540
      running_now = 1;
541
      if (!No_Update)
542
        Tcl_Eval (gdbtk_interp, "gdbtk_tcl_busy");
543
      (*cmdblk->function.cfunc) (arg, from_tty);
544
      running_now = 0;
545
      if (!No_Update)
546
        Tcl_Eval (gdbtk_interp, "gdbtk_tcl_idle");
547
    }
548
  else
549
    (*cmdblk->function.cfunc) (arg, from_tty);
550
}
551
 
552
/* Called after a `set' command succeeds.  Runs the Tcl hook
553
   `gdb_set_hook' with the full name of the variable (a Tcl list) as
554
   the first argument and the new value as the second argument.  */
555
 
556
static void
557
gdbtk_set_hook (struct cmd_list_element *cmdblk)
558
{
559
  Tcl_DString cmd;
560
  char *p;
561
  char *buffer = NULL;
562
 
563
  Tcl_DStringInit (&cmd);
564
  Tcl_DStringAppendElement (&cmd, "gdbtk_tcl_set_variable");
565
 
566
  /* Append variable name as sublist.  */
567
  Tcl_DStringStartSublist (&cmd);
568
  p = cmdblk->prefixname;
569
  while (p && *p)
570
    {
571
      char *q = strchr (p, ' ');
572
      char save = '\0';
573
      if (q)
574
        {
575
          save = *q;
576
          *q = '\0';
577
        }
578
      Tcl_DStringAppendElement (&cmd, p);
579
      if (q)
580
        *q = save;
581
      p = q + 1;
582
    }
583
  Tcl_DStringAppendElement (&cmd, cmdblk->name);
584
  Tcl_DStringEndSublist (&cmd);
585
 
586
  switch (cmdblk->var_type)
587
    {
588
    case var_string_noescape:
589
    case var_filename:
590
    case var_enum:
591
    case var_string:
592
      Tcl_DStringAppendElement (&cmd, (*(char **) cmdblk->var
593
                                       ? *(char **) cmdblk->var
594
                                       : "(null)"));
595
      break;
596
 
597
    case var_boolean:
598
      Tcl_DStringAppendElement (&cmd, (*(int *) cmdblk->var ? "1" : "0"));
599
      break;
600
 
601
    case var_uinteger:
602
    case var_zinteger:
603
      xasprintf (&buffer, "%u", *(unsigned int *) cmdblk->var);
604
      Tcl_DStringAppendElement (&cmd, buffer);
605
      break;
606
 
607
    case var_integer:
608
      xasprintf (&buffer, "%d", *(int *) cmdblk->var);
609
      Tcl_DStringAppendElement (&cmd, buffer);
610
      break;
611
 
612
    default:
613
      /* This case should already be trapped by the hook caller.  */
614
      Tcl_DStringAppendElement (&cmd, "error");
615
      break;
616
    }
617
 
618
  if (Tcl_Eval (gdbtk_interp, Tcl_DStringValue (&cmd)) != TCL_OK)
619
    report_error ();
620
 
621
  Tcl_DStringFree (&cmd);
622
 
623
  if (buffer != NULL)
624
    {
625
       free(buffer);
626
    }
627
}
628
 
629
int
630
gdbtk_load_hash (const char *section, unsigned long num)
631
{
632
  char *buf;
633
  xasprintf (&buf, "Download::download_hash %s %ld", section, num);
634
  if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)
635
    report_error ();
636
  free(buf);
637
 
638
  return atoi (gdbtk_interp->result);
639
}
640
 
641
 
642
/* This hook is called whenever we are ready to load a symbol file so that
643
   the UI can notify the user... */
644
static void
645
gdbtk_pre_add_symbol (name)
646
     char *name;
647
{
648
  gdbtk_two_elem_cmd ("gdbtk_tcl_pre_add_symbol", name);
649
}
650
 
651
/* This hook is called whenever we finish loading a symbol file. */
652
static void
653
gdbtk_post_add_symbol ()
654
{
655
  if (Tcl_Eval (gdbtk_interp, "gdbtk_tcl_post_add_symbol") != TCL_OK)
656
    report_error ();
657
}
658
 
659
/* This hook function is called whenever we want to wait for the
660
   target.  */
661
 
662
static ptid_t
663
gdbtk_wait (ptid, ourstatus)
664
     ptid_t ptid;
665
     struct target_waitstatus *ourstatus;
666
{
667
  gdbtk_force_detach = 0;
668
  gdbtk_start_timer ();
669
  ptid = target_wait (ptid, ourstatus);
670
  gdbtk_stop_timer ();
671
 
672
  return ptid;
673
}
674
 
675
/*
676
 * This handles all queries from gdb.
677
 * The first argument is a printf style format statement, the rest are its
678
 * arguments.  The resultant formatted string is passed to the Tcl function
679
 * "gdbtk_tcl_query".
680
 * It returns the users response to the query, as well as putting the value
681
 * in the result field of the Tcl interpreter.
682
 */
683
 
684
static int
685
gdbtk_query (query, args)
686
     const char *query;
687
     va_list args;
688
{
689
  char *buf;
690
  long val;
691
 
692
  xvasprintf (&buf, query, args);
693
  gdbtk_two_elem_cmd ("gdbtk_tcl_query", buf);
694
  free(buf);
695
 
696
  val = atol (gdbtk_interp->result);
697
  return val;
698
}
699
 
700
 
701
static void
702
gdbtk_print_frame_info (s, line, stopline, noerror)
703
     struct symtab *s;
704
     int line;
705
     int stopline;
706
     int noerror;
707
{
708
  current_source_symtab = s;
709
  current_source_line = line;
710
}
711
 
712
/*
713
 * gdbtk_trace_find
714
 *
715
 * This is run by the trace_find_command.  arg is the argument that was passed
716
 * to that command, from_tty is 1 if the command was run from a tty, 0 if it
717
 * was run from a script.  It runs gdbtk_tcl_tfind_hook passing on these two
718
 * arguments.
719
 *
720
 */
721
 
722
static void
723
gdbtk_trace_find (arg, from_tty)
724
     char *arg;
725
     int from_tty;
726
{
727
  Tcl_Obj *cmdObj;
728
 
729
  cmdObj = Tcl_NewListObj (0, NULL);
730
  Tcl_ListObjAppendElement (gdbtk_interp, cmdObj,
731
                        Tcl_NewStringObj ("gdbtk_tcl_trace_find_hook", -1));
732
  Tcl_ListObjAppendElement (gdbtk_interp, cmdObj, Tcl_NewStringObj (arg, -1));
733
  Tcl_ListObjAppendElement (gdbtk_interp, cmdObj, Tcl_NewIntObj (from_tty));
734
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 1
735
  if (Tcl_GlobalEvalObj (gdbtk_interp, cmdObj) != TCL_OK)
736
    report_error ();
737
#else
738
  if (Tcl_EvalObj (gdbtk_interp, cmdObj, TCL_EVAL_GLOBAL) != TCL_OK)
739
    report_error ();
740
#endif
741
}
742
 
743
/*
744
 * gdbtk_trace_start_stop
745
 *
746
 * This is run by the trace_start_command and trace_stop_command.
747
 * The START variable determines which, 1 meaning trace_start was run,
748
 * 0 meaning trace_stop was run.
749
 *
750
 */
751
 
752
static void
753
gdbtk_trace_start_stop (start, from_tty)
754
     int start;
755
     int from_tty;
756
{
757
 
758
  if (start)
759
    Tcl_GlobalEval (gdbtk_interp, "gdbtk_tcl_tstart");
760
  else
761
    Tcl_GlobalEval (gdbtk_interp, "gdbtk_tcl_tstop");
762
 
763
}
764
 
765
static void
766
gdbtk_selected_frame_changed (level)
767
     int level;
768
{
769
  Tcl_UpdateLinkedVar (gdbtk_interp, "gdb_selected_frame_level");
770
}
771
 
772
/* Called when the current thread changes. */
773
/* gdb_context is linked to the tcl variable "gdb_context_id" */
774
static void
775
gdbtk_context_change (num)
776
     int num;
777
{
778
  gdb_context = num;
779
}
780
 
781
/* Called from file_command */
782
static void
783
gdbtk_file_changed (filename)
784
     char *filename;
785
{
786
  gdbtk_two_elem_cmd ("gdbtk_tcl_file_changed", filename);
787
}
788
 
789
/* Called from exec_file_command */
790
static void
791
gdbtk_exec_file_display (filename)
792
     char *filename;
793
{
794
  gdbtk_two_elem_cmd ("gdbtk_tcl_exec_file_display", filename);
795
}
796
 
797
/* Called from error_begin, this hook is used to warn the gui
798
   about multi-line error messages */
799
static void
800
gdbtk_error_begin ()
801
{
802
  if (result_ptr != NULL)
803
    result_ptr->flags |= GDBTK_ERROR_ONLY;
804
}
805
 
806
/* notify GDBtk when a signal occurs */
807
static void
808
gdbtk_annotate_signal ()
809
{
810
  char *buf;
811
 
812
  /* Inform gui that the target has stopped. This is
813
     a necessary stop button evil. We don't want signal notification
814
     to interfere with the elaborate and painful stop button detach
815
     timeout. */
816
  Tcl_Eval (gdbtk_interp, "gdbtk_stop_idle_callback");
817
 
818
  xasprintf (&buf, "gdbtk_signal %s {%s}", target_signal_to_name (stop_signal),
819
           target_signal_to_string (stop_signal));
820
  if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)
821
    report_error ();
822
  free(buf);
823
}
824
 
825
static void
826
gdbtk_attach ()
827
{
828
  if (Tcl_Eval (gdbtk_interp, "after idle \"update idletasks;gdbtk_attached\"") != TCL_OK)
829
    {
830
      report_error ();
831
    }
832
}
833
 
834
static void
835
gdbtk_detach ()
836
{
837
  if (Tcl_Eval (gdbtk_interp, "gdbtk_detached") != TCL_OK)
838
    {
839
      report_error ();
840
    }
841
}
842
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.