GDB (API)
/home/stan/gdb/src/gdb/gdbtk/library/interface.tcl
Go to the documentation of this file.
00001 # Interface between GDB and Insight.
00002 # Copyright (C) 1997, 1998, 1999, 2001, 2002, 2004, 2008 Red Hat, Inc.
00003 #
00004 # This program is free software; you can redistribute it and/or modify it
00005 # under the terms of the GNU General Public License (GPL) as published by
00006 # the Free Software Foundation; either version 2 of the License, or (at
00007 # your option) any later version.
00008 #
00009 # This program is distributed in the hope that it will be useful,
00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 # GNU General Public License for more details.
00013 
00014 
00015 # This variable is reserved for this module.  Ensure it is an array.
00016 global gdbtk_state
00017 set gdbtk_state(busyCount) 0
00018 
00019 # *** DEPRECATED: Use GDBEventHandler::breakpoint instead.
00020 # This is run when a breakpoint changes.  The arguments are the
00021 # action, the breakpoint number, and the breakpoint info.
00022 #define_hook gdb_breakpoint_change_hook
00023 
00024 # *** DEPRECATED: Use GDBEventHandler::set_variable instead.
00025 # This is run when a `set' command successfully completes in gdb.  The
00026 # first argument is the gdb variable name (as a Tcl list).  The second
00027 # argument is the new value.
00028 #define_hook gdb_set_hook
00029 
00030 # ------------------------------------------------------------
00031 #  PROC:  gdbtk_tcl_set_variable - A "set" command was issued
00032 #          in gdb to change an internal variable. Notify
00033 #          gui.
00034 # ------------------------------------------------------------
00035 proc gdbtk_tcl_set_variable {var val} {
00036   set e [SetVariableEvent \#auto -variable $var -value $val]
00037   GDBEventHandler::dispatch $e
00038   delete object $e
00039 }
00040 
00041 ####################################################################
00042 #                                                                  #
00043 #                        GUI STATE HOOKS                           #
00044 #                                                                  #
00045 ####################################################################
00046 # !!!!!   NOTE   !!!!!
00047 # For debugging purposes, please put debug statements at the very
00048 # beginning and ends of all GUI state hooks.
00049 
00050 # *** DEPRECATED: Use GDBEventHandler::busy instead.
00051 # GDB_BUSY_HOOK
00052 #   This hook is used to register a callback when the UI should
00053 #   be disabled because the debugger is either busy or talking
00054 #   to the target.
00055 #
00056 #   All callbacks should disable ALL user input which could cause
00057 #   any state changes in either the target or the debugger.
00058 #define_hook gdb_busy_hook
00059 
00060 # *** DEPRECATED: Use GDBEventHandler::idle instead.
00061 # GDB_IDLE_HOOK
00062 #   This hook is used to register a callback when the UI should
00063 #   be enabled because the debugger is no longer busy.
00064 #
00065 #   All callbacks should enable user input. These callbacks
00066 #   should also be as fast as possible to avoid any significant
00067 #   time delays when enabling the UI.
00068 define_hook gdb_idle_hook
00069 
00070 # *** DEPRECATED: Use GDBEventHandler::update instead.
00071 # GDB_UPDATE_HOOK
00072 #   This hook is used to register a callback to update the widget
00073 #   when debugger state has changed.
00074 #define_hook gdb_update_hook
00075 
00076 # GDB_NO_INFERIOR_HOOK
00077 #   This hook is used to register a callback which should be invoked
00078 #   whenever there is no inferior (either at startup time or when
00079 #   an inferior is killed).
00080 #
00081 #   All callbacks should reset their windows to a known, "startup"
00082 #   state.
00083 define_hook gdb_no_inferior_hook
00084 
00085 # GDB_DISPLAY_CHANGE_HOOK
00086 # This is run when a display changes.  The arguments are the action,
00087 # the breakpoint number, and (optionally) the value.
00088 define_hook gdb_display_change_hook
00089 
00090 # GDB_TRACE_FIND_HOOK
00091 #    This hook is run by the trace find command.  It is used to switch
00092 #    from control to browse mode when the user runs tfind commands...
00093 #
00094 define_hook gdb_trace_find_hook
00095 
00096 # ------------------------------------------------------------------
00097 #  gdbtk_tcl_preloop - This function is called after gdb is initialized
00098 #  but before the mainloop is started.  It sets the app name, and
00099 #  opens the first source window.
00100 # ------------------------------------------------------------------
00101 
00102 proc gdbtk_tcl_preloop { } {
00103   global gdb_exe_name gdb_current_directory
00104 
00105   set_baud
00106 
00107   tk appname gdbtk
00108   # If there was an error loading an executible specified on the command line
00109   # then we will have called pre_add_symbol, which would set us to busy,
00110   # but not the corresponding post_add_symbol.  Do this here just in case...
00111   after idle gdbtk_idle 
00112   ManagedWin::startup
00113 
00114   if {$gdb_exe_name != ""} {
00115     # At startup, file_changed_hook is called too late for us, so we
00116     # must notice the initial session by hand.  If the arguments exist
00117     # -- if the user used `gdb --args' -- then we want the new
00118     # arguments and pwd to override what is set in the session.
00119     set current_args [gdb_get_inferior_args]
00120     set current_dir $gdb_current_directory
00121     Session::notice_file_change
00122     set_baud
00123     if {[string length $current_args] > 0} {
00124       gdb_set_inferior_args $current_args
00125       gdb_cmd "cd $current_dir"
00126     }
00127   }
00128   
00129   gdbtk_update
00130 }
00131 
00132 
00133 # ------------------------------------------------------------------
00134 #  PROCEDURE:  gdbtk_busy - Dispatch a busy event
00135 #
00136 #         Use this procedure from within GUI code to indicate that
00137 #         the debugger is busy, either running the inferior or
00138 #         talking to the target.
00139 # ------------------------------------------------------------------
00140 proc gdbtk_busy {} {
00141 
00142   set e [BusyEvent \#auto]
00143   GDBEventHandler::dispatch $e
00144   delete object $e
00145 
00146   # Force the screen to update
00147   update
00148 }
00149 
00150 # ------------------------------------------------------------------
00151 #   PROCEDURE:  gdbtk_update - run all update hooks
00152 #
00153 #          Use this procedure to force all widgets to update
00154 #          themselves. This hook is usually run after command
00155 #          that could change target state.
00156 # ------------------------------------------------------------------
00157 proc gdbtk_update {} {
00158 
00159   set e [UpdateEvent \#auto]
00160   GDBEventHandler::dispatch $e
00161   delete object $e
00162   
00163   # Force the screen to update
00164   update
00165 }
00166 
00167 # ------------------------------------------------------------------
00168 #   PROCEDURE:  gdbtk_update_safe - run all update hooks in a safe way
00169 #
00170 #          Use this procedure to force all widgets to update
00171 #          themselves. This hook is usually run after command
00172 #          that could change target state.
00173 #          Like gdbtk_update but safe to be used in "after idle"
00174 #          which is used in update hooks.
00175 # ------------------------------------------------------------------
00176 proc gdbtk_update_safe {} {
00177   global gdb_running
00178 
00179   # Fencepost: Do not update if we are running the target
00180   # We get here because script commands may have changed memory or
00181   # registers and "after idle" events registered as a consequence
00182   # If we try to update while the target is running we are doomed.
00183   if {!$gdb_running} {
00184     gdbtk_update
00185   }
00186 }
00187 
00188 # ------------------------------------------------------------------
00189 #   PROCEDURE: gdbtk_idle - dispatch IdleEvent
00190 #
00191 #          Use this procedure to free the UI for more user input.
00192 #          This should only be run AFTER all communication with
00193 #          the target has halted, otherwise the risk of two (or
00194 #          more) widgets talking to the target arises.
00195 # ------------------------------------------------------------------
00196 proc gdbtk_idle {} {
00197   global gdb_running
00198 
00199   # Put the unfiltered hook back in place, just in case
00200   # somebody swapped it out, and then died before they
00201   # could replace it.
00202   gdb_restore_fputs
00203 
00204   set err [catch {run_hooks gdb_idle_hook}]
00205   if {$err} {
00206     dbug E "Error running gdb_idle_hook: $::errorInfo"
00207   }
00208 
00209   set e [IdleEvent \#auto]
00210   GDBEventHandler::dispatch $e
00211   delete object $e
00212 
00213   if {!$gdb_running} {
00214     set err [catch {run_hooks gdb_no_inferior_hook} txt]
00215     if {$err} { 
00216       dbug E "no_inferior_hook error: $txt" 
00217     }
00218   }
00219 
00220   # Force the screen to update
00221   update
00222 }
00223 
00224 define_hook download_progress_hook
00225 
00226 # ------------------------------------------------------------------
00227 #  PROCEDURE:  gdbtk_quit_check - Ask if the user really wants to quit.
00228 # ------------------------------------------------------------------
00229 proc gdbtk_quit_check {} {
00230   global gdb_downloading gdb_running gdb_exe_name
00231   
00232   if {$gdb_downloading} {
00233     set msg "Downloading to target,\n really close the debugger?"
00234     if {![gdbtk_tcl_query $msg no]} {
00235       return 0
00236     }
00237   } elseif {$gdb_running} {
00238     # While we are running the inferior, gdb_cmd is fenceposted and
00239     # returns immediately. Therefore, we need to ask here. Do we need
00240     # to stop the target, too?
00241     set msg "A debugging session is active.\n"
00242     append msg "Do you still want to close the debugger?"
00243     if {![gdbtk_tcl_query $msg no]} {
00244       return 0
00245     }
00246   }
00247   
00248   return 1
00249 }
00250 
00251 # ------------------------------------------------------------------
00252 #  PROCEDURE:  gdbtk_quit - Quit the debugger
00253 #         Call this procedure anywhere the user can request to quit.
00254 #         This procedure will ask all the right questions before
00255 #         exiting.
00256 # ------------------------------------------------------------------
00257 proc gdbtk_quit {} {
00258   if {[gdbtk_quit_check]} {
00259     gdbtk_force_quit
00260   }
00261 }
00262 
00263 # ------------------------------------------------------------------
00264 #  PROCEDURE:  gdbtk_force_quit - Quit the debugger immediately
00265 # ------------------------------------------------------------------
00266 proc gdbtk_force_quit {} {
00267   # If we don't delete source windows, GDB hooks will
00268   # try to update them as we exit
00269   foreach win [ManagedWin::find SrcWin] {
00270     delete object $win
00271   }
00272   # Calling gdb_force_quit is probably not necessary here
00273   # because it should have been called when the source window(s)
00274   # were deleted, but just in case...
00275   gdb_force_quit
00276 }
00277 
00278 # ------------------------------------------------------------------
00279 #  PROCEDURE:  gdbtk_cleanup - called by GDB immediately
00280 #         before exiting.  Last chance to cleanup!
00281 # ------------------------------------------------------------------
00282 proc gdbtk_cleanup {} {
00283   global gdb_exe_name
00284 
00285   # Save the session
00286   if {$gdb_exe_name != ""} {
00287     Session::save
00288   }
00289 
00290   # This is a sign that it is too late to be doing updates, etc...
00291   set ::gdb_shutting_down 1
00292 
00293   # Shutdown the window manager and save all preferences
00294   # This way a "quit" in the console window will cause
00295   # preferences to be saved.
00296   ManagedWin::shutdown
00297   pref_save
00298 }
00299 
00300 # ------------------------------------------------------------------
00301 # PROC: gdbtk_tcl_query -
00302 # ------------------------------------------------------------------
00303 proc gdbtk_tcl_query {message {default yes}} {
00304   global gdb_checking_for_exit gdbtk_state gdbtk_platform
00305 
00306   # FIXME We really want a Help button here.  But Tk's brain-damaged
00307   # modal dialogs won't really allow it.  Should have async dialog
00308   # here.
00309 
00310   set title "GDB"
00311   set modal "task"
00312 
00313   # If we are checking whether to exit gdb, we want a system modal
00314   # box.  Otherwise it may be hidden by some other program, and the
00315   # user will have no idea what is going on.
00316   if {[info exists gdb_checking_for_exit] && $gdb_checking_for_exit} {
00317     set modal "system"
00318   }
00319   
00320   if {$gdbtk_platform(platform) == "windows"} {
00321     # On Windows, we want to only ask each question once.
00322     # If we're already asking the question, just wait for the answer
00323     # to come back.
00324     set ans [list answer $message]
00325     set pending [list pending $message]
00326 
00327     if {[info exists gdbtk_state($pending)]} {
00328       incr gdbtk_state($pending)
00329     } else {
00330       set gdbtk_state($pending) 1
00331       set gdbtk_state($ans) {}
00332 
00333       ide_messageBox [list set gdbtk_state($ans)] -icon warning \
00334   -default $default -message $message -title $title \
00335   -type yesno -modal $modal -parent .
00336     }
00337 
00338     vwait gdbtk_state($ans)
00339     set r $gdbtk_state($ans)
00340     if {[incr gdbtk_state($pending) -1] == 0} {
00341       # Last call waiting for this answer, so clear it.
00342       unset gdbtk_state($pending)
00343       unset gdbtk_state($ans)
00344     }
00345   } else {
00346     # On Unix, apparently it doesn't matter how many times we ask a
00347     # question.
00348     set r [tk_messageBox -icon warning -default $default \
00349        -message $message -title $title \
00350        -type yesno -parent .]
00351   }
00352 
00353   update idletasks
00354   return [expr {$r == "yes"}]
00355 }
00356 
00357 # ------------------------------------------------------------------
00358 # PROC: gdbtk_tcl_warning -
00359 # ------------------------------------------------------------------
00360 proc gdbtk_tcl_warning {message} {
00361   debug "$message"
00362 
00363 # ADD a warning message here if the gui must NOT display it
00364 # add the message at the beginning of the switch followed by - 
00365 
00366   switch -regexp $message {
00367         "Unable to find dynamic linker breakpoint function.*" {return}
00368   "Internal error.*" { gdbtk_tcl_fputs_error $message }
00369         "incomplete CFI.*" { gdbtk_tcl_fputs_error $message }
00370   "RTTI symbol not found for class.*" { gdbtk_tcl_fputs_error $message }
00371         "DW_AT.*" { gdbtk_tcl_fputs_error $message }
00372         "unsupported tag.*" { gdbtk_tcl_fputs_error $message }
00373         default {show_warning $message}
00374        }
00375 }
00376 
00377 # ------------------------------------------------------------------
00378 # PROC: show_warning -
00379 # ------------------------------------------------------------------
00380 proc show_warning {message} {
00381   global gdbtk_platform
00382 
00383   # FIXME We really want a Help button here.  But Tk's brain-damaged
00384   # modal dialogs won't really allow it.  Should have async dialog
00385   # here.
00386   set title "GDB"
00387   set modal "task"
00388 
00389 # On Windows, we use ide_messageBox which runs the Win32 MessageBox function
00390 # in another thread.  This permits a program which handles IDE requests from
00391 # other programs to not return from the request until the MessageBox completes.
00392 # This is not possible without using another thread, since the MessageBox
00393 # function call will be running its own event loop, and will be higher on the
00394 # stack than the IDE request.
00395 #
00396 # On Unix tk_messageBox runs in the regular Tk event loop, so
00397 # another thread is not required.
00398 
00399  
00400   if {$gdbtk_platform(platform) == "windows"} {
00401       ide_messageBox [list set r] -icon warning \
00402         -default ok -message $message -title $title \
00403         -type ok -modal $modal -parent .
00404   } else {
00405     set r [tk_messageBox -icon warning -default ok \
00406              -message $message -title $title \
00407              -type ok -parent .]
00408   }
00409 } 
00410 
00411 # ------------------------------------------------------------------
00412 # PROC: gdbtk_tcl_ignorable_warning -
00413 # ------------------------------------------------------------------
00414 proc gdbtk_tcl_ignorable_warning {class message} {
00415   catch {ManagedWin::open WarningDlg -center -transient \
00416      -message [list $message] -ignorable $class}
00417 }
00418 
00419 # ------------------------------------------------------------------
00420 # PROC: gdbtk_tcl_fputs -
00421 # ------------------------------------------------------------------
00422 proc gdbtk_tcl_fputs {message} {
00423   global gdbtk_state
00424   # Restore the fputs hook, in case anyone forgot to put it back...
00425   gdb_restore_fputs
00426 
00427   if {[info exists gdbtk_state(console)] &&   $gdbtk_state(console) != ""} {
00428     $gdbtk_state(console) insert $message
00429   }
00430 }
00431 
00432 # ------------------------------------------------------------------
00433 # PROC: echo -
00434 # ------------------------------------------------------------------
00435 proc echo {args} {
00436   gdbtk_tcl_fputs [concat $args]\n
00437 }
00438 
00439 # ------------------------------------------------------------------
00440 # PROC: gdbtk_tcl_fputs_error - write an error message
00441 # ------------------------------------------------------------------
00442 proc gdbtk_tcl_fputs_error {message} {
00443   if {[info exists ::gdbtk_state(console)] && $::gdbtk_state(console) != ""} {
00444     $::gdbtk_state(console) insert $message err_tag
00445     update
00446   }
00447 }
00448 
00449 # ------------------------------------------------------------------
00450 # PROC: gdbtk_tcl_fputs_log - write a log message
00451 # ------------------------------------------------------------------
00452 proc gdbtk_tcl_fputs_log {message} {
00453   if {[info exists ::gdbtk_state(console)] && $::gdbtk_state(console) != ""} {
00454     $::gdbtk_state(console) insert $message log_tag
00455     update
00456   }
00457 }
00458 
00459 # ------------------------------------------------------------------
00460 # PROC: gdbtk_tcl_fputs_target - write target output
00461 # ------------------------------------------------------------------
00462 proc gdbtk_tcl_fputs_target {message} {
00463   if {$::gdbtk_state(console) == ""} {
00464     ManagedWin::open Console -force
00465   }
00466   $::gdbtk_state(console) insert $message target_tag
00467   update
00468 }
00469 
00470 
00471 # ------------------------------------------------------------------
00472 # PROC: gdbtk_tcl_fputs_target_err - write target error output
00473 # ------------------------------------------------------------------
00474 proc gdbtk_tcl_fputs_target_err {message} {
00475   if {$::gdbtk_state(console) == ""} {
00476     ManagedWin::open Console -force
00477   }  
00478   $::gdbtk_state(console) insert $message err_tag
00479 }
00480 
00481 # ------------------------------------------------------------------
00482 # PROC: gdbtk_tcl_flush -
00483 # ------------------------------------------------------------------
00484 proc gdbtk_tcl_flush {} {
00485   debug [info level 0]
00486 }
00487 
00488 # ------------------------------------------------------------------
00489 # PROC: gdbtk_tcl_start_variable_annotation -
00490 # ------------------------------------------------------------------
00491 proc gdbtk_tcl_start_variable_annotation {valaddr ref_type stor_cl
00492                                     cum_expr field type_cast} {
00493   debug [info level 0]
00494 }
00495 
00496 # ------------------------------------------------------------------
00497 # PROC: gdbtk_tcl_end_variable_annotation -
00498 # ------------------------------------------------------------------
00499 proc gdbtk_tcl_end_variable_annotation {} {
00500   debug [info level 0]
00501 }
00502 
00503 # ------------------------------------------------------------------
00504 # PROC: gdbtk_tcl_breakpoint - A breakpoint was changed -- notify
00505 #                               gui.
00506 # ------------------------------------------------------------------
00507 proc gdbtk_tcl_breakpoint {action bpnum} {
00508 #  debug "BREAKPOINT: $action $bpnum"
00509   set e [BreakpointEvent \#auto -action $action -number $bpnum]
00510   GDBEventHandler::dispatch $e
00511   delete object $e
00512 }
00513 
00514 # ------------------------------------------------------------------
00515 # PROC: gdbtk_tcl_tracepoint - A tracepoint was changed -- notify
00516 #                               gui.
00517 # ------------------------------------------------------------------
00518 proc gdbtk_tcl_tracepoint {action tpnum} {
00519 #  debug "TRACEPOINT: $action $tpnum"
00520   set e [TracepointEvent \#auto -action $action -number $tpnum]
00521   GDBEventHandler::dispatch $e
00522   delete object $e
00523 }
00524 
00525 # ------------------------------------------------------------------
00526 # PROC: gdbtk_tcl_trace_find_hook -
00527 # ------------------------------------------------------------------
00528 proc gdbtk_tcl_trace_find_hook {arg from_tty} {
00529 #  debug "$arg $from_tty"
00530   run_hooks gdb_trace_find_hook $arg $from_tty
00531 }
00532 
00533 ################################################################
00534 #
00535 # Handle `readline' interface.
00536 #
00537 
00538 # Run a command that is known to use the "readline" interface.  We set
00539 # up the appropriate buffer, and then run the actual command via
00540 # gdb_cmd.  Calls into the "readline" callbacks just return values
00541 # from our list.
00542 
00543 # ------------------------------------------------------------------
00544 # PROC: gdb_run_readline_command -
00545 # ------------------------------------------------------------------
00546 proc gdb_run_readline_command {command args} {
00547   global gdbtk_state
00548   debug "$command $args"
00549   set gdbtk_state(readlineArgs) $args
00550   set gdbtk_state(readlineShowUser) 1
00551   gdb_cmd $command
00552 }
00553 
00554 # ------------------------------------------------------------------
00555 # PROC: gdb_run_readline_command_no_output
00556 # Run a readline command, but don't show the commands to the user.
00557 # ------------------------------------------------------------------
00558 proc gdb_run_readline_command_no_output {command args} {
00559   global gdbtk_state
00560   debug "$command $args"
00561   set gdbtk_state(readlineArgs) $args
00562   set gdbtk_state(readlineShowUser) 0
00563   gdb_cmd $command
00564 }
00565 
00566 # ------------------------------------------------------------------
00567 # PROC: gdbtk_tcl_readline_begin -
00568 # ------------------------------------------------------------------
00569 proc gdbtk_tcl_readline_begin {message} {
00570   global gdbtk_state
00571 #  debug
00572   set gdbtk_state(readline) 0
00573   if {$gdbtk_state(console) != "" && $gdbtk_state(readlineShowUser)} {
00574     $gdbtk_state(console) insert $message
00575   }
00576 }
00577 
00578 # ------------------------------------------------------------------
00579 # PROC: gdbtk_tcl_readline -
00580 # ------------------------------------------------------------------
00581 proc gdbtk_tcl_readline {prompt} {
00582   global gdbtk_state
00583 #  debug "prompt=$prompt"
00584   if {[info exists gdbtk_state(readlineArgs)]} {
00585     # Not interactive, so pop the list, and print element.
00586     set cmd [lvarpop gdbtk_state(readlineArgs)]
00587     if {$gdbtk_state(console) != "" && $gdbtk_state(readlineShowUser)} {
00588       $gdbtk_state(console) insert $cmd
00589     }
00590   } else {
00591     # Interactive.
00592 #    debug "interactive"
00593     set gdbtk_state(readline) 1
00594     $gdbtk_state(console) activate $prompt
00595     vwait gdbtk_state(readline_response)
00596     set cmd $gdbtk_state(readline_response)
00597 #    debug "got response: $cmd"
00598     unset gdbtk_state(readline_response)
00599     set gdbtk_state(readline) 0
00600   }
00601   return $cmd
00602 }
00603 
00604 # ------------------------------------------------------------------
00605 # PROC: gdbtk_tcl_readline_end -
00606 # ------------------------------------------------------------------
00607 proc gdbtk_tcl_readline_end {} {
00608   global gdbtk_state
00609 #  debug
00610   catch {unset gdbtk_state(readlineArgs)}
00611   catch {unset gdbtk_state(readlineActive)}
00612 }
00613 
00614 # ------------------------------------------------------------------
00615 # PROC: gdbtk_tcl_busy - this is called immediately before gdb 
00616 #    executes a command.
00617 #
00618 # ------------------------------------------------------------------
00619 proc gdbtk_tcl_busy {} {
00620   global gdbtk_state
00621   if {[incr gdbtk_state(busyCount)] == 1} {
00622     gdbtk_busy
00623   }
00624 }
00625 
00626 ################################################################
00627 #
00628 # 
00629 #
00630 
00631 # ------------------------------------------------------------------
00632 # PROC: gdbtk_tcl_idle - this is called immediately after gdb 
00633 #    executes a command.
00634 # ------------------------------------------------------------------
00635 proc gdbtk_tcl_idle {} {
00636   global gdbtk_state
00637   if {$gdbtk_state(busyCount) > 0
00638       && [incr gdbtk_state(busyCount) -1] == 0} {
00639     gdbtk_update
00640     gdbtk_idle
00641   }
00642 }
00643 
00644 # ------------------------------------------------------------------
00645 # PROC: gdbtk_tcl_tstart -
00646 # ------------------------------------------------------------------
00647 proc gdbtk_tcl_tstart {} {
00648   set srcwin [lindex [manage find src] 0]
00649   $srcwin.toolbar do_tstop 0
00650   
00651 }
00652 
00653 # ------------------------------------------------------------------
00654 # PROC: gdbtk_tcl_tstop -
00655 # ------------------------------------------------------------------
00656 proc gdbtk_tcl_tstop {} {
00657   set srcwin [lindex [manage find src] 0]
00658   $srcwin.toolbar do_tstop 0
00659   
00660 }
00661 
00662 
00663 # ------------------------------------------------------------------
00664 # PROC: gdbtk_tcl_display -
00665 #
00666 # A display changed.  ACTION is `enable', `disable', `delete',
00667 # `create', or `update'.  VALUE is only meaningful in the `update'
00668 # case.
00669 # ------------------------------------------------------------------
00670 proc gdbtk_tcl_display {action number {value {}}} {
00671   # Handle create explicitly.
00672   if {$action == "create"} {
00673     manage create_if_never data
00674   }
00675   run_hooks gdb_display_change_hook $action $number $value
00676 }
00677 
00678 # ------------------------------------------------------------------
00679 #  PROCEDURE: gdbtk_register_changed
00680 #         This hook is called from value_assign to inform us that
00681 #         the user has changed the contents of a register.
00682 # ------------------------------------------------------------------
00683 proc gdbtk_register_changed {} {
00684   after idle gdbtk_update_safe
00685 }
00686 
00687 # ------------------------------------------------------------------
00688 #  PROCEDURE: gdbtk_memory_changed
00689 #         This hook is called from value_assign to inform us that
00690 #         the user has changed the contents of memory (including
00691 #         the program's variables).
00692 # ------------------------------------------------------------------
00693 proc gdbtk_memory_changed {} {
00694   after idle gdbtk_update_safe
00695 }
00696 
00697 ####################################################################
00698 #                                                                  #
00699 #                           FILE HOOKS                             #
00700 #                                                                  #
00701 #    There are a number of hooks that are installed in gdb to      #
00702 #    aid with file-like commands (selecting an exectuable and      #
00703 #    loading symbols):                                             #
00704 #         - exec_file_display_hook                                 #
00705 #            Called in exec_file_command. The tcl hook is          #
00706 #            "gdbtk_tcl_exec_file_display"                         #
00707 #         - file_changed_hook                                      #
00708 #            Called in file_command. The tcl hook is               #
00709 #            "gdbtk_tcl_file_changed"                              #
00710 #         - deprecated_pre_add_symbol_hook                         #
00711 #            Called in symbol_file_add before loading. The tcl     #
00712 #            hook is "gdbtk_tcl_pre_add_symbol"                    #
00713 #         - deprecated_post_add_symbol_hook                        #
00714 #            Called in symbol_file_add when finished loading       #
00715 #            a symbol file. The tcl hook is                        #
00716 #            "gdbtk_tcl_post_add_symbol"                           #
00717 #                                                                  #
00718 #  Together, these hooks should give the gui enough information    #
00719 #  to cover the two most common uses of file commands:             #
00720 #  1. executable with symbols                                      #
00721 #  2. separate executable and symbol file(s)                       #
00722 #                                                                  #
00723 ####################################################################
00724 define_hook file_changed_hook
00725 
00726 # ------------------------------------------------------------------
00727 #  PROCEDURE:  gdbtk_tcl_pre_add_symbol
00728 #         This hook is called before any symbol files
00729 #         are loaded so that we can inform the user.
00730 # ------------------------------------------------------------------
00731 proc gdbtk_tcl_pre_add_symbol {file} {
00732 
00733   gdbtk_busy
00734 
00735   # Display some feedback to the user
00736   set srcs [ManagedWin::find SrcWin]
00737   foreach w $srcs {
00738     $w set_status "Reading symbols from $file..."
00739   }
00740   update idletasks
00741 }
00742 
00743 # ------------------------------------------------------------------
00744 #   PROCEDURE: gdbtk_tcl_post_add_symbol
00745 #          This hook is called after we finish reading a symbol
00746 #          file, so the source windows' combo boxes need filling.
00747 # ------------------------------------------------------------------
00748 proc gdbtk_tcl_post_add_symbol {} {
00749 
00750   set srcs [ManagedWin::find SrcWin]
00751   foreach w $srcs {
00752     $w fillNameCB
00753   }
00754   gdbtk_idle
00755 }
00756 
00757 # ------------------------------------------------------------------
00758 #  PROCEDURE: gdbtk_tcl_file_changed
00759 #         This hook is called whenever the exec file changes.
00760 #         This is called AFTER symbol reading, so it is
00761 #         ok to point to main when we get called.
00762 # ------------------------------------------------------------------
00763 proc gdbtk_tcl_file_changed {filename} {
00764 
00765   if {$filename == ""} {
00766     gdb_clear_file
00767     catch {run_hooks gdb_clear_file_hook}
00768     set ::gdb_exe_name ""
00769     set ::gdb_loaded 0
00770     set ::gdb_running 0
00771     gdbtk_update
00772   } else {
00773     SrcWin::point_to_main
00774     run_hooks file_changed_hook
00775   }
00776 }
00777 
00778 # ------------------------------------------------------------------
00779 #  PROCEDURE: gdbtk_tcl_exec_file_display 
00780 #         This hook is called from exec_file_command. It's purpose
00781 #         is to setup the gui for a new file. Note that we cannot
00782 #         look for main, since this hook is called BEFORE we
00783 #         read symbols. If the user used the "file" command,
00784 #         gdbtk_tcl_file_changed will set the source window to
00785 #         look at main. If the user used "exec-file" and "add-symbol"
00786 #         commands, then we cannot look for main.
00787 # ------------------------------------------------------------------
00788 proc gdbtk_tcl_exec_file_display {filename} {
00789   global gdb_exe_changed
00790 
00791   # DO NOT CALL set_exe here! 
00792 
00793   # Clear out the GUI, don't do it if filename is "" so that
00794   # you avoid distracting flashes in the source window.
00795 
00796   if {$filename != ""} {
00797     gdbtk_clear_file
00798   }
00799 
00800   # set_exe calls file command with the filename in
00801   # quotes, so we need to strip them here.
00802   # We need to make sure that we turn filename into
00803   # an absolute path or sessions won't work.
00804   if {[file tail $filename] == $filename} {
00805     # want full pathname
00806     set filename [file join $::gdb_current_directory $filename]
00807   }
00808   set_exe_name $filename
00809   set gdb_exe_changed 0
00810 
00811   SrcWin::point_to_main
00812 }
00813 
00814 # ------------------------------------------------------------------
00815 #  PROCEDURE: gdbtk_locate_main 
00816 #         This proc tries to locate a suitable main function from
00817 #         a list of names defined in the gdb/main_names preference; 
00818 #         returns the linespec (see below) if found, or a null string
00819 #         if not.
00820 #
00821 #  The return linespec looks like this:
00822 #  0: basename of the file
00823 #  1: function name
00824 #  2: full filename
00825 #  3: source line number
00826 #  4: address
00827 #  5: current PC - which will often be the same as address, but not when
00828 #  we are browsing, or walking the stack.
00829 #  6: shared library name if the pc is in a shared lib
00830 #
00831 # ------------------------------------------------------------------
00832 proc gdbtk_locate_main {{init ""}} {
00833   global _main_cache gdb_exe_name
00834   debug
00835 
00836   if {$init == "" && $_main_cache != ""} {
00837     #debug "returning $_main_cache from cache"
00838     return $_main_cache
00839   }
00840   set _main_cache {}
00841 
00842   set main_names [pref get gdb/main_names]
00843   foreach main $main_names {
00844     if {![catch {gdb_loc $main} linespec]} {
00845       set _main_cache $linespec
00846       break
00847     }
00848   }
00849   if {$_main_cache == {} 
00850       && ![catch gdb_entry_point entry_point]
00851       && ![catch {gdb_loc "*$entry_point"} linespec]} {
00852     set _main_cache $linespec
00853   }
00854   
00855   # need to see if result is valid
00856   lassign $_main_cache file func ffile line addr rest
00857   if {$addr == 0x0 && $func == {}} { set _main_cache {} }
00858 
00859   #debug "returning $_main_cache"
00860   return $_main_cache
00861 }
00862 
00863 ##############################################
00864 #  The rest of this file is an assortment of Tcl wrappers
00865 #  for various bits of gdb functionality.
00866 #
00867 #############################################
00868 
00869 # ------------------------------------------------------------------
00870 # PROC: set_exe_name - Update the executable name
00871 # ------------------------------------------------------------------
00872 proc set_exe_name {exe} {
00873   global gdb_exe_name gdb_exe_changed
00874   #debug "exe=$exe  gdb_exe_name=$gdb_exe_name"
00875 
00876   set gdb_exe_name $exe
00877   set gdb_exe_changed 1    
00878 }
00879 
00880 
00881 # ------------------------------------------------------------------
00882 # PROC: set_exe -
00883 # ------------------------------------------------------------------ 
00884 proc set_exe {} {
00885   global gdb_exe_name gdb_exe_changed gdb_target_changed gdb_loaded file_done
00886 #  debug "gdb_exe_changed=$gdb_exe_changed gdb_exe_name=$gdb_exe_name"
00887   if {$gdb_exe_changed} {
00888     set gdb_exe_changed 0
00889     if {$gdb_exe_name == ""} { return }
00890     set err [catch {gdb_cmd "file '$gdb_exe_name'" 1} msg]
00891     if {$err} {
00892       dbug E "$msg"
00893       set l [split $msg :]
00894       set errtxt [join [lrange $l 1 end] :]
00895       set msg "Error loading \"$gdb_exe_name\":\n"
00896       append msg $errtxt
00897       tk_messageBox -title "Error" -message $msg -icon error \
00898   -type ok
00899       set gdb_exe_name {}
00900       set file_done 0
00901       return
00902     } elseif {[string match {*no debugging symbols found*} $msg]} {
00903       tk_messageBox -icon error -default ok \
00904   -title "GDB" -type ok \
00905   -message "This executable has no debugging information."
00906     }
00907 
00908     # force new target command
00909     set gdb_target_changed 1
00910     set gdb_loaded 0
00911     set file_done 1
00912   }
00913 }
00914 
00915 # ------------------------------------------------------------------
00916 #  _open_file - open a file dialog to select a file for debugging.
00917 #  If filename is not "", then open this file.
00918 # ------------------------------------------------------------------
00919 
00920 proc _open_file {{file ""}} {
00921   global gdb_running gdb_downloading gdbtk_platform
00922   
00923   if {$gdb_running || $gdb_downloading} {
00924     # We are already running/downloading something..
00925     if {$gdb_running} {
00926       set msg "A debugging session is active.\nAbort session and load new file?"
00927     } else {
00928       set msg "A download is in progress.\nAbort download and load new file?"
00929     }
00930     if {![gdbtk_tcl_query $msg no]} {
00931       return 0
00932     }
00933   }
00934 
00935   if {[string compare $file ""] == 0} {
00936     set curFocus [focus]
00937     
00938     # Make sure that this is really a modal dialog...
00939     # FIXME: Add a disable_all to ide_grab_support.
00940     
00941     ide_grab_support disable_except {}
00942     
00943     set file [tk_getOpenFile -parent . -title "Load New Executable"]
00944   
00945     ide_grab_support enable_all
00946     
00947     # If no one had the focus before, leave it that way (since I
00948     # am not sure how this could happen...  Also, the vwait in 
00949     # tk_getOpenFile could have allowed the curFocus window to actually
00950     # be destroyed, so make sure it is still around.
00951     
00952     if {$curFocus != "" && [winfo exists $curFocus]} {
00953       raise [winfo toplevel $curFocus]
00954       focus $curFocus
00955     }
00956   } elseif {![file exists $file]} {
00957     tk_messageBox -message "File \"$file\" does not exist"
00958     return 0
00959   }
00960     
00961 
00962   if {$file == ""} {
00963     return 0
00964   }
00965   # Add the base dir for this file to the source search path.
00966   set root [file dirname $file]
00967   if {$gdbtk_platform(os) == "cygwin"} {
00968     set root [ide_cygwin_path to_posix $root]
00969     set file [ide_cygwin_path to_posix $file]
00970   }
00971   
00972   catch {gdb_cmd "cd $root"}
00973 
00974   # Clear out gdb's internal state, so that it will allow us
00975   # (the gui) to ask the user questions.
00976   gdb_clear_file
00977 
00978   # The gui needs to set this...
00979   set_exe_name $file
00980   
00981   # set_exe needs to be called anywhere the gui does a file_command...
00982   if {[set_exe] == "cancel"} {
00983     gdbtk_update
00984     gdbtk_idle
00985     return 0
00986   }
00987 
00988   return 1
00989 }
00990 
00991 # ------------------------------------------------------------------
00992 #  _close_file - close the current executable and prepare for
00993 #    another executable.
00994 # ------------------------------------------------------------------
00995 proc _close_file {} {
00996 
00997   # If there is already an inferior, ask him if he wants to close
00998   # the file. If there is already an exec file loaded (and not run)
00999   # also ask, but don't ask twice.
01000   set okay 1
01001   if {[gdb_target_has_execution]} {
01002     set okay [gdbtk_tcl_query "Program is already running.\nClose file anyway?"]
01003   } elseif {$::gdb_exe_name != ""} {
01004     set okay [gdbtk_tcl_query "Program already loaded.\nClose file anyway?"]
01005   } else {
01006     # No exec file yet
01007     return
01008   }
01009 
01010   if {$okay} {
01011     Session::save
01012     gdb_clear_file
01013     gdbtk_tcl_file_changed ""
01014 
01015     # Print out a little message to all console windows
01016     foreach cw [ManagedWin::find Console] {
01017       $cw insert "No executable file now.\n"
01018     }
01019   }
01020 }
01021 
01022 # ------------------------------------------------------------------
01023 # PROC: set_target_name - Update the target name.  
01024 #
01025 # This function will prompt for a new target and update
01026 # all variables.
01027 #
01028 # If $prompt is 0 it will just update gdb_target_cmd from gdb_target.
01029 #
01030 # RETURN:
01031 #     1 if successful, 
01032 #     0 if the not (the user canceled the target selection dialog)
01033 # ------------------------------------------------------------------
01034 proc set_target_name {{prompt 1}} {
01035   global gdb_target_name gdb_target_changed gdb_exe_changed
01036   global gdb_target_cmd gdb_pretty_name
01037 #  debug
01038   set cmd_tmp $gdb_target_cmd
01039   set name_tmp $gdb_target_name
01040 
01041 #  debug "gdb_target_name=$gdb_target_name; name_tmp=$name_tmp"
01042   if {$prompt} {
01043     set win [ManagedWin::open TargetSelection -exportcancel 1 -center \
01044          -transient]
01045     # need to call update here so the target selection dialog can take over
01046     update idletasks
01047   }
01048 
01049 #  debug "gdb_target_name=$gdb_target_name"
01050   if {$gdb_target_name == "CANCEL"} {
01051     set gdb_target_cmd $cmd_tmp
01052     set gdb_target_name $name_tmp
01053     return 0
01054   }
01055   set target $gdb_target_name
01056   set targ [TargetSelection::getname $target cmd]
01057   set gdb_target_cmd $cmd_tmp
01058   set gdb_pretty_name [TargetSelection::getname $target pretty-name]
01059 
01060 #  debug "target=$target pretty_name=$gdb_pretty_name"
01061   set targ_opts ""
01062   switch -regexp -- $gdb_target_name {
01063     sim|ice {
01064       set targ $gdb_target_name
01065       set targ_opts [pref getd gdb/load/${gdb_target_name}-opts]
01066     }
01067     default {
01068       set port [pref getd gdb/load/$target-port]
01069       if {$port == ""} {
01070   set port [pref get gdb/load/default-port]
01071       }
01072       set portnum [pref getd gdb/load/$target-portname]
01073       if {$portnum == ""} {
01074   set portnum [pref get gdb/load/default-portname]
01075       }
01076       set hostname [pref getd gdb/load/$target-hostname]
01077       if {$hostname == ""} {
01078   set hostname [pref getd gdb/load/default-hostname]
01079       }
01080       # replace "com1" with the real port name
01081       set targ [lrep $targ "com1" $port]
01082       # replace "tcpX" with hostname:portnum
01083       set targ [lrep $targ "tcpX" ${hostname}:${portnum}]
01084       # replace "ethX" with hostname
01085       set targ [lrep $targ "ethX" e=${hostname}]
01086     }
01087   }
01088   
01089 #  debug "targ=$targ gdb_target_cmd=$gdb_target_cmd"
01090   if {$gdb_target_cmd != $targ || $gdb_target_changed} {
01091     set gdb_target_changed 1
01092     set gdb_target_cmd "$targ $targ_opts"
01093   }
01094   return 1
01095 }
01096 
01097 # ------------------------------------------------------------------
01098 # PROC: set_target - Change the target
01099 # ------------------------------------------------------------------
01100 proc set_target {} {
01101   global gdb_target_cmd gdb_target_changed gdb_pretty_name gdb_target_name
01102   #debug "gdb_target_changed=$gdb_target_changed gdb_target_cmd=\"$gdb_target_cmd\""
01103   #debug "gdb_target_name=$gdb_target_name"
01104   if {$gdb_target_cmd == "" && ![TargetSelection::native_debugging]} {
01105     if {$gdb_target_name == ""} {
01106       set prompt 1
01107 
01108       # get the default
01109       #set gdb_target_name [pref getd gdb/load/target]
01110     } else {
01111       set prompt 0
01112     }
01113     if {![set_target_name $prompt]} {
01114       set gdb_target_name ""
01115       return CANCELED
01116     }
01117   }
01118   
01119   if {$gdb_target_changed} {
01120     set srcWin [lindex [ManagedWin::find SrcWin] 0]
01121 
01122     $srcWin set_status "Trying to communicate with target $gdb_pretty_name" 1
01123     update
01124     catch {gdb_cmd "detach"}
01125     debug "CONNECTING TO TARGET: $gdb_target_cmd"
01126     gdbtk_busy
01127     set err [catch {gdb_immediate "target $gdb_target_cmd"} msg ]
01128     $srcWin set_status
01129     gdbtk_idle
01130 
01131     if {$err} {
01132       if {[string first "Program not killed" $msg] != -1} {
01133   return CANCELED
01134       }
01135       update
01136       set dialog_title "GDB"
01137       set debugger_name "GDB"
01138       tk_messageBox -icon error -title $dialog_title -type ok \
01139   -message "$msg\n\n$debugger_name cannot connect to the target board\
01140 using [lindex $gdb_target_cmd 1].\nVerify that the board is securely connected and, if\
01141 necessary,\nmodify the port setting with the debugger preferences."
01142       return ERROR
01143     }
01144     
01145     if {![catch {pref get gdb/load/$gdb_target_name-after_attaching} aa] && $aa != ""} {
01146       if {[catch {gdb_cmd $aa} err]} {
01147   catch {[ManagedWin::find Console] insert $err err_tag}
01148       }
01149     }
01150     set gdb_target_changed 0
01151     return TARGET_CHANGED
01152   }
01153   return TARGET_UNCHANGED
01154 }
01155 
01156 # ------------------------------------------------------------------
01157 # PROC: run_executable -
01158 #
01159 # This procedure is used to run an executable.  It is called when the 
01160 # run button is used.
01161 # ------------------------------------------------------------------
01162 proc run_executable { {auto_start 1} } {
01163   global gdb_loaded gdb_downloading gdb_target_name
01164   global gdb_exe_changed gdb_target_changed gdb_program_has_run
01165   global gdb_running gdb_exe_name gdbtk_platform
01166 
01167 #  debug "auto_start=$auto_start gdb_target_name=$gdb_target_name"
01168 
01169   set gdb_running_saved $gdb_running
01170   set gdb_running 0
01171 
01172   # No executable was specified.  Prompt the user for one.
01173   if {$gdb_exe_name == ""} {
01174     if {[_open_file]} {
01175       run_executable $auto_start
01176       return
01177     } else {
01178       # The user canceled the load of a new executable.
01179       return
01180     }
01181   }
01182 
01183   if {$gdb_downloading} { return }
01184   if {[pref get gdb/control_target]} {
01185     # Breakpoint mode
01186     set_exe
01187 
01188     # Attach
01189     if {$gdb_target_name == "" || [pref get gdb/src/run_attach]} {
01190       set r [gdbtk_attach_remote]
01191       if {$r == "ATTACH_CANCELED" || $r == "ATTACH_ERROR"} {
01192   return
01193       }
01194     }
01195 
01196     # Download
01197     if {[pref get gdb/src/run_load] && $gdb_target_name != "exec"} {
01198       debug "Downloading..."
01199       set gdb_loaded 0
01200       
01201       # if the app has not been downloaded or the app has already
01202       # started, we need to redownload before running
01203       if {!$gdb_loaded} {
01204   if {[Download::download_it]} {
01205     # user cancelled the command
01206 #   debug "user cancelled the command $gdb_running"
01207     set gdb_loaded 0
01208     gdbtk_update
01209     gdbtk_idle
01210   }
01211   if {!$gdb_loaded} {
01212     # The user cancelled the download after it started
01213 #   debug "User cancelled the download after it started $gdb_running"
01214     gdbtk_update
01215     gdbtk_idle
01216     return
01217   }
01218       }
01219     }
01220 
01221     # _Now_ set/clear breakpoints
01222     if {[pref get gdb/load/exit] && ![TargetSelection::native_debugging]} {
01223       debug "Setting new BP at exit"
01224       catch {gdb_cmd "clear exit"}
01225       catch {gdb_cmd "break exit"}
01226     }
01227       
01228     if {[pref get gdb/load/main]} {
01229       set main "main"
01230       if {[set linespec [gdbtk_locate_main]] != ""} {
01231         set main [lindex $linespec 1]
01232       }
01233       debug "Setting new BP at $main"
01234       catch {gdb_cmd "clear $main"}
01235       catch {gdb_cmd "break $main"}
01236     }
01237 
01238     # set BP at user-specified function
01239     if {[pref get gdb/load/bp_at_func]} {
01240       foreach bp [pref get gdb/load/bp_func] {
01241   debug "Setting BP at $bp"
01242   catch {gdb_cmd "clear $bp"}
01243   catch {gdb_cmd "break $bp"}
01244       }
01245     }
01246 
01247     # This is a hack.  If the target is "sim" the opts are appended
01248     # to the target command. Otherwise they are assumed to be command line
01249     # args.  What about simulators that accept command line args?
01250     if {$gdb_target_name != "sim"} {
01251       # set args
01252       set gdb_args [pref getd gdb/load/$gdb_target_name-opts]
01253       if { $gdb_args != ""} {
01254   debug "set args $gdb_args"
01255   gdb_set_inferior_args $gdb_args
01256       }
01257     }
01258 
01259     # If the user requested it, start an xterm for use as the
01260     # inferior's tty.
01261     if {$gdbtk_platform(platform) != "windows"
01262   && [pref getd gdb/process/xtermtty] == "yes"} {
01263       tty::create
01264     }
01265 
01266     # 
01267     # Run
01268 
01269     if {$auto_start} {
01270       if {[pref get gdb/src/run_run]} {
01271   debug "Runnning target..."
01272   set run run
01273       } else {
01274   debug "Continuing target..."
01275   set run cont
01276       }
01277       if {$gdb_target_name == "exec"} {
01278   set run run
01279       }
01280       if {[catch {gdb_immediate $run} msg]} {
01281   dbug W "msg=$msg"
01282   gdbtk_idle
01283   if {[string match "*help target*" $msg]} {
01284     set_target_name
01285     run_executable $auto_start
01286     return
01287   }
01288   if {[string match "No executable*" $msg]} {
01289     # No executable was specified.  Prompt the user for one.
01290     if {[_open_file]} {
01291       run_executable $auto_start
01292     } else {
01293       debug "CANCELLED"
01294     }
01295     return
01296   }
01297   set gdb_running $gdb_running_saved
01298       } else {
01299   debug RUNNING
01300   set gdb_running 1
01301       }
01302     } else {
01303       SrcWin::point_to_main
01304     }
01305     
01306     gdbtk_update
01307     gdbtk_idle
01308   } elseif {[pref get gdb/mode]} {
01309     # tracepoint -- need to tstart
01310     set gdb_running 1
01311     tstart
01312   }
01313   return
01314 }
01315 
01316 # ------------------------------------------------------------------
01317 #  PROC: gdbtk_attach_remote - attach to the target
01318 #        This proc returns the following status messages:
01319 #
01320 #        ATTACH_ERROR: An error occurred connecting to target.
01321 #        ATTACH_CANCELED: The attach was canceled.
01322 #        ATTACH_TARGET_CHANGED: Successfully attached, target changed.
01323 #        ATTACH_TARGET_UNCHANGED: Successfully attached, target unchanged.
01324 #        UNKNOWN: An unknown error occurred.
01325 # ------------------------------------------------------------------
01326 proc gdbtk_attach_remote {} {
01327   global gdb_loaded
01328 
01329   debug "Attaching...."
01330   set r UNKNOWN
01331   while {1} {
01332 
01333     switch [set_target] {
01334 
01335       ERROR {
01336   # target command failed, ask for a new target name
01337   if {![set_target_name]} {
01338     # canceled again
01339     set r ATTACH_ERROR
01340     break
01341   }
01342       }
01343 
01344       TARGET_CHANGED {
01345   # success -- target changed
01346   set gdb_loaded 0
01347   set r ATTACH_TARGET_CHANGED
01348   break
01349       }
01350 
01351       CANCELED {
01352   # command cancelled by user
01353   set r ATTACH_CANCELED
01354   break
01355       }
01356 
01357       TARGET_UNCHANGED {
01358   # success -- target NOT changed (i.e., rerun)
01359   set r ATTACH_TARGET_UNCHANGED
01360   break
01361       }
01362     }
01363   }
01364 
01365 #  debug "Attach returning: \"$r\""
01366   return $r
01367 }
01368 
01369 # ------------------------------------------------------------------
01370 # PROC:  gdbtk_connect: connect to a remote target 
01371 #                      in asynch mode if async is 1
01372 # ------------------------------------------------------------------
01373 proc gdbtk_connect {{async 0}} {
01374   global file_done
01375 
01376   debug "async=$async"
01377 
01378   gdbtk_busy
01379 
01380   set result [gdbtk_attach_remote]
01381   switch $result {
01382     ATTACH_ERROR {
01383       set successful 0
01384     }
01385 
01386     ATTACH_TARGET_CHANGED {
01387   if {[pref get gdb/load/check] && $file_done} {
01388     set err [catch {gdb_cmd "compare-sections"} errTxt]
01389     if {$err} {
01390       set successful 0
01391       tk_messageBox -title "Error" -message $errTxt \
01392         -icon error -type ok
01393       break
01394     }
01395   }
01396 
01397   tk_messageBox -title "GDB" -message "Successfully connected" \
01398     -icon info -type ok
01399   set successful 1
01400     }
01401 
01402     ATTACH_CANCELED {
01403   tk_messageBox -title "GDB" -message "Connection Canceled" -icon info \
01404     -type ok
01405   set successful 0
01406     }
01407 
01408     ATTACH_TARGET_UNCHANGED {
01409   tk_messageBox -title "GDB" -message "Successfully connected" \
01410     -icon info -type ok
01411   set successful 1
01412     }
01413 
01414     default {
01415   dbug E "Unhandled response from gdbtk_attach_remote: \"$result\""
01416   set successful 0
01417     }
01418   }
01419 
01420   gdbtk_idle
01421 
01422   # Whenever we attach, we need to do an update
01423   if {$successful} {
01424     gdbtk_attached
01425   }
01426   return $successful
01427 }
01428 
01429 # ------------------------------------------------------------------
01430 #  PROC: gdbtk_step - step the target
01431 # ------------------------------------------------------------------
01432 proc gdbtk_step {} {
01433   catch {gdb_immediate step}
01434 }
01435 
01436 # ------------------------------------------------------------------
01437 #  PROC: gdbtk_next
01438 # ------------------------------------------------------------------
01439 proc gdbtk_next {} {
01440   catch {gdb_immediate next}
01441 }
01442 
01443 # ------------------------------------------------------------------
01444 #  PROC: gdbtk_finish
01445 # ------------------------------------------------------------------
01446 proc gdbtk_finish {} {
01447   catch {gdb_immediate finish}
01448 }
01449 
01450 # ------------------------------------------------------------------
01451 #  PROC: gdbtk_continue
01452 # ------------------------------------------------------------------
01453 proc gdbtk_continue {} {
01454   catch {gdb_immediate continue}
01455 }
01456 
01457 # ------------------------------------------------------------------
01458 #  PROC: gdbtk_stepi
01459 # ------------------------------------------------------------------
01460 proc gdbtk_stepi {} {
01461   catch {gdb_immediate stepi}
01462 }
01463 
01464 # ------------------------------------------------------------------
01465 #  PROC: gdbtk_nexti
01466 # ------------------------------------------------------------------
01467 proc gdbtk_nexti {} {
01468   catch {gdb_immediate nexti}
01469 }
01470 
01471 # ------------------------------------------------------------------
01472 #  PROC: gdbtk_attached
01473 # ------------------------------------------------------------------
01474 #
01475 # This is called AFTER gdb has successfully done an attach.  Use it to 
01476 # bring the GUI up to a current state...
01477 proc gdbtk_attached {} {
01478   gdbtk_update
01479 }
01480 
01481 # ------------------------------------------------------------------
01482 #  PROC: gdbtk_detached
01483 # ------------------------------------------------------------------
01484 #
01485 # This is called AFTER gdb has successfully done an detach.  Use it to 
01486 # bring the GUI up to a current state...
01487 proc gdbtk_detached {} {
01488   if {!$::gdb_shutting_down} {
01489     run_hooks gdb_no_inferior_hook
01490   }
01491 }
01492 
01493 # ------------------------------------------------------------------
01494 #  PROC: gdbtk_stop
01495 # ------------------------------------------------------------------
01496 #
01497 # The stop button is tricky. In order to use the stop button,
01498 # the debugger must be able to keep gui alive while target_wait is
01499 # blocking (so that the user can interrupt or detach from it).
01500 # 
01501 # The best solution for this is to capture gdb deep down where it can
01502 # block. For _any_ target board, this will be in either serial or
01503 # socket code. These places call deprecated_ui_loop_hook to keep us
01504 # alive. For native unix, we use an interval timer.  Simulators either
01505 # call deprecated_ui_loop_hook directly (older sims, at least) or they
01506 # call gdb's os_poll_quit callback, where we insert a call to
01507 # deprecated_ui_loop_hook. Some targets (like v850ice and windows
01508 # native) require a call to deprecated_ui_loop_hook directly in
01509 # target_wait. See comments before gdb_stop and x_event to find out
01510 # more about how this is accomplished.
01511 #
01512 # The stop button's behavior:
01513 # Pressing the stop button should attempt to stop the target. If, after
01514 # some time (like 3 seconds), gdb fails to fall out of target_wait (i.e.,
01515 # the gui's idle hooks are run), then open a dialog asking the user if
01516 # he'd like to detach.
01517 proc gdbtk_stop {} {
01518   global _gdbtk_stop
01519 
01520   if {$_gdbtk_stop(timer) == ""} {
01521     add_hook gdb_idle_hook gdbtk_stop_idle_callback
01522     set _gdbtk_stop(timer) [after 15000 gdbtk_detach]
01523     catch {gdb_stop}
01524   }
01525 }
01526 
01527 # ------------------------------------------------------------------
01528 #  PROC: gdbtk_stop_idle_callback
01529 # ------------------------------------------------------------------
01530 # This callback normally does nothing. When the stop button has
01531 # been pressed, though, and gdb has successfully stopped the target,
01532 # this callback will clean up after gdbtk_stop, removing the "Detach"
01533 # dialog (if it's open) and gettingg rid of any outstanding timers
01534 # and hooks.
01535 proc gdbtk_stop_idle_callback {} {
01536   global _gdbtk_stop gdbtk_state
01537 
01538   # Check if the dialog asking if user wants to detach is open
01539   # and unpost it if it exists.
01540   if {$_gdbtk_stop(msg) != ""} {
01541     set ans [list answer $_gdbtk_stop(msg)]
01542     set gdbtk_state($ans) no
01543   }
01544 
01545   if {$_gdbtk_stop(timer) != ""} {
01546     # Cancel the timer callback
01547     after cancel $_gdbtk_stop(timer)
01548     set _gdbtk_stop(timer) ""
01549     catch {remove_hook gdb_idle_hook gdbtk_stop_idle_callback}
01550   }
01551 }
01552 
01553 # ------------------------------------------------------------------
01554 #  PROC: gdbtk_detach
01555 # ------------------------------------------------------------------
01556 # This proc is installed as a timer event when the stop button
01557 # is pressed. If target_wait doesn't return (we were unable to stop
01558 # the target), then this proc is called.
01559 #
01560 # Open a dialog box asking if the user would like to detach. If so,
01561 # try to detach. If not, do nothing and go away.
01562 proc gdbtk_detach {} {
01563   global _gdbtk_stop
01564 
01565   set _gdbtk_stop(msg) "No response from target. Detach from target\n(and stop debugging it)?"
01566   if {[gdbtk_tcl_query  $_gdbtk_stop(msg) no]} {
01567     catch {gdb_stop detach}
01568   }
01569 
01570   set _gdbtk_stop(timer) ""
01571   set _gdbtk_stop(msg) ""
01572   remove_hook gdb_idle_hook gdbtk_stop_idle_callback
01573 }
01574 
01575 # ------------------------------------------------------------------
01576 #  PROC: gdbtk_run
01577 # ------------------------------------------------------------------
01578 proc gdbtk_run {} {
01579   if {$::gdb_running == 1} {
01580     set msg "A program is currently being debugged.\n"
01581     append msg "Do you want to restart?"
01582     if {![gdbtk_tcl_query $msg no]} {
01583       # NO
01584       return
01585     }
01586   }
01587   run_executable
01588 }
01589 
01590 # ------------------------------------------------------------------
01591 # PROC:  gdbtk_attach_native: attach to a running target
01592 # ------------------------------------------------------------------
01593 proc gdbtk_attach_native {} {
01594     ManagedWin::open_dlg AttachDlg ;#-transient
01595 
01596     debug "ManagedWin got [AttachDlg::last_button] [AttachDlg::pid]"
01597 
01598     if {[AttachDlg::last_button]} {
01599   set pid [AttachDlg::pid]
01600   set symbol_file [AttachDlg::symbol_file]
01601   if {$symbol_file != "" && ![_open_file $symbol_file]} {
01602       ManagedWin::open WarningDlg -transient \
01603               -message "Could not load symbols from $symbol_file."
01604       return
01605   }
01606   
01607   if {[catch {gdb_cmd "attach $pid"} result]} {
01608       ManagedWin::open WarningDlg -transient \
01609               -message [list "Could not attach to $pid:\n$result"]
01610       return
01611   }
01612     }
01613 }
01614 
01615 # ------------------------------------------------------------------
01616 # PROC: set_baud -  Tell GDB the baud rate.
01617 # ------------------------------------------------------------------
01618 proc set_baud {} {
01619   global gdb_target_name
01620   #set target [ide_property get target-internal-name]
01621   set baud [pref getd gdb/load/${gdb_target_name}-baud]
01622   if {$baud == ""} {
01623     set baud [pref get gdb/load/baud]
01624   }
01625 #  debug "setting baud to $baud"
01626   catch {gdb_cmd "set remotebaud $baud"}
01627 }
01628 
01629 # ------------------------------------------------------------------
01630 # PROC: do_state_hook -
01631 # ------------------------------------------------------------------
01632 proc do_state_hook {varname ind op} {
01633   run_hooks state_hook $varname
01634 }
01635 
01636 # ------------------------------------------------------------------
01637 # PROC: gdbtk_disconnect -
01638 # ------------------------------------------------------------------
01639 proc gdbtk_disconnect {{async 0}} {
01640    global gdb_loaded gdb_target_changed
01641    catch {gdb_cmd "detach"}
01642    # force a new target command to do something
01643    set gdb_loaded 0
01644    set gdb_target_changed 1
01645    set gdb_running 0
01646    gdbtk_idle
01647    gdbtk_update
01648  }
01649 
01650 # ------------------------------------------------------------------
01651 # PROC: tstart -
01652 # ------------------------------------------------------------------
01653 proc tstart {} {
01654    if {[catch {gdb_cmd "tstart"} errTxt]} {
01655      tk_messageBox -title "Error" -message $errTxt -icon error \
01656        -type ok
01657     gdbtk_idle
01658      return 0
01659    }
01660   return 1
01661 }
01662 
01663 # ------------------------------------------------------------------
01664 # PROC: tstop -
01665 # ------------------------------------------------------------------
01666 proc tstop {} {
01667 
01668    if {[catch {gdb_cmd "tstop"} errTxt]} {
01669      tk_messageBox -title "Error" -message $errTxt -icon error \
01670        -type ok
01671      gdbtk_idle
01672      return 0
01673    }
01674    return 1
01675  }
01676 
01677 # ------------------------------------------------------------------
01678 # PROC: source_file -
01679 # ------------------------------------------------------------------
01680 proc source_file {} {
01681   set file_name [tk_getOpenFile -title "Choose GDB Command file"]
01682   if {$file_name != ""} {
01683     gdb_cmd "source $file_name"
01684   }
01685 }
01686 
01687 
01688 # -----------------------------------------------------------------------------
01689 # NAME:           gdbtk_signal
01690 #
01691 # SYNOPSIS:       gdbtk_signal {name longname}
01692 #
01693 # DESC:           This procedure is called from GDB when a signal 
01694 #         is generated, for example, a SIGSEGV.
01695 #
01696 # ARGS:           name - The name of the signal, as returned by
01697 #                 target_signal_to_name().
01698 #         longname - A description of the signal.
01699 # -----------------------------------------------------------------------------
01700 proc gdbtk_signal {name {longname ""}} {
01701   dbug W "caught signal $name $longname"
01702   set longname
01703   set message "Program received signal $name, $longname"
01704   set srcs [ManagedWin::find SrcWin]
01705   foreach w $srcs {
01706     $w set_status $message
01707   }
01708   gdbtk_tcl_ignorable_warning signal $message
01709   update idletasks
01710 }
01711 
01712 # Hook for clearing out executable state. Widgets should register a callback
01713 # for this hook if they have anything that may need cleaning if the user
01714 # requests to re-load an executable.
01715 define_hook gdb_clear_file_hook
01716 
01717 # -----------------------------------------------------------------------------
01718 # NAME:       gdbtk_clear_file
01719 #
01720 # SYNOPSIS:   gdbtk_clear_file
01721 #
01722 # DESC:       This procedure is called when the user requests a new exec
01723 #             file load. It runs the gdb_clear_file_hook, which tells
01724 #             all widgets to clear state. It CANNOT call gdb_clear_file,
01725 #             since this hook runs AFTER we load a new exec file (i.e.,
01726 #             gdb_clear_file would clear the file name).
01727 #
01728 # ARGS:       none
01729 # -----------------------------------------------------------------------------
01730 proc gdbtk_clear_file {} {
01731   global gdb_target_name
01732 
01733   debug
01734   # Give widgets a chance to clean up
01735   catch {run_hooks gdb_clear_file_hook}
01736 
01737   # Save the target name in case the user has already selected a
01738   # target. No need to force the user to select it again.
01739   set old_target $gdb_target_name
01740 
01741   # Finally, reset our state
01742   initialize_gdbtk
01743 
01744   set gdb_target_name $old_target
01745 }
01746 
01747 # ------------------------------------------------------------------
01748 #  PROC: intialize_gdbtk - (re)initialize gdbtk's state
01749 # ------------------------------------------------------------------
01750 proc initialize_gdbtk {} {
01751   global gdb_exe_changed gdb_target_changed gdb_running gdb_downloading \
01752     gdb_loaded gdb_program_has_run file_done gdb_pretty_name gdb_exec \
01753     gdb_target_cmd download_dialog gdb_pretty_name gdb_exe_name _gdbtk_stop \
01754     gdb_target_name gdb_target_changed gdbtk_state gdb_kod_cmd gdb_shutting_down
01755 
01756   # initialize state variables
01757   set gdb_exe_changed 0
01758   set gdb_target_changed 0
01759   set gdb_running 0
01760   set gdb_downloading 0
01761   set gdb_loaded 0
01762   set gdb_program_has_run 0
01763   set file_done 0
01764   set gdb_pretty_name {}
01765   set gdb_exec {}
01766   set gdb_target_cmd ""
01767   set gdb_running 0
01768   set gdb_shutting_down 0
01769 
01770   set download_dialog ""
01771 
01772   # gdb_pretty_name is the name of the GDB target as it should be
01773   # displayed to the user.
01774   set gdb_pretty_name ""
01775 
01776   # gdb_exe_name is the name of the executable we are debugging.  
01777   set gdb_exe_name ""
01778 
01779   # Initialize readline
01780   if {![info exists gdbtk_state(readline)]} {
01781     # Only do this once...
01782     set gdbtk_state(readline) 0
01783     set gdbtk_state(console) ""
01784     set gdbtk_state(readlineShowUser) 1
01785   }
01786 
01787   # flush cache for gdbtk_locate_main
01788   gdbtk_locate_main 1
01789 
01790   # check for existence of a kod command and get it's name and
01791   # text for menu entry
01792   set gdb_kod_cmd ""
01793   set msg ""
01794   if {![catch {gdb_cmd "show os"} msg] && ($msg != "")} {
01795     set line1 [string range $msg 0 [expr [string first \n $msg] -1]]
01796     if {[regexp -- \"(.*)\" $line1 dummy cmd]} {
01797       set gdb_kod_cmd $cmd
01798     }
01799   }
01800 #  debug "kod_cmd=$gdb_kod_cmd"
01801 
01802   # setup stop button
01803   set _gdbtk_stop(timer) ""
01804   set _gdbtk_stop(msg) ""
01805 
01806   # gdb_target_name is the name of the GDB target; that is, the argument
01807   # to the GDB target command.
01808   set gdb_target_name ""
01809 
01810   # By setting gdb_target_changed, we force a target dialog
01811   # to be displayed on the first "run"
01812   set gdb_target_changed 1
01813 }
01814 
01815 # The architecture changed. Inform the UI.
01816 proc gdbtk_tcl_architecture_changed {} {
01817   set e [ArchChangedEvent \#auto]
01818   # First perform global actions as a result of the architecture change.
01819   gdb_reg_arch_changed $e 
01820   # Now dispatch to all the other event handlers.
01821   GDBEventHandler::dispatch $e
01822   delete object $e
01823 }
01824 
01825 proc gdbtk_console_read {} {
01826   if {$::gdbtk_state(console) == ""} {
01827     ManagedWin::open Console -force
01828   } else {
01829     raise [namespace tail $::gdbtk_state(console)]
01830   }
01831   set result [$::gdbtk_state(console) gets]
01832   debug "result=$result"
01833   return $result
01834 }
01835 
01836 # This is based on TIP 171 to enable better default behavior
01837 # with the MouseWheel event. I don't know why this is not in 
01838 # Tk yet (at least 8.5), but this allows all of our windows to
01839 # scroll without having to do anything.
01840 proc ::tk::MouseWheel {wFired X Y D {shifted 0}} {
01841     # Set event to check based on call
01842     set evt "<[expr {$shifted?{Shift-}:{}}]MouseWheel>"
01843     # do not double-fire in case the class already has a binding
01844     if {[bind [winfo class $wFired] $evt] ne ""} { return }
01845     # obtain the window the mouse is over
01846     set w [winfo containing $X $Y]
01847     # if we are outside the app, try and scroll the focus widget
01848     if {![winfo exists $w]} { catch {set w [focus]} }
01849     if {[winfo exists $w]} {
01850   if {[bind $w $evt] ne ""} {
01851       # Awkward ... this widget has a MouseWheel binding, but to
01852       # trigger successfully in it, we must give it focus.
01853       catch {focus} old
01854       if {$w ne $old} { focus $w }
01855       event generate $w $evt -rootx $X -rooty $Y -delta $D
01856       if {$w ne $old} { focus $old }
01857       return
01858   }
01859   # aqua and x11/win32 have different delta handling
01860   if {[tk windowingsystem] ne "aqua"} {
01861       set delta [expr {- ($D / 30)}]
01862   } else {
01863       set delta [expr {- ($D)}]
01864   }
01865   # scrollbars have different call conventions
01866   if {[string match "*Scrollbar" [winfo class $w]]} {
01867       catch {tk::ScrollByUnits $w \
01868                  [string index [$w cget -orient] 0] $delta}
01869   } else {
01870       # Walking up to find the proper widget handles cases like
01871       # embedded widgets in a canvas
01872 
01873       # 20091008-keiths: This cannot possibly work the way it
01874       # was written in the TIP, so I've rewritten it to work the
01875       # way the comments say it should.
01876       set cmd [list "%W" [expr {$shifted ? "xview" : "yview"}] \
01877                    scroll $delta units]
01878       while {[catch [regsub "%W" $cmd $w]] && [winfo toplevel $w] ne $w} {
01879           set w [winfo parent $w]
01880       }
01881   }
01882     }
01883 }
01884 
01885 bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0]
01886 bind all <Shift-MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 1]
01887 if {[tk windowingsystem] eq "x11"} {
01888     # Support for mousewheels on Linux/Unix commonly comes through
01889     # mapping the wheel to the extended buttons.
01890     bind all <4> [list ::tk::MouseWheel %W %X %Y 120]
01891     bind all <5> [list ::tk::MouseWheel %W %X %Y -120]
01892 }
01893 
01894 set mw_classes [list Text Listbox Table TreeCtrl]
01895 foreach class $mw_classes { bind $class <MouseWheel> {} }
01896 if {[tk windowingsystem] eq "x11"} {
01897     foreach class $mw_classes {
01898    bind $class <4> {}
01899    bind $class <5> {}
01900     }
01901 }
01902 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines