This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

Frozen variable objects 2


This is the final patch to add frozen variable objects. It includes testsuite
changes and documentation.

Since the time I've posted the first version the code has seen some extra
testing, and basically works fine. The only change is that now the "frozen=1"
fields is only output for frozen variable objects and "frozen=0" is never output.
This is to avoid adjusting everything single use of -var-create in the testsuite.

This patch depends on some of my previously posted patches, namely:

	- mi_continue_to cleanup
	- varobj doc cleanup
	- simplified MI tests

OK?

- Volodya

	gdb/
	* varobj.h (varobj_set_frozen): New
	(varobj_get_frozen): New.
	(varobj_update): New parameter explicit.	
	* varobj.c (struct varobj): New fields frozen
	and not_fetched.
	(varobj_set_frozen, varobj_get_frozen): New.
	(install_new_value): Don't fetch values for 
	frozen variable object, or children thereof.  Allow
	a frozen variable object to have non-fetched value.
	(varobj_update): Allow updating child variables.
	Don't traverse frozen children.
	(new_variable): Initialize the frozen field.
	(c_value_of_variable): Return NULL for frozen
	variable without any value yet.	
	* mi/mi-cmd-var.c (varobj_update_one): New parameter
	'explicit'.
	(mi_cmd_var_create): Output the 'frozen' field,
	as soon as testsuite is adjusted to expect that field.
	(mi_cmd_var_set_frozen): New.
	(mi_cmd_var_update): Pass the 'explicit' parameter to
	varobj_update_one.
	* mi/mi-cmds.c (mi_cmds): Register '-var-set-frozen'.
	* mi/mi-cmds.h (mi_cmd_var_set_frozen): Declare.

	doc/
	* gdb.texinfo (GDB/MI Variable Objects): Document
	frozen variables objects.

	testsuite/
	* gdb.mi/mi-var-cmd.exp: Delete varobjs left by previous
	tests. Run the frozen varobjs test.
	* gdb.mi/var-cmd.c (do_frozen_tests): New.
	* lib/mi-support.exp (mi_varobj_delete): New.
	(mi_varobj_update): Fix thinko.
	
--- gdb/doc/gdb.texinfo	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/doc/gdb.texinfo	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -19587,7 +19587,10 @@ Variable objects have hierarchical struc
 that corresponds to a composite type, such as structure in C, has
 a number of child variable objects, for example corresponding to each
 element of a structure.  Child variable objects can children themself,
-util we reach leaf variable objects of built-in types.
+util we reach leaf variable objects of built-in types.  Child variable
+objects are created only by explicit request, so if a frontend 
+is not interested in children of a particular variable object, no
+child will be created.
 
 For a leaf variable object it is possible to obtain its value as a
 string, or set the value from a string.  String value can be also
@@ -19599,7 +19602,19 @@ A frontend need not read the values of a
 the program stops.  Instead, MI provides update command that lists all
 variable objects which values has changed since the last update
 operation.  This considerably reduces the amount of data that must
-be transferred to the frontend.
+be transferred to the frontend.  As noted above, children variable
+objects are created on demand, and only leaf variable object have a
+real value.  As result, gdb will read target memory only for leaf
+variables that frontend has created.
+
+The automatic update is not always desirable.  For example, a frontend
+might want to keep a value of some expression for future reference,
+and never update it.  For another example,  fetching memory is
+relatively slow for embedded targets, so a frontend might want
+to disable automatic update for the variables that are either not
+visible on the screen, or ``closed''.  This is possible using so
+called ``frozen variable objects''.  Such variable objects are never
+implicitly updated.  
 
 The following is the complete set of @sc{gdb/mi} operations defined to
 access this functionality:
@@ -19632,6 +19647,8 @@ access this functionality:
 @tab set the value of this variable
 @item @code{-var-update}
 @tab update the variable and its children
+@item @code{-var-set-frozen}
+@tab set frozeness attribute
 @end multitable
 
 In the next subsection we describe each operation in detail and suggest
