GDB (API)
|
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 (¤t_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 }