This is the mail archive of the insight@sources.redhat.com mailing list for the Insight project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] major register window changes


The motivation for this huge patch is to allow the register window to properly 
handle display and editing of SIMD registers.  This caused me to have to 
rewrite numerous functions and while I was doing that I fixed a bunch of 
things that were either broken, slow or really annoying.

-- 
Martin Hunt
GDB Engineer
Red Hat, Inc.

2002-05-15  Martin M. Hunt  <hunt@redhat.com>

	* library/help/register.html: Rewrite docs.
	
	* library/regwin.ith (_types): New private variable array to save
	the possible types for each register.
	(_type): New private variable array to save the selected type for 
	each register.
	(_rows): New private variable. Number of rows in the table.
	(_cols): New private variable. Number of cols in the table.
	(_load_prefs): New private method.
	(_open_memory): New private method.
	(_edit_menu): Deleted:
	(_select): Deleted.
	(_change_format): Add optional type argument.
	
	* library/regwin.itb (RegWin::_load_prefs): New method. Collects
	all the prefs stuff here instead of in _layout_table. Prefs
	code was all rewritten to handle new types and formats.
	(RegWin::_build_win): Disable Double-1 binding. Bind
	button 1 to edit the cell. Don't make an Edit menu item.
	Remove Natural, Binary, Octal, and Raw formats. Add "Open
	Memory Window" menu item. 
	(RegWin::_dimensions): This function was being abused so I removed 
	it. Replaced with inline code in _layout_table which saves its
	computed values so it doesn't have to be recalculated unless 
	something changes.
	(RegWin::_layout_table): Rewritten to be more efficient. Grabs
	all values in one call to gdb_reginfo instead of one for each register.
	Uses new types and formats.  Calls _load_prefs.
	(RegWin::_accept_edit): Use type information when setting value.
	When done, call _unedit to remove tags.
	(RegWin::_open_memory): Open memory window with initial value
	set to the value of a register.	
	(RegWin::_but3): Add types menu items. Limit format options
	to reasonable ones. Add "Open Memory Window". Add "Help" 
	(RegWin::_edit): Just call _select_cell.
	(RegWin::_edit_menu): Deleted.
	(RegWin::_move): Don't recompute rows and cols; use _rows and
	_cols computed by _layout_table.
	(RegWin::_post_menu): Update types and formats. Disable "Open Memory
	Window" if register is not integer. Remove Edit.
	(RegWin::_select): Deleted.
	(RegWin::_select_cell):	Tag cell as being edited. Then
	call focus, which is a workaround for a TkTable glitch where
	the insertion bar sometimes disappeared.
	(RegWin::_unedit): Clear selection. Call focus. Don't change
	any bindings.
	(RegWin::_get_value): Eliminate previous crap and just call 
	"gdb_reginfo value".
	(RegWin::_change_format): Add optional type arg.  Call 
	"gdb_reginfo format".
	(RegWin::_update): Get a list of all the changed registers
	instead of checking one at a time.

	* generic/gdbtk-register.c (Gdbtk_Register_Init): Don't
	create gdb_pc_reg.  It is not used. Call register_gdbarch_swap 
	with regformat and regtype.
	(gdb_register_info): Add "type" and "format" options.
	(get_pc_register): Delete.
	(get_register_types): New function.  Returns list of valid types 
	for a list of registers.
	(get_register): Use saved format and type for each register. Check if
	there are any registers yet (target not running). Use mem_file 
	to collect output. Append output to a list.
	(map_arg_registers): If passed a list, iterate though each element
	and build a list of values to return.
	(setup_architecture_data): Memory was not being initialized, so
	use xcalloc(). Allocate memory for regformat and regtype.
	(gdb_regformat): New function called by "gdb_reginfo format".
Index: library/help/register.html
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk/library/help/register.html,v
retrieving revision 1.1
diff -u -u -r1.1 register.html
--- register.html	2000/02/04 13:52:34	1.1
+++ register.html	2002/05/15 23:25:10
@@ -4,7 +4,6 @@
 </HEAD>
 <BODY>
 <H1>The Register Window</H1>
-<H2>Overview</H2>
 <P>The Register Window lists all the registers and their contents for
 the selected stack frame. It permits viewing the contents of registers
 in different formats, editing register values, and some display
@@ -12,103 +11,32 @@
 
 <P>The Register Window will update the register contents in the display
 to match the stack frame currently being viewed in the <A HREF="source.html">
-Source Window</A> and <A HREF="stack.html">Stack Winodw</A>.</P>
-
-<P>Register Window topics:
+Source Window</A> and <A HREF="stack.html">Stack Window</A>.</P>
+<p>Each time the program stops, the register window will automatically update.
+Registers that have changed since the last stop will be displayed in blue.</p>
+<H3>The Register Display</H3>
 <UL>
-    <LI><UL><A HREF="#menus">Register Menu</A>
-            <LI><A HREF="#menus_edit">Edit</A>
-            <LI><A HREF="#menus_fmt">Format</A>
-            <LI><A HREF="#menus_remove">Remove from Display</A>
-            <LI><A HREF="#menus_all">Display All Registers</A>
-        </UL>
-    <LI><UL><A HREF="#display">Register Display</A>
-            <LI><A HREF="#display_nav">Navigating the Register Display</A>
-            <LI><A HREF="#display_popup">Register Pop-up Menu</A>
-            <LI><A HREF="#display_edit">Editing a Register</A>
-            <LI><A HREF="#display_format">Changing the Display Format of
-                a Register</A>
-            <LI><A HREF="#display_remove">Removing a Register
-                 from the display</A>
-            <LI><A HREF="#display_all">Displaying all Registers</A>
-        </UL>
-</UL></P>
-
-<H3><A NAME="menus">Register Menu</A></H3>
-The Register Menu provides on-screen access to the functionality of the
-Register Window. To use any item from this menu, first use the mouse and
-select (click the left mouse button) on any register cell. Users may then
-select:
-<BR>
-<DL>
-    <DT><A NAME="menus_edit"><A HREF="#display_edit">Edit</A></A>
-        <DD>Edit the contents of the selected register
-    <DT><A NAME="menus_fmt"><A HREF="#display_format">Format</A></A>
-        <DD>Change the display format of the selected register
-    <DT><A NAME="menus_remove"><A HREF="#display_remove">Remove
-        from Display</A></A>
-        <DD>Remove the selected register from the Register
-            Window Display
-    <DT><A NAME="menus_all"><A HREF="#display_all">Display All
-        Registers</A></A>
-        <DD>Display all registers in the Display. This item
-            is only available when a register was previously
-            removed from the Display.
-</DL>
-
-<H3><A NAME="display">Register Display</A></H3>
-The Register Display contains name and value pairs for each register
-available on the target hardware. These "cells" are layed out as a
-spreadsheet for ease of use.
-
-<P><A NAME="display_nav"></A>To navigate the Register Display, use either
-the mouse and left mouse button or the arrow keys on the keyboard to
-highlight the appropriate cell. Users may then use the <A HREF="#menus">
-Register Menu</A> or use the Register Pop-up Menu to access special display
-and editing options for the Register Window.</P>
-<BR>
-
+        <LI><A HREF="#display_edit">Editing a Register</A></LI>
+        <LI><A HREF="#display_popup">Register Pop-up Menu</A></LI>
+</UL>
+
+<H4><A NAME="display_edit">Editing a Register</A> </H4>
+<P>
+To edit a register, simply click on it with the left mouse button.  Type
+in the new value and hit enter.  You can enter a decimal, hex, or float number and
+the type will be converted if possible. You may also enter an expression to be evaluated.
+For example, to set  $r3 to the same as $r4, edit $r3 and enter "$r4" as the value.  In the same
+way, you can set $pc to "main".
+The value of the register is set to the current value of the expression; it will not be reevaluated
+if the expression's value later changes.
+</P>
+<P>Press the escape key on the keyboard to cancel your edit.</P>
 <H4><A NAME="display_popup">The Register Pop-up Menu</A></H4>