@@ -19925,6 +19942,37 @@ type_changed="false"@}]
 (gdb)
 @end smallexample
 
+@subheading The @code{-var-set-frozen} Command
+@findex -var-set-frozen
+
+@subsubheading Synopsis
+
+@smallexample
+ -var-set-frozen @var{name} @samp{flag}
+@end smallexample
+
+Set the frozeness flag on the variable object @var{name}.  The
+@samp{flag} parameter should be either @samp{1} to make the variable
+frozen or @samp{0} to make it unfozen.  If a variable object is
+frozen, then neither itself, nor any of its children, are 
+implicitly updated by @code{-var-update} of a parent variable or
+by @code{-var-update *}.  Only
+@code{-var-update} of the variable itself will update its value and
+values of its children.  After a variable object is unfrozen, it is
+implicitly updated by all subsequent @code{-var-update} operations.  
+Unfreezing a variable does not update it, only subsequent
+@code{-var-update} does.
+
+@subsubheading Example
+
+@smallexample
+(gdb)
+-var-set-frozen V 1
+^done
+(gdb)
+@end smallexample
+
+
 @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 @node GDB/MI Data Manipulation
 @section @sc{gdb/mi} Data Manipulation
--- gdb/testsuite/gdb.mi/mi-var-cmd.exp	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/testsuite/gdb.mi/mi-var-cmd.exp	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -586,5 +586,19 @@ mi_gdb_test "-var-update selected_a" \
 	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
 	"update selected_a in do_special_tests"
 
+mi_varobj_delete selected_a
+mi_varobj_delete array_ptr
+
+proc set_frozen {varobjs flag} {
+    foreach v $varobjs {
+        mi_gdb_test "-var-set-frozen $v $flag" \
+            "\\^done" \
+            "-var-set-frozen $v $flag"
+    }
+}
+
+mi_prepare_inline_tests $srcfile
+mi_run_inline_test frozen
+
 mi_gdb_exit
 return 0
--- gdb/testsuite/gdb.mi/var-cmd.c	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/testsuite/gdb.mi/var-cmd.c	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -315,6 +315,92 @@ do_special_tests (void)
   incr_a(2);
 }
 
