GDB (API)
/home/stan/gdb/src/gdb/gdbtk/generic/gdbtk.c
Go to the documentation of this file.
00001 /* Startup code for Insight
00002    Copyright (C) 1994-2013 Free Software Foundation, Inc.
00003 
00004    Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
00005 
00006    This file is part of GDB.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021    Boston, MA 02110-1301, USA.  */
00022 
00023 #include "defs.h"
00024 #include "inferior.h"
00025 #include "symfile.h"
00026 #include "objfiles.h"
00027 #include "gdbcore.h"
00028 #include "tracepoint.h"
00029 #include "demangle.h"
00030 #include "version.h"
00031 #include "top.h"
00032 #include "annotate.h"
00033 #include "exceptions.h"
00034 #include "main.h"
00035 
00036 #if defined(_WIN32) || defined(__CYGWIN__)
00037 #define WIN32_LEAN_AND_MEAN
00038 #include <windows.h>
00039 #endif
00040 
00041 /* tcl header files includes varargs.h unless HAS_STDARG is defined,
00042    but gdb uses stdarg.h, so make sure HAS_STDARG is defined.  */
00043 #define HAS_STDARG 1
00044 
00045 #include <tcl.h>
00046 #include <tk.h>
00047 #include "guitcl.h"
00048 #include "gdbtk.h"
00049 
00050 #include <fcntl.h>
00051 #include "gdb_stat.h"
00052 #ifdef HAVE_SYS_IOCTL_H
00053 #include <sys/ioctl.h>
00054 #endif
00055 #include <sys/time.h>
00056 #include <signal.h>
00057 
00058 #include "gdb_string.h"
00059 #include "dis-asm.h"
00060 #include "gdbcmd.h"
00061 
00062 #ifdef __CYGWIN32__
00063 #include <sys/cygwin.h>         /* for cygwin32_attach_handle_to_fd */
00064 #endif
00065 
00066 extern void _initialize_gdbtk (void);
00067 
00068 #ifndef __MINGW32__
00069 /* For unix natives, we use a timer to periodically keep the gui alive.
00070    See comments before x_event. */
00071 static sigset_t nullsigmask;
00072 static struct sigaction act1, act2;
00073 static struct itimerval it_on, it_off;
00074 
00075 static void
00076 x_event_wrapper (int signo)
00077 {
00078   x_event (signo);
00079 }
00080 #endif
00081 
00082 /*
00083  * This variable controls the interaction with an external editor.
00084  */
00085 
00086 char *external_editor_command = NULL;
00087 
00088 extern int Tktable_Init (Tcl_Interp * interp);
00089 
00090 void gdbtk_init (void);
00091 
00092 void gdbtk_interactive (void);
00093 
00094 static void cleanup_init (void *ignore);
00095 
00096 static void tk_command (char *, int);
00097 
00098 static int target_should_use_timer (struct target_ops *t);
00099 
00100 int target_is_native (struct target_ops *t);
00101 
00102 int gdbtk_test (char *);
00103 
00104 static void view_command (char *, int);
00105 
00106 /* Handle for TCL interpreter */
00107 Tcl_Interp *gdbtk_interp = NULL;
00108 
00109 static int gdbtk_timer_going = 0;
00110 
00111 /* linked variable used to tell tcl what the current thread is */
00112 int gdb_context = 0;
00113 
00114 /* This variable is true when the inferior is running.  See note in
00115  * gdbtk.h for details.
00116  */
00117 int running_now;
00118 
00119 /* This variable holds the name of a Tcl file which should be sourced by the
00120    interpreter when it goes idle at startup. Used with the testsuite. */
00121 static char *gdbtk_source_filename = NULL;
00122 
00123 int gdbtk_disable_fputs = 1;
00124 
00125 #ifndef _WIN32
00126 
00127 /* Supply malloc calls for tcl/tk.  We do not want to do this on
00128    Windows, because Tcl_Alloc is probably in a DLL which will not call
00129    the mmalloc routines.
00130    We also don't need to do it for Tcl/Tk8.1, since we locally changed the
00131    allocator to use malloc & free. */
00132 
00133 #if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
00134 char *
00135 TclpAlloc (unsigned int size)
00136 {
00137   return xmalloc (size);
00138 }
00139 
00140 char *
00141 TclpRealloc (char *ptr, unsigned int size)
00142 {
00143   return xrealloc (ptr, size);
00144 }
00145 
00146 void
00147 TclpFree (char *ptr)
00148 {
00149   free (ptr);
00150 }
00151 #endif /* TCL_VERSION == 8.0 */
00152 
00153 #endif /* ! _WIN32 */
00154 
00155 #ifdef _WIN32
00156 
00157 /* On Windows, if we hold a file open, other programs can't write to
00158  * it.  In particular, we don't want to hold the executable open,
00159  * because it will mean that people have to get out of the debugging
00160  * session in order to remake their program.  So we close it, although
00161  * this will cost us if and when we need to reopen it.
00162  */
00163 
00164 void
00165 close_bfds (void)
00166 {
00167   struct objfile *o;
00168   
00169   ALL_OBJFILES (o)
00170     {
00171       if (o->obfd != NULL)
00172         bfd_cache_close (o->obfd);
00173     }
00174   
00175   if (exec_bfd != NULL)
00176     bfd_cache_close (exec_bfd);
00177 }
00178 
00179 #endif /* _WIN32 */
00180 
00181 
00182 /* TclDebug (const char *fmt, ...) works just like printf() but 
00183  * sends the output to the GDB TK debug window. 
00184  * Not for normal use; just a convenient tool for debugging
00185  */
00186 
00187 void
00188 TclDebug (char level, const char *fmt,...)
00189 {
00190   va_list args;
00191   char *buf;
00192   const char *v[3];
00193   char *merge;
00194   char *priority;
00195 
00196   switch (level)
00197     {
00198     case 'W':
00199       priority = "W";
00200       break;
00201     case 'E':
00202       priority = "E";
00203       break;
00204     case 'X':
00205       priority = "X";
00206       break;
00207     default:
00208       priority = "I";
00209     }
00210 
00211   va_start (args, fmt);
00212 
00213 
00214   buf = xstrvprintf (fmt, args);
00215   va_end (args);
00216 
00217   v[0] = "dbug";
00218   v[1] = priority;
00219   v[2] = buf;
00220 
00221   merge = Tcl_Merge (3, v);
00222   if (Tcl_Eval (gdbtk_interp, merge) != TCL_OK)
00223     Tcl_BackgroundError (gdbtk_interp);
00224   Tcl_Free (merge);
00225   free(buf);
00226 }
00227 
00228 
00229 /*
00230  * The rest of this file contains the start-up, and event handling code for gdbtk.
00231  */
00232 
00233 /*
00234  * This cleanup function is added to the cleanup list that surrounds the Tk
00235  * main in gdbtk_init.  It deletes the Tcl interpreter.
00236  */
00237 
00238 static void
00239 cleanup_init (void *ignore)
00240 {
00241   if (gdbtk_interp != NULL)
00242     Tcl_DeleteInterp (gdbtk_interp);
00243   gdbtk_interp = NULL;
00244 }
00245 
00246 /* Come here during long calculations to check for GUI events.  Usually invoked
00247    via the QUIT macro.  */
00248 
00249 void
00250 gdbtk_interactive (void)
00251 {
00252   /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
00253 }
00254 
00255 /* Start a timer which will keep the GUI alive while in target_wait. */
00256 void
00257 gdbtk_start_timer (void)
00258 {
00259   static int first = 1;
00260 
00261   if (first)
00262     {
00263       /* first time called, set up all the structs */
00264       first = 0;
00265 #ifndef __MINGW32__
00266       sigemptyset (&nullsigmask);
00267 
00268       act1.sa_handler = x_event_wrapper;
00269       act1.sa_mask = nullsigmask;
00270       act1.sa_flags = 0;
00271 
00272       act2.sa_handler = SIG_IGN;
00273       act2.sa_mask = nullsigmask;
00274       act2.sa_flags = 0;
00275 
00276       it_on.it_interval.tv_sec = 0;
00277       it_on.it_interval.tv_usec = 250000;       /* .25 sec */
00278       it_on.it_value.tv_sec = 0;
00279       it_on.it_value.tv_usec = 250000;
00280 
00281       it_off.it_interval.tv_sec = 0;
00282       it_off.it_interval.tv_usec = 0;
00283       it_off.it_value.tv_sec = 0;
00284       it_off.it_value.tv_usec = 0;
00285 #endif
00286     }
00287 
00288   if (target_should_use_timer (&current_target))
00289     {
00290       if (!gdbtk_timer_going)
00291         {
00292 #ifndef __MINGW32__
00293           sigaction (SIGALRM, &act1, NULL);
00294           setitimer (ITIMER_REAL, &it_on, NULL);
00295 #endif
00296           gdbtk_timer_going = 1;
00297         }
00298     }
00299   return;
00300 }
00301 
00302 /* Stop the timer if it is running. */
00303 void
00304 gdbtk_stop_timer (void)
00305 {
00306   if (gdbtk_timer_going)
00307     {
00308       gdbtk_timer_going = 0;
00309 #ifndef __MINGW32__
00310       setitimer (ITIMER_REAL, &it_off, NULL);
00311       sigaction (SIGALRM, &act2, NULL);
00312 #endif
00313     }
00314   return;
00315 }
00316 
00317 /* Should this target use the timer? See comments before
00318    x_event for the logic behind all this. */
00319 static int
00320 target_should_use_timer (struct target_ops *t)
00321 {
00322   return target_is_native (t);
00323 }
00324 
00325 /* Is T a native target? */
00326 int
00327 target_is_native (struct target_ops *t)
00328 {
00329   char *name = t->to_shortname;
00330 
00331   if (strcmp (name, "exec") == 0 || strcmp (name, "hpux-threads") == 0
00332       || strcmp (name, "child") == 0 || strcmp (name, "procfs") == 0
00333       || strcmp (name, "solaris-threads") == 0
00334       || strcmp (name, "linuxthreads") == 0
00335       || strcmp (name, "multi-thread") == 0)
00336     return 1;
00337 
00338   return 0;
00339 }
00340 
00341 /* gdbtk_init installs this function as a final cleanup.  */
00342 
00343 static void
00344 gdbtk_cleanup (PTR dummy)
00345 {
00346   Tcl_Eval (gdbtk_interp, "gdbtk_cleanup");
00347   Tcl_Finalize ();
00348 }
00349 
00350 
00351 /* Initialize gdbtk.  This involves creating a Tcl interpreter,
00352  * defining all the Tcl commands that the GUI will use, pointing
00353  * all the gdb "hooks" to the correct functions,
00354  * and setting the Tcl auto loading environment so that we can find all
00355  * the Tcl based library files.
00356  */
00357 
00358 void
00359 gdbtk_init (void)
00360 {
00361   struct cleanup *old_chain;
00362   char *s;
00363   int element_count;
00364   const char **exec_path;
00365   CONST char *internal_exec_name;
00366   Tcl_Obj *command_obj;
00367   int running_from_builddir;
00368 
00369   old_chain = make_cleanup (cleanup_init, 0);
00370 
00371   /* First init tcl and tk. */
00372   Tcl_FindExecutable (get_gdb_program_name ());
00373   gdbtk_interp = Tcl_CreateInterp ();
00374 
00375 #ifdef TCL_MEM_DEBUG
00376   Tcl_InitMemory (gdbtk_interp);
00377 #endif
00378 
00379   if (!gdbtk_interp)
00380     error ("Tcl_CreateInterp failed");
00381 
00382   /* Set up some globals used by gdb to pass info to gdbtk
00383      for start up options and the like */
00384   s = xstrprintf ("%d", inhibit_gdbinit);
00385   Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "inhibit_prefs", s, TCL_GLOBAL_ONLY);
00386   free(s);
00387    
00388   /* Note: Tcl_SetVar2() treats the value as read-only (making a
00389      copy).  Unfortunately it does not mark the parameter as
00390      ``const''. */
00391   Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "host_name", (char*) host_name, TCL_GLOBAL_ONLY);
00392   Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "target_name", (char*) target_name, TCL_GLOBAL_ONLY);
00393   {
00394 #ifdef __CYGWIN
00395     char *srcdir = (char *) alloca (cygwin_posix_to_win32_path_list_buf_size (SRC_DIR));
00396     cygwin_posix_to_win32_path_list (SRC_DIR, srcdir);
00397 #else /* !__CYGWIN */
00398     char *srcdir = SRC_DIR;
00399 #endif /* !__CYGWIN */
00400     Tcl_SetVar2 (gdbtk_interp, "GDBStartup", "srcdir", srcdir, TCL_GLOBAL_ONLY);
00401   }
00402 
00403   /* This is really lame, but necessary. We need to set the path to our
00404      library sources in the global GDBTK_LIBRARY. This was only necessary
00405      for running from the build dir, but when using a system-supplied
00406      Tcl/Tk/Itcl, we cannot rely on the user installing Insight into
00407      the same tcl library directory. */
00408 
00409   internal_exec_name = Tcl_GetNameOfExecutable ();
00410 
00411   Tcl_SplitPath ((char *) internal_exec_name, &element_count, &exec_path);
00412   if (strcmp (exec_path[element_count - 2], "bin") == 0)
00413     running_from_builddir = 0;
00414   else
00415     running_from_builddir = 1;
00416   Tcl_Free ((char *) exec_path);
00417 
00418   /* This seems really complicated, and that's because it is.
00419      We would like to preserve the following ways of running
00420      Insight (and having it work, of course):
00421 
00422      1. Installed using installed Tcl et al
00423      2. From build directory using installed Tcl et al
00424      3. Installed using Tcl et al from the build tree
00425      4. From build directory using Tcl et al from the build tree
00426 
00427      When running from the builddir (nos. 2,4), we set all the
00428      *_LIBRARY variables manually to point at the proper locations in
00429      the source tree. (When Tcl et al are installed, their
00430      corresponding variables get set incorrectly, but tcl_findLibrary
00431      will still find the correct installed versions.)
00432 
00433      When not running from the build directory, we must set GDBTK_LIBRARY,
00434      just in case we are running from a non-standard install directory
00435      (i.e., Tcl and Insight were installed into two different
00436      install directories). One snafu: we use libgui's Paths
00437      environment variable to do this, so we cannot actually
00438      set GDBTK_LIBRARY until libgui is initialized. */
00439 
00440   if (running_from_builddir)
00441     {
00442       /* We check to see if TCL_LIBRARY, TK_LIBRARY,
00443          ITCL_LIBRARY, ITK_LIBRARY, and maybe a couple other
00444          environment variables have been set (we don't want
00445          to override the User's settings).
00446 
00447          If the *_LIBRARY variable is is not set, point it at
00448          the source directory. */
00449       static char set_lib_paths_script[] = "\
00450           set srcDir [file dirname $GDBStartup(srcdir)]\n\
00451           if {![info exists env(TCL_LIBRARY)]} {\n\
00452               set env(TCL_LIBRARY) [file join $srcDir tcl library]\n\
00453           }\n\
00454 \
00455           if {![info exists env(TK_LIBRARY)]} {\n\
00456               set env(TK_LIBRARY) [file join $srcDir tk library]\n\
00457           }\n\
00458 \
00459           if {![info exists env(ITCL_LIBRARY)]} {\n\
00460               set env(ITCL_LIBRARY) [file join $srcDir itcl itcl library]\n\
00461           }\n\
00462 \
00463           if {![info exists env(ITK_LIBRARY)]} {\n\
00464               set env(ITK_LIBRARY) [file join $srcDir itcl itk library]\n\
00465           }\n\
00466 \
00467           if {![info exists env(IWIDGETS_LIBRARY)]} {\n\
00468               set env(IWIDGETS_LIBRARY) \
00469                      [file join $srcDir itcl iwidgets generic]\n\
00470           }\n\
00471 \
00472           if {![info exists env(GDBTK_LIBRARY)]} {\n\
00473               set env(GDBTK_LIBRARY) [file join $GDBStartup(srcdir) gdbtk library]\n\
00474           }\n\
00475 \
00476           # Append the directory with the itcl/itk/iwidgets pkg indexes\n\
00477           set startDir [file dirname [file dirname [info nameofexecutable]]]\n\
00478           lappend ::auto_path [file join $startDir itcl itcl]\n\
00479           lappend ::auto_path [file join $startDir itcl itk]\n\
00480           lappend ::auto_path [file join $startDir itcl iwidgets]\n";
00481 
00482       command_obj = Tcl_NewStringObj (set_lib_paths_script, -1);
00483       Tcl_IncrRefCount (command_obj);
00484       Tcl_EvalObj (gdbtk_interp, command_obj);
00485       Tcl_DecrRefCount (command_obj);
00486     }
00487 
00488   make_final_cleanup (gdbtk_cleanup, NULL);
00489 
00490   if (Tcl_Init (gdbtk_interp) != TCL_OK)
00491     error ("Tcl_Init failed: %s", Tcl_GetStringResult (gdbtk_interp));
00492 
00493   /* Initialize the Paths variable.  */
00494   if (ide_initialize_paths (gdbtk_interp, "") != TCL_OK)
00495     error ("ide_initialize_paths failed: %s", Tcl_GetStringResult (gdbtk_interp));
00496 
00497   if (Tk_Init (gdbtk_interp) != TCL_OK)
00498     error ("Tk_Init failed: %s", Tcl_GetStringResult (gdbtk_interp));
00499 
00500   if (Tktable_Init (gdbtk_interp) != TCL_OK)
00501     error ("Tktable_Init failed: %s", Tcl_GetStringResult (gdbtk_interp));
00502 
00503   Tcl_StaticPackage (gdbtk_interp, "Tktable", Tktable_Init,
00504                      (Tcl_PackageInitProc *) NULL);
00505 
00506   /* If we are not running from the build directory,
00507      initialize GDBTK_LIBRARY. See comments above. */
00508   if (!running_from_builddir)
00509     {
00510       static char set_gdbtk_library_script[] = "\
00511           if {![info exists env(GDBTK_LIBRARY)]} {\n\
00512               set env(GDBTK_LIBRARY) [file join [file dirname [file dirname $Paths(guidir)]] insight1.0]\n\
00513           }\n";
00514 
00515       command_obj = Tcl_NewStringObj (set_gdbtk_library_script, -1);
00516       Tcl_IncrRefCount (command_obj);
00517       Tcl_EvalObj (gdbtk_interp, command_obj);
00518       Tcl_DecrRefCount (command_obj);
00519     }
00520 
00521   /*
00522    * These are the commands to do some Windows Specific stuff...
00523    */
00524 
00525 #ifdef __WIN32__
00526   if (ide_create_messagebox_command (gdbtk_interp) != TCL_OK)
00527     error ("messagebox command initialization failed");
00528   /* On Windows, create a sizebox widget command */
00529 #if 0
00530   if (ide_create_sizebox_command (gdbtk_interp) != TCL_OK)
00531     error ("sizebox creation failed");
00532 #endif
00533   if (ide_create_winprint_command (gdbtk_interp) != TCL_OK)
00534     error ("windows print code initialization failed");
00535   if (ide_create_win_grab_command (gdbtk_interp) != TCL_OK)
00536     error ("grab support command initialization failed");
00537   if (ide_create_shell_execute_command (gdbtk_interp) != TCL_OK)
00538     error ("cygwin shell execute command initialization failed");
00539 #endif
00540 #ifdef __CYGWIN32__
00541   /* Path conversion functions.  */
00542   if (ide_create_cygwin_path_command (gdbtk_interp) != TCL_OK)
00543     error ("cygwin path command initialization failed");
00544 #endif
00545 
00546   /* Only for testing -- and only when it can't be done any
00547      other way. */
00548   if (cyg_create_warp_pointer_command (gdbtk_interp) != TCL_OK)
00549     error ("warp_pointer command initialization failed");
00550 
00551   /*
00552    * This adds all the Gdbtk commands.
00553    */
00554 
00555   if (Gdbtk_Init (gdbtk_interp) != TCL_OK)
00556     {
00557       error ("Gdbtk_Init failed: %s", Tcl_GetStringResult (gdbtk_interp));
00558     }
00559 
00560   Tcl_StaticPackage (gdbtk_interp, "Insight", Gdbtk_Init, NULL);
00561 
00562   /* Add a back door to Tk from the gdb console... */
00563 
00564   add_com ("tk", class_obscure, tk_command,
00565            "Send a command directly into tk.");
00566 
00567   add_com ("view", class_obscure, view_command,
00568            "View a location in the source window.");
00569 
00570   /*
00571    * Set the variable for external editor:
00572    */
00573 
00574   if (external_editor_command != NULL)
00575     {
00576       Tcl_SetVar (gdbtk_interp, "external_editor_command",
00577                   external_editor_command, 0);
00578       xfree (external_editor_command);
00579       external_editor_command = NULL;
00580     }
00581 
00582 #ifdef __CYGWIN32__
00583   (void) FreeConsole ();
00584 #endif
00585 
00586   discard_cleanups (old_chain);
00587 }
00588 
00589 void
00590 gdbtk_source_start_file (void)
00591 {
00592   /* find the gdb tcl library and source main.tcl */
00593 #ifdef NO_TCLPRO_DEBUGGER
00594   static char script[] = "\
00595 proc gdbtk_find_main {} {\n\
00596     global Paths GDBTK_LIBRARY\n\
00597     rename gdbtk_find_main {}\n\
00598     tcl_findLibrary insight 1.0 {} main.tcl GDBTK_LIBRARY GDBTKLIBRARY\n\
00599     set Paths(appdir) $GDBTK_LIBRARY\n\
00600 }\n\
00601 gdbtk_find_main";
00602 #else
00603     static char script[] = "\
00604 proc gdbtk_find_main {} {\n\
00605     global Paths GDBTK_LIBRARY env\n\
00606     rename gdbtk_find_main {}\n\
00607     if {[info exists env(DEBUG_STUB)]} {\n\
00608         source $env(DEBUG_STUB)\n\
00609         debugger_init\n\
00610         set debug_startup 1\n\
00611     } else {\n\
00612         set debug_startup 0\n\
00613     }\n\
00614     tcl_findLibrary insight 1.0 {} main.tcl GDBTK_LIBRARY GDBTK_LIBRARY\n\
00615     set Paths(appdir) $GDBTK_LIBRARY\n\
00616 }\n\
00617 gdbtk_find_main";
00618 #endif /* NO_TCLPRO_DEBUGGER */
00619 
00620   /* now enable gdbtk to parse the output from gdb */
00621   gdbtk_disable_fputs = 0;
00622     
00623   if (Tcl_GlobalEval (gdbtk_interp, (char *) script) != TCL_OK)
00624     {
00625       struct gdb_exception e;
00626       const char *msg;
00627 
00628       /* Force errorInfo to be set up propertly.  */
00629       Tcl_AddErrorInfo (gdbtk_interp, "");
00630       msg = Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY);
00631 
00632 #ifdef _WIN32
00633       /* On windows, display the error using a pop-up message box.
00634          If GDB wasn't started from the DOS prompt, the user won't
00635          get to see the failure reason.  */
00636       MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
00637 #else
00638       /* gdb_stdout is already pointing to OUR stdout, so we cannot
00639          use *_[un]filtered here. Since we're "throwing" an exception
00640          which should cause us to exit, just print out the error
00641          to stderr. */
00642       fputs (msg, stderr);
00643 #endif
00644 
00645       e.reason  = RETURN_ERROR;
00646       e.error   = GENERIC_ERROR;
00647       e.message = msg;
00648       throw_exception (e);
00649     }
00650 
00651   /* Now source in the filename provided by the --tclcommand option.
00652      This is mostly used for the gdbtk testsuite... */
00653 
00654   if (gdbtk_source_filename != NULL)
00655     {
00656       char *s = "after idle source ";
00657       char *script = concat (s, gdbtk_source_filename, (char *) NULL);
00658       Tcl_Eval (gdbtk_interp, script);
00659       free (gdbtk_source_filename);
00660       free (script);
00661     }
00662 }
00663 
00664 /* gdbtk_test is used in main.c to validate the -tclcommand option to
00665    gdb, which sources in a file of tcl code after idle during the
00666    startup procedure. */
00667 
00668 int
00669 gdbtk_test (char *filename)
00670 {
00671   if (access (filename, R_OK) != 0)
00672     return 0;
00673   else
00674     gdbtk_source_filename = xstrdup (filename);
00675   return 1;
00676 }
00677 
00678 /* Come here during initialize_all_files () */
00679 
00680 void
00681 _initialize_gdbtk (void)
00682 {
00683 #ifdef __CYGWIN__
00684   /* Current_interpreter not set yet, so we must check
00685      if "interpreter_p" is set to "insight" to know if
00686      insight is GOING to run. */
00687   if (strcmp (interpreter_p, "insight") != 0)
00688     {
00689       DWORD ft = GetFileType (GetStdHandle (STD_INPUT_HANDLE));
00690 
00691       switch (ft)
00692         {
00693         case FILE_TYPE_DISK:
00694         case FILE_TYPE_CHAR:
00695         case FILE_TYPE_PIPE:
00696           break;
00697         default:
00698           AllocConsole ();
00699           cygwin_attach_handle_to_fd ("/dev/conin", 0,
00700                                       GetStdHandle (STD_INPUT_HANDLE),
00701                                       1, GENERIC_READ);
00702           cygwin_attach_handle_to_fd ("/dev/conout", 1,
00703                                       GetStdHandle (STD_OUTPUT_HANDLE),
00704                                       0, GENERIC_WRITE);
00705           cygwin_attach_handle_to_fd ("/dev/conout", 2,
00706                                       GetStdHandle (STD_ERROR_HANDLE),
00707                                       0, GENERIC_WRITE);
00708           break;
00709         }
00710     }
00711 #endif
00712 }
00713 
00714 static void
00715 tk_command (char *cmd, int from_tty)
00716 {
00717   int retval;
00718   char *result;
00719   struct cleanup *old_chain;
00720 
00721   /* Catch case of no argument, since this will make the tcl interpreter 
00722      dump core. */
00723   if (cmd == NULL)
00724     error_no_arg ("tcl command to interpret");
00725 
00726   retval = Tcl_Eval (gdbtk_interp, cmd);
00727 
00728   result = xstrdup (Tcl_GetStringResult (gdbtk_interp));
00729 
00730   old_chain = make_cleanup (xfree, result);
00731 
00732   if (retval != TCL_OK)
00733     error ("%s", result);
00734 
00735   printf_unfiltered ("%s\n", result);
00736 
00737   do_cleanups (old_chain);
00738 }
00739 
00740 static void
00741 view_command (char *args, int from_tty)
00742 {
00743   char *script;
00744   struct cleanup *old_chain;
00745 
00746   if (args != NULL)
00747     {
00748       script = xstrprintf (
00749                  "[lindex [ManagedWin::find SrcWin] 0] location BROWSE_TAG [gdb_loc %s]",
00750                  args);
00751       old_chain = make_cleanup (xfree, script);
00752       if (Tcl_Eval (gdbtk_interp, script) != TCL_OK)
00753         {
00754           Tcl_Obj *obj = Tcl_GetObjResult (gdbtk_interp);
00755           error ("%s", Tcl_GetStringFromObj (obj, NULL));
00756         }
00757 
00758       do_cleanups (old_chain);
00759     }
00760   else
00761     error ("Argument required (location to view)");
00762 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines