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

Subversion Repositories or1k

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

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, 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 "version.h"
36
#include "cli-out.h"
37
 
38
#if defined(_WIN32) || defined(__CYGWIN__)
39
#define WIN32_LEAN_AND_MEAN
40
#include <windows.h>
41
#endif
42
 
43
#include <sys/stat.h>
44
 
45
#include <tcl.h>
46
#include <tk.h>
47
#include <itcl.h>
48
#include <tix.h>
49
#include <itk.h>
50
#include "guitcl.h"
51
#include "gdbtk.h"
52
 
53
#include <signal.h>
54
#include <fcntl.h>
55
#include "top.h"
56
#include <sys/ioctl.h>
57
#include "gdb_string.h"
58
#include "dis-asm.h"
59
#include <stdio.h>
60
#include "gdbcmd.h"
61
 
62
#include "annotate.h"
63
#include <sys/time.h>
64
 
65
#ifdef __CYGWIN32__
66
#include <sys/cygwin.h>         /* for cygwin32_attach_handle_to_fd */
67
#endif
68
 
69
extern void _initialize_gdbtk (void);
70
 
71
/* For unix natives, we use a timer to periodically keep the gui alive.
72
   See comments before x_event. */
73
static sigset_t nullsigmask;
74
static struct sigaction act1, act2;
75
static struct itimerval it_on, it_off;
76
 
77
static void x_event_wrapper (int);
78
static void
79
x_event_wrapper (signo)
80
     int signo;
81
{
82
  x_event (signo);
83
}
84
 
85
 /*
86
  * These two variables control the interaction with an external editor.
87
  * If enable_external_editor is set at startup, BEFORE Gdbtk_Init is run
88
  * then the Tcl variable of the same name will be set, and a command will
89
  * called external_editor_command will be invoked to call out to the
90
  * external editor.  We give a dummy version here to warn if it is not set.
91
  */
92
int enable_external_editor = 0;
93
char *external_editor_command = "tk_dialog .warn-external \\\n\
94
\"No command is specified.\nUse --tclcommand <tcl/file> or --external-editor <cmd> to specify a new command\" 0 Ok";
95
 
96
extern int Tktable_Init (Tcl_Interp * interp);
97
 
98
static void gdbtk_init (char *);
99
 
100
void gdbtk_interactive (void);
101
 
102
static void cleanup_init (void *ignore);
103
 
104
static void tk_command (char *, int);
105
 
106
static int target_should_use_timer (struct target_ops *t);
107
 
108
int target_is_native (struct target_ops *t);
109
 
110
int gdbtk_test (char *);
111
 
112
/* Handle for TCL interpreter */
113
Tcl_Interp *gdbtk_interp = NULL;
114
 
115
static int gdbtk_timer_going = 0;
116
 
117
/* linked variable used to tell tcl what the current thread is */
118
int gdb_context = 0;
119
 
120
/* This variable is true when the inferior is running.  See note in
121
 * gdbtk.h for details.
122
 */
123
int running_now;
124
 
125
/* This variable holds the name of a Tcl file which should be sourced by the
126
   interpreter when it goes idle at startup. Used with the testsuite. */
127
static char *gdbtk_source_filename = NULL;
128
 
129
int gdbtk_disable_fputs = 1;
130
 
131
 
132
#ifndef _WIN32
133
 
134
/* Supply malloc calls for tcl/tk.  We do not want to do this on
135
   Windows, because Tcl_Alloc is probably in a DLL which will not call
136
   the mmalloc routines.
137
   We also don't need to do it for Tcl/Tk8.1, since we locally changed the
138
   allocator to use malloc & free. */
139
 
140
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
141
char *
142
TclpAlloc (size)
143
     unsigned int size;
144
{
145
  return xmalloc (size);
146
}
147
 
148
char *
149
TclpRealloc (ptr, size)
150
     char *ptr;
151
     unsigned int size;
152
{
153
  return xrealloc (ptr, size);
154
}
155
 
156
void
157
TclpFree (ptr)
158
     char *ptr;
159
{
160
  free (ptr);
161
}
162
#endif /* TCL_VERSION == 8.0 */
163
 
164
#endif /* ! _WIN32 */
165
 
166
#ifdef _WIN32
167
 
168
/* On Windows, if we hold a file open, other programs can't write to
169
 * it.  In particular, we don't want to hold the executable open,
170
 * because it will mean that people have to get out of the debugging
171
 * session in order to remake their program.  So we close it, although
172
 * this will cost us if and when we need to reopen it.
173
 */
