Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Siva Chandra <sivachandra@google.com>
To: gdb-patches@sourceware.org
Subject: Re: [RFC] A new command 'explore'
Date: Wed, 08 Feb 2012 09:34:00 -0000	[thread overview]
Message-ID: <CAGyQ6gxfsOrZofwg-tvArXERiw2symHLoUzYy_fLfYsZtHk6Kg@mail.gmail.com> (raw)
In-Reply-To: <CAGyQ6gy+gXEZ=0eBeA8kt5nYO-C70igE3BqLi5KRFAqOYBvOXw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3431 bytes --]

Hello,

I have not yet seen anything about a policy on contributions
implemented in extension languages. However, I have now implemented
the 'explore' command in C. The patch is attached. I will add
documentation after the basics of this patch are approved.

2012-02-08 Siva Chandra <sivachandra@google.com>

        New command 'explore' which helps explore values in scope.
        * explore.c: Implemention of the 'explore' command.
        * Makefile.in: Add rules for compiling and linked explore.c.
        * testsuite/gdb.base/explore.c: C program used for testing
        the new 'explore' command.
        * testsuite/gdb.base/explore.exp: Tests for the new 'explore'
        command.
        * testsuite/gdb.base/Makefile.in: Add explore to EXECUTABLES

To recollect, the idea behind the 'explore' command is as follows:
Often, when exploring a new code base which has complicated data
structures, we would like to explore the data structure values
top-down. For example, if a struct is part of a struct/union is part
of another struct/union, then we typically explore the top-level
struct/union in the first pass. In subsequent passes, we might want to
go deeper by exploring the structs/unions embedded in the top level
struct. We might infact want to explore all the way up to the leaf
values. The ‘explore’ command enables a user to do such a top-down
exploration of data structures interactively. Not only values, even
types can be explored in a similar fashion.

Example of value exploration:
========================
(gdb) explore cs
The value of 'cs' is of type 'struct ComplexStruct' with the following fields:
   s = <Enter 0 to explore this field of type 'struct SimpleStruct'>
   u = <Enter 1 to explore this field of type 'union SimpleUnion'>
  sa = <Enter 2 to explore this field of type 'SS [10]'>

Enter the field number of choice: 2
'cs.sa' is an array of elements of type 'SS'.
Enter the index you want to explore in 'cs.sa': 1
The value of '(cs.sa)[1]' is of type 'SS' which is a typedef of type
'struct SimpleStruct'.
The value of '(cs.sa)[1]' is of type 'struct SimpleStruct' with the
following fields:
  a = 1 .. (Value of type 'int')
  d = 11.1 .. (Value of type 'double')

Press enter to return to parent value:

Returning to parent value...

'cs.sa' is an array of elements of type 'SS'.
Enter the index you want to explore in 'cs.sa':
Returning to parent value...
The value of 'cs' is of type 'struct ComplexStruct' with the following fields:
   s = <Enter 0 to explore this field of type 'struct SimpleStruct'>
   u = <Enter 1 to explore this field of type 'union SimpleUnion'>
  sa = <Enter 2 to explore this field of type 'SS [10]'>

Enter the field number of choice:
(gdb)

Example of type exploration:
========================
(gdb) explore struct SimpleStruct
'struct SimpleStruct' has the following fields:
  a = <Enter 0 to explore this field of type 'int'>
  d = <Enter 1 to explore this field of type 'double'>

Enter the field number of choice: 1
field 'd' of 'struct SimpleStruct' is of a scalar type 'double'.
Press enter to return to enclosing type:

Returning to parent type...
'struct SimpleStruct' has the following fields:
  a = <Enter 0 to explore this field of type 'int'>
  d = <Enter 1 to explore this field of type 'double'>

Enter the field number of choice:
(gdb)

Thanks,
Siva Chandra

