gdb/
[deliverable/binutils-gdb.git] / gdb / varobj.c
index f3d3b5abef637cb1fe7f2673aea4a6546770c035..e8556d78fd3d6f62d647a81657c5bbb644c38e26 100644 (file)
@@ -1,7 +1,7 @@
 /* Implementation of the GDB variable objects API.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include "wrapper.h"
 #include "gdbcmd.h"
 #include "block.h"
+#include "valprint.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
@@ -430,14 +431,15 @@ find_frame_addr_in_frame_chain (CORE_ADDR frame_addr)
   if (frame_addr == (CORE_ADDR) 0)
     return NULL;
 
-  while (1)
+  for (frame = get_current_frame ();
+       frame != NULL;
+       frame = get_prev_frame (frame))
     {
-      frame = get_prev_frame (frame);
-      if (frame == NULL)
-       return NULL;
       if (get_frame_base_address (frame) == frame_addr)
        return frame;
     }
+
+  return NULL;
 }
 
 struct varobj *
@@ -459,22 +461,27 @@ varobj_create (char *objname,
       char *p;
       enum varobj_languages lang;
       struct value *value = NULL;
-      int expr_len;
 
-      /* Parse and evaluate the expression, filling in as much
-         of the variable's data as possible */
+      /* Parse and evaluate the expression, filling in as much of the
+         variable's data as possible.  */
 
-      /* Allow creator to specify context of variable */
-      if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
-       fi = deprecated_safe_get_selected_frame ();
+      if (has_stack_frames ())
+       {
+         /* Allow creator to specify context of variable */
+         if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
+           fi = get_selected_frame (NULL);
+         else
+           /* FIXME: cagney/2002-11-23: This code should be doing a
+              lookup using the frame ID and not just the frame's
+              ``address''.  This, of course, means an interface
+              change.  However, with out that interface change ISAs,
+              such as the ia64 with its two stacks, won't work.
+              Similar goes for the case where there is a frameless
+              function.  */
+           fi = find_frame_addr_in_frame_chain (frame);
+       }
       else
-       /* FIXME: cagney/2002-11-23: This code should be doing a
-          lookup using the frame ID and not just the frame's
-          ``address''.  This, of course, means an interface change.
-          However, with out that interface change ISAs, such as the
-          ia64 with its two stacks, won't work.  Similar goes for the
-          case where there is a frameless function.  */
-       fi = find_frame_addr_in_frame_chain (frame);
+       fi = NULL;
 
       /* frame = -2 means always use selected frame */
       if (type == USE_SELECTED_FRAME)
@@ -504,10 +511,9 @@ varobj_create (char *objname,
 
       var->format = variable_default_display (var);
       var->root->valid_block = innermost_block;
-      expr_len = strlen (expression);
-      var->name = savestring (expression, expr_len);
+      var->name = xstrdup (expression);
       /* For a root var, the name and the expr are the same.  */
-      var->path_expr = savestring (expression, expr_len);
+      var->path_expr = xstrdup (expression);
 
       /* When the frame is different from the current frame, 
          we must select the appropriate frame before parsing
@@ -553,7 +559,7 @@ varobj_create (char *objname,
 
   if ((var != NULL) && (objname != NULL))
     {
-      var->obj_name = savestring (objname, strlen (objname));
+      var->obj_name = xstrdup (objname);
 
       /* If a varobj name is duplicated, the install will fail so
          we must clenup */
@@ -583,8 +589,8 @@ varobj_gen_name (void)
   return obj_name;
 }
 
-/* Given an "objname", returns the pointer to the corresponding varobj
-   or NULL if not found */
+/* Given an OBJNAME, returns the pointer to the corresponding varobj.  Call
+   error if OBJNAME cannot be found.  */
 
 struct varobj *
 varobj_get_handle (char *objname)