174
 
175
void
176
close_bfds ()
177
{
178
  struct objfile *o;
179
 
180
  ALL_OBJFILES (o)
181
  {
182
    if (o->obfd != NULL)
183
      bfd_cache_close (o->obfd);
184
  }
185
 
186
  if (exec_bfd != NULL)
187
    bfd_cache_close (exec_bfd);
188
}
189
 
190
#endif /* _WIN32 */
191
 
192
 
193
/* TclDebug (const char *fmt, ...) works just like printf() but
194
 * sends the output to the GDB TK debug window.
195
 * Not for normal use; just a convenient tool for debugging
196
 */
197
 
198
void
199
TclDebug (char level, const char *fmt,...)
200
{
201
  va_list args;
202
  char *buf, *v[3], *merge, *priority;
203
 
204
  switch (level)
205
    {
206
    case 'W':
207
      priority = "W";
208
      break;
209
    case 'E':
210
      priority = "E";
211
      break;
212
    case 'X':
213
      priority = "X";
214
      break;
215
    default:
216
      priority = "I";
217
    }
218
 
219
  va_start (args, fmt);
220
 
221
 
222
  xvasprintf (&buf, fmt, args);
223
  va_end (args);
224
 
225
  v[0] = "dbug";
226
  v[1] = priority;
227
  v[2] = buf;
228
 
229
  merge = Tcl_Merge (3, v);
230
  if (Tcl_Eval (gdbtk_interp, merge) != TCL_OK)
231
    Tcl_BackgroundError (gdbtk_interp);
232
  Tcl_Free (merge);
233
  free(buf);
234
}
235
 
236
 
237
/*
238
 * The rest of this file contains the start-up, and event handling code for gdbtk.
239
 */
240
 
241
/*
242
 * This cleanup function is added to the cleanup list that surrounds the Tk
243
 * main in gdbtk_init.  It deletes the Tcl interpreter.
244
 */
245
 
246
static void
247
cleanup_init (void *ignore)
248
{
249
  if (gdbtk_interp != NULL)
250
    Tcl_DeleteInterp (gdbtk_interp);
251
  gdbtk_interp = NULL;
252
}
253
 
254
/* Come here during long calculations to check for GUI events.  Usually invoked
255
   via the QUIT macro.  */
256
 
257
void
258
gdbtk_interactive ()
259
{
260
  /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
261
}
262
 
263
/* Start a timer which will keep the GUI alive while in target_wait. */
264
void
265
gdbtk_start_timer ()
266
{
267
  static int first = 1;
268
 
269
  if (first)
270
    {
271
      /* first time called, set up all the structs */
272
      first = 0;
273
      sigemptyset (&nullsigmask);
274
 
275
      act1.sa_handler = x_event_wrapper;
276
      act1.sa_mask = nullsigmask;
277
      act1.sa_flags = 0;
278
 
279
      act2.sa_handler = SIG_IGN;
280
      act2.sa_mask = nullsigmask;
281
      act2.sa_flags = 0;
282
 
283
      it_on.it_interval.tv_sec = 0;
284
      it_on.it_interval.tv_usec = 250000;       /* .25 sec */
285
      it_on.it_value.tv_sec = 0;
286
      it_on.it_value.tv_usec = 250000;
287
 
288
      it_off.it_interval.tv_sec = 0;
289
      it_off.it_interval.tv_usec = 0;
290
      it_off.it_value.tv_sec = 0;
291
      it_off.it_value.tv_usec = 0;
292
    }
293
 
294
  if (target_should_use_timer (&current_target))
295
    {
296
      if (!gdbtk_timer_going)
297
        {
298
          sigaction (SIGALRM, &act1, NULL);
299
          setitimer (ITIMER_REAL, &it_on, NULL);
300
          gdbtk_timer_going = 1;
301
        }
302
    }
303
  return;
304
}
305
 
306
/* Stop the timer if it is running. */
307
void
308
gdbtk_stop_timer ()
309
{
310
  if (gdbtk_timer_going)
311
    {
312
      gdbtk_timer_going = 0;
313
      setitimer (ITIMER_REAL, &it_off, NULL);
314
      sigaction (SIGALRM, &act2, NULL);
315
    }
316
  return;
317
}
318
 