-All of the special functions of the register window are accessed through
-the Register Pop-up Menu. To use the Menu, simply select a register (see
-<A HREF="#display_nav">Navigating the Register Display</A>) and click the
-right mouse button. The Menu offers:
-<DL>
-    <DT><A NAME="display_edit">Edit</A>
-        <DD>Edit the contents of the selected register. This item
-            is also accessible by simply double-clicking the left
-            mouse button on any register in the Display. The value
-            of the register is set to the entered value -- the debugger
-            does diffferentiate between decimal, hexadecimal, octal,
-            and binary input. Press the escape key on the keyboard
-            to cancel.
-    <DT><A NAME="display_format">Format</A>
-        <DD><DL>Change the display format of the register. Valid display types
-            are:
-                <DT>Hex
-                    <DD>The register's contents are displayed in
-                        hexadecimal (base 16).
-                <DT>Decimal
-                    <DD>The value is shown as
-                        a decimal number (base 10).
-                <DT>Natural
-                    <DD>The register is displayed in its natural format.
-                <DT>Binary
-                    <DD>The contents of the register are displayed 
-                        as a binary number (base 2).
-                <DT>Octal
-                    <DD>The register's contents are shown in octal (base 8).
-                <DT>Raw
-                    <DD>The raw contents of the register are shown.
-             </DL>
-    <DT><A NAME="display_remove">Remove</A>
-        <DD>Remove the selected register from the display. To display
-            the removed register again, select the "Display All Registers"
-            option from the Register Menu or the Register Pop-up Menu.
-    <DT><A NAME="display_all">Display All Registers</A>
-        <DD>Causes the Register Window Display to show all registers,
-            including those which were previously "removed". This menu
-            item is only available when removed registers exist.
-</DL>
+<P>
+To activate the pop-up menu, click the right mouse button over a register.
+This will allow you change the way the register is displayed, or to remove
+it from the display.  Or you can add the register to the watch window.
+For integer registers, you can also open a memory window at the
+location pointed to by the register.</P>
 </BODY>
 </HTML>
Index: library/regwin.ith
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk/library/regwin.ith,v
retrieving revision 1.6
diff -u -u -r1.6 regwin.ith
--- regwin.ith	2001/08/16 18:07:17	1.6
+++ regwin.ith	2002/05/15 23:25:10
@@ -32,20 +32,26 @@
     # the register was "removed" from the display.
     variable _cell
 
-    # Display formats for the registers (indexed by regnum)
-    variable _format
-
     # Is REGNUM editable?
     variable _editable
 
-    # Is REGNUM typed?
-    variable _typed
+    # List of possible display types for the registers (indexed by regnum)
+    variable _types
+    # The display type to use for each register (indexed by regnum)
+    variable _type
+    # The display format to use for each register (indexed by regnum)
+    variable _format
 
     # The list of registers we're displaying
     variable _reg_display_list {}
 
     # Size of columns
     variable _col_size
+    variable _max_label_width
+
+    # Dimensions
+    variable _rows
+    variable _cols
 
     # Fencepost
     variable _running 0
@@ -53,8 +59,8 @@
 
     # Table layout/display methods
     method _build_win {}
-    method _dimensions {}
     method _layout_table {}
+    method _load_prefs {}
     method _prefs_changed {pref value}
     method _size_cell_column {cell down}
     method _size_column {col down}
@@ -66,16 +72,15 @@
     method _delete_from_display {rn} 
     method _display_all {} 
     method _edit {x y}
-    method _edit_menu {rn}
     method _move {direction}
+    method _open_memory {rn}
     method _post_menu {}
-    method _select {x y}
     method _select_cell {cell}
     method _unedit {}
 
     # Register operations
     method _get_value {rn}
-    method _change_format {rn}
+    method _change_format {rn {t {}}}
     method _update_register {rn}
   }
 
Index: library/regwin.itb
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk/library/regwin.itb,v
retrieving revision 1.11
diff -u -u -r1.11 regwin.itb
--- regwin.itb	2002/03/17 02:37:29	1.11
+++ regwin.itb	2002/05/15 23:25:11
@@ -2,7 +2,7 @@
 # Copyright 1998, 1999, 2001, 2002 Red Hat, Inc.
 #
 # Written by Keith Seitz (keiths@redhat.com)
-# based on work by Martin Hunt (hunt@redhat.com)
+#        and Martin Hunt (hunt@redhat.com)
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License (GPL) as published by
@@ -22,6 +22,8 @@
 #
 # Want really badly:
 # o Multiple selections
+# o Multiple displays
+# o Better resizing
 # o Register groups (gdb and user-defined)
 # o format register values before inserting into table?
 #   (Instead of displaying "0x0", we should use "0x00000000" on
@@ -63,7 +65,81 @@
   debug
 }
 