@@ -693,7 +699,7 @@ varobj_set_display_format (struct varobj *var,
   if (varobj_value_is_changeable_p (var) 
       && var->value && !value_lazy (var->value))
     {
-      free (var->print_value);
+      xfree (var->print_value);
       var->print_value = value_get_print_value (var->value, var->format);
     }
 
@@ -974,9 +980,12 @@ varobj_list (struct varobj ***varlist)
    this is the first assignement after the variable object was just
    created, or changed type.  In that case, just assign the value 
    and return 0.
-   Otherwise, assign the value and if type_changeable returns non-zero,
-   find if the new value is different from the current value.
-   Return 1 if so, and 0 if the values are equal.  
+   Otherwise, assign the new value, and return 1 if the value is different
+   from the current one, 0 otherwise. The comparison is done on textual
+   representation of value. Therefore, some types need not be compared. E.g.
+   for structures the reported value is always "{...}", so no comparison is
+   necessary here. If the old value was NULL and new one is not, or vice versa,
+   we always return 1.
 
    The VALUE parameter should not be released -- the function will
    take care of releasing it when needed.  */
@@ -1097,6 +1106,15 @@ install_new_value (struct varobj *var, struct value *value, int initial)
        }
     }
 
+  if (!initial && !changeable)
+    {
+      /* For values that are not changeable, we don't compare the values.
+        However, we want to notice if a value was not NULL and now is NULL,
+        or vise versa, so that we report when top-level varobjs come in scope
+        and leave the scope.  */
+      changed = (var->value != NULL) != (value != NULL);
+    }
+
   /* We must always keep the new value, since children depend on it.  */
   if (var->value != NULL && var->value != value)
     value_free (var->value);
@@ -1120,9 +1138,6 @@ install_new_value (struct varobj *var, struct value *value, int initial)
    expression to see if it's changed.  Then go all the way
    through its children, reconstructing them and noting if they've
    changed.
-   Return value: 
-    < 0 for error values, see varobj.h.
-    Otherwise it is the number of children + parent changed.
 
    The EXPLICIT parameter specifies if this call is result
    of MI request to update this specific variable, or 
@@ -1133,9 +1148,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
    returns TYPE_CHANGED, 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,
-              int explicit)
+VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
 {
   int changed = 0;
   int type_changed = 0;
@@ -1146,52 +1159,50 @@ varobj_update (struct varobj **varp, struct varobj ***changelist,
   struct varobj **templist = NULL;
   struct value *new;
   VEC (varobj_p) *stack = NULL;
-  VEC (varobj_p) *result = NULL;
+  VEC (varobj_update_result) *result = NULL;
   struct frame_info *fi;
 
-  /* sanity check: have we been passed a pointer?  */
-  gdb_assert (changelist);
-
   /* 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;
+    return result;
 
   if (!(*varp)->root->is_valid)
-    return INVALID;
+    {
+      varobj_update_result r = {*varp};
+      r.status = VAROBJ_INVALID;
+      VEC_safe_push (varobj_update_result, result, &r);
+      return result;
+    }
 
   if ((*varp)->root->rootvar == *varp)
     {
+      varobj_update_result r = {*varp};
+      r.status = VAROBJ_IN_SCOPE;
+
       /* 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.  */
       new = value_of_root (varp, &type_changed);
-      
-      /* If this is a floating varobj, and its type has changed,
-        them note that it's changed.  */
-      if (type_changed)
-       VEC_safe_push (varobj_p, result, *varp);
-      
-        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);
-           VEC_safe_push (varobj_p, result, *varp);
-         }
+      r.varobj = *varp;
 
+      r.type_changed = type_changed;
+      if (install_new_value ((*varp), new, type_changed))
+       r.changed = 1;
+      
       if (new == NULL)
-       {
-         /* This means the varobj itself is out of scope.
-            Report it.  */
-         VEC_free (varobj_p, result);
-         return NOT_IN_SCOPE;
-       }
+       r.status = VAROBJ_NOT_IN_SCOPE;
+
+      if (r.type_changed || r.changed)
+       VEC_safe_push (varobj_update_result, result, &r);
+
+      if (r.status == VAROBJ_NOT_IN_SCOPE)
+       return result;
     }
 
   VEC_safe_push (varobj_p, stack, *varp);