319
/* Should this target use the timer? See comments before
320
   x_event for the logic behind all this. */
321
static int
322
target_should_use_timer (t)
323
     struct target_ops *t;
324
{
325
  return target_is_native (t);
326
}
327
 
328
/* Is T a native target? */
329
int
330
target_is_native (t)
331
     struct target_ops *t;
332
{
333
  char *name = t->to_shortname;
334
 
335
  if (STREQ (name, "exec") || STREQ (name, "hpux-threads")
336
      || STREQ (name, "child") || STREQ (name, "procfs")
337
      || STREQ (name, "solaris-threads") || STREQ (name, "linuxthreads")
338
      || STREQ (name, "multi-thread"))
339
    return 1;
340
 
341
  return 0;
342
}
343
 
344
/* gdbtk_init installs this function as a final cleanup.  */
345
 
346
static void
347
gdbtk_cleanup (dummy)
348
     PTR dummy;
349
{
350
  Tcl_Eval (gdbtk_interp, "gdbtk_cleanup");
351
  Tcl_Finalize ();
352
}
353
 
354
 
355
/* Initialize gdbtk.  This involves creating a Tcl interpreter,
356
 * defining all the Tcl commands that the GUI will use, pointing
357
 * all the gdb "hooks" to the correct functions,
358
 * and setting the Tcl auto loading environment so that we can find all
359
 * the Tcl based library files.
360
 */
361
 
362
static void
363
gdbtk_init (argv0)
364
     char *argv0;
365
{
366
  struct cleanup *old_chain;
367
  char *s;
368
 
369
  /* If there is no DISPLAY environment variable, Tk_Init below will fail,
370
     causing gdb to abort.  If instead we simply return here, gdb will
371
     gracefully degrade to using the command line interface. */
372
 
373
#ifndef _WIN32
374
  if (getenv ("DISPLAY") == NULL)
375
    return;
376
#endif
377
 
378
  old_chain = make_cleanup (cleanup_init, 0);
379
 
380
  /* First init tcl and tk. */
381
  Tcl_FindExecutable (argv0);
382
  gdbtk_interp = Tcl_CreateInterp ();
383
 
384
#ifdef TCL_MEM_DEBUG
385
  Tcl_InitMemory (gdbtk_interp);
386
#endif
387
 
388
  if (!gdbtk_interp)
389
    error ("Tcl_CreateInterp failed");
390
 
391
  if (Tcl_Init (gdbtk_interp) != TCL_OK)
392
    error ("Tcl_Init failed: %s", gdbtk_interp->result);
393
 
394
  /* Set up some globals used by gdb to pass info to gdbtk
395
     for start up options and the like */
396
  xasprintf (&s, "%d", inhibit_gdbinit);
397
  Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "inhibit_prefs", s, TCL_GLOBAL_ONLY);
398
  free(s);
399
 
400
  /* Note: Tcl_SetVar2() treats the value as read-only (making a
401
     copy).  Unfortunatly it does not mark the parameter as
402
     ``const''. */
403
  Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "host_name", (char*) host_name, TCL_GLOBAL_ONLY);
404
  Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "target_name", (char*) target_name, TCL_GLOBAL_ONLY);
405
 
406
  make_final_cleanup (gdbtk_cleanup, NULL);
407
 
408
  /* Initialize the Paths variable.  */
409
  if (ide_initialize_paths (gdbtk_interp, "") != TCL_OK)
410
    error ("ide_initialize_paths failed: %s", gdbtk_interp->result);
411
 
412
  if (Tk_Init (gdbtk_interp) != TCL_OK)
413
    error ("Tk_Init failed: %s", gdbtk_interp->result);
414
 
415
  if (Itcl_Init (gdbtk_interp) == TCL_ERROR)
416
    error ("Itcl_Init failed: %s", gdbtk_interp->result);
417
  Tcl_StaticPackage (gdbtk_interp, "Itcl", Itcl_Init,
418
                     (Tcl_PackageInitProc *) NULL);
419
 
420
  if (Itk_Init (gdbtk_interp) == TCL_ERROR)
421
    error ("Itk_Init failed: %s", gdbtk_interp->result);
422
  Tcl_StaticPackage (gdbtk_interp, "Itk", Itk_Init,
423
                     (Tcl_PackageInitProc *) NULL);
424
 
425
  if (Tix_Init (gdbtk_interp) != TCL_OK)
426
    error ("Tix_Init failed: %s", gdbtk_interp->result);