+void do_frozen_tests ()
+{
+  /*: BEGIN: frozen :*/
+  struct {
+    int i;
+    struct {
+      int j;
+      int k;
+    } nested;
+  } v1 = {1, {2, 3}};
+
+  int v2 = 4;
+  /*: 
+    mi_create_varobj V1 v1 "create varobj for v1" 
+    mi_create_varobj V2 v2 "create varobj for v2"
+
+    mi_list_varobj_children "V1" {
+        {"V1.i" "i" "0" "int"}
+	{"V1.nested" "nested" "2" "struct {...}"}
+    } "list children of v1"
+
+    mi_list_varobj_children "V1.nested" {
+        {"V1.nested.j" "j" "0" "int"}
+        {"V1.nested.k" "k" "0" "int"}
+    } "list children of v1.nested"
+
+    mi_check_varobj_value V1.i 1 "check V1.i: 1"
+    mi_check_varobj_value V1.nested.j 2 "check V1.nested.j: 2"
+    mi_check_varobj_value V1.nested.k 3 "check V1.nested.j: 3"
+    mi_check_varobj_value V2 4 "check V2: 4"
+  :*/
+  v2 = 5;
+  /*: 
+    mi_varobj_update * {V2} "update varobjs: V2 changed"
+    set_frozen V2 1
+  :*/
+  v2 = 6;
+  /*: 
+    mi_varobj_update * {} "update varobjs: nothing changed"
+    mi_check_varobj_value V2 5 "check V2: 5"
+    mi_varobj_update V2 {V2} "update V2 explicitly"
+    mi_check_varobj_value V2 6 "check V2: 6"
+  :*/
+  v1.i = 7;
+  v1.nested.j = 8;
+  v1.nested.k = 9;
+  /*:
+    set_frozen V1 1
+    mi_varobj_update * {} "update varobjs: nothing changed"
+    mi_check_varobj_value V1.i 1 "check V1.i: 1"
+    mi_check_varobj_value V1.nested.j 2 "check V1.nested.j: 2"
+    mi_check_varobj_value V1.nested.k 3 "check V1.nested.j: 3"    
+    # Check that explicit update for elements of structures
+    # works.
+    # Update v1.j
+    mi_varobj_update V1.nested.j {V1.nested.j} "update V1.nested.j"
+    mi_check_varobj_value V1.i 1 "check V1.i: 1"
+    mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
+    mi_check_varobj_value V1.nested.k 3 "check V1.nested.j: 3"    
+    # Update v1.nested, check that children is updated.
+    mi_varobj_update V1.nested {V1.nested.k} "update V1.nested"
+    mi_check_varobj_value V1.i 1 "check V1.i: 1"
+    mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
+    mi_check_varobj_value V1.nested.k 9 "check V1.nested.j: 9"    
+    # Update v1.i
+    mi_varobj_update V1.i {V1.i} "update V1.i"
+    mi_check_varobj_value V1.i 7 "check V1.i: 7"
+  :*/
+  v1.i = 10;
+  v1.nested.j = 11;
+  v1.nested.k = 12;
+  /*:
+    # Check that unfreeze itself does not updates the values.
+    set_frozen V1 0
+    mi_check_varobj_value V1.i 7 "check V1.i: 7"
+    mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
+    mi_check_varobj_value V1.nested.k 9 "check V1.nested.j: 9"    
+    mi_varobj_update V1 {V1.i V1.nested.j V1.nested.k} "update V1"
+    mi_check_varobj_value V1.i 10 "check V1.i: 10"
+    mi_check_varobj_value V1.nested.j 11 "check V1.nested.j: 11"
+    mi_check_varobj_value V1.nested.k 12 "check V1.nested.j: 12"    
+  :*/    
+  
+  /*: END: frozen :*/
+}
+
 int
 main (int argc, char *argv [])
 {
@@ -322,6 +408,7 @@ main (int argc, char *argv [])
   do_block_tests ();
   do_children_tests ();
   do_special_tests ();
+  do_frozen_tests ();
   exit (0);
 }
 
--- gdb/testsuite/lib/mi-support.exp	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/testsuite/lib/mi-support.exp	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -1013,6 +1013,12 @@ proc mi_create_varobj { name expression 
         $testname
 }
 
+proc mi_varobj_delete { name } {
+    mi_gdb_test "-var-delete $name" \
+        "\\^done,ndeleted=\"1\"" \
+        "-var-delete $name"
+}
+
 # Updates varobj named NAME and checks that all varobjs in EXPECTED
 # are reported as updated, and no other varobj is updated.
 # Assumes that no varobj is out of scope and that no varobj changes