+# ------------------------------------------------------------------
+#  NAME:         RegWin::_load_prefs
+#  DESCRIPTION:  Load register preferences
+#
+#  ARGUMENTS:    None
+#  RETURNS:      Nothing
+# ------------------------------------------------------------------
+body RegWin::_load_prefs {} {
+  debug
+
+  # Find out largest register name length.
+  set _max_label_width 0;	# for reg labels
+  set _reg_display_list {}
+  set _register(hidden) {}
+
+  foreach r [gdb_reginfo name -numbers] {
+    set nm [lindex $r 0]
+    set rn [lindex $r 1]
+
+    set size [string length $nm]
+    if {$size > $_max_label_width} {
+      set _max_label_width $size
+    }
+
+    # Set type from prefs or default to first in list of types
+    set _types($rn) [gdb_reginfo type $rn]
+    set tp [pref getd gdb/reg/${nm}-type]
+    set _type($rn,name) ""
+    if {$tp != ""} {
+      foreach t $_types($rn) {
+	if {[lindex $t 0] == $tp} {
+	  set _type($rn,name) $tp
+	  set _type($rn,addr) [lindex $t 1]
+	  set _type($rn,code) [lindex $t 2]
+	  break
+	}
+      }
+    }
+    if {$_type($rn,name) == ""} {
+      # either not set or couldn't find it in list of types
+      set _type($rn,name) [lindex [lindex $_types($rn) 0] 0]
+      set _type($rn,addr) [lindex [lindex $_types($rn) 0] 1]
+      set _type($rn,code) [lindex [lindex $_types($rn) 0] 2]
+    }
+
+    # Check preferences for format
+    set _format($rn) [pref getd gdb/reg/${nm}-format]
+    if {$_format($rn) == ""} {
+      # no preference set.  Set it to hex or float
+      if {$_type($rn,code) == "int"} {
+	set _format($rn) "x"
+      } else {
+	set _format($rn) "f"
+      }
+      pref setd gdb/reg/${nm}-format $_format($rn)
+    }
+    
+    gdb_reginfo format $rn $_type($rn,addr) $_format($rn)
 
+    # Check if the user prefers not to show this register
+    if {[pref getd gdb/reg/$nm] == "no"} {
+      set _cell($rn) hidden
+      lappend _register(hidden) $rn
+    } else {
+      lappend _reg_display_list $rn
+    }
+
+    # assume editable, for now
+    set _editable($rn) 1
+  }
+
+  incr _max_label_width 2;	# padding
+}
+
+
 #
 # Table layout/display methods
 #
@@ -109,7 +185,8 @@
     [format "%s; break" [code $this _move right]]
   bind $itk_component(table) <3>        \
     [code $this _but3 %x %y %X %Y]
-  bind $itk_component(table) <Double-1> \
+  bind $itk_component(table) <Double-1> break 
+  bind $itk_component(table) <1> \
     [code $this _edit %x %y]
   bind $itk_component(table) <Return>   \
     [format "%s; break" [code $this _accept_edit]]
@@ -186,12 +263,6 @@
   $itk_component(menubar) add cascade -menu $itk_component(reg_menu) \
     -label "Register" -underline 0
 
-  if {![pref get gdb/mode]} {
-    $itk_component(reg_menu) add command -label "Edit" \
-      -underline 0 -state disabled
-    set _menuitems(edit) [$itk_component(reg_menu) index last]
-  }
-
   # Create register->format cascade menu
   itk_component add reg_format {
     menu $itk_component(reg_menu).format -tearoff false
@@ -207,17 +278,11 @@
     -underline 0 -state disabled -command [code $this update dummy]
   $itk_component(reg_format) add radio -label "Unsigned" -value u \
     -underline 0 -state disabled -command [code $this update dummy]
-  $itk_component(reg_format) add radio -label "Natural" -value {} \
-    -underline 0 -state disabled -command [code $this update dummy]
-  $itk_component(reg_format) add radio -label "Binary" -value t \
-    -underline 0 -state disabled -command [code $this update dummy]
-  $itk_component(reg_format) add radio -label "Octal" -value o \
-    -underline 0 -state disabled -command [code $this update dummy]
-  $itk_component(reg_format) add radio -label "Raw" -value r \
-    -underline 0 -state disabled -command [code $this update dummy]
   $itk_component(reg_format) add radio -label "Floating Point" -value f \
     -underline 0 -state disabled -command [code $this update dummy]
-
+  $itk_component(reg_menu) add command -label "Open Memory Window" \
+    -underline 7 -state disabled
+  set _menuitems(open_memory) [$itk_component(reg_menu) index last]
   $itk_component(reg_menu) add command -label "Add to Watch" \
     -underline 7 -state disabled
   set _menuitems(add_to_watch) [$itk_component(reg_menu) index last]
@@ -241,30 +306,6 @@
 }
 
 # ------------------------------------------------------------------
-#  NAME:         private method RegWin::_dimensions
-#  DESCRIPTION:  Determine dimensions for the table
-#
-#  ARGUMENTS:    None
-#  RETURNS:      A list of {cols,rows} which may be used to
-#                configure the table
-#
-#  NOTES:        I don't like this. (KRS 20010718)
-# ------------------------------------------------------------------
-body RegWin::_dimensions {} {
-
-  # Always layout the table based on the TOTAL number
-  # of registers (not just the shown ones).
-  set num [llength [gdb_reginfo name]]
-  set rows [pref get gdb/reg/rows]
-  set cols [expr {$num / $rows}]
-  if {[expr {$num % $rows}] != 0} {
-    incr cols
-  }
-
-  return [list [expr {2 * $cols}] $rows]
-}
-
-# ------------------------------------------------------------------
 #  NAME:         private method RegWin::_layout_table
 #  DESCRIPTION:  Configures and lays out the table
 #