@@ -1221,32 +1232,16 @@ varobj_update (struct varobj **varp, struct varobj ***changelist,
          if (install_new_value (v, new, 0 /* type not changed */))
            {
              /* Note that it's changed */
-             VEC_safe_push (varobj_p, result, v);
+             varobj_update_result r = {v};
+             r.changed = 1;
+             VEC_safe_push (varobj_update_result, result, &r);
              v->updated = 0;
            }
        }
     }
 
-  /* Alloc (changed + 1) list entries.  */
-  changed = VEC_length (varobj_p, result);
-  *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *));
-  cv = *changelist;
-
-  for (i = 0; i < changed; ++i)
-    {
-      *cv = VEC_index (varobj_p, result, i);
-      gdb_assert (*cv != NULL);
-      ++cv;
-    }
-  *cv = 0;
-
   VEC_free (varobj_p, stack);
-  VEC_free (varobj_p, result);
-
-  if (type_changed)
-    return TYPE_CHANGED;
-  else
-    return changed;
+  return result;
 }
 \f
 
@@ -1527,10 +1522,12 @@ new_root_variable (void)
 static void
 free_variable (struct varobj *var)
 {
+  value_free (var->value);
+
   /* Free the expression if this is a root variable. */
   if (is_root_p (var))
     {
-      free_current_contents (&var->root->exp);
+      xfree (var->root->exp);
       xfree (var->root);
     }
 
@@ -1766,8 +1763,7 @@ value_of_root (struct varobj **var_handle, int *type_changed)
        }
       else
        {
-         tmp_var->obj_name =
-           savestring (var->obj_name, strlen (var->obj_name));
+         tmp_var->obj_name = xstrdup (var->obj_name);
          varobj_delete (var, NULL, 0);
 
          install_variable (tmp_var);
@@ -1814,6 +1810,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format)
   struct ui_file *stb;
   struct cleanup *old_chain;
   char *thevalue;
+  struct value_print_options opts;
 
   if (value == NULL)
     return NULL;
@@ -1821,7 +1818,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format)
   stb = mem_fileopen ();
   old_chain = make_cleanup_ui_file_delete (stb);
 
-  common_val_print (value, stb, format_code[(int) format], 1, 0, 0);
+  get_formatted_print_options (&opts, format_code[(int) format]);
+  opts.deref_ref = 0;
+  common_val_print (value, stb, 0, &opts, current_language);
   thevalue = ui_file_xstrdup (stb, &dummy);
 
   do_cleanups (old_chain);
@@ -1973,7 +1972,7 @@ c_number_of_children (struct varobj *var)
     {
     case TYPE_CODE_ARRAY:
       if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0
-         && TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED)
+         && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
        children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
       else
        /* If we don't know how many elements there are, don't display
@@ -2013,7 +2012,7 @@ c_number_of_children (struct varobj *var)
 static char *
 c_name_of_variable (struct varobj *parent)
 {
-  return savestring (parent->name, strlen (parent->name));
+  return xstrdup (parent->name);
 }
 
 /* Return the value of element TYPE_INDEX of a structure
@@ -2035,7 +2034,7 @@ value_struct_element_index (struct value *value, int type_index)
 
   TRY_CATCH (e, RETURN_MASK_ERROR)
     {
-      if (TYPE_FIELD_STATIC (type, type_index))
+      if (field_is_static (&TYPE_FIELD (type, type_index)))
        result = value_static_field (type, type_index);
       else
        result = value_primitive_field (value, 0, type_index, type);
@@ -2094,7 +2093,7 @@ c_describe_child (struct varobj *parent, int index,
        {
          int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
          struct value *indval = 
-           value_from_longest (builtin_type_int, (LONGEST) real_index);
+           value_from_longest (builtin_type_int32, (LONGEST) real_index);
          gdb_value_subscript (value, indval, cvalue);
        }
 
@@ -2112,10 +2111,7 @@ c_describe_child (struct varobj *parent, int index,
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
       if (cname)
-       {
-         char *string = TYPE_FIELD_NAME (type, index);
-         *cname = savestring (string, strlen (string));
-       }
+       *cname = xstrdup (TYPE_FIELD_NAME (type, index));
 
       if (cvalue && value)
        {
@@ -2220,8 +2216,7 @@ c_value_of_root (struct varobj **var_handle)
     /* Not a root var */
     return NULL;
 