@@ -1022,8 +1028,9 @@ proc mi_varobj_update { name expected te
     set first 1
     foreach item $expected {
         set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\"}"
-        if {$first} {
+        if {$first == 1} {
             set er "$er$v"
+            set first 0
         } else {
             set er "$er,$v"
         }
--- gdb/mi/mi-cmds.h	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/mi/mi-cmds.h	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -112,6 +112,7 @@ extern mi_cmd_argv_ftype mi_cmd_var_info
 extern mi_cmd_argv_ftype mi_cmd_var_info_type;
 extern mi_cmd_argv_ftype mi_cmd_var_list_children;
 extern mi_cmd_argv_ftype mi_cmd_var_set_format;
+extern mi_cmd_argv_ftype mi_cmd_var_set_frozen;
 extern mi_cmd_argv_ftype mi_cmd_var_show_attributes;
 extern mi_cmd_argv_ftype mi_cmd_var_show_format;
 extern mi_cmd_argv_ftype mi_cmd_var_update;
--- gdb/mi/mi-cmds.c	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/mi/mi-cmds.c	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -160,6 +160,7 @@ struct mi_cmd mi_cmds[] =
   { "var-info-type", { NULL, 0 }, 0, mi_cmd_var_info_type},
   { "var-list-children", { NULL, 0 }, 0, mi_cmd_var_list_children},
   { "var-set-format", { NULL, 0 }, 0, mi_cmd_var_set_format},
+  { "var-set-frozen", { NULL, 0 }, 0, mi_cmd_var_set_frozen},
   { "var-show-attributes", { NULL, 0 }, 0, mi_cmd_var_show_attributes},
   { "var-show-format", { NULL, 0 }, 0, mi_cmd_var_show_format},
   { "var-update", { NULL, 0 }, 0, mi_cmd_var_update},
--- gdb/mi/mi-cmd-var.c	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/mi/mi-cmd-var.c	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -37,7 +37,8 @@ const char mi_all_values[] = "--all-valu
 extern int varobjdebug;		/* defined in varobj.c */
 
 static int varobj_update_one (struct varobj *var,
-			      enum print_values print_values);
+			      enum print_values print_values,
+			      int explicit);
 
 static int mi_print_value_p (struct type *type, enum print_values print_values);
 
@@ -64,6 +65,9 @@ print_varobj (struct varobj *var, enum p
       ui_out_field_string (uiout, "type", type);
       xfree (type);
     }
+
+  if (varobj_get_frozen (var))
+    ui_out_field_int (uiout, "frozen", 1);
 }
 
 /* VAROBJ operations */
@@ -233,6 +237,35 @@ mi_cmd_var_set_format (char *command, ch
 }
 
 enum mi_cmd_result
+mi_cmd_var_set_frozen (char *command, char **argv, int argc)
+{
+  struct varobj *var;
+  int frozen;
+
+  if (argc != 2)
+    error (_("mi_cmd_var_set_format: Usage: NAME FROZEN_FLAG."));
+
+  var = varobj_get_handle (argv[0]);
+  if (var == NULL)
+    error (_("Variable object not found"));
+
+  if (strcmp (argv[1], "0") == 0)
+    frozen = 0;
+  else if (strcmp (argv[1], "1") == 0)
+    frozen = 1;
+  else
+    error (_("Invalid flag value"));
+
+  varobj_set_frozen (var, frozen);
+
+  /* We don't automatically return the new value, or what varobjs got new
+     values during unfreezing.  If this information is required, client
+     should call -var-update explicitly.  */
+  return MI_CMD_DONE;
+}
+
+
+enum mi_cmd_result
 mi_cmd_var_show_format (char *command, char **argv, int argc)
 {
   enum varobj_display_formats format;
@@ -513,7 +546,7 @@ mi_cmd_var_update (char *command, char *
       cr = rootlist;
       while (*cr != NULL)
 	{
-	  varobj_update_one (*cr, print_values);
+	  varobj_update_one (*cr, print_values, 0 /* implicit */);
 	  cr++;
 	}
       do_cleanups (cleanup);
@@ -529,7 +562,7 @@ mi_cmd_var_update (char *command, char *
         cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "changelist");
       else
         cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changelist");
-      varobj_update_one (var, print_values);
+      varobj_update_one (var, print_values, 1 /* explicit */);
       do_cleanups (cleanup);
     }
     return MI_CMD_DONE;
@@ -540,14 +573,15 @@ mi_cmd_var_update (char *command, char *
    scope), and 1 if it succeeds. */
 
 static int
-varobj_update_one (struct varobj *var, enum print_values print_values)
+varobj_update_one (struct varobj *var, enum print_values print_values,
+		   int explicit)
 {
   struct varobj **changelist;
   struct varobj **cc;
   struct cleanup *cleanup = NULL;
   int nc;
 
-  nc = varobj_update (&var, &changelist);
+  nc = varobj_update (&var, &changelist, explicit);
 
   /* nc == 0 means that nothing has changed.
      nc == -1 means that an error occured in updating the variable.
--- gdb/varobj.c	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/varobj.c	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -126,6 +126,16 @@ struct varobj
 
   /* Was this variable updated via a varobj_set_value operation */
   int updated;
+
+  /* Is this variable frozen. Frozen variables are never implicitly
+     updated by -var-update * or -var-update <direct-or-indirect-parent>.
+  */
+  int frozen;
+
+  /* Is the value of this variable intentionally not fetched?  It is
+     not fetched if either the variable is frozen, or any parents is
+     frozen.  */
+  int not_fetched;
 };
 
 /* Every variable keeps a linked list of its children, described
@@ -678,6 +688,26 @@ varobj_get_display_format (struct varobj
   return var->format;
 }
 
+void
+varobj_set_frozen (struct varobj *var, int frozen)
+{
+  /* When a variable is unfrozen, we don't fetch its value.
+     The 'not_fetched' flag remains set, so next -var-update
+     won't complain.
+
+     We don't fetch the value, because for structures the client
+     should do -var-update anyway.  It would be bad to have different
+     client-size logic for structure and other types.  */
+  var->frozen = frozen;
+}
+
+int
+varobj_get_frozen (struct varobj *var)
+{
+  return var->frozen;
+}
+
+
 int
 varobj_get_num_children (struct varobj *var)
 {
@@ -906,6 +936,7 @@ install_new_value (struct varobj *var, s
   int changeable;
   int need_to_fetch;
   int changed = 0;
+  int intentionally_not_fetched = 0;
 
   var->error = 0;
   /* We need to know the varobj's type to decide if the value should
@@ -939,10 +970,23 @@ install_new_value (struct varobj *var, s
   /* The new value might be lazy.  If the type is changeable,
      that is we'll be comparing values of this type, fetch the
      value now.  Otherwise, on the next update the old value
-     will be lazy, which means we've lost that old value.  */
+     will be lazy, which means we've lost that old value.  */     
   if (need_to_fetch && value && value_lazy (value))
     {
-      if (!gdb_value_fetch_lazy (value))
+      struct varobj *parent = var->parent;
+      int frozen = var->frozen;
+      for (; !frozen && parent; parent = parent->parent)
+	frozen |= parent->frozen;
+
+      if (frozen && initial)
+	{
+	  /* For variables that are frozen, or are children of frozen
+	     variables, we don't do fetch on initial assignment.
+	     For non-initial assignemnt we do the fetch, since it means we're
+	     explicitly asked to compare the new value with the old one.  */
+	  intentionally_not_fetched = 1;
+	}
+      else if (!gdb_value_fetch_lazy (value))
 	{
 	  var->error = 1;
 	  /* Set the value to NULL, so that for the next -var-update,
@@ -969,28 +1013,43 @@ install_new_value (struct varobj *var, s
 	{
 	  /* Try to compare the values.  That requires that both
 	     values are non-lazy.  */
-	  
-	  /* Quick comparison of NULL values.  */
-	  if (var->value == NULL && value == NULL)
-	    /* Equal. */
-	    ;
-	  else if (var->value == NULL || value == NULL)
-	    changed = 1;
-	  else
+	  if (var->not_fetched && value_lazy (var->value))
 	    {
-	      gdb_assert (!value_lazy (var->value));
-	      gdb_assert (!value_lazy (value));
-	      
-	      if (!value_contents_equal (var->value, value))
+	      /* This is a frozen varobj and the value was never read.
+		 Presumably, UI shows some "never read" indicator.
+		 Now that we've fetched the real value, we need to report
+		 this varobj as changed so that UI can show the real
+		 value.  */
+	      changed = 1;
+	    }
+	  else
+	    {	  
+	      /* Quick comparison of NULL values.  */
+	      if (var->value == NULL && value == NULL)
+		/* Equal. */
+		;
+	      else if (var->value == NULL || value == NULL)
 		changed = 1;
+	      else
+		{
+		  gdb_assert (!value_lazy (var->value));
+		  gdb_assert (!value_lazy (value));
+		  
+		  if (!value_contents_equal (var->value, value))
+		    changed = 1;
+		}
 	    }
 	}
     }
     
   /* We must always keep the new value, since children depend on it.  */
-  if (var->value != NULL)
+  if (var->value != NULL && var->value != value)
     value_free (var->value);
   var->value = value;
+  if (value && value_lazy (value) && intentionally_not_fetched)
+    var->not_fetched = 1;
+  else
+    var->not_fetched = 0;
   var->updated = 0;
   
   gdb_assert (!var->value || value_type (var->value));
@@ -1009,18 +1068,22 @@ install_new_value (struct varobj *var, s
     -2 if the type changed
     Otherwise it is the number of children + parent changed
 
-   Only root variables can be updated... 
+   The EXPLICIT parameter specifies if this call is result
+   of MI request to update this specific variable, or 
+   result of implicit -var-update *. For implicit request, we don't
+   update frozen variables.
 
    NOTE: This function may delete the caller's varobj. If it
    returns -2, then it has done this and VARP will be modified
    to point to the new varobj. */
 
 int
-varobj_update (struct varobj **varp, struct varobj ***changelist)
+varobj_update (struct varobj **varp, struct varobj ***changelist,
+	       int explicit)
 {
   int changed = 0;
   int error = 0;
-  int type_changed;
+  int type_changed = 0;
   int i;
   int vleft;
   struct varobj *v;
@@ -1036,64 +1099,69 @@ varobj_update (struct varobj **varp, str
   if (changelist == NULL)
     return -1;
 
-  /*  Only root variables can be updated... */
-  if ((*varp)->root->rootvar != *varp)
-    /* Not a root var */
-    return -1;
+
+  /* Frozen means frozen -- we don't check for any change in
+     this varobj, including its going out of scope, or
+     changing type.  One use case for frozen varobjs is
+     retaining previously evaluated expressions, and we don't
+     want them to be reevaluated at all.  */
+  if (!explicit && (*varp)->frozen)
+    return 0;
 
   /* Save the selected stack frame, since we will need to change it
      in order to evaluate expressions. */
   old_fid = get_frame_id (deprecated_selected_frame);
 
-  /* Update the root variable. value_of_root can return NULL
-     if the variable is no longer around, i.e. we stepped out of
-     the frame in which a local existed. We are letting the 
-     value_of_root variable dispose of the varobj if the type
-     has changed. */
-  type_changed = 1;
-  new = value_of_root (varp, &type_changed);
-
-  /* Restore selected frame */
-  fi = frame_find_by_id (old_fid);
-  if (fi)
-    select_frame (fi);
-
-  if (new == NULL)
-    {
-      (*varp)->error = 1;
-      return -1;
-    }
-
   /* Initialize a stack for temporary results */
   vpush (&result, NULL);
 
-  /* If this is a "use_selected_frame" varobj, and its type has changed,
-     them note that it's changed. */
-  if (type_changed)
-    {
-      vpush (&result, *varp);
-      changed++;
-    }
-
-  if (install_new_value ((*varp), new, type_changed))
-    {
-      /* If type_changed is 1, install_new_value will never return
-	 non-zero, so we'll never report the same variable twice.  */
-      gdb_assert (!type_changed);
-      vpush (&result, (*varp));
-      changed++;
-    }
-
-  /* Initialize a stack */
+  /* Initialize a stack for traversing children.  */
   vpush (&stack, NULL);
 
-  /* Push the root's children */
-  if ((*varp)->children != NULL)
+  if ((*varp)->root->rootvar == *varp)
     {
-      struct varobj_child *c;
-      for (c = (*varp)->children; c != NULL; c = c->next)
-	vpush (&stack, c->child);
+      /* Update the root variable. value_of_root can return NULL
+	 if the variable is no longer around, i.e. we stepped out of
+	 the frame in which a local existed. We are letting the 
+	 value_of_root variable dispose of the varobj if the type
+	 has changed. */
+      type_changed = 1;
+      new = value_of_root (varp, &type_changed);
+      if (new == NULL)
+	{
+	  (*varp)->error = 1;
+	  return -1;
+	}
+      
+      /* If this is a "use_selected_frame" varobj, and its type has changed,
+	 them note that it's changed. */
+      if (type_changed)
+	{
+	  vpush (&result, *varp);
+	  changed++;
+	}
+      
+      if (install_new_value ((*varp), new, type_changed))
+	{
+	  /* If type_changed is 1, install_new_value will never return
+	     non-zero, so we'll never report the same variable twice.  */
+	  gdb_assert (!type_changed);
+	  vpush (&result, (*varp));
+	  changed++;
+	}
+      
+      /* Push the root's children */
+      if ((*varp)->children != NULL)
+	{
+	  struct varobj_child *c;
+	  for (c = (*varp)->children; c != NULL; c = c->next)
+	    if (!c->child->frozen)
+	      vpush (&stack, c->child);
+	}
     }
+  else
+    vpush (&stack, *varp);
+
 
   /* Walk through the children, reconstructing them all. */
   v = vpop (&stack);
@@ -1104,9 +1172,10 @@ varobj_update (struct varobj **varp, str
 	{
 	  struct varobj_child *c;
 	  for (c = v->children; c != NULL; c = c->next)
-	    vpush (&stack, c->child);
+	    if (!c->child->frozen)
+	      vpush (&stack, c->child);
 	}
-
+      
       /* Update this variable */
       new = value_of_child (v->parent, v->index);
       if (install_new_value (v, new, 0 /* type not changed */))
@@ -1470,6 +1539,8 @@ new_variable (void)
   var->format = 0;
   var->root = NULL;
   var->updated = 0;
+  var->frozen = 0;
+  var->not_fetched = 0;
 
   return var;
 }
@@ -2153,6 +2224,12 @@ c_value_of_variable (struct varobj *var)
 	    struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
 	    char *thevalue;
 
+	    if (var->not_fetched && value_lazy (var->value))
+	      /* Frozen variable and no value yet.  We don't
+		 implicitly fetch the value.  MI response will
+		 use empty string for the value, which is OK.  */
+	      return NULL;
+
 	    gdb_assert (type_changeable (var));
 	    gdb_assert (!value_lazy (var->value));
 	    common_val_print (var->value, stb,
--- gdb/varobj.h	(/patches/gdb/varobj_doc/gdb_mainline)	(revision 2761)
+++ gdb/varobj.h	(/patches/gdb/frozen/gdb_mainline)	(revision 2761)
@@ -78,6 +78,10 @@ extern enum varobj_display_formats varob
 extern enum varobj_display_formats varobj_get_display_format (
 							struct varobj *var);
 
+extern void varobj_set_frozen (struct varobj *var, int frozen);
+
+extern int varobj_get_frozen (struct varobj *var);
+
 extern int varobj_get_num_children (struct varobj *var);
 
 extern int varobj_list_children (struct varobj *var,
@@ -97,6 +101,7 @@ extern int varobj_set_value (struct varo
 
 extern int varobj_list (struct varobj ***rootlist);
 
-extern int varobj_update (struct varobj **varp, struct varobj ***changelist);
+extern int varobj_update (struct varobj **varp, struct varobj ***changelist,
+			  int explicit);
 
 #endif /* VAROBJ_H */

Property changes on: 
___________________________________________________________________
Name: csl:base
 -/all/patches/gdb/mi_inline_tests/gdb_mainline
 +/all/patches/gdb/varobj_doc/gdb_mainline
  
Name: svk:merge
  d48a11ec-ee1c-0410-b3f5-c20844f99675:/patches/gdb/mi_continue_to/gdb_mainline:2736
  d48a11ec-ee1c-0410-b3f5-c20844f99675:/patches/gdb/mi_inline_tests/gdb_mainline:2758
 +d48a11ec-ee1c-0410-b3f5-c20844f99675:/patches/gdb/varobj_doc/gdb_mainline:2759
 +e7755896-6108-0410-9592-8049d3e74e28:/mirrors/gdb/trunk:157978


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