427
  Tcl_StaticPackage (gdbtk_interp, "Tix", Tix_Init,
428
                     (Tcl_PackageInitProc *) NULL);
429
 
430
  if (Tktable_Init (gdbtk_interp) != TCL_OK)
431
    error ("Tktable_Init failed: %s", gdbtk_interp->result);
432
 
433
  Tcl_StaticPackage (gdbtk_interp, "Tktable", Tktable_Init,
434
                     (Tcl_PackageInitProc *) NULL);
435
  /*
436
   * These are the commands to do some Windows Specific stuff...
437
   */
438
 
439
#ifdef __CYGWIN32__
440
  if (ide_create_messagebox_command (gdbtk_interp) != TCL_OK)
441
    error ("messagebox command initialization failed");
442
  /* On Windows, create a sizebox widget command */
443
  if (ide_create_sizebox_command (gdbtk_interp) != TCL_OK)
444
    error ("sizebox creation failed");
445
  if (ide_create_winprint_command (gdbtk_interp) != TCL_OK)
446
    error ("windows print code initialization failed");
447
  if (ide_create_win_grab_command (gdbtk_interp) != TCL_OK)
448
    error ("grab support command initialization failed");
449
  /* Path conversion functions.  */
450
  if (ide_create_cygwin_path_command (gdbtk_interp) != TCL_OK)
451
    error ("cygwin path command initialization failed");
452
  if (ide_create_shell_execute_command (gdbtk_interp) != TCL_OK)
453
    error ("cygwin shell execute command initialization failed");
454
#endif
455
 
456
  /* Only for testing -- and only when it can't be done any
457
     other way. */
458
  if (cyg_create_warp_pointer_command (gdbtk_interp) != TCL_OK)
459
    error ("warp_pointer command initialization failed");
460
 
461
  /*
462
   * This adds all the Gdbtk commands.
463
   */
464
 
465
  if (Gdbtk_Init (gdbtk_interp) != TCL_OK)
466
    {
467
      error ("Gdbtk_Init failed: %s", gdbtk_interp->result);
468
    }
469
 
470
  Tcl_StaticPackage (gdbtk_interp, "Gdbtk", Gdbtk_Init, NULL);
471
 
472
  /* This adds all the hooks that call up from the bowels of gdb
473
   *  back into Tcl-land...
474
   */
475
 
476
  gdbtk_add_hooks ();
477
 
478
 
479
  /* Add a back door to Tk from the gdb console... */
480
 
481
  add_com ("tk", class_obscure, tk_command,
482
           "Send a command directly into tk.");
483
 
484
  /*
485
   * Set the variables for external editor:
486
   */
487
 
488
  Tcl_SetVar (gdbtk_interp, "enable_external_editor",
489
              enable_external_editor ? "1" : "0", 0);
490
  Tcl_SetVar (gdbtk_interp, "external_editor_command",
491
              external_editor_command, 0);
492
 
493
  /* close old output and send new to GDBTK */
494
  ui_file_delete (gdb_stdout);
495
  ui_file_delete (gdb_stderr);
496
  gdb_stdout = gdbtk_fileopen ();
497
  gdb_stderr = gdbtk_fileopen ();
498
  gdb_stdlog = gdbtk_fileopen ();
499
  gdb_stdtarg = gdbtk_fileopen ();
500
  uiout = cli_out_new (gdb_stdout);
501
 
502
#ifdef __CYGWIN32__
503
      (void) FreeConsole ();
504
#endif
505
 
506
  /* find the gdb tcl library and source main.tcl */
507
 