[-- Attachment #2: c_explore_command_patch_v1.txt --]
[-- Type: text/plain, Size: 50714 bytes --]

diff -rupN src/gdb/explore.c src_explore/src/gdb/explore.c
--- src/gdb/explore.c	1970-01-01 05:30:00.000000000 +0530
+++ src_explore/src/gdb/explore.c	2012-02-08 12:06:30.106071131 +0530
@@ -0,0 +1,1010 @@
+/* Implementation of the 'explore' command.
+
+   Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+
+/* For domain_enum */
+#include "symtab.h"
+
+#include "arch-utils.h"
+#include "command.h"
+#include "exceptions.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include "gdbtypes.h"
+#include "language.h"
+#include "ui-file.h"
+#include "value.h"
+#include "valprint.h"
+
+static void explore_value (struct value *, const char *, int);
+static void explore_type (struct type *, const char *, int);
+
+/* Different types of exploration.  */
+
+enum exploration_type
+{
+  /* For value exploration.  */
+  VALUE_EXPLORATION = 0,
+
+  /* For type exploration.  */
+  TYPE_EXPLORATION = 1
+};
+
+/* Return 1 if STR is all spaces. O otherwise.  */
+
+static int
+is_all_spaces (const char *str)
+{
+  int i;
+  int len = strlen (str);
+
+  for (i = 0; i < len; ++i)
+    {
+      if (str[i] != ' ')
+        {
+          return 0;
+        }
+    }
+
+  return 1;
+}
+
+static void
+strip_leading_spaces (char **str_ptr)
+{
+  char *str = *str_ptr;
+  for (; *str != '\0'; str++)
+    {
+      if (*str != ' ')
+        {
+          *str_ptr = str;
+          return;
+        }
+    }
+}
+
+/* Prompt the user to return the state of exploration to the
+   parent value. Used in value exploration.  */
+
+static void
+return_to_parent_value_prompt (void)
+{
+  xfree (gdb_readline (_("Press enter to return to parent value: ")));
+  printf_filtered ("\n");
+}
+
+/* Prompt the user to return the state of exploration to the
+   enclosing/parent type. Used in type exploration.  */
+
+static void
+return_to_parent_type_prompt (void)
+{
+  xfree (gdb_readline (_("Press enter to return to enclosing type: ")));
+  printf_filtered ("\n");
+}
+
+/* Print a message for the user informing that the the state of
+   exploration is moving to the parent value.  */
+
+static void
+return_to_parent_value (void)
+{
+  printf_filtered (_("Returning to parent value...\n"));
+}
+
+/* Print a message for the user informing that the the state of
+   exploration is moving to the parent/enclosing type.  */
+
+static void
+return_to_parent_type (void)
+{
+  printf_filtered (_("Returning to parent type...\n"));
+}
+
+/* Retrun the string representation of VAL. The returned value
+   should be cleaned up after use.  */
+
+static char *
+get_value_string (struct value *val)
+{
+  struct ui_file *mem_file = mem_fileopen ();
+  struct value_print_options opts;
+  char *val_string;
+
+  get_user_print_options (&opts);
+  common_val_print (val, mem_file, 0, &opts, current_language);
+  val_string = ui_file_xstrdup (mem_file, NULL);
+  
+  ui_file_delete (mem_file);
+  return val_string;
+}
+
+/* Return the type name of VAL_TYPE. The returned value should be cleaned up
+   after use.  */
+
+static char *
+get_type_name (struct type *val_type)
+{
+  struct ui_file *mem_file = mem_fileopen ();
+  char *type_name;
+
+  LA_PRINT_TYPE (val_type, "", mem_file, 0, 0);
+  type_name = ui_file_xstrdup (mem_file, NULL);
+
+  ui_file_delete (mem_file);
+  return type_name;
+}
+
+/* Add parentheses to an EXP_STR if required. The added parenthesis
+   serves as a guard which ensures proper operator precedence when, for
+   example, dereferencing the value of which EXP_STR evaluates to. The
+   returned value should be cleaned up after use.  */
+
+static char *
+guard_exp_str (const char *exp_str)
+{
+  int len = strlen (exp_str);
+  int i, guard = 0;
+  char *new_exp;
+
+  if (exp_str[0] == '(' && exp_str[len - 1] == ')')
+    {
+      ;
+    }
+  else
+    {
+      for (i = 0; i < len; i++)
+        {
+          char c = exp_str[i];
+          if (c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
+              || ('0' <= c && c <= '9'))
+            {
+              ;
+            }
+          else
+            {
+              guard = 1;
+              break;
+            }
+        }
+    }
+
+  if (guard)
+    {
+      new_exp = xstrprintf (_("(%s)"), exp_str);
+    }
+  else
+    {
+      new_exp = xstrprintf (_("%s"), exp_str);
+    }
+
+  return new_exp;
+}
+
+/* Return 1 if VAL_TYPE is a scalar type, 0 otherwise.  */
+
+static int
+is_scalar_type (struct type *val_type)
+{
+  switch (TYPE_CODE (val_type))
+    {
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_ENUM:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+/* Explore scalar value.  */
+
+static int
+explore_scalar_value (struct value *val, const char *exp_str, int is_child)
+{
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+
+  char *type_name = get_type_name (value_type (val));
+  char *val_str = get_value_string (val);
+  make_cleanup (xfree, type_name);
+  make_cleanup (xfree, val_str);
+
+  printf_filtered (_("'%s' is a scalar value of type '%s'.\n"), exp_str,
+                   type_name);
+  printf_filtered (_("%s = %s\n"), exp_str, val_str);
+
+  if (is_child)
+    {
+      return_to_parent_value_prompt ();
+      return_to_parent_value ();
+    }
+
+  do_cleanups (cleanup_obj);
+  return 0;
+}
+
+/* Explore scalar type.  */
+
+static int
+explore_scalar_type (struct type *type, const char *path, int is_child)
+{
+  if (is_child)
+    {
+      char *type_name = get_type_name (type);
+      printf_filtered (_("%s is of a scalar type '%s'.\n"), path, type_name);
+      return_to_parent_type_prompt ();
+      return_to_parent_type ();
+
+      xfree (type_name);
+    }
+  else
+    {
+      printf_filtered (_("'%s' is of a scalar type.\n"), path);
+    }
+
+  return 0;
+}
+
+/* Explore pointer value.  */
+
+static int
+explore_pointer_value (struct value *val, const char *exp_str, int is_child)
+{
+  struct value *deref_val = value_ind (val);
+  struct type *deref_type = value_type (deref_val);
+  char *resp1, *deref_type_name, *guarded_exp_str;
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+
+  deref_type_name = get_type_name (deref_type);
+  make_cleanup (xfree, deref_type_name);
+
+  guarded_exp_str = guard_exp_str (exp_str);
+  make_cleanup (xfree, guarded_exp_str);
+
+  printf_filtered (_("'%s' is a pointer to a value of type '%s'.\n"),
+                   exp_str, deref_type_name);
+
+  if (!can_dereference (value_type (val)))
+    {
+      printf_filtered (_("Cannot dereference '%s' for further exploration.\n"),
+                       exp_str);
+      if (is_child)
+        {
+          return_to_parent_value_prompt ();
+        }
+
+      return 0;
+    }
+
+  resp1 = gdb_readline (_("Do you want to explore it as an array or a single "
+                          "value pointer [a/s] : "));
+  make_cleanup (xfree, resp1);
+  if (strcmp (resp1, "a") == 0)
+    {
+      char *array_index_prompt = xstrprintf (_("Enter the index you want to "
+                                               "explore in '%s': "), exp_str);
+      make_cleanup (xfree, array_index_prompt);
+
+      while (1)
+        {
+          char *resp2 = gdb_readline (array_index_prompt);
+          make_cleanup (xfree, resp2);
+          strip_leading_spaces (&resp2);
+          if (resp2 && resp2[0] != '\0' && !is_all_spaces (resp2))
+            {
+              struct value *elem_val;
+              char *new_exp;
+
+              const char *endptr;
+              LONGEST index = strtoulst (resp2, &endptr, 10);
+              if (endptr == resp2)
+                {
+                  break;
+                }
+
+              elem_val = value_subscript (val, index);
+
+              new_exp = xstrprintf ("%s[%ld]", guarded_exp_str, index);
+              make_cleanup (xfree, new_exp);
+
+              explore_value (elem_val, new_exp, 1);
+            }
+          else
+            {
+              break;
+            }
+        }
+    }
+  else if (strcmp (resp1, "s") == 0)
+    {
+      char *new_exp = xstrprintf (_("*%s"), guarded_exp_str);
+      make_cleanup (xfree, new_exp);
+
+      explore_value (deref_val, new_exp, is_child);
+    }
+  else
+    {
+      if (is_child)
+        {
+          return_to_parent_value ();
+        }
+    }
+
+  do_cleanups (cleanup_obj);
+  return 0;
+}
+
+/* Explore pointer type.  */
+
+static int
+explore_pointer_type (struct type *type, const char *path, int is_child)
+{
+  struct type *target_type = TYPE_TARGET_TYPE (type);
+  char *type_name = get_type_name (target_type);
+  char *new_path = NULL;
+
+  printf_filtered (_("%s is of a pointer type pointing to a value of type "
+                     "'%s'.\n"), path, type_name);
+
+  new_path = xstrprintf (_("the pointee type of %s"), path);
+  explore_type (target_type, new_path, is_child);
+
+  xfree (type_name);
+  xfree (new_path);
+  return 0;
+}
+
+/* Explore array value.  */
+
+static int
+explore_array_value (struct value *val, const char *exp_str, int is_child)
+{
+  char *array_index_prompt, *resp, *guarded_exp_str;
+  struct type *elem_type = TYPE_TARGET_TYPE (value_type (val));
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+
+  char *elem_type_name = get_type_name (elem_type);
+  make_cleanup (xfree, elem_type_name);
+
+  guarded_exp_str = guard_exp_str (exp_str);
+  make_cleanup (xfree, guarded_exp_str);
+
+  printf_filtered ("'%s' is an array of elements of type '%s'.\n", exp_str,
+                   elem_type_name);
+
+  array_index_prompt = xstrprintf (_("Enter the index you want to explore "
+                                     "in '%s': "),
+                                   exp_str);
+  make_cleanup (xfree, array_index_prompt);
+
+  resp = gdb_readline (array_index_prompt);
+  make_cleanup (xfree, resp);
+  strip_leading_spaces (&resp);
+  if (resp && resp[0] != '\0' && !is_all_spaces(resp))
+    {
+      struct value *elem_val;
+      char *new_exp;
+
+      const char *endptr;
+      LONGEST index = strtoulst (resp, &endptr, 10);
+      if (endptr == resp)
+        {
+          do_cleanups (cleanup_obj);
+          return 0;
+        }
+
+      elem_val = value_subscript (val, index);
+
+      new_exp = xstrprintf ("%s[%ld]", guarded_exp_str, index);
+      make_cleanup (xfree, new_exp);
+
+      explore_value (elem_val, new_exp, 1);
+
+      do_cleanups (cleanup_obj);
+      return 1;
+    }  
+  else
+    {
+      if (is_child)
+        {
+          return_to_parent_value();
+        }
+
+      do_cleanups (cleanup_obj);
+      return 0;
+    }
+}
+
+/* Explore array type.  */
+
+static int
+explore_array_type (struct type *type, const char *path, int is_child)
+{
+  struct type *target_type = TYPE_TARGET_TYPE (type);
+  char *type_name = get_type_name (target_type);
+  char *new_path = NULL;
+
+  printf_filtered (_("%s is an array type with elements of type '%s'.\n"),
+                   path, type_name);
+
+  new_path = xstrprintf (_("the array element of %s"), path);
+  explore_type (target_type, new_path, is_child);
+
+  xfree (type_name);
+  xfree (new_path);
+  return 0;
+}
+
+struct field_desc
+{
+  const char *field_name;
+  struct value *field_value;
+  struct type *field_type;
+};
+
+/* Print fields of a compound type/value. FIELDS is an array of size NFIELDS.
+   PARENT_VAL_TYPE is the type_code of the compound type. It is either
+   TYPE_CODE_STRUCT or TYPE_CODE_UNION. EXPLR_TYPE indicates the exploration
+   type, VALUE_EXPLORATION or TYPE_EXPLORATION.  */
+
+static void
+print_fields (struct field_desc *fields, int nfields,
+              enum type_code parent_val_type,
+              enum exploration_type explr_type)
+{
+  int max_field_name_length = 0;
+  int i;
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+
+  for (i = 0; i < nfields; i++)
+    {
+      int field_name_length = strlen (fields[i].field_name);
+      if (field_name_length > max_field_name_length)
+        {
+          max_field_name_length = field_name_length;
+        }
+    }
+
+  for (i = 0; i < nfields; i++)
+    {
+      int spaces = max_field_name_length - strlen (fields[i].field_name);
+      struct type *field_type = fields[i].field_type;
+      char *field_type_name = get_type_name (field_type);
+      make_cleanup (xfree, field_type_name);
+
+      print_spaces_filtered (spaces + 2, gdb_stdout);
+      printf_filtered ("%s = ", fields[i].field_name);
+      
+      if (explr_type == VALUE_EXPLORATION && parent_val_type == TYPE_CODE_STRUCT
+          && is_scalar_type (field_type))
+        {
+          char *field_value_string = get_value_string (fields[i].field_value);
+          make_cleanup (xfree, field_value_string);
+
+          printf_filtered (_("%s .. (Value of type '%s')\n"),
+                           field_value_string, field_type_name);
+        }
+      else
+        {
+          printf_filtered (_("<Enter %d to explore this field of type '%s'>\n"),
+                           i, field_type_name);
+        }
+    }
+}
+
+/* Explore compound value. A compound value is a struct, class or a union
+   value.  */
+
+static int
+explore_compound_value (struct value *val, const char *exp_str, int is_child)
+{
+  struct type *val_type = value_type (val);
+  char *type_name;
+  enum type_code val_type_code = TYPE_CODE (val_type);
+  int nfields = TYPE_NFIELDS (val_type);
+  int i;
+  int further_exploration = (val_type_code == TYPE_CODE_UNION) ? 1 : 0;
+  struct field_desc *fields;
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+
+  fields = (struct field_desc *) xzalloc (nfields * sizeof (struct field_desc));
+  make_cleanup (xfree, fields);
+
+  type_name = get_type_name (val_type);
+  make_cleanup (xfree, type_name);
+
+  printf_filtered (_("The value of '%s' is of type '%s' with the following "
+                     "fields:\n"), exp_str, type_name);
+
+  for (i = 0; i < nfields; i++)
+    {
+      struct type *field_type = TYPE_FIELD_TYPE (val_type, i);
+      const char *field_name = TYPE_FIELD_NAME (val_type, i);
+
+      fields[i].field_name = field_name;
+      fields[i].field_value = value_field (val, i);
+      fields[i].field_type = field_type;
+
+      if (!is_scalar_type (field_type) && val_type_code == TYPE_CODE_STRUCT)
+        {
+          further_exploration = 1;
+        }
+    }
+
+  print_fields (fields, nfields, val_type_code, VALUE_EXPLORATION);
+
+  if (further_exploration)
+    {
+      char *choice_str = gdb_readline ("\nEnter the field number of choice: ");
+      make_cleanup (xfree, choice_str);
+      strip_leading_spaces (&choice_str);
+
+      if (choice_str && choice_str[0] != '\0' && !is_all_spaces (choice_str))
+        {
+          const char *endptr;
+          LONGEST choice = strtoulst (choice_str, &endptr, 10);
+          if (endptr != choice_str && choice >= 0 && choice < nfields)
+            {
+              char *guarded_exp_str = guard_exp_str (exp_str);
+              char *new_exp = xstrprintf ("%s.%s", guarded_exp_str,
+                                          fields[choice].field_name);
+              make_cleanup (xfree, new_exp);
+              make_cleanup (xfree, guarded_exp_str);
+
+              explore_value (fields[choice].field_value, new_exp, 1);
+
+              do_cleanups (cleanup_obj);
+              return 1;
+            }
+        }
+    }
+  else
+    {
+      if (is_child)
+        {
+          printf_filtered ("\n");
+          return_to_parent_value_prompt ();
+        }
+    }
+
+  if (is_child)
+    {
+      return_to_parent_value ();
+      printf_filtered ("\n");
+    }
+
+  do_cleanups (cleanup_obj);
+  return 0;
+}
+
+/* Explore compound type. A compound type is a struct, class or a union
+   type.  */
+
+static int
+explore_compound_type (struct type *type, const char *path, int is_child)
+{
+  char *type_name;
+  int nfields = TYPE_NFIELDS (type);
+  int i;
+  struct field_desc *fields;
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+  
+  fields = (struct field_desc *) xzalloc (nfields * sizeof (struct field_desc));
+  make_cleanup (xfree, fields);
+
+  type_name = get_type_name (type);
+  make_cleanup (xfree, type_name);
+
+  if (is_child)
+    {
+      printf_filtered (_("%s is of type '%s' with the following fields:\n"),
+                       path, type_name);
+    }
+  else
+    {
+      printf_filtered ("'%s' has the following fields:\n", path);
+    }
+
+  for (i = 0; i < nfields; i++)
+    {
+      fields[i].field_name = TYPE_FIELD_NAME (type, i);
+      fields[i].field_type = TYPE_FIELD_TYPE (type, i);
+      fields[i].field_value = NULL;
+    }
+
+  print_fields (fields, nfields, TYPE_CODE (type), TYPE_EXPLORATION);
+
+  if (nfields)
+    {
+      char *choice_str = gdb_readline (_("\nEnter the field number of "
+                                         "choice: "));
+      make_cleanup (xfree, choice_str);
+      strip_leading_spaces (&choice_str);
+
+      if (choice_str && choice_str[0] != '\0' && !is_all_spaces (choice_str))
+        {
+          const char *endptr;
+          LONGEST choice = strtoulst (choice_str, &endptr, 10);
+          if (endptr != choice_str && choice >= 0 && choice < nfields)
+            {
+              char *new_path;
+                if (is_child)
+                  {
+                    new_path  = xstrprintf (_("field '%s' of %s"),
+                                            fields[choice].field_name, path);
+                  }
+                else
+                  {
+                    new_path  = xstrprintf (_("field '%s' of '%s'"),
+                                            fields[choice].field_name, path);
+                  }
+              make_cleanup (xfree, new_path);
+
+              explore_type (fields[choice].field_type, new_path, 1);
+
+              do_cleanups (cleanup_obj);
+              return 1;
+            }
+        }
+    }
+  else
+    {
+      if (is_child)
+        {
+          printf_filtered ("\n");
+          return_to_parent_type_prompt ();
+        }
+    }
+
+  if (is_child)
+    {
+      return_to_parent_type ();
+      printf_filtered ("\n");
+    }
+
+  do_cleanups (cleanup_obj);
+  return 0;
+}
+
+/* Explore a value which of a typedef type.  */
+
+static int
+explore_typedef_value (struct value *val, const char *exp_str, int is_child)
+{
+  struct type *curr_type, *orig_type;
+  char *curr_type_name, *orig_type_name;
+  struct value *cast_value;
+  struct cleanup *cleanup_obj = make_cleanup (null_cleanup, NULL);
+
+  curr_type = value_type (val);
+  curr_type_name = get_type_name (curr_type);
+  make_cleanup (xfree, curr_type_name);
+
+  orig_type = check_typedef (curr_type);
+  orig_type_name = get_type_name (orig_type);
+  make_cleanup (xfree, orig_type_name);
+
+  printf_filtered (_("The value of '%s' is of type '%s' which is a typedef of "
+                     "type '%s'.\n"), exp_str, curr_type_name, orig_type_name);
+
+  cast_value = value_cast (orig_type, val);
+  explore_value (cast_value, exp_str, is_child);
+
+  do_cleanups (cleanup_obj);
+  return 0;
+}
+
+/* Explore a type which is a typedef of another type.  */
+
+static int
+explore_typedef_type (struct type *type, const char *path, int is_child)
+{
+  struct type *orig_type = check_typedef (type);
+  char *orig_type_name = get_type_name (orig_type);
+
+  if (is_child)
+    {
+      printf_filtered (_("The type of %s is a typedef of type '%s'.\n"), path,
+                       orig_type_name);
+    }
+  else
+    {
+      printf_filtered (_("The type '%s' is a typedef of type '%s'.\n"), path,
+                       orig_type_name);
+    }
+
+  explore_type (orig_type, path, is_child);
+  return 0;
+}
+
+/* Explore VAL of any type (or type_code). ARG_STR is the expression which
+   evaluates to VAL in the current language. IS_CHILD, in a way, denotes the
+   state of the exploration. IS_CHILD is 0 if ARG_STR is the same as the
+   expression string entered by the user, 1 otherwise. For example, the user
+   is probably exploring a variable 's' which is of a struct type with a
+   field 'a'. Then, during the exploration of s.a, the value of IS_CHILD will
+   be 1.  */
+
+static void
+explore_value (struct value *val, const char *arg_str, int is_child)
+{
+  struct type *val_type = value_type (val);
+  int repeat = 0;
+  char *type_name = NULL;
+
+  do
+    {
+      switch (TYPE_CODE (val_type))
+        {
+        case TYPE_CODE_INT:
+        case TYPE_CODE_FLT:
+        case TYPE_CODE_CHAR:
+        case TYPE_CODE_BOOL:
+        case TYPE_CODE_ENUM:
+          repeat = explore_scalar_value (val, arg_str, is_child);
+          break;
+        case TYPE_CODE_PTR:
+          repeat = explore_pointer_value (val, arg_str, is_child);
+          break;
+        case TYPE_CODE_ARRAY:
+          repeat = explore_array_value (val, arg_str, is_child);
+          break;
+        case TYPE_CODE_STRUCT:
+        case TYPE_CODE_UNION:
+          repeat = explore_compound_value (val, arg_str, is_child);
+          break;
+        case TYPE_CODE_TYPEDEF:
+          repeat = explore_typedef_value (val, arg_str, is_child);
+          break;
+        default:
+          type_name = get_type_name (val_type);
+          printf_filtered (_("Exploration of type '%s' of '%s' is not yet "
+                             "available.\n"), type_name, arg_str);
+          xfree (type_name);
+          break;
+        }
+    }
+  while (repeat);
+}
+
+/* Explore any type CURR_TYPE. PATH is the descriptive path to the entity
+   explored. IS_CHILD, in a way, denotes the state of the current exploration.
+   If CURR_TYPE is the type entered by the user, the IS_CHILD is 0, otherwise
+   it is 1. For example, when exploring the type of the field 'a' of a type
+   'struct S' (which was the actual type entered by the user), the value of
+   IS_CHILD will be 1.  */
+
+static void
+explore_type (struct type *curr_type, const char *path, int is_child)
+{
+  char *type_name = NULL;
+  int repeat = 0;
+  do
+    {
+      switch (TYPE_CODE (curr_type))
+        {
+        case TYPE_CODE_INT:
+        case TYPE_CODE_FLT:
+        case TYPE_CODE_CHAR:
+        case TYPE_CODE_BOOL:
+        case TYPE_CODE_ENUM:
+          repeat = explore_scalar_type (curr_type, path, is_child);
+          break;
+        case TYPE_CODE_PTR:
+          repeat = explore_pointer_type (curr_type, path, is_child);
+          break;
+        case TYPE_CODE_ARRAY:
+          repeat = explore_array_type (curr_type, path, is_child);
+          break;
+        case TYPE_CODE_STRUCT:
+        case TYPE_CODE_UNION:
+          repeat = explore_compound_type (curr_type, path, is_child);
+          break;
+        case TYPE_CODE_TYPEDEF:
+          repeat = explore_typedef_type (curr_type, path, is_child);
+          break;
+        default:
+          type_name = get_type_name (curr_type);
+          if (is_child)
+            {
+              printf_filtered (_("Exploration of type '%s' of '%s' is not yet "
+                                 "available.\n"), type_name, path);
+            }
+          else
+            {
+              printf_filtered (_("Exploration of type '%s' is not yet "
+                                 "available.\n"), type_name);
+            }
+          xfree (type_name);
+          break;
+        }
+    }
+  while (repeat);
+}
+
+/* Parse a string into a value in the current language. Return NULL if the
+   string STR does not evaluate to any value.  */
+
+static struct value *
+parse_as_value (char *str)
+{
+  struct gdb_exception except;
+  struct value *str_val = NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ERROR)
+    {
+      str_val = parse_and_eval (str);
+    }
+  if (except.reason < 0)
+    {
+      return NULL;
+    }
+
+  return str_val;
+}
+
+/* Parse a string into a type in the current language. Return NULL if the
+   string STR does not evaluate to any type.  */
+
+static struct type *
+parse_as_type (const char *str)
+{
+  struct type *type = NULL;
+  volatile struct gdb_exception except;
+
+  if (current_language->la_language == language_c
+      || current_language->la_language == language_cplus)
+    {
+      /* This helps in exploring types like int*, int** and the like.  */
+      char *exp = xstrprintf (_("(%s *) 0"), str);
+      struct value *dummy_value = parse_as_value (exp);
+
+      xfree (exp);
+
+      if (!dummy_value)
+        {
+          return NULL;
+        }
+
+      return value_type (value_ind (dummy_value));
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!strncmp (str, "struct ", 7))
+	type = lookup_struct (str + 7, NULL);
+      else if (!strncmp (str, "union ", 6))
+	type = lookup_union (str + 6, NULL);
+      else if (!strncmp (str, "enum ", 5))
+	type = lookup_enum (str + 5, NULL);
+      else
+	type = lookup_typename (current_language, get_current_arch(),
+				str, NULL, 0);
+    }
+  if (except.reason < 0)
+    {
+      return NULL;
+    }
+
+  return type;
+}
+
+static void
+explore_command (char* arg_str, int from_tty)
+{
+  struct value *exp_val;
+  struct type *str_type;
+
+  if (!arg_str)
+    {
+      printf_filtered (_("'explore' command requires an argument.\n"));
+      return;
+    }
+
+  /* Try if ARG_STR can be parsed into a value.  */
+  exp_val = parse_as_value (arg_str);
+  if (exp_val)
+    {
+      explore_value (exp_val, arg_str, 0);
+
+      free_all_values ();
+      return;
+    }
+
+  /* Try if ARG_STR can be parsed into a type.  */
+  str_type = parse_as_type (arg_str);
+  if (str_type)
+    {
+      explore_type (str_type, arg_str, 0);
+      return;
+    }
+
+  /* If ARG_STR cannot be parsed into a value or a type, print an error
+     message.  */
+  printf_filtered (_("'%s' does not evaluate to any value or type in the "
+                     "current context.\n"), arg_str);
+}
+
+static void
+explore_value_command (char* arg_str, int from_tty)
+{
+  struct value *exp_val;
+
+  if (!arg_str)
+    {
+      printf_filtered (_("'explore value' command requires an argument.\n"));
+      return;
+    }
+
+  exp_val = parse_as_value (arg_str);
+  if (exp_val)
+    {
+      explore_value (exp_val, arg_str, 0);
+
+      free_all_values ();
+      return;
+    }
+
+  printf_filtered (_("'%s' does not evaluate to any value in the "
+                     "current context.\n"), arg_str);
+}
+
+static void
+explore_type_command (char* arg_str, int from_tty)
+{
+  struct type *str_type;
+
+  if (!arg_str)
+    {
+      printf_filtered (_("'explore type' command requires an argument.\n"));
+      return;
+    }
+
+  str_type = parse_as_type (arg_str);
+  if (str_type)
+    {
+      explore_type (str_type, arg_str, 0);
+      return;
+    }
+
+  printf_filtered (_("'%s' does not evaluate to any type in the "
+                     "current context.\n"), arg_str);
+}
+
+struct cmd_list_element *explore_list = NULL;
+
+void
+_initialize_explore (void)
+{
+  add_prefix_cmd ("explore", no_class, explore_command, _("\
+Explore values and types valid in the current context.\nUsage:\n\n\
+explore ARG\n\nARG is either a valid expression or a type name."),
+                  &explore_list, "explore ", 1, &cmdlist);
+
+  add_cmd ("value", no_class, explore_value_command, _("\
+Explore values of expressions valid in the current context.\nUsage:\n\n\
+explore value ARG\n\nARG is a valid expression."), &explore_list);
+
+  add_cmd ("type", no_class, explore_type_command, _("\
+Explore types valid in the current context.\nUsage:\n\n\
+explore type ARG\n\nARG is a valid type name."), &explore_list);
+}
diff -rupN src/gdb/Makefile.in src_explore/src/gdb/Makefile.in
--- src/gdb/Makefile.in	2012-02-07 11:51:59.459955595 +0530
+++ src_explore/src/gdb/Makefile.in	2012-02-07 11:51:49.309894099 +0530
@@ -695,7 +695,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
 	dwarf2-frame-tailcall.c \
 	elfread.c environ.c eval.c event-loop.c event-top.c \
-	exceptions.c expprint.c \
+	exceptions.c explore.c expprint.c \
 	f-exp.y f-lang.c f-typeprint.c f-valprint.c filesystem.c \
 	findcmd.c findvar.c frame.c frame-base.c frame-unwind.c \
 	gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
@@ -861,6 +861,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	infcmd.o infrun.o \
 	expprint.o environ.o stack.o thread.o \
 	exceptions.o \
+	explore.o \
 	filesystem.o \
 	inf-child.o \
 	interps.o \
diff -rupN src/gdb/testsuite/gdb.base/explore.c src_explore/src/gdb/testsuite/gdb.base/explore.c
--- src/gdb/testsuite/gdb.base/explore.c	1970-01-01 05:30:00.000000000 +0530
+++ src_explore/src/gdb/testsuite/gdb.base/explore.c	2012-02-04 17:29:00.055238706 +0530
@@ -0,0 +1,82 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see  <http://www.gnu.org/licenses/>.
+*/
+
+#define ARRAY_SIZE 10
+
+struct SimpleStruct
+{
+  int a;
+  double d;
+};
+
+union SimpleUnion
+{
+  int i;
+  char c;
+  float f;
+  double d;
+};
+
+typedef struct SimpleStruct SS;
+
+struct ComplexStruct
+{
+  struct SimpleStruct s;
+  union SimpleUnion u;
+  SS sa[ARRAY_SIZE];
+};
+
+union ComplexUnion
+{
+  SS s;
+  struct SimpleStruct sa[ARRAY_SIZE];
+};
+
+int
+main (void)
+{
+  struct SimpleStruct ss;
+  struct SimpleStruct* ss_ptr = &ss;
+  SS ss_t;
+
+  union SimpleUnion su;
+  struct ComplexStruct cs;
+  struct ComplexStruct* cs_ptr = &cs;
+  union ComplexUnion cu;
+  int i;
+  double darray[5] = {0.1, 0.2, 0.3, 0.4, 0.5};
+  double *darray_ref = darray;
+
+  ss.a = 10;
+  ss.d = 100.01;
+  ss_t = ss;
+  
+  su.d = 100.1;
+
+  cs.s = ss;
+  cs.u = su;
+  for (i = 0; i < ARRAY_SIZE; i++)
+    {
+      cs.sa[i].a = i;
+      cs.sa[i].d = 10.10 + i;
+      cu.sa[i].a = i;
+      cu.sa[i].d = 100.10 + i;
+    }
+
+  return 0; /* Break here. */
+}
diff -rupN src/gdb/testsuite/gdb.base/explore.exp src_explore/src/gdb/testsuite/gdb.base/explore.exp
--- src/gdb/testsuite/gdb.base/explore.exp	1970-01-01 05:30:00.000000000 +0530
+++ src_explore/src/gdb/testsuite/gdb.base/explore.exp	2012-02-08 11:28:47.078627124 +0530
@@ -0,0 +1,430 @@
+# Copyright 2012 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+set testfile "explore"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+set SS "struct SimpleStruct"
+set SU "union SimpleUnion"
+set CS "struct ComplexStruct"
+set CU "union ComplexUnion"
+set enter_field_number_prompt  {Enter the field number of choice: }
+set return_to_parent_prompt {Press enter to return to parent value: }
+set array_index_prompt {Enter the index you want to explore in .*: }
+
+proc compound_description { value_name type_name } {
+    return "The value of '$value_name' is of type '$type_name' with the following fields:\[\r\n\]+"
+}
+
+proc typedef_description { value_name typedef_name type_name } {
+    return "The value of '$value_name' is of type '$typedef_name' which is a typedef of type '$type_name'\.\[\r\n\]+"
+}
+
+proc scalar_description { value_name type } {
+    return "'$value_name' is a scalar value of type '$type'\.\[\r\n\]+"
+}
+
+proc array_description { value_name type } {
+    return "'$value_name' is an array of elements of type '$type'\.\[\r\n\]+"
+}
+
+proc pointer_description { value_name type_name } {
+    set type_description "'$value_name' is a pointer to a value of type '$type_name'\.\[\r\n\]+"
+    set prompt "Do you want to explore it as an array or a single value pointer \[\[\]a/s\[\]\] : " 
+    return "$type_description$prompt"
+}
+
+proc field_values { args } {
+    set result ""
+    foreach field $args {
+        set result "$result\[ \]*$field \[\.\]\[\.\] \[\(\]Value of type .*\[\)\]\[\r\n\]+"
+    }
+    return $result
+}
+
+proc field_choices { args } {
+    set result ""
+    set field_num 0
+    foreach field $args {
+        set result "$result$field\[ \]+=\[ \]+<Enter $field_num to explore this field of type .*"
+        incr field_num
+    }
+    return $result
+}
+
+proc scalar_value { value_name value } {
+    return "$value_name = $value\[r\n\]+"
+}
+
+set SS_fields [field_values {a = 10} {d = 100[.].*}]
+
+if ![runto_main] {
+   return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "Break here."]
+gdb_continue_to_breakpoint "Break here" ".*Break here.*"
+
+#########################
+# Value exploration tests
+#########################
+
+gdb_test "explore i" "[scalar_description {i} {int}].*i = .*"
+gdb_test "explore ss" "[compound_description {ss} $SS].*$SS_fields"
+gdb_test "explore *ss_ptr" "[compound_description {\*ss_ptr} $SS].*$SS_fields"
+gdb_test "explore ss_t" "[typedef_description {ss_t} {SS} $SS].*[compound_description {ss_t} $SS].*$SS_fields"
+
+gdb_test_multiple "explore ss_ptr" "" {
+    -re "[pointer_description {ss_ptr} $SS].*" {
+        pass "explore ss_ptr"
+        gdb_test_multiple "s" "explore_as_single_value_pointer" {
+            -re "$SS_fields" {
+                pass "explore ss_ptr as single value pointer"
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore darray_ref" "" {
+    -re "[pointer_description {darray_ref} {double}].*" {
+        pass "explore darray_ref"
+        gdb_test_multiple "a" "explore_as_array" {
+            -re ".*Enter the index you want to explore in 'darray_ref':.*"  {
+                pass "explore_as_array"
+                gdb_test_multiple "2" "explore_as_array_index_2" {
+                    -re ".*'darray_ref\\\[2\\\]' is a scalar value of type 'double'\..*darray_ref\\\[2\\\] = 0.*" {
+                        pass "explore_as_array_index_2"
+                        gdb_test_multiple "\0" "end explore_as_array_index_2" {
+                            -re ".*Returning to parent value.*Enter the index you want to explore in 'darray_ref':.*" {
+                                pass "end explore_as_array_index_2"
+                                gdb_test_multiple "\0" "end explore_as_array" {
+                                    -re "\[\n\r\]+" {
+                                        pass "end explore_as_array"
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } 
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore su" "" {
+    -re "[compound_description {su} {union SimpleUnion}].*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
+        pass "explore su"
+        gdb_test_multiple "3" "explore su.d" {
+            -re "[scalar_description {su.d} {double}].*[scalar_value {su.d} {100[.].*}].*$return_to_parent_prompt" {
+                pass "explore su.d"
+                gdb_test_multiple " " "end su.d exploration" {
+                    -re ".*[compound_description {su} {union SimpleUnion}].*[field_choices {i} {c} {f} {d}].*$enter_field_number_prompt" {
+                        pass "end su.d exploration"
+                        gdb_test_multiple "\0" "end su exploration" {
+                            -re "$gdb_prompt" {
+                                pass "end su exploration"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore cs" "" {
+    -re "[compound_description {cs} {struct ComplexStruct}].*[field_choices {s} {u} {sa}].*$enter_field_number_prompt" {
+        pass "explore cs"
+        gdb_test_multiple "0" "explore cs.s" {
+            -re "[compound_description {cs.s} {struct SimpleStruct}].*[field_values {a = 10} {d = 100[.].*}].*$return_to_parent_prompt" {
+                pass "explore cs.s"
+                gdb_test_multiple " " "end cs.s exploration" {
+                    -re ".*$enter_field_number_prompt" {
+                        pass "end cs.s exploration"
+                        gdb_test_multiple "\0" "end cs exploration" {
+                            -re "$gdb_prompt" {
+                                pass "end cs exploration"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore cu" "" {
+    -re "[compound_description {cu} {union ComplexUnion}].*[field_choices {s} {sa}].*$enter_field_number_prompt" {
+        pass "explore cu"
+        gdb_test_multiple "1" "explore cu.sa" {
+            -re ".*[array_description {cu.sa} $SS].*$array_index_prompt" {
+                pass "explore cu.sa"
+                gdb_test_multiple "0" "explore cu.sa\[0\]" {
+                    -re "[compound_description {\(cu.sa\)\[0\]} {struct SimpleStruct}].*[field_values {a = 0} {d = 100[.].*}].*$return_to_parent_prompt" {
+                        pass "explore cu.sa\[0\]"
+                        gdb_test_multiple "\0" "end cu.sa\[0\] exploration" {
+                            -re "[array_description {cu.sa} $SS]$array_index_prompt" {
+                                pass "end cu.sa\[0\] exploration"
+                            }
+                        }
+                    }
+                }
+                gdb_test_multiple "\0" "end cu.sa exploration" {
+                    -re ".*$enter_field_number_prompt" {
+                        pass "end cu.sa exploration"
+                        gdb_test_multiple "\0" "end cu exploration" {
+                            -re "$gdb_prompt" {
+                                pass "end cu exploration"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+########################
+# Type exploration tests
+########################
+
+proc scalar_type_decsription {type} {
+    return "'$type' is of a scalar type\."
+}
+
+proc child_scalar_type_description {path type} {
+    return "$path is of a scalar type '$type'\."
+}
+
+proc compound_type_description { type_name } {
+    return "'$type_name' has the following fields:"
+}
+
+proc child_compound_type_description { path type_name } {
+    return "$path is of type '$type_name' with the following fields:"
+}
+
+proc child_array_type_description { path target_type_name } {
+    return "$path is an array type with elements of type '$target_type_name'\."
+}
+
+proc typedef_type_description { type_name target_name } {
+    return "The type '$type_name' is a typedef of type '$target_name'\."
+}
+
+set SS_fields_types [field_choices {a} {d}]
+set SU_fields_types [field_choices {i} {c} {f} {d}]
+set CS_fields_types [field_choices {s} {u} {sa}]
+set CU_fields_types [field_choices {s} {sa}]
+
+set CS_field_0 "field 's' of 'struct ComplexStruct'"
+set CS_field_1 "field 'u' of 'struct ComplexStruct'"
+set CS_field_2 "field 'sa' of 'struct ComplexStruct'"
+set CS_field_2_array_element "an array element of $CS_field_2"
+
+set CU_field_0 "field 's' of 'union ComplexUnion'"
+set CU_field_1 "field 'sa' of 'union ComplexUnion'"
+set CU_field_1_array_element "an array element of $CU_field_1"
+
+gdb_test "explore int" ".*[scalar_type_decsription {int}].*"
+
+gdb_test_multiple "explore struct SimpleStruct" "" {
+    -re ".*[compound_type_description $SS].*$SS_fields_types.*" {
+        pass "explore struct SimpleStruct"
+        gdb_test_multiple "0" "explore type struct SimpleStruct feild 0" {
+            -re ".*[child_scalar_type_description {field 'a' of 'struct SimpleStruct'} {int}].*" {
+                pass "explore type struct SimpleStruct feild 0"
+                gdb_test_multiple "\0" "return to struct SimpleStruct from field 0" {
+                    -re ".*[compound_type_description $SS].*$SS_fields_types.*" {
+                        pass "return to struct SimpleStruct from field 0"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "1" "explore type struct SimpleStruct feild 1" {
+            -re ".*[child_scalar_type_description {field 'd' of 'struct SimpleStruct'} {double}].*" {
+                pass "explore type struct SimpleStruct feild 1"
+                gdb_test_multiple "\0" "return to struct SimpleStruct from field 1" {
+                    -re ".*[compound_type_description $SS].*$SS_fields_types.*" {
+                        pass "return to struct SimpleStruct from field 1"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "\0" "return to GDB prompt from struct SimpleStruct" {
+            -re "$gdb_prompt" {
+                pass "return to GDB prompt from struct SimpleStruct"
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore union SimpleUnion" "" {
+  -re ".*[compound_type_description $SU].*$SU_fields_types.*" {
+      pass "explore union SimpleUnion"
+        gdb_test_multiple "0" "explore type union SimpleUnion feild 0" {
+            -re ".*[child_scalar_type_description {field 'i' of 'union SimpleUnion'} {int}].*" {
+                pass "explore type union SimpleUnion feild 0"
+                gdb_test_multiple "\0" "return to union SimpleUnion from field 0" {
+                    -re ".*[compound_type_description $SU].*$SU_fields_types.*" {
+                        pass "return to union SimpleUnion from field 0"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "1" "explore type union SimpleUnion feild 1" {
+            -re ".*[child_scalar_type_description {field 'c' of 'union SimpleUnion'} {char}].*" {
+                pass "explore type union SimpleUnion feild 1"
+                gdb_test_multiple "\0" "return to union SimpleUnion from field 1" {
+                    -re ".*[compound_type_description $SU].*$SU_fields_types.*" {
+                        pass "return to union SimpleUnion from field 1"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "2" "explore type union SimpleUnion feild 2" {
+            -re ".*[child_scalar_type_description {field 'f' of 'union SimpleUnion'} {float}].*" {
+                pass "explore type union SimpleUnion feild 2"
+                gdb_test_multiple "\0" "return to union SimpleUnion from field 2" {
+                    -re ".*[compound_type_description $SU].*$SU_fields_types.*" {
+                        pass "return to union SimpleUnion from field 2"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "3" "explore type union SimpleUnion feild 3" {
+            -re ".*[child_scalar_type_description {field 'd' of 'union SimpleUnion'} {double}].*" {
+                pass "explore type union SimpleUnion feild 3"
+                gdb_test_multiple "\0" "return to union SimpleUnion from field 3" {
+                    -re ".*[compound_type_description $SU].*$SU_fields_types.*" {
+                        pass "return to union SimpleUnion from field 3"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "\0" "return to GDB prompt from union SimpleUnion" {
+            -re "$gdb_prompt" {
+                pass "return to GDB prompt from union SimpleUnion"
+            }
+        }
+  }
+}
+
+gdb_test_multiple "explore SS" "" {
+    -re ".*[typedef_type_description {SS} $SS].*[compound_type_description {SS}].*$SS_fields_types.*" {
+        pass "explore SS"
+        gdb_test_multiple "0" "explore type SS feild 0" {
+            -re ".*[child_scalar_type_description {field 'a' of 'SS'} {int}].*" {
+                pass "explore type SS feild 0"
+                gdb_test_multiple "\0" "return to SS from field 0" {
+                    -re ".*[compound_type_description {SS}].*$SS_fields_types.*" {
+                        pass "return to SS from field 0"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "1" "explore type SS feild 1" {
+            -re ".*[child_scalar_type_description {field 'd' of 'SS'} {double}].*" {
+                pass "explore type SS feild 1"
+                gdb_test_multiple "\0" "return to struct SimpleStruct from field 1" {
+                    -re ".*[compound_type_description {SS}].*$SS_fields_types.*" {
+                        pass "return to SS field 1"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "\0" "return to GDB prompt from SS" {
+            -re "$gdb_prompt" {
+                pass "return to GDB prompt from SS"
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore type struct ComplexStruct" "" {
+    -re ".*[compound_type_description $CS].*$CS_fields_types.*" {
+        pass "explore type struct ComplexStruct"
+        gdb_test_multiple "0" "explore type struct ComplexStruct field 0" {
+            -re ".*[child_compound_type_description $CS_field_0 $SS].*$SS_fields_types.*" {
+                pass "explore type struct ComplexStruct field 0"
+                gdb_test_multiple "\0" "return to ComplexStruct from field 0" {
+                    -re ".*[compound_type_description $CS].*$CS_fields_types.*" {
+                        pass "return to ComplexStruct from field 0"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "1" "explore type struct ComplexStruct field 1" {
+            -re ".*[child_compound_type_description $CS_field_1 $SU].*$SU_fields_types.*" {
+                pass "explore type struct ComplexStruct field 1"
+                gdb_test_multiple "\0" "return to ComplexStruct from field 1" {
+                    -re ".*[compound_type_description $CS].*$CS_fields_types.*" {
+                        pass "return to ComplexStruct from field 1"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "2" "explore type struct ComplexStruct field 2" {
+            -re ".*[child_array_type_description $CS_field_2 {SS}].*" {
+                pass "explore type struct ComplexStruct field 2"
+                gdb_test_multiple "\0" "return to ComplexStruct from field 2" {
+                    -re ".*[compound_type_description $CS].*$CS_fields_types.*" {
+                        pass "return to ComplexStruct from field 2"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "\0" "return to GDB prompt from ComplexStruct type exploration" {
+            -re "$gdb_prompt" {
+                pass "return to GDB prompt from ComplexStruct type exploration"
+            }
+        }
+    }
+}
+
+gdb_test_multiple "explore type union ComplexUnion" "" {
+    -re ".*[compound_type_description $CU].*$CU_fields_types.*" {
+        pass "explore type union ComplexUnion"
+        gdb_test_multiple "0" "explore type union ComplexStruct field 0" {
+            -re ".*[child_compound_type_description $CU_field_0 $SS].*$SS_fields_types.*" {
+                pass "explore type union ComplexUnion field 0"
+                gdb_test_multiple "\0" "return to ComplexUnion from field 0" {
+                    -re ".*[compound_type_description $CU].*$CU_fields_types.*" {
+                        pass "return to ComplexUnion from field 0"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "1" "explore type union ComplexUnion field 1" {
+            -re ".*[child_array_type_description $CU_field_1 $SS].*" {
+                pass "explore type union ComplexUnion field 1"
+                gdb_test_multiple "\0" "return to ComplexUnion array" {
+                    -re ".*[compound_type_description $CU].*$CU_fields_types.*" {
+                        pass "return to ComplexUnion from field 1"
+                    }
+                }
+            }
+        }
+        gdb_test_multiple "\0" "return to GDB prompt from ComplexUnion type exploration" {
+            -re "$gdb_prompt" {
+                pass "return to GDB prompt from ComplexUnion type exploration"
+            }
+        }
+    }
+}
diff -rupN src/gdb/testsuite/gdb.base/Makefile.in src_explore/src/gdb/testsuite/gdb.base/Makefile.in
--- src/gdb/testsuite/gdb.base/Makefile.in	2011-11-01 20:21:25.000000000 +0530
+++ src_explore/src/gdb/testsuite/gdb.base/Makefile.in	2012-02-04 12:03:13.812856890 +0530
@@ -11,7 +11,7 @@ EXECUTABLES = a2-run advance all-types a
 	chng-syms code_elim1 code_elim2 commands compiler complex \
 	condbreak consecutive constvars coremaker cursal cvexpr \
 	dbx-test del disasm-end-cu display dump dup-sect dup-sect.debug \
-	dup-sect.stripped ending-run execd-prog expand-psymtabs exprs \
+	dup-sect.stripped ending-run execd-prog expand-psymtabs explore exprs \
 	fileio find finish fixsection float foll-exec foll-fork foll-vfork \
 	frame-args freebpcmd fullname funcargs gcore \
 	gcore-buffer-overflow-012* \

  reply	other threads:[~2012-02-08  9:34 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CAGyQ6gyAwr2zuv3NYpdk09vPyYpuFkyiErEhw-vws-WfuLDxiw@mail.gmail.com>
2011-12-19 19:05 ` Siva Chandra
2011-12-21 19:36   ` Tom Tromey
2011-12-22 11:00     ` Siva Chandra
2011-12-22  5:21   ` Joel Brobecker
2011-12-22 11:48     ` Siva Chandra
2011-12-22 12:53       ` Joel Brobecker
2011-12-27  6:29   ` Siva Chandra
2012-02-08  9:34     ` Siva Chandra [this message]
2012-02-17  7:40       ` Doug Evans
2012-02-17 10:00         ` Siva Chandra
2012-02-17 13:14           ` Phil Muldoon
2012-02-17 10:09         ` Siva Chandra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAGyQ6gxfsOrZofwg-tvArXERiw2symHLoUzYy_fLfYsZtHk6Kg@mail.gmail.com \
    --to=sivachandra@google.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox