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 . */
+
+#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 (_("\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 .
+*/
+
+#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 .
+
+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\[ \]+=\[ \]+