508
  {
509
#ifdef NO_TCLPRO_DEBUGGER
510
    static char script[] = "\
511
proc gdbtk_find_main {} {\n\
512
    global Paths GDBTK_LIBRARY\n\
513
    rename gdbtk_find_main {}\n\
514
    tcl_findLibrary gdb 1.0 {} main.tcl GDBTK_LIBRARY GDBTK_LIBRARY gdbtk/library gdbtcl {}\n\
515
    set Paths(appdir) $GDBTK_LIBRARY\n\
516
}\n\
517
gdbtk_find_main";
518
#else
519
    static char script[] = "\
520
proc gdbtk_find_main {} {\n\
521
    global Paths GDBTK_LIBRARY env\n\
522
    rename gdbtk_find_main {}\n\
523
    if {[info exists env(DEBUG_STUB)]} {\n\
524
        source $env(DEBUG_STUB)\n\
525
        debugger_init\n\
526
        set debug_startup 1\n\
527
    } else {\n\
528
        set debug_startup 0\n\
529
    }\n\
530
    tcl_findLibrary gdb 1.0 {} main.tcl GDBTK_LIBRARY GDBTK_LIBRARY gdbtk/library gdbtcl {} $debug_startup\n\
531
    set Paths(appdir) $GDBTK_LIBRARY\n\
532
}\n\
533
gdbtk_find_main";
534
#endif /* NO_TCLPRO_DEBUGGER */
535
 
536
    /* now enable gdbtk to parse the output from gdb */
537
    gdbtk_disable_fputs = 0;
538
 
539
    if (Tcl_GlobalEval (gdbtk_interp, (char *) script) != TCL_OK)
540
      {
541
        char *msg;
542
 
543
        /* Force errorInfo to be set up propertly.  */
544
        Tcl_AddErrorInfo (gdbtk_interp, "");
545
        msg = Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY);
546
 
547
#ifdef _WIN32
548
        MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
549
#else
550
        fprintf (stderr,msg);
551
#endif
552
 
553
        error ("");
554
      }
555
  }
556
 
557
 
558
  /* Now source in the filename provided by the --tclcommand option.
559
     This is mostly used for the gdbtk testsuite... */
560
 
561
  if (gdbtk_source_filename != NULL)
562
    {
563
      char *s = "after idle source ";
564
      char *script = concat (s, gdbtk_source_filename, (char *) NULL);
565
      Tcl_Eval (gdbtk_interp, script);
566
      free (gdbtk_source_filename);
567
      free (script);
568
    }
569
 
570
  discard_cleanups (old_chain);
571
}
572
 
573
/* gdbtk_test is used in main.c to validate the -tclcommand option to
574
   gdb, which sources in a file of tcl code after idle during the
575
   startup procedure. */
576
 
577
int
578
gdbtk_test (filename)
579
     char *filename;
580
{
581
  if (access (filename, R_OK) != 0)
582
    return 0;
583
  else
584
    gdbtk_source_filename = xstrdup (filename);
585
  return 1;
586
}
587
 
588
/* Come here during initialize_all_files () */
589
 
590
void
591
_initialize_gdbtk ()
592
{
593
  if (use_windows)
594
    {
595
      /* Tell the rest of the world that Gdbtk is now set up. */
596
      init_ui_hook = gdbtk_init;
597
    }
598
#ifdef __CYGWIN32__
599
  else
600
    {
601
      DWORD ft = GetFileType (GetStdHandle (STD_INPUT_HANDLE));
602
 
603
      switch (ft)
604
        {
605
        case FILE_TYPE_DISK:
606
        case FILE_TYPE_CHAR:
607
        case FILE_TYPE_PIPE:
608
          break;
609
        default:
610
          AllocConsole ();
611
          cygwin32_attach_handle_to_fd ("/dev/conin", 0,
612
                                        GetStdHandle (STD_INPUT_HANDLE),
613
                                        1, GENERIC_READ);
614
          cygwin32_attach_handle_to_fd ("/dev/conout", 1,
615
                                        GetStdHandle (STD_OUTPUT_HANDLE),
616
                                        0, GENERIC_WRITE);
617
          cygwin32_attach_handle_to_fd ("/dev/conout", 2,
618
                                        GetStdHandle (STD_ERROR_HANDLE),
619
                                        0, GENERIC_WRITE);
620
          break;
621
        }
622
    }
623
#endif
624
}
625
 
626
static void
627
tk_command (cmd, from_tty)
628
     char *cmd;
629
     int from_tty;
630
{
631
  int retval;
632
  char *result;
633
  struct cleanup *old_chain;
634
 
635
  /* Catch case of no argument, since this will make the tcl interpreter dump core. */
636
  if (cmd == NULL)
637
    error_no_arg ("tcl command to interpret");
638
 
639
  retval = Tcl_Eval (gdbtk_interp, cmd);
640
 
641
  result = xstrdup (gdbtk_interp->result);
642
 
643
  old_chain = make_cleanup (free, result);
644
 
645
  if (retval != TCL_OK)
646
    error (result);
647
 
648
  printf_unfiltered ("%s\n", result);
649
 
650
  do_cleanups (old_chain);
651
}
652
 

powered by: WebSVN 2.1.0

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