-  back_to = make_cleanup_restore_current_thread (
-    inferior_ptid, get_frame_id (deprecated_safe_get_selected_frame ()));
+  back_to = make_cleanup_restore_current_thread ();
 
   /* Determine whether the variable is still around. */
   if (var->root->valid_block == NULL || var->root->floating)
@@ -2762,6 +2757,7 @@ When non-zero, varobj debugging is enabled."),
 /* Invalidate the varobjs that are tied to locals and re-create the ones that
    are defined on globals.
    Invalidated varobjs will be always printed in_scope="invalid".  */
+
 void 
 varobj_invalidate (void)
 {
@@ -2769,38 +2765,40 @@ varobj_invalidate (void)
   struct varobj **varp;
 
   if (varobj_list (&all_rootvarobj) > 0)
-  {
-    varp = all_rootvarobj;
-    while (*varp != NULL)
-      {
-       /* Floating varobjs are reparsed on each stop, so we don't care if
-          the presently parsed expression refers to something that's gone.  */
-       if ((*varp)->root->floating)
-         continue;
-
-        /* global var must be re-evaluated.  */     
-        if ((*varp)->root->valid_block == NULL)
-        {
-          struct varobj *tmp_var;
-
-          /* Try to create a varobj with same expression.  If we succeed replace
-             the old varobj, otherwise invalidate it.  */
-          tmp_var = varobj_create (NULL, (*varp)->name, (CORE_ADDR) 0, USE_CURRENT_FRAME);
-          if (tmp_var != NULL) 
-            { 
-             tmp_var->obj_name = xstrdup ((*varp)->obj_name);
-              varobj_delete (*varp, NULL, 0);
-              install_variable (tmp_var);
-            }
-          else
-              (*varp)->root->is_valid = 0;
-        }
-        else /* locals must be invalidated.  */
-          (*varp)->root->is_valid = 0;
-
-        varp++;
-      }
-    xfree (all_rootvarobj);
-  }
+    {
+      varp = all_rootvarobj;
+      while (*varp != NULL)
+       {
+         /* Floating varobjs are reparsed on each stop, so we don't care if
+            the presently parsed expression refers to something that's gone.
+            */
+         if ((*varp)->root->floating)
+           continue;
+
+         /* global var must be re-evaluated.  */     
+         if ((*varp)->root->valid_block == NULL)
+           {
+             struct varobj *tmp_var;
+
+             /* Try to create a varobj with same expression.  If we succeed
+                replace the old varobj, otherwise invalidate it.  */
+             tmp_var = varobj_create (NULL, (*varp)->name, (CORE_ADDR) 0,
+                                      USE_CURRENT_FRAME);
+             if (tmp_var != NULL) 
+               { 
+                 tmp_var->obj_name = xstrdup ((*varp)->obj_name);
+                 varobj_delete (*varp, NULL, 0);
+                 install_variable (tmp_var);
+               }
+             else
+               (*varp)->root->is_valid = 0;
+           }
+         else /* locals must be invalidated.  */
+           (*varp)->root->is_valid = 0;
+
+         varp++;
+       }
+    }
+  xfree (all_rootvarobj);
   return;
 }
This page took 0.031946 seconds and 4 git commands to generate.