]> Git Repo - binutils.git/blob - gdb/gdbtk.tcl
* exec.c: Merge in RS6000 support from xcoffexec.c.
[binutils.git] / gdb / gdbtk.tcl
1 # GDB GUI setup
2
3 set cfile Blank
4 set wins($cfile) .text
5 set current_label {}
6 set screen_height 0
7 set screen_top 0
8 set screen_bot 0
9 set current_output_win .command.text
10 set cfunc NIL
11
12 proc test {} {
13         update_listing {termcap.c foo /etc/termcap 200}
14 }
15
16 proc echo string {puts stdout $string}
17
18 if [info exists env(EDITOR)] then {
19         set editor $env(EDITOR)
20         } else {
21         set editor emacs
22 }
23
24 # GDB callbacks
25 #
26 #  These functions are called by GDB (from C code) to do various things in
27 #  TK-land.  All start with the prefix `gdbtk_tcl_' to make them easy to find.
28 #
29
30 #
31 # GDB Callback:
32 #
33 #       gdbtk_tcl_fputs (text) - Output text to the command window
34 #
35 # Description:
36 #
37 #       GDB calls this to output TEXT to the GDB command window.  The text is
38 #       placed at the end of the text widget.  Note that output may not occur,
39 #       due to buffering.  Use gdbtk_tcl_flush to cause an immediate update.
40 #
41
42 proc gdbtk_tcl_fputs {arg} {
43         global current_output_win
44
45         $current_output_win insert end "$arg"
46         $current_output_win yview -pickplace end
47 }
48
49 #
50 # GDB Callback:
51 #
52 #       gdbtk_tcl_flush () - Flush output to the command window
53 #
54 # Description:
55 #
56 #       GDB calls this to force all buffered text to the GDB command window.
57 #
58
59 proc gdbtk_tcl_flush {} {
60         $current_output_win yview -pickplace end
61         update idletasks
62 }
63
64 #
65 # GDB Callback:
66 #
67 #       gdbtk_tcl_query (message) - Create a yes/no query dialog box
68 #
69 # Description:
70 #
71 #       GDB calls this to create a yes/no dialog box containing MESSAGE.  GDB
72 #       is hung while the dialog box is active (ie: no commands will work),
73 #       however windows can still be refreshed in case of damage or exposure.
74 #
75
76 proc gdbtk_tcl_query {message} {
77         tk_dialog .query "gdb : query" "$message" {} 1 "No" "Yes"
78         }
79
80 #
81 # GDB Callback:
82 #
83 #       gdbtk_start_variable_annotation (args ...) - 
84 #
85 # Description:
86 #
87 #       Not yet implemented.
88 #
89
90 proc gdbtk_tcl_start_variable_annotation {valaddr ref_type stor_cl cum_expr field type_cast} {
91         echo "gdbtk_tcl_start_variable_annotation $valaddr $ref_type $stor_cl $cum_expr $field $type_cast"
92 }
93
94 #
95 # GDB Callback:
96 #
97 #       gdbtk_end_variable_annotation (args ...) - 
98 #
99 # Description:
100 #
101 #       Not yet implemented.
102 #
103
104 proc gdbtk_tcl_end_variable_annotation {} {
105         echo gdbtk_tcl_end_variable_annotation
106 }
107
108 #
109 # GDB Callback:
110 #
111 #       gdbtk_tcl_breakpoint (action bpnum file line) - Notify the TK
112 #       interface of changes to breakpoints.
113 #
114 # Description:
115 #
116 #       GDB calls this to notify TK of changes to breakpoints.  ACTION is one
117 #       of:
118 #               create          - Notify of breakpoint creation
119 #               delete          - Notify of breakpoint deletion
120 #               enable          - Notify of breakpoint enabling
121 #               disable         - Notify of breakpoint disabling
122 #
123 #       All actions take the same set of arguments:  BPNUM is the breakpoint
124 #       number,  FILE is the source file and LINE is the line number, and PC is
125 #       the pc of the affected breakpoint.
126 #
127
128 proc gdbtk_tcl_breakpoint {action bpnum file line pc} {
129         ${action}_breakpoint $bpnum $file $line $pc
130 }
131
132 proc asm_win_name {funcname} {
133         regsub -all {\.} $funcname _ temp
134
135         return .asm.func_${temp}
136 }
137
138 #
139 # Local procedure:
140 #
141 #       create_breakpoint (bpnum file line pc) - Record breakpoint info in TK land
142 #
143 # Description:
144 #
145 #       GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
146 #       land of breakpoint creation.  This consists of recording the file and
147 #       line number in the breakpoint_file and breakpoint_line arrays.  Also,
148 #       if there is already a window associated with FILE, it is updated with
149 #       a breakpoint tag.
150 #
151
152 proc create_breakpoint {bpnum file line pc} {
153         global wins
154         global breakpoint_file
155         global breakpoint_line
156         global pos_to_breakpoint
157         global pos_to_bpcount
158         global cfunc
159         global pclist
160
161 # Record breakpoint locations
162
163         set breakpoint_file($bpnum) $file
164         set breakpoint_line($bpnum) $line
165         set pos_to_breakpoint($file:$line) $bpnum
166         if ![info exists pos_to_bpcount($file:$line)] {
167                 set pos_to_bpcount($file:$line) 0
168         }
169         incr pos_to_bpcount($file:$line)
170         set pos_to_breakpoint($pc) $bpnum
171         if ![info exists pos_to_bpcount($pc)] {
172                 set pos_to_bpcount($pc) 0
173         }
174         incr pos_to_bpcount($pc)
175         
176 # If there's a window for this file, update it
177
178         if [info exists wins($file)] {
179                 insert_breakpoint_tag $wins($file) $line
180         }
181
182 # If there's an assembly window, update that too
183
184         set win [asm_win_name $cfunc]
185         if [winfo exists $win] {
186                 insert_breakpoint_tag $win [pc_to_line $pclist($cfunc) $pc]
187         }
188 }
189
190 #
191 # Local procedure:
192 #
193 #       delete_breakpoint (bpnum file line pc) - Delete breakpoint info from TK land
194 #
195 # Description:
196 #
197 #       GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
198 #       land of breakpoint destruction.  This consists of removing the file and
199 #       line number from the breakpoint_file and breakpoint_line arrays.  Also,
200 #       if there is already a window associated with FILE, the tags are removed
201 #       from it.
202 #
203
204 proc delete_breakpoint {bpnum file line pc} {
205         global wins
206         global breakpoint_file
207         global breakpoint_line
208         global pos_to_breakpoint
209         global pos_to_bpcount
210         global cfunc pclist
211
212 # Save line number and file for later
213
214         set line $breakpoint_line($bpnum)
215
216         set file $breakpoint_file($bpnum)
217
218 # Reset breakpoint annotation info
219
220         if {$pos_to_bpcount($file:$line) > 0} {
221                 decr pos_to_bpcount($file:$line)
222
223                 if {$pos_to_bpcount($file:$line) == 0} {
224                         catch "unset pos_to_breakpoint($file:$line)"
225
226                         unset breakpoint_file($bpnum)
227                         unset breakpoint_line($bpnum)
228
229 # If there's a window for this file, update it
230
231                         if [info exists wins($file)] {
232                                 delete_breakpoint_tag $wins($file) $line
233                         }
234                 }
235         }
236
237 # If there's an assembly window, update that too
238
239         if {$pos_to_bpcount($pc) > 0} {
240                 decr pos_to_bpcount($pc)
241
242                 if {$pos_to_bpcount($pc) == 0} {
243                         catch "unset pos_to_breakpoint($pc)"
244
245                         set win [asm_win_name $cfunc]
246                         if [winfo exists $win] {
247                                 delete_breakpoint_tag $win [pc_to_line $pclist($cfunc) $pc]
248                         }
249                 }
250         }
251 }
252
253 #
254 # Local procedure:
255 #
256 #       enable_breakpoint (bpnum file line pc) - Record breakpoint info in TK land
257 #
258 # Description:
259 #
260 #       GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
261 #       land of a breakpoint being enabled.  This consists of unstippling the
262 #       specified breakpoint indicator.
263 #
264
265 proc enable_breakpoint {bpnum file line pc} {
266         global wins
267         global cfunc pclist
268
269         if [info exists wins($file)] {
270                 $wins($file) tag configure $line -fgstipple {}
271         }
272
273 # If there's an assembly window, update that too
274
275         set win [asm_win_name $cfunc]
276         if [winfo exists $win] {
277                 $win tag configure [pc_to_line $pclist($cfunc) $pc] -fgstipple {}
278         }
279 }
280
281 #
282 # Local procedure:
283 #
284 #       disable_breakpoint (bpnum file line pc) - Record breakpoint info in TK land
285 #
286 # Description:
287 #
288 #       GDB calls this indirectly (through gdbtk_tcl_breakpoint) to notify TK
289 #       land of a breakpoint being disabled.  This consists of stippling the
290 #       specified breakpoint indicator.
291 #
292
293 proc disable_breakpoint {bpnum file line pc} {
294         global wins
295         global cfunc pclist
296
297         if [info exists wins($file)] {
298                 $wins($file) tag configure $line -fgstipple gray50
299         }
300
301 # If there's an assembly window, update that too
302
303         set win [asm_win_name $cfunc]
304         if [winfo exists $win] {
305                 $win tag configure [pc_to_line $pclist($cfunc) $pc] -fgstipple gray50
306         }
307 }
308
309 #
310 # Local procedure:
311 #
312 #       insert_breakpoint_tag (win line) - Insert a breakpoint tag in WIN.
313 #
314 # Description:
315 #
316 #       GDB calls this indirectly (through gdbtk_tcl_breakpoint) to insert a
317 #       breakpoint tag into window WIN at line LINE.
318 #
319
320 proc insert_breakpoint_tag {win line} {
321         $win configure -state normal
322         $win delete $line.0
323         $win insert $line.0 "B"
324         $win tag add $line $line.0
325
326         $win configure -state disabled
327 }
328
329 #
330 # Local procedure:
331 #
332 #       delete_breakpoint_tag (win line) - Remove a breakpoint tag from WIN.
333 #
334 # Description:
335 #
336 #       GDB calls this indirectly (through gdbtk_tcl_breakpoint) to remove a
337 #       breakpoint tag from window WIN at line LINE.
338 #
339
340 proc delete_breakpoint_tag {win line} {
341         $win configure -state normal
342         $win delete $line.0
343         $win insert $line.0 " "
344         $win tag delete $line
345         $win configure -state disabled
346 }
347
348 #
349 # Local procedure:
350 #
351 #       decr (var val) - compliment to incr
352 #
353 # Description:
354 #
355 #
356 proc decr {var {val 1}} {
357         upvar $var num
358         set num [expr $num - $val]
359         return $num
360 }
361
362 #
363 # Local procedure:
364 #
365 #       pc_to_line (pclist pc) - convert PC to a line number.
366 #
367 # Description:
368 #
369 #       Convert PC to a line number from PCLIST.  If exact line isn't found,
370 #       we return the first line that starts before PC.
371 #
372 proc pc_to_line {pclist pc} {
373         set line [lsearch -exact $pclist $pc]
374
375         if {$line >= 1} { return $line }
376
377         set line 1
378         foreach linepc [lrange $pclist 1 end] {
379                 if {$pc < $linepc} { decr line ; return $line }
380                 incr line
381         }
382         return [expr $line - 1]
383 }
384
385 #
386 # Menu:
387 #
388 #       file popup menu - Define the file popup menu.
389 #
390 # Description:
391 #
392 #       This menu just contains a bunch of buttons that do various things to
393 #       the line under the cursor.
394 #
395 # Items:
396 #
397 #       Edit - Run the editor (specified by the environment variable EDITOR) on
398 #              this file, at the current line.
399 #       Breakpoint - Set a breakpoint at the current line.  This just shoves
400 #               a `break' command at GDB with the appropriate file and line
401 #               number.  Eventually, GDB calls us back (at gdbtk_tcl_breakpoint)
402 #               to notify us of where the breakpoint needs to show up.
403 #
404
405 menu .file_popup -cursor hand2
406 .file_popup add command -label "Not yet set" -state disabled
407 .file_popup add separator
408 .file_popup add command -label "Edit" -command {exec $editor +$selected_line $selected_file &}
409 .file_popup add command -label "Set breakpoint" -command {gdb_cmd "break $selected_file:$selected_line"}
410
411 #
412 # Bindings:
413 #
414 #       file popup menu - Define the file popup menu bindings.
415 #
416 # Description:
417 #
418 #       This defines the binding for the file popup menu.  Currently, there is
419 #       only one, which is activated when Button-1 is released.  This causes
420 #       the menu to be unposted, releases the grab for the menu, and then
421 #       unhighlights the line under the cursor.  After that, the selected menu
422 #       item is invoked.
423 #
424
425 bind .file_popup <Any-ButtonRelease-1> {
426         global selected_win
427
428 # First, remove the menu, and release the pointer
429
430         .file_popup unpost
431         grab release .file_popup
432
433 # Unhighlight the selected line
434
435         $selected_win tag delete breaktag
436
437 # Actually invoke the menubutton here!
438
439         tk_invokeMenu %W
440 }
441
442 #
443 # Local procedure:
444 #
445 #       file_popup_menu (win x y xrel yrel) - Popup the file popup menu.
446 #
447 # Description:
448 #
449 #       This procedure is invoked as a result of a command binding in the
450 #       listing window.  It does several things:
451 #               o - It highlights the line under the cursor.
452 #               o - It pops up the file popup menu which is intended to do
453 #                   various things to the aforementioned line.
454 #               o - Grabs the mouse for the file popup menu.
455 #
456
457 # Button 1 has been pressed in a listing window.  Pop up a menu.
458
459 proc file_popup_menu {win x y xrel yrel} {
460         global wins
461         global win_to_file
462         global file_to_debug_file
463         global highlight
464         global selected_line
465         global selected_file
466         global selected_win
467
468 # Map TK window name back to file name.
469
470         set file $win_to_file($win)
471
472         set pos [$win index @$xrel,$yrel]
473
474 # Record selected file and line for menu button actions
475
476         set selected_file $file_to_debug_file($file)
477         set selected_line [lindex [split $pos .] 0]
478         set selected_win $win
479
480 # Highlight the selected line
481
482         eval $win tag config breaktag $highlight
483         $win tag add breaktag "$pos linestart" "$pos linestart + 1l"
484
485 # Post the menu near the pointer, (and grab it)
486
487         .file_popup entryconfigure 0 -label "$selected_file:$selected_line"
488         .file_popup post [expr $x-[winfo width .file_popup]/2] [expr $y-10]
489         grab .file_popup
490 }
491
492 #
493 # Local procedure:
494 #
495 #       listing_window_button_1 (win x y xrel yrel) - Handle button 1 in listing window
496 #
497 # Description:
498 #
499 #       This procedure is invoked as a result of holding down button 1 in the
500 #       listing window.  The action taken depends upon where the button was
501 #       pressed.  If it was in the left margin (the breakpoint column), it
502 #       sets or clears a breakpoint.  In the main text area, it will pop up a
503 #       menu.
504 #
505
506 proc listing_window_button_1 {win x y xrel yrel} {
507         global wins
508         global win_to_file
509         global file_to_debug_file
510         global highlight
511         global selected_line
512         global selected_file
513         global selected_win
514         global pos_to_breakpoint
515
516 # Map TK window name back to file name.
517
518         set file $win_to_file($win)
519
520         set pos [split [$win index @$xrel,$yrel] .]
521
522 # Record selected file and line for menu button actions
523
524         set selected_file $file_to_debug_file($file)
525         set selected_line [lindex $pos 0]
526         set selected_col [lindex $pos 1]
527         set selected_win $win
528
529 # If we're in the margin, then toggle the breakpoint
530
531         if {$selected_col < 8} {
532                 set pos_break $selected_file:$selected_line
533                 set pos $file:$selected_line
534                 set tmp pos_to_breakpoint($pos)
535                 if [info exists $tmp] {
536                         set bpnum [set $tmp]
537                         gdb_cmd "delete $bpnum"
538                 } else {
539                         gdb_cmd "break $pos_break"
540                 }
541                 return
542         }
543
544 # Post the menu near the pointer, (and grab it)
545
546         .file_popup entryconfigure 0 -label "$selected_file:$selected_line"
547         .file_popup post [expr $x-[winfo width .file_popup]/2] [expr $y-10]
548         grab .file_popup
549 }
550
551 #
552 # Local procedure:
553 #
554 #       asm_window_button_1 (win x y xrel yrel) - Handle button 1 in asm window
555 #
556 # Description:
557 #
558 #       This procedure is invoked as a result of holding down button 1 in the
559 #       assembly window.  The action taken depends upon where the button was
560 #       pressed.  If it was in the left margin (the breakpoint column), it
561 #       sets or clears a breakpoint.  In the main text area, it will pop up a
562 #       menu.
563 #
564
565 proc asm_window_button_1 {win x y xrel yrel} {
566         global wins
567         global win_to_file
568         global file_to_debug_file
569         global highlight
570         global selected_line
571         global selected_file
572         global selected_win
573         global pos_to_breakpoint
574         global pclist
575         global cfunc
576
577         set pos [split [$win index @$xrel,$yrel] .]
578
579 # Record selected file and line for menu button actions
580
581         set selected_line [lindex $pos 0]
582         set selected_col [lindex $pos 1]
583         set selected_win $win
584
585 # Figure out the PC
586
587         set pc [lindex $pclist($cfunc) $selected_line]
588
589 # If we're in the margin, then toggle the breakpoint
590
591         if {$selected_col < 8} {
592                 set tmp pos_to_breakpoint($pc)
593                 if [info exists $tmp] {
594                         set bpnum [set $tmp]
595                         gdb_cmd "delete $bpnum"
596                 } else {
597                         gdb_cmd "break *$pc"
598                 }
599                 return
600         }
601
602 # Post the menu near the pointer, (and grab it)
603
604 #       .file_popup entryconfigure 0 -label "$selected_file:$selected_line"
605 #       .file_popup post [expr $x-[winfo width .file_popup]/2] [expr $y-10]
606 #       grab .file_popup
607 }
608
609 #
610 # Local procedure:
611 #
612 #       do_nothing - Does absoultely nothing.
613 #
614 # Description:
615 #
616 #       This procedure does nothing.  It is used as a placeholder to allow
617 #       the disabling of bindings that would normally be inherited from the
618 #       parent widget.  I can't think of any other way to do this.
619 #
620
621 proc do_nothing {} {}
622
623 #
624 # Local procedure:
625 #
626 #       create_file_win (filename) - Create a win for FILENAME.
627 #
628 # Return value:
629 #
630 #       The new text widget.
631 #
632 # Description:
633 #
634 #       This procedure creates a text widget for FILENAME.  It returns the
635 #       newly created widget.  First, a text widget is created, and given basic
636 #       configuration info.  Second, all the bindings are setup.  Third, the
637 #       file FILENAME is read into the text widget.  Fourth, margins and line
638 #       numbers are added.
639 #
640
641 proc create_file_win {filename} {
642         global breakpoint_file
643         global breakpoint_line
644
645 # Replace all the dirty characters in $filename with clean ones, and generate
646 # a unique name for the text widget.
647
648         regsub -all {\.|/} $filename {} temp
649         set win .text$temp
650
651 # Open the file, and read it into the text widget
652
653         if [catch "open $filename" fh] {
654 # File can't be read.  Put error message into .nofile window and return.
655
656                 catch {destroy .nofile}
657                 text .nofile -height 25 -width 80 -relief raised -borderwidth 2 -yscrollcommand textscrollproc -setgrid true -cursor hand2
658                 .nofile insert 0.0 $fh
659                 .nofile configure -state disabled
660                 bind .nofile <1> do_nothing
661                 bind .nofile <B1-Motion> do_nothing
662                 return .nofile
663         }
664
665 # Actually create and do basic configuration on the text widget.
666
667         text $win -height 25 -width 80 -relief raised -borderwidth 2 -yscrollcommand textscrollproc -setgrid true -cursor hand2
668
669 # Setup all the bindings
670
671         bind $win <Enter> {focus %W}
672         bind $win <1> {listing_window_button_1 %W %X %Y %x %y}
673         bind $win <B1-Motion> do_nothing
674         bind $win n {gdb_cmd next ; update_ptr}
675         bind $win s {gdb_cmd step ; update_ptr}
676         bind $win c {gdb_cmd continue ; update_ptr}
677         bind $win f {gdb_cmd finish ; update_ptr}
678         bind $win u {gdb_cmd up ; update_ptr}
679         bind $win d {gdb_cmd down ; update_ptr}
680
681         $win delete 0.0 end
682         $win insert 0.0 [read $fh]
683         close $fh
684
685 # Add margins (for annotations) and a line number to each line
686
687         set numlines [$win index end]
688         set numlines [lindex [split $numlines .] 0]
689         for {set i 1} {$i <= $numlines} {incr i} {
690                 $win insert $i.0 [format "   %4d " $i]
691                 }
692
693 # Scan though the breakpoint data base and install any destined for this file
694
695         foreach bpnum [array names breakpoint_file] {
696                 if {$breakpoint_file($bpnum) == $filename} {
697                         insert_breakpoint_tag $win $breakpoint_line($bpnum)
698                         }
699                 }
700
701 # Disable the text widget to prevent user modifications
702
703         $win configure -state disabled
704         return $win
705 }
706
707 #
708 # Local procedure:
709 #
710 #       create_asm_win (funcname pc) - Create an assembly win for FUNCNAME.
711 #
712 # Return value:
713 #
714 #       The new text widget.
715 #
716 # Description:
717 #
718 #       This procedure creates a text widget for FUNCNAME.  It returns the
719 #       newly created widget.  First, a text widget is created, and given basic
720 #       configuration info.  Second, all the bindings are setup.  Third, the
721 #       function FUNCNAME is read into the text widget.
722 #
723
724 proc create_asm_win {funcname pc} {
725         global breakpoint_file
726         global breakpoint_line
727         global current_output_win
728         global pclist
729
730 # Replace all the dirty characters in $filename with clean ones, and generate
731 # a unique name for the text widget.
732
733         set win [asm_win_name $funcname]
734
735 # Actually create and do basic configuration on the text widget.
736
737         text $win -height 25 -width 80 -relief raised -borderwidth 2 \
738                 -setgrid true -cursor hand2 -yscrollcommand asmscrollproc
739
740 # Setup all the bindings
741
742         bind $win <Enter> {focus %W}
743         bind $win <1> {asm_window_button_1 %W %X %Y %x %y}
744         bind $win <B1-Motion> do_nothing
745         bind $win n {gdb_cmd nexti ; update_ptr}
746         bind $win s {gdb_cmd stepi ; update_ptr}
747         bind $win c {gdb_cmd continue ; update_ptr}
748         bind $win f {gdb_cmd finish ; update_ptr}
749         bind $win u {gdb_cmd up ; update_ptr}
750         bind $win d {gdb_cmd down ; update_ptr}
751
752 # Disassemble the code, and read it into the new text widget
753
754         set current_output_win $win
755         gdb_cmd "disassemble $pc"
756         set current_output_win .command.text
757
758         set numlines [$win index end]
759         set numlines [lindex [split $numlines .] 0]
760         decr numlines
761
762 # Delete the first and last lines, cuz these contain useless info
763
764         $win delete 1.0 2.0
765         $win delete {end - 1 lines} end
766         decr numlines 2
767
768 # Add margins (for annotations) and note the PC for each line
769
770         catch "unset pclist($funcname)"
771         lappend pclist($funcname) Unused
772         for {set i 1} {$i <= $numlines} {incr i} {
773                 scan [$win get $i.0 "$i.0 lineend"] "%s " pc
774                 lappend pclist($funcname) $pc
775                 $win insert $i.0 "    "
776                 }
777
778
779 # Scan though the breakpoint data base and install any destined for this file
780
781 #       foreach bpnum [array names breakpoint_file] {
782 #               if {$breakpoint_file($bpnum) == $filename} {
783 #                       insert_breakpoint_tag $win $breakpoint_line($bpnum)
784 #                       }
785 #               }
786
787 # Disable the text widget to prevent user modifications
788
789         $win configure -state disabled
790         return $win
791 }
792
793 #
794 # Local procedure:
795 #
796 #       asmscrollproc (WINHEIGHT SCREENHEIGHT SCREENTOP SCREENBOT) - Update the
797 #       asm window scrollbar.
798 #
799 # Description:
800 #
801 #       This procedure is called to update the assembler window's scrollbar.
802 #
803
804 proc asmscrollproc {args} {
805         global asm_screen_height asm_screen_top asm_screen_bot
806
807         eval ".asm.scroll set $args"
808         set asm_screen_height [lindex $args 1]
809         set asm_screen_top [lindex $args 2]
810         set asm_screen_bot [lindex $args 3]
811 }
812
813 #
814 # Local procedure:
815 #
816 #       update_listing (linespec) - Update the listing window according to
817 #                                   LINESPEC.
818 #
819 # Description:
820 #
821 #       This procedure is called from various places to update the listing
822 #       window based on LINESPEC.  It is usually invoked with the result of
823 #       gdb_loc.
824 #
825 #       It will move the cursor, and scroll the text widget if necessary.
826 #       Also, it will switch to another text widget if necessary, and update
827 #       the label widget too.
828 #
829 #       LINESPEC is a list of the form:
830 #
831 #       { DEBUG_FILE FUNCNAME FILENAME LINE }, where:
832 #
833 #       DEBUG_FILE - is the abbreviated form of the file name.  This is usually
834 #                    the file name string given to the cc command.  This is
835 #                    primarily needed for breakpoint commands, and when an
836 #                    abbreviated for of the filename is desired.
837 #       FUNCNAME - is the name of the function.
838 #       FILENAME - is the fully qualified (absolute) file name.  It is usually
839 #                  the same as $PWD/$DEBUG_FILE, where PWD is the working dir
840 #                  at the time the cc command was given.  This is used to
841 #                  actually locate the file to be displayed.
842 #       LINE - The line number to be displayed.
843 #
844 #       Usually, this procedure will just move the cursor one line down to the
845 #       next line to be executed.  However, if the cursor moves out of range
846 #       or into another file, it will scroll the text widget so that the line
847 #       of interest is in the middle of the viewable portion of the widget.
848 #
849
850 proc update_listing {linespec} {
851         global pointers
852         global screen_height
853         global screen_top
854         global screen_bot
855         global wins cfile
856         global current_label
857         global win_to_file
858         global file_to_debug_file
859
860 # Rip the linespec apart
861
862         set line [lindex $linespec 3]
863         set filename [lindex $linespec 2]
864         set funcname [lindex $linespec 1]
865         set debug_file [lindex $linespec 0]
866
867 # Sometimes there's no source file for this location
868
869         if {$filename == ""} {set filename Blank}
870
871 # If we want to switch files, we need to unpack the current text widget, and
872 # stick in the new one.
873
874         if {$filename != $cfile} then {
875                 pack forget $wins($cfile)
876                 set cfile $filename
877
878 # Create a text widget for this file if necessary
879
880                 if ![info exists wins($cfile)] then {
881                         set wins($cfile) [create_file_win $cfile]
882                         if {$wins($cfile) != ".nofile"} {
883                                 set win_to_file($wins($cfile)) $cfile
884                                 set file_to_debug_file($cfile) $debug_file
885                                 set pointers($cfile) 1.1
886                                 }
887                         }
888
889 # Pack the text widget into the listing widget, and scroll to the right place
890
891                 pack $wins($cfile) -side left -expand yes -in .listing -fill both -after .label
892                 $wins($cfile) yview [expr $line - $screen_height / 2]
893                 }
894
895 # Update the label widget in case the filename or function name has changed
896
897         if {$current_label != "$filename.$funcname"} then {
898                 set tail [expr [string last / $filename] + 1]
899                 .label configure -text "[string range $filename $tail end] : ${funcname}()"
900                 set current_label $filename.$funcname
901                 }
902
903 # Update the pointer, scrolling the text widget if necessary to keep the
904 # pointer in an acceptable part of the screen.
905
906         if [info exists pointers($cfile)] then {
907                 $wins($cfile) configure -state normal
908                 set pointer_pos $pointers($cfile)
909                 $wins($cfile) configure -state normal
910                 $wins($cfile) delete $pointer_pos
911                 $wins($cfile) insert $pointer_pos " "
912
913                 set pointer_pos [$wins($cfile) index $line.1]
914                 set pointers($cfile) $pointer_pos
915
916                 $wins($cfile) delete $pointer_pos
917                 $wins($cfile) insert $pointer_pos "\xbb"
918
919                 if {$line < $screen_top + 1
920                     || $line > $screen_bot} then {
921                         $wins($cfile) yview [expr $line - $screen_height / 2]
922                         }
923
924                 $wins($cfile) configure -state disabled
925                 }
926 }
927
928 #
929 # Local procedure:
930 #
931 #       update_ptr - Update the listing window.
932 #
933 # Description:
934 #
935 #       This routine will update the listing window using the result of
936 #       gdb_loc.
937 #
938
939 proc update_ptr {} {update_listing [gdb_loc]}
940
941 #
942 # Local procedure:
943 #
944 #       asm_command - Open up the assembly window.
945 #
946 # Description:
947 #
948 #       Create an assembly window if it doesn't exist.
949 #
950
951 proc asm_command {} {
952         global cfunc
953
954         if ![winfo exists .asm] {
955                 set cfunc *None*
956                 set win [asm_win_name $cfunc]
957
958                 toplevel .asm
959                 wm minsize .asm 1 1
960                 wm title .asm Assembly
961
962                 label .asm.label -text "*NIL*" -borderwidth 2 -relief raised
963                 text $win -height 25 -width 80 -relief raised -borderwidth 2 \
964                         -setgrid true -cursor hand2 \
965                         -yscrollcommand asmscrollproc
966                 scrollbar .asm.scroll -orient vertical -command {$win yview}
967                 frame .asm.buts
968
969                 button .asm.stepi -text Stepi \
970                         -command {gdb_cmd stepi ; update_ptr}
971                 button .asm.nexti -text Nexti \
972                         -command {gdb_cmd nexti ; update_ptr}
973                 button .asm.continue -text Continue \
974                         -command {gdb_cmd continue ; update_ptr}
975                 button .asm.finish -text Finish \
976                         -command {gdb_cmd finish ; update_ptr}
977                 button .asm.up -text Up -command {gdb_cmd up ; update_ptr}
978                 button .asm.down -text Down \
979                         -command {gdb_cmd down ; update_ptr}
980                 button .asm.bottom -text Bottom \
981                         -command {gdb_cmd {frame 0} ; update_ptr}
982                 button .asm.close -text Close -command {destroy .asm}
983
984                 pack .asm.label -side top -fill x
985                 pack .asm.stepi .asm.nexti .asm.continue .asm.finish .asm.up \
986                      .asm.down .asm.bottom .asm.close -side left -in .asm.buts
987                 pack .asm.buts -side top -fill x
988                 pack $win -side left -expand yes -fill both
989                 pack .asm.scroll -side left -fill y
990
991                 update
992         }
993 }
994
995 #
996 # Local procedure:
997 #
998 #       registers_command - Open up the register display window.
999 #
1000 # Description:
1001 #
1002 #       Create the register display window, with automatic updates.
1003 #
1004
1005 proc registers_command {} {
1006         global cfunc
1007
1008         if ![winfo exists .reg] {
1009                 toplevel .reg
1010                 wm minsize .reg 1 1
1011                 wm title .reg Registers
1012                 set win .reg.regs
1013
1014                 text $win -height 25 -width 80 -relief raised \
1015                         -borderwidth 2 \
1016                         -setgrid true -cursor hand2
1017
1018                 pack $win -side left -expand yes -fill both
1019         } else {
1020                 destroy .reg
1021         }
1022 }
1023
1024 #
1025 # Local procedure:
1026 #
1027 #       update_registers - Update the registers window.
1028 #
1029 # Description:
1030 #
1031 #       This procedure updates the registers window.
1032 #
1033
1034 proc update_registers {} {
1035         global current_output_win
1036
1037         set win .reg.regs
1038
1039         $win configure -state normal
1040
1041         $win delete 0.0 end
1042
1043         set current_output_win $win
1044         gdb_cmd "info registers"
1045         set current_output_win .command.text
1046
1047         $win yview 1
1048         $win configure -state disabled
1049 }
1050
1051 #
1052 # Local procedure:
1053 #
1054 #       update_assembly - Update the assembly window.
1055 #
1056 # Description:
1057 #
1058 #       This procedure updates the assembly window.
1059 #
1060
1061 proc update_assembly {linespec} {
1062         global asm_pointers
1063         global screen_height
1064         global screen_top
1065         global screen_bot
1066         global wins cfunc
1067         global current_label
1068         global win_to_file
1069         global file_to_debug_file
1070         global current_asm_label
1071         global pclist
1072         global asm_screen_height asm_screen_top asm_screen_bot
1073
1074 # Rip the linespec apart
1075
1076         set pc [lindex $linespec 4]
1077         set line [lindex $linespec 3]
1078         set filename [lindex $linespec 2]
1079         set funcname [lindex $linespec 1]
1080         set debug_file [lindex $linespec 0]
1081
1082         set win [asm_win_name $cfunc]
1083
1084 # Sometimes there's no source file for this location
1085
1086         if {$filename == ""} {set filename Blank}
1087
1088 # If we want to switch funcs, we need to unpack the current text widget, and
1089 # stick in the new one.
1090
1091         if {$funcname != $cfunc } {
1092                 pack forget $win
1093                 set cfunc $funcname
1094
1095                 set win [asm_win_name $cfunc]
1096
1097 # Create a text widget for this func if necessary
1098
1099                 if {![winfo exists $win]} {
1100                         create_asm_win $cfunc $pc
1101                         set asm_pointers($cfunc) 1.1
1102                         set current_asm_label NIL
1103                         }
1104
1105 # Pack the text widget, and scroll to the right place
1106
1107                 pack $win -side left -expand yes -fill both \
1108                         -after .asm.buts
1109                 set line [pc_to_line $pclist($cfunc) $pc]
1110                 $win yview [expr $line - $asm_screen_height / 2]
1111                 }
1112
1113 # Update the label widget in case the filename or function name has changed
1114
1115         if {$current_asm_label != "$pc $funcname"} then {
1116                 .asm.label configure -text "$pc $funcname"
1117                 set current_asm_label "$pc $funcname"
1118                 }
1119
1120 # Update the pointer, scrolling the text widget if necessary to keep the
1121 # pointer in an acceptable part of the screen.
1122
1123         if [info exists asm_pointers($cfunc)] then {
1124                 $win configure -state normal
1125                 set pointer_pos $asm_pointers($cfunc)
1126                 $win configure -state normal
1127                 $win delete $pointer_pos
1128                 $win insert $pointer_pos " "
1129
1130 # Map the PC back to a line in the window               
1131
1132                 set line [pc_to_line $pclist($cfunc) $pc]
1133
1134                 if {$line == -1} {
1135                         echo "Can't find PC $pc"
1136                         return
1137                         }
1138
1139                 set pointer_pos [$win index $line.1]
1140                 set asm_pointers($cfunc) $pointer_pos
1141
1142                 $win delete $pointer_pos
1143                 $win insert $pointer_pos "\xbb"
1144
1145                 if {$line < $asm_screen_top + 1
1146                     || $line > $asm_screen_bot} then {
1147                         $win yview [expr $line - $asm_screen_height / 2]
1148                         }
1149
1150 #               echo "Picking line $line"
1151 #               $win yview -pickplace $line
1152
1153                 $win configure -state disabled
1154                 }
1155 }
1156
1157 proc update_ptr {} {
1158         update_listing [gdb_loc]
1159         if [winfo exists .asm] {
1160                 update_assembly [gdb_loc]
1161         }
1162         if [winfo exists .reg] {
1163                 update_registers
1164         }
1165 }
1166
1167 #
1168 # Window:
1169 #
1170 #       listing window - Define the listing window.
1171 #
1172 # Description:
1173 #
1174 #
1175
1176 # Setup listing window
1177
1178 frame .listing
1179
1180 wm minsize . 1 1
1181
1182 label .label -text "*No file*" -borderwidth 2 -relief raised
1183 text $wins($cfile) -height 25 -width 80 -relief raised -borderwidth 2 -yscrollcommand textscrollproc -setgrid true -cursor hand2
1184 scrollbar .scroll -orient vertical -command {$wins($cfile) yview}
1185
1186 if {[tk colormodel .text] == "color"} {
1187         set highlight "-background red2 -borderwidth 2 -relief sunk"
1188 } else {
1189         set fg [lindex [.text config -foreground] 4]
1190         set bg [lindex [.text config -background] 4]
1191         set highlight "-foreground $bg -background $fg -borderwidth 0"
1192 }
1193
1194 proc textscrollproc {args} {global screen_height screen_top screen_bot
1195                             eval ".scroll set $args"
1196                             set screen_height [lindex $args 1]
1197                             set screen_top [lindex $args 2]
1198                             set screen_bot [lindex $args 3]}
1199
1200 $wins($cfile) insert 0.0 "  This page intentionally left blank."
1201 $wins($cfile) configure -state disabled
1202
1203 pack .label -side bottom -fill x -in .listing
1204 pack $wins($cfile) -side left -expand yes -in .listing -fill both
1205 pack .scroll -side left -fill y -in .listing
1206
1207 button .start -text Start -command \
1208         {gdb_cmd {break main}
1209          gdb_cmd {enable delete $bpnum}
1210          gdb_cmd run
1211          update_ptr }
1212 button .step -text Step -command {gdb_cmd step ; update_ptr}
1213 button .next -text Next -command {gdb_cmd next ; update_ptr}
1214 button .continue -text Continue -command {gdb_cmd continue ; update_ptr}
1215 button .finish -text Finish -command {gdb_cmd finish ; update_ptr}
1216 #button .test -text Test -command {echo [info var]}
1217 button .exit -text Exit -command {gdb_cmd quit}
1218 button .up -text Up -command {gdb_cmd up ; update_ptr}
1219 button .down -text Down -command {gdb_cmd down ; update_ptr}
1220 button .bottom -text Bottom -command {gdb_cmd {frame 0} ; update_ptr}
1221 button .asm_but -text Asm -command {asm_command ; update_ptr}
1222 button .registers -text Regs -command {registers_command ; update_ptr}
1223
1224 proc files_command {} {
1225         toplevel .files_window
1226
1227         wm minsize .files_window 1 1
1228 #       wm overrideredirect .files_window true
1229         listbox .files_window.list -geometry 30x20 -setgrid true
1230         button .files_window.close -text Close -command {destroy .files_window}
1231         tk_listboxSingleSelect .files_window.list
1232         eval .files_window.list insert 0 [lsort [gdb_listfiles]]
1233         pack .files_window.list -side top -fill both -expand yes
1234         pack .files_window.close -side bottom -fill x -expand no -anchor s
1235         bind .files_window.list <Any-ButtonRelease-1> {
1236                 set file [%W get [%W curselection]]
1237                 gdb_cmd "list $file:1,0"
1238                 update_listing [gdb_loc $file:1]
1239                 destroy .files_window}
1240 }
1241
1242 button .files -text Files -command files_command
1243
1244 pack .listing -side bottom -fill both -expand yes
1245 #pack .test -side bottom -fill x
1246 pack .start .step .next .continue .finish .up .down .bottom .asm_but \
1247         .registers .files .exit -side left
1248 toplevel .command
1249 wm title .command Command
1250
1251 # Setup command window
1252
1253 label .command.label -text "* Command Buffer *" -borderwidth 2 -relief raised
1254 text .command.text -height 25 -width 80 -relief raised -borderwidth 2 -setgrid true -cursor hand2
1255
1256 pack .command.label -side top -fill x
1257 pack .command.text -side top -expand yes -fill both
1258
1259 set command_line {}
1260
1261 gdb_cmd {set language c}
1262 gdb_cmd {set height 0}
1263 gdb_cmd {set width 0}
1264
1265 bind .command.text <Any-Key> {
1266         global command_line
1267
1268         %W insert end %A
1269         %W yview -pickplace end
1270         append command_line %A
1271         }
1272 bind .command.text <Key-Return> {
1273         global command_line
1274
1275         %W insert end \n
1276         %W yview -pickplace end
1277         gdb_cmd $command_line
1278         set command_line {}
1279         update_ptr
1280         %W insert end "(gdb) "
1281         %W yview -pickplace end
1282         }
1283 bind .command.text <Enter> {focus %W}
1284 bind .command.text <Delete> {delete_char %W}
1285 bind .command.text <BackSpace> {delete_char %W}
1286 bind .command.text <Control-u> {delete_line %W}
1287 proc delete_char {win} {
1288         global command_line
1289
1290         tk_textBackspace $win
1291         $win yview -pickplace insert
1292         set tmp [expr [string length $command_line] - 2]
1293         set command_line [string range $command_line 0 $tmp]
1294 }
1295
1296 proc delete_line {win} {
1297         global command_line
1298
1299         $win delete {end linestart + 6 chars} end
1300         $win yview -pickplace insert
1301         set command_line {}
1302 }
1303
1304 wm minsize .command 1 1
This page took 0.098785 seconds and 4 git commands to generate.