@@ -275,102 +316,77 @@
 #                is displayed
 # ------------------------------------------------------------------
 body RegWin::_layout_table {} {
-
-  # Set table dimensions
-  lassign [_dimensions] cols rows
-  $itk_component(table) configure -cols $cols -rows $rows
+  debug
 
   if {[info exists _cell]} {
     unset _cell
     unset _register
   }
-  set _register(hidden) {}
-
-  # Find out largest register name length and register size length.
-  set width 0;				# for reg values
-  set max_width 0;			# for reg labels
-  foreach r [gdb_reginfo name -numbers] {
-    set nm [lindex $r 0]
-    set rn [lindex $r 1]
-
-    set size [string length $nm]
-    if {$size > $max_width} {
-      set max_width $size
-    }
-
-    set size [gdb_reginfo size $rn]
-    if {$size > $width} {
-      set width $size
-    }
-  }
-  incr max_width 2;			# padding
-
-  # Minwidth = size * 2 (hex) + 2 ("0x") + 2 (padding, one space each side)
-  set minwidth [expr {$size * 2 + 2 + 2}]
-
   # Clear any column spans
   foreach span [$itk_component(table) spans] {
     $itk_component(table) spans $span 0,0
   }
 
+  _load_prefs
+
   # Fill data array with register names.
   # 
   # The table is indexed by (row,col). All odd columns will contain
   # register values and all even columns will contain the labels.
   #
-  # This loop will also initialize _typed and _editable arrays.
   set x 0
   set y 0
-  set _reg_display_list {}
-  foreach r [gdb_reginfo name -numbers] {
 
+  # get register list
+  set regs [gdb_reginfo name -numbers $_reg_display_list]
+
+  # Set table dimensions
+  set num [llength $regs]
+  set _rows [pref get gdb/reg/rows]
+  set _cols [expr $num / $_rows]
+  if {[expr $num % $_rows] != 0} { incr _cols }
+  set _cols [expr 2 * $_cols]
+  $itk_component(table) configure -cols $_cols -rows $_rows
+
+  # get values
+  if {[catch {gdb_reginfo value $_reg_display_list} values]} {
+    dbug W "values=$values"
+    set values ""
+  }
+  set i 0
+
+  # now build table
+  foreach r $regs {
     set name [lindex $r 0]
     set rn [lindex $r 1]
 
-    # All registers shall be considered editable
-    # and non-typed until proved otherwise
-    set _typed($rn) 0
-    set _editable($rn) 0
-
-    # If user has no preference, show register in hex (if we can)
-    set format [pref getd gdb/reg/${name}-format]
-    if {$format == ""} { set format x }
-    set _format($rn) $format
+    set _cell($rn) "$y,[expr {$x+1}]"
+    set _register($_cell($rn)) $rn
+    set _data($y,$x) $name
+    set _data($_cell($rn)) [lindex $values $i]
+    incr i
 
-    # Check if the user prefers not to show this register
-    if {[pref getd gdb/reg/$name] == "no"} {
-      set _cell($rn) hidden
-      lappend _register(hidden) $rn
-    } else {
-      lappend _reg_display_list $rn
-      set _cell($rn) "$y,[expr {$x+1}]"
-      set _register($_cell($rn)) $rn
-      set _data($y,$x) $name
-      _update_register $rn
+    # Go to next row/column
+    incr y
+    if {$y == $_rows} {
+      set _col_size([expr {$x+1}]) 0
+      
+      # Size the column
+      if {$::gdb_running} {
+	_size_column [expr {$x+1}] 1
+      }
 
-      $itk_component(table) width $x $max_width
-      $itk_component(table) width [expr {$x+1}] $width
+      $itk_component(table) width $x $_max_label_width
       $itk_component(table) tag col header $x
       $itk_component(table) tag col normal [expr {$x+1}]
-
-      # Go to next row/column
-      incr y
-      if {$y == $rows} {
-	set _col_size([expr {$x+1}]) 0
-
-	# Size the column
-	if {$::gdb_running} {
-	  _size_column [expr {$x+1}] 1
-	}
-
-	set y 0
-	incr x 2
-      }
+      
+      set y 0
+      incr x 2
     }
   }
 
   # Mark empty cells
-  while {$y != $rows && $x != $cols} {
+  while {$y != $_rows && $x != $_cols} {
     set _data($y,$x) ""
     set _data($y,[expr {$x+1}]) ""
     $itk_component(table) spans $y,$x 0,1
@@ -378,11 +394,14 @@
     set _col_size([expr {$x+1}]) 0
 
     incr y
-    if {$y == $rows} {
+    if {$y == $_rows} {
       # Size the column
       if {$::gdb_running} {
 	_size_column [expr {$x+1}] 1
       }
+      $itk_component(table) width $x $_max_label_width
+      $itk_component(table) tag col header $x
+      $itk_component(table) tag col normal [expr {$x+1}]
 
       set y 0
       incr x 2
@@ -510,14 +529,19 @@
 #                in table
 # ------------------------------------------------------------------
 body RegWin::_accept_edit {} {
-
+  debug
   set cell [$itk_component(table) tag cell edit]
   if {[llength $cell] == 1 && [info exists _register($cell)]} {
     # Select the same cell again. This forces the table
     # to keep this value. Otherwise, we'll never see it...
     _select_cell $cell
-    set n [gdb_reginfo name $_register($cell)]
+    set rn $_register($cell)
+    set n [gdb_reginfo name $rn]
+    if {[llength $_types($rn)] > 1} {
+      append n ".$_type($rn,name)"
+    }
     set v [string trim [$itk_component(table) curvalue] \ \r\n]
+    debug "n=$n v=$v"
     if {$v != ""} {
       if {[catch {gdb_cmd "set \$${n}=$v"} result]} {
 	tk_messageBox -icon error -type ok -message $result \
@@ -531,9 +555,7 @@
     _size_cell_column $cell 1
   }
 
-  # Reset the table bindings (see RegWin::_edit comments)
-  bind $itk_component(table) <1> {}
-  bind $itk_component(table) <ButtonRelease-1> {}
+  _unedit
 }
 
 # ------------------------------------------------------------------
@@ -550,6 +572,19 @@
 }
 
 # ------------------------------------------------------------------
+#  NAME:         private method RegWin::_add_to_watch
+#  DESCRIPTION:  Add a register to the watch window
+#
+#  ARGUMENTS:    rn  - the register number to add to the WatchWin
+#  RETURNS:      Nothing
+#
+#  NOTES:        Only works with one WatchWin...
+# ------------------------------------------------------------------
+body RegWin::_open_memory {rn} {
+  ManagedWin::open MemWin -force -addr_exp $_data($_cell($rn))
+}
+
+# ------------------------------------------------------------------
 #  NAME:         private method RegWin::_but3
 #  DESCRIPTION:  Configure the popup menu before posting it
 #
@@ -574,45 +609,43 @@
       $itk_component(popup) delete 0 end
       $itk_component(popup) add command -label $name -state disabled
       $itk_component(popup) add separator
-      if {!$_typed($rn)} {
-	$itk_component(popup) add radio -label "Hex"            \
-	  -variable [scope _format($rn)] -value x               \
-	  -command [code $this _change_format $rn]
+      if {[llength $_types($rn)] > 1} {
+	foreach t $_types($rn) {
+	  $itk_component(popup) add radio -label [lindex $t 0] \
+	    -variable [scope _type($rn,addr)] \
+	    -value [lindex $t 1] \
+	    -command [code $this _change_format $rn [lindex $t 0]]
+	}
+	$itk_component(popup) add separator
+      }
+
+      $itk_component(popup) add radio -label "Hex"            \
+	-variable [scope _format($rn)] -value x               \
+	-command [code $this _change_format $rn]
+
+      if {$_type($rn,code) == "int"} {
 	$itk_component(popup) add radio -label "Decimal"        \
 	  -variable [scope _format($rn)] -value d               \
 	  -command [code $this _change_format $rn]
 	$itk_component(popup) add radio -label "Unsigned"       \
 	  -variable [scope _format($rn)] -value u               \
-	  -command [code $this _change_format $rn]
-	$itk_component(popup) add radio -label "Natural"        \
-	  -variable [scope _format($rn)] -value {}              \
-	  -command [code $this _change_format $rn]
-	$itk_component(popup) add radio -label "Binary"         \
-	  -variable [scope _format($rn)] -value t               \
 	  -command [code $this _change_format $rn]
-	$itk_component(popup) add radio -label "Octal"          \
-	  -variable [scope _format($rn)] -value o               \
-	  -command [code $this _change_format $rn]
-	$itk_component(popup) add radio -label "Raw"            \
-	  -variable [scope _format($rn)] -value r               \
-	  -command [code $this _change_format $rn]
+      } elseif {$_type($rn,code) == "float"} {
 	$itk_component(popup) add radio -label "Floating Point" \
 	  -variable [scope _format($rn)] -value f               \
 	  -command [code $this _change_format $rn]
-	$itk_component(popup) add separator
       }
+      $itk_component(popup) add separator
+
       if {$_editable($rn)} {
 	set state normal
       } else {
 	set state disabled
       }
       
-      # I'm disabling this, since it doesn't work very well.
-      # All kinds of goofy interactions with the insertion cursor
-      # and focus when editing is invoked from a menu. (KRS 20010717)
-      if {1} {
-	$itk_component(popup) add command  \
-	  -label "Edit" -command "after idle [code $this _edit $x $y]" -state $state
+      if {$_type($rn,code) == "int"} {
+	$itk_component(popup) add command    \
+	  -label "Open Memory Window" -command [code $this _open_memory $rn]
       }
       $itk_component(popup) add command    \
 	-label "Add to Watch" -command [code $this _add_to_watch $rn]
@@ -624,6 +657,13 @@
 	$itk_component(popup) add command -label "Display all Registers" \
 	  -command [code $this _display_all]
       }
+
+      # Help
+      $itk_component(popup) add separator
+      $itk_component(popup) add command    \
+	-label "Help" \
+	-command {ManagedWin::open HtmlViewer -force -file register.html}
+
       tk_popup $itk_component(popup) $X $Y
     }
   }
@@ -668,6 +708,7 @@
   foreach r $_register(hidden) {
     pref setd gdb/reg/[gdb_reginfo name $r] {}
   }
+
   set _register(hidden) {}
 
   # Note which register is active and restore it
@@ -691,47 +732,13 @@
 #                y  - the y coordinate of the button press
 #  RETURNS:      Nothing
 #
-#  NOTES:        Event handler for <Double-1> in table.
-#                Sets special bindings for <1> and <ButtonRelease-1>.
+#  NOTES:        Event handler for <1> in table.
+#                
 # ------------------------------------------------------------------
 body RegWin::_edit {x y} {
-  global gdb_running
-
-  focus $itk_component(table)
-
-  # Get and select the cell and set the edit tag on it
-  set cell [_select_cell [$itk_component(table) index @$x,$y]]
-
-  # Ugh. In order to click on the label and keep the value
-  # focused, we need to disrupt the ButtonRelease-1 event.
-  bind $itk_component(table) <ButtonRelease-1> break
-  
-  # Disable the <1> binding while editing
-  bind $itk_component(table) <1> break
-
-  # Now mark the cell as being edited.
-  if {$gdb_running && [info exists _register($cell)]} {
-    $itk_component(table) tag cell edit $cell
-  }
+  _select_cell [$itk_component(table) index @$x,$y]
 }
 
-# ------------------------------------------------------------------
-#  NAME:         private method RegWin::_edit_menu
-#  DESCRIPTION:  Enables a cell for editing when invoked from
-#                a menu
-#
-#  ARGUMENTS:
-#                rn  - the register to edit
-#  RETURNS:      Nothing
-#
-#  NOTES:        
-# ------------------------------------------------------------------
-body RegWin::_edit_menu {rn} {
-
-  set bbox [$itk_component(table) bbox $_cell($rn)]
-  _edit [lindex $bbox 0] [lindex $bbox 1]
-  event generate $_top <Enter>
-}
 
 # ------------------------------------------------------------------
 #  NAME:         private method _move
@@ -750,6 +757,8 @@
 # ------------------------------------------------------------------
 body RegWin::_move {direction} {
 
+  debug $direction
+
   # If there is no active cell, the table will call error
   if {[catch {$itk_component(table) index active row} row]} {
     return
@@ -790,20 +799,19 @@
     # Not editing
 
     set col [$itk_component(table) index active col]
-    lassign [_dimensions] cols rows
 
     switch $direction {
       up {
 	incr row -1
 	if {$row < 0} {
 	  # go to bottom
-	  set row $rows
+	  set row $_rows
 	}
       }
 
       down {
 	incr row 1
-	if {$row == $rows} {
+	if {$row == $_rows} {
 	  # go to top
 	  set row 0
 	}
@@ -813,13 +821,13 @@
 	incr col -2
 	if {$col < 0} {
 	  # go to right
-	  set col [expr {$cols -1}]
+	  set col [expr {$_cols -1}]
 	}
       }
 
       right {
 	incr col 2
-	if {$col > $cols} {
+	if {$col > $_cols} {
 	  # go to left
 	  set col 0
 	}
@@ -847,14 +855,14 @@
   # Configure the menu for the active cell
   if {![catch {$itk_component(table) index active} cell]
       && [info exists _register($cell)] && $gdb_running} {
+
+    set code $_type($_register($cell),code)
+
     $itk_component(reg_menu) entryconfigure $_menuitems(remove_from_display) \
       -state normal -command [code $this _delete_from_display $_register($cell)]
 
-    if {$_typed($_register($cell))} {
-      set state disabled
-    } else {
-      set state normal
-    }
+    set state normal
+
     for {set i 0} {$i <= [$itk_component(reg_format) index end]} {incr i} {
       $itk_component(reg_format) entryconfigure $i \
 	-state $state \
@@ -862,15 +870,28 @@
 	-command [code $this _change_format $_register($cell)]
     }
 
+    if {$code == "float"} {
+      # disable decimal and unsigned
+      $itk_component(reg_format) entryconfigure 1 -state disabled
+      $itk_component(reg_format) entryconfigure 2 -state disabled
+    } elseif {$code == "int"} {
+      # disable float
+      $itk_component(reg_format) entryconfigure 3 -state disabled
+    }
+
+    # memory window
+    if {$code == "int"} {
+      $itk_component(reg_menu) entryconfigure $_menuitems(open_memory) \
+	-state normal -command [code $this _open_memory $_register($cell)]
+    } else {
+      $itk_component(reg_menu) entryconfigure $_menuitems(open_memory) \
+	-state disabled
+    }
+
+    # add to watch
     $itk_component(reg_menu) entryconfigure $_menuitems(add_to_watch) \
       -state normal -command [code $this _add_to_watch $_register($cell)]
 
-    # This doesn't seem to work on my linux box. It works fine on
-    # Cygwin, though... (KRS 010806)
-    if {$_editable($_register($cell))} {
-      $itk_component(reg_menu) entryconfigure $_menuitems(edit) \
-	-state normal -command [code $this _edit_menu $_register($cell)]
-    }
   } else {
     # Disable everything
     $itk_component(reg_menu) entryconfigure $_menuitems(remove_from_display) \
@@ -881,6 +902,9 @@
 	-variable {}
     }
 
+    $itk_component(reg_menu) entryconfigure $_menuitems(open_memory) \
+      -state disabled -command {}
+
     $itk_component(reg_menu) entryconfigure $_menuitems(add_to_watch) \
       -state disabled -command {}
 
@@ -891,18 +915,6 @@
   }
 }
 
-# ------------------------------------------------------------------
-#  NAME:         private method RegWin::_select
-#  DESCRIPTION:  Selects the cell with the given coordinates
-#
-#  ARGUMENTS:
-#                x - the x-coordinate of the cell to select
-#                y - the y-coordinate of the cell to select
-#  RETURNS:      The actual cell selected
-# ------------------------------------------------------------------
-body RegWin::_select {x y} {
-  return [_select_cell [$itk_component(table) index @$x,$y]]
-}
 
 # ------------------------------------------------------------------
 #  NAME:         private method RegWin::_select_cell
@@ -927,6 +939,7 @@
     # going onto a label
     incr col 1
   }
+  set cell "$row,$col"
 
   # Make the selected cell the active one
   $itk_component(table) activate $row,$col
@@ -935,9 +948,16 @@
   # Select this cell and its label
   # FIXME: multiple selections?
   $itk_component(table) selection clear all
-  $itk_component(table) selection set $row,$col $row,[expr {$col-1}]
+  $itk_component(table) selection set $cell $row,[expr {$col-1}]
+
+  # Now mark the cell as being edited.
+  if {$::gdb_running && [info exists _register($cell)]} {
+    $itk_component(table) tag cell edit $cell
+  }
 
-  return $row,$col
+  focus $itk_component(table)
+
+  return $cell
 }
 
 # ------------------------------------------------------------------
@@ -951,11 +971,12 @@
 
   # clear the tag
   set cell [$itk_component(table) tag cell edit]
-  $itk_component(table) tag cell normal $cell
 
-  # Reset the table binding (see RegWin::_edit comments)
-  bind $itk_component(table) <ButtonRelease-1> {}
-  bind $itk_component(table) <1> {}
+  if {$cell != ""} {
+    $itk_component(table) selection clear all
+    $itk_component(table) tag cell normal $cell 
+    focus $itk_component(table)
+  }
 }
 
 #
@@ -970,33 +991,15 @@
 #                      fetched
 #  RETURNS:      The register's value or ""
 #
-#  NOTES:        This function uses RegWin::_format to determine
-#                how the value is returned
-#                It also does some other weird stuff...
+#  NOTES:        
 # ------------------------------------------------------------------
 body RegWin::_get_value {rn} {
-
-  # Typed registers natural values start with a brace (escaped by a slash)
-  if {[catch {gdb_reginfo value {} $rn} valtest]} {
+  if {[catch {gdb_reginfo value $rn} value]} {
+    dbug W "\"gdb_reginfo value $rn\" returned $value"
     set value ""
   } else {
-    if {[string index $valtest 1] == "\{"} {
-      # If it is a typed register, we print it raw
-      set format r
-      set _format($rn) r
-      set _typed($rn) 1
-      set _editable($rn) 0
-    } else {
-      set format $_format($rn)
-      set _editable($rn) 1
-    }
-    if {[catch {gdb_reginfo value $format $rn} value]} {
-      set value ""
-    } else {
-      set value [string trim $value \ ]
-    }
+    set value [string trim $value \ ]
   }
-
   return $value
 }
 
@@ -1005,21 +1008,26 @@
 #  DESCRIPTION:  Change the display format of the register
 #
 #  ARGUMENTS:    rn  - the register number to change
+#		 newtype - type name (optional if just format changed)
+#
 #  RETURNS:      Nothing
 #
-#  NOTES:        Assumes that hex, "x", is the default
+#  NOTES:        
 # ------------------------------------------------------------------
-body RegWin::_change_format {rn} {
+body RegWin::_change_format {rn {newtype {}}} {
 
-  # Set the new format. Hex (x) is the default.
   set name [gdb_reginfo name $rn]
-  if {$_format($rn) == "x"} {
-    set fmt ""
-  } else {
-    set fmt $_format($rn)
+
+  if {$newtype != ""} {
+    set _type($rn,name) $newtype
+    pref setd gdb/reg/${name}-type $newtype
   }
+  
+  gdb_reginfo format $rn $_type($rn,addr) $_format($rn)
+
+  # Set the new format in prefs. 
+  pref setd gdb/reg/${name}-format $_format($rn)
 
-  pref setd gdb/reg/${name}-format $fmt
   _update_register $rn
   _size_cell_column $_cell($rn) 1
 
@@ -1038,7 +1046,6 @@
 #  RETURNS:      Nothing
 # ------------------------------------------------------------------
 body RegWin::_update_register {rn} {
-
   set _data($_cell($rn)) [_get_value $rn]
 }
 
@@ -1138,7 +1145,7 @@
 
   # Now update and highlight the newly changed values
   set _change_list {}
-  if {![catch {eval gdb_reginfo changed $_reg_display_list} changed]} {
+  if {![catch {gdb_reginfo changed $_reg_display_list} changed]} {
     set _change_list $changed
   }
 
Index: generic/gdbtk-register.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk/generic/gdbtk-register.c,v
retrieving revision 1.9
diff -u -u -r1.9 gdbtk-register.c
--- gdbtk-register.c	2002/05/06 15:34:41	1.9
+++ gdbtk-register.c	2002/05/15 23:25:11
@@ -22,6 +22,7 @@
 #include "frame.h"
 #include "regcache.h"
 #include "value.h"
+#include "target.h"
 
 #include <tcl.h>
 #include "gdbtk.h"
@@ -32,29 +33,33 @@
 
    It is an array of (NUM_REGS+NUM_PSEUDO_REGS)*MAX_REGISTER_RAW_SIZE bytes. */
 
-static char *old_regs = NULL;
-
-static int get_pc_register (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
-static int gdb_register_info (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
+static int gdb_register_info (ClientData, Tcl_Interp *, int, Tcl_Obj **);
 static void get_register (int, void *);
 static void get_register_name (int, void *);
 static void get_register_size (int regnum, void *arg);
-static int map_arg_registers (int, Tcl_Obj * CONST[],
+static int map_arg_registers (Tcl_Interp *, int, Tcl_Obj **,
 			      void (*)(int, void *), void *);
 static void register_changed_p (int, void *);
 static void setup_architecture_data (void);
+static int gdb_regformat (ClientData, Tcl_Interp *, int, Tcl_Obj **);
+static void get_register_types (int regnum, void *arg);
 
+static char *old_regs = NULL;
+static int *regformat = (int *)NULL;
+static struct type **regtype = (struct type **)NULL;
+
 int
 Gdbtk_Register_Init (Tcl_Interp *interp)
 {
   Tcl_CreateObjCommand (interp, "gdb_reginfo", gdbtk_call_wrapper,
                         gdb_register_info, NULL);
-  Tcl_CreateObjCommand (interp, "gdb_pc_reg", gdbtk_call_wrapper, get_pc_register,
-			NULL);
 
   /* Register/initialize any architecture specific data */
   setup_architecture_data ();
+
   register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL);
+  register_gdbarch_swap (&regformat, sizeof (regformat), NULL);
+  register_gdbarch_swap (&regtype, sizeof (regtype), NULL);
   register_gdbarch_swap (NULL, 0, setup_architecture_data);
 
   return TCL_OK;
@@ -102,31 +107,32 @@
  * value
  *    Returns a list of register values.
  *
- *    usage: gdb_reginfo value format [regnum0, ..., regnumN]
- *       format: The format string for printing the values, "N", "x", "d", etc
+ *    usage: gdb_reginfo value [regnum0, ..., regnumN]
  */
 static int
 gdb_register_info (ClientData clientData, Tcl_Interp *interp, int objc,
-                   Tcl_Obj *CONST objv[])
+                   Tcl_Obj **objv)
 {
   int index;
   void *argp;
   void (*func)(int, void *);
-  static char *commands[] = {"changed", "name", "size", "value", NULL};
-  enum commands_enum { REGINFO_CHANGED, REGINFO_NAME, REGINFO_SIZE, REGINFO_VALUE };
+  static char *commands[] = {"changed", "name", "size", "value", "type", "format", NULL};
+  enum commands_enum { REGINFO_CHANGED, REGINFO_NAME, REGINFO_SIZE, 
+		       REGINFO_VALUE, REGINFO_TYPE, REGINFO_FORMAT };
 
   if (objc < 2)
     {
-      Tcl_WrongNumArgs (interp, 1, objv, "name|size|value [regnum1 ... regnumN]");
+      Tcl_WrongNumArgs (interp, 1, objv, "name|size|value|type|format [regnum1 ... regnumN]");
       return TCL_ERROR;
     }
 
   if (Tcl_GetIndexFromObj (interp, objv[1], commands, "options", 0,
-			   &index) != TCL_OK)
+  			   &index) != TCL_OK)
     {
+      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
       return TCL_ERROR;
     }
-
+  
   /* Skip the option */
   objc -= 2;
   objv += 2;
@@ -162,16 +168,22 @@
 
     case REGINFO_VALUE:
       func = get_register;
-      argp = (void *) (int) *(Tcl_GetStringFromObj (objv[0], NULL));
-      objc--;
-      objv++;
+      argp = NULL;
+      break;
+
+    case REGINFO_TYPE:
+      func = get_register_types;
+      argp = NULL;
       break;
 
+    case REGINFO_FORMAT:
+      return gdb_regformat (clientData, interp, objc, objv);
+
     default:
       return TCL_ERROR;
     }
 
-  return map_arg_registers (objc, objv, func, argp);
+  return map_arg_registers (interp, objc, objv, func, argp);
 }
 
 static void
@@ -181,36 +193,87 @@
 			    Tcl_NewIntObj (REGISTER_RAW_SIZE (regnum)));
 }
 
-/* This implements the tcl command get_pc_reg
- * It returns the value of the PC register
- *
- * Tcl Arguments:
- *    None
- * Tcl Result:
- *    The value of the pc register.
- */
-static int
-get_pc_register (ClientData clientData, Tcl_Interp *interp,
-		 int objc, Tcl_Obj *CONST objv[])
-{
-  char *buff;
-  xasprintf (&buff, "0x%s", paddr_nz (read_register (PC_REGNUM)));
-  Tcl_SetStringObj (result_ptr->obj_ptr, buff, -1);
-  free(buff);
-  return TCL_OK;
+/* returns a list of valid types for a register */
+/* Normally this will be only one type, except for SIMD and other */
+/* special registers. */
+
+static void
+get_register_types (int regnum, void *arg)
+{ 
+  struct type *reg_vtype;
+  int i,n;
+
+  reg_vtype = REGISTER_VIRTUAL_TYPE (regnum);
+  if (TYPE_CODE (reg_vtype) == TYPE_CODE_UNION)
+    {
+      n = TYPE_NFIELDS (reg_vtype);
+      /* limit to 16 types */
+      if (n > 16) 
+	n = 16;
+      
+      for (i = 0; i < n; i++)
+	{
+	  Tcl_Obj *ar[3], *list;
+	  char *buff;
+	  xasprintf (&buff, "%lx", (long)TYPE_FIELD_TYPE (reg_vtype, i));
+	  ar[0] = Tcl_NewStringObj (TYPE_FIELD_NAME (reg_vtype, i), -1);
+	  ar[1] = Tcl_NewStringObj (buff, -1);
+	  if (TYPE_CODE (TYPE_FIELD_TYPE (reg_vtype, i)) == TYPE_CODE_FLT)
+	    ar[2] = Tcl_NewStringObj ("float", -1);
+	  else
+	    ar[2] = Tcl_NewStringObj ("int", -1);	    
+	  list = Tcl_NewListObj (3, ar);
+	  Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, list);
+	  xfree (buff);
+	}
+    }
+  else
+    {
+      Tcl_Obj *ar[3], *list;
+      char *buff;
+      xasprintf (&buff, "%lx", (long)reg_vtype);
+      ar[0] = Tcl_NewStringObj (TYPE_NAME(reg_vtype), -1);
+      ar[1] = Tcl_NewStringObj (buff, -1);
+      if (TYPE_CODE (reg_vtype) == TYPE_CODE_FLT)
+	ar[2] = Tcl_NewStringObj ("float", -1);
+      else
+	ar[2] = Tcl_NewStringObj ("int", -1);	    
+      list = Tcl_NewListObj (3, ar);
+      xfree (buff);
+      Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, list);
+    }
 }
 
+
 static void
-get_register (int regnum, void *fp)
+get_register (int regnum, void *arg)
 {
   struct type *reg_vtype;
   char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE);
   char *virtual_buffer = alloca (MAX_REGISTER_VIRTUAL_SIZE);
-  int format = (int) fp;
-  int optim;
+  int optim, format;
+  struct cleanup *old_chain = NULL;
+  struct ui_file *stb;
+  long dummy;
+  char *res;
+ 
+  format = regformat[regnum];
+  if (format == 0)
+    format = 'x';
+  
+  reg_vtype = regtype[regnum];
+  if (reg_vtype == NULL)
+    reg_vtype = REGISTER_VIRTUAL_TYPE (regnum);
+
 
-  if (format == 'N')
-    format = 0;
+  if (!target_has_registers)
+    {
+      if (result_ptr->flags & GDBTK_MAKES_LIST)
+	Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj ("", -1));
+      else
+	Tcl_SetStringObj (result_ptr->obj_ptr, "", -1);
+      return;
+    }
 
   get_saved_register (raw_buffer, &optim, (CORE_ADDR *) NULL, selected_frame,
 		      regnum, (enum lval_type *) NULL);
@@ -222,8 +285,6 @@
     }
 
   /* Convert raw data to virtual format if necessary.  */
-
-  reg_vtype = REGISTER_VIRTUAL_TYPE (regnum);
   if (REGISTER_CONVERTIBLE (regnum))
     {
       REGISTER_CONVERT_TO_VIRTUAL (regnum, reg_vtype,
@@ -232,8 +293,12 @@
   else
     memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
 
+  stb = mem_fileopen ();
+  old_chain = make_cleanup_ui_file_delete (stb);
+
   if (format == 'r')
     {
+      /* shouldn't happen. raw format is deprecated */
       int j;
       char *ptr, buf[1024];
 
@@ -241,24 +306,36 @@
       ptr = buf + 2;
       for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++)
 	{
-	  register int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
+	  int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
 	    : REGISTER_RAW_SIZE (regnum) - 1 - j;
 	  sprintf (ptr, "%02x", (unsigned char) raw_buffer[idx]);
 	  ptr += 2;
 	}
-      fputs_filtered (buf, gdb_stdout);
+      fputs_unfiltered (buf, stb);
     }
   else
-    if ((TYPE_CODE (reg_vtype) == TYPE_CODE_UNION)
-        && (strcmp (FIELD_NAME (TYPE_FIELD (reg_vtype, 0)), REGISTER_NAME (regnum)) == 0))
-      {
-        val_print (FIELD_TYPE (TYPE_FIELD (reg_vtype, 0)), virtual_buffer, 0, 0,
-	           gdb_stdout, format, 1, 0, Val_pretty_default);
-      }
-    else
-      val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0,
-	         gdb_stdout, format, 1, 0, Val_pretty_default);
+    {
+      if ((TYPE_CODE (reg_vtype) == TYPE_CODE_UNION)
+	  && (strcmp (FIELD_NAME (TYPE_FIELD (reg_vtype, 0)), 
+		      REGISTER_NAME (regnum)) == 0))
+	{
+	  val_print (FIELD_TYPE (TYPE_FIELD (reg_vtype, 0)), virtual_buffer, 0, 0,
+		     stb, format, 1, 0, Val_pretty_default);
+	}
+      else
+	val_print (reg_vtype, virtual_buffer, 0, 0,
+		   stb, format, 1, 0, Val_pretty_default);
+    }
+  
+  res = ui_file_xstrdup (stb, &dummy);
 
+  if (result_ptr->flags & GDBTK_MAKES_LIST)
+    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj (res, -1));
+  else
+    Tcl_SetStringObj (result_ptr->obj_ptr, res, -1);
+
+  xfree (res);
+  do_cleanups (old_chain);
 }
 
 static void
@@ -288,9 +365,8 @@
 /* This is a sort of mapcar function for operations on registers */
 
 static int
-map_arg_registers (int objc, Tcl_Obj *CONST objv[],
-		   void (*func) (int regnum, void *argp),
-		   void *argp)
+map_arg_registers (Tcl_Interp *interp, int objc, Tcl_Obj **objv,
+		   void (*func) (int regnum, void *argp), void *argp)
 {
   int regnum, numregs;
 
@@ -302,25 +378,26 @@
 
   numregs = NUM_REGS + NUM_PSEUDO_REGS;
 
-  if (objc == 0 || objc > 1)
-    result_ptr->flags |= GDBTK_MAKES_LIST;
-
   if (objc == 0)		/* No args, just do all the regs */
     {
-      for (regnum = 0;
-	   regnum < numregs;
-	   regnum++)
+      result_ptr->flags |= GDBTK_MAKES_LIST;
+      for (regnum = 0; regnum < numregs; regnum++)
 	{
 	  if (REGISTER_NAME (regnum) == NULL
 	      || *(REGISTER_NAME (regnum)) == '\0')
 	    continue;
-	  
 	  func (regnum, argp);
-	}
-      
+	}      
       return TCL_OK;
     }
 
+  if (objc == 1)
+    if (Tcl_ListObjGetElements (interp, *objv, &objc, &objv ) != TCL_OK)
+      return TCL_ERROR;
+
+  if (objc > 1)
+    result_ptr->flags |= GDBTK_MAKES_LIST;
+
   /* Else, list of register #s, just do listed regs */
   for (; objc > 0; objc--, objv++)
     {
@@ -330,8 +407,7 @@
 	  return TCL_ERROR;
 	}
 
-      if (regnum >= 0
-	  && regnum < numregs
+      if (regnum >= 0  && regnum < numregs
 	  && REGISTER_NAME (regnum) != NULL
 	  && *REGISTER_NAME (regnum) != '\000')
 	func (regnum, argp);
@@ -341,7 +417,6 @@
 	  return TCL_ERROR;
 	}
     }
-
   return TCL_OK;
 }
 
@@ -368,10 +443,47 @@
 static void
 setup_architecture_data ()
 {
-  if (old_regs != NULL)
-    xfree (old_regs);
-
-  old_regs = xmalloc ((NUM_REGS + NUM_PSEUDO_REGS) * MAX_REGISTER_RAW_SIZE + 1);
-  memset (old_regs, 0, sizeof  (old_regs));
+  xfree (old_regs);
+  xfree (regformat);
+  xfree (regtype);
+
+  old_regs = xcalloc (1, (NUM_REGS + NUM_PSEUDO_REGS) * MAX_REGISTER_RAW_SIZE + 1);
+  regformat = (int *)xcalloc ((NUM_REGS + NUM_PSEUDO_REGS) , sizeof(int));
+  regtype = (struct type **)xcalloc ((NUM_REGS + NUM_PSEUDO_REGS), sizeof(struct type **));
 }
 
+/* gdb_regformat sets the format for a register */
+/* This is necessary to allow "gdb_reginfo value" to return a list */
+/* of registers and values. */
+/* Usage: gdb_reginfo format regno typeaddr format */
+
+static int
+gdb_regformat (ClientData clientData, Tcl_Interp *interp,
+	       int objc, Tcl_Obj **objv)
+{
+  int fm, regno;
+  struct type *type;
+
+  if (objc != 3)
+    {
+      Tcl_WrongNumArgs (interp, 1, objv, "regno type format");
+      return TCL_ERROR;
+    }
+
+  if (Tcl_GetIntFromObj (interp, objv[0], &regno) != TCL_OK)
+    return TCL_ERROR;
+
+  type = (struct type *)strtol (Tcl_GetStringFromObj (objv[1], NULL), NULL, 16);  
+  fm = (int)*(Tcl_GetStringFromObj (objv[2], NULL));
+
+  if (regno >= NUM_REGS + NUM_PSEUDO_REGS)
+    {
+      gdbtk_set_result (interp, "Register number %d too large", regno);
+      return TCL_ERROR;
+    }
+  
+  regformat[regno] = fm;
+  regtype[regno] = type;
+
+  return TCL_OK;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]