X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=03edf0eb9692ab524926ae01289aa51e06b63993;hb=59b21252a88aa6ba488cfb19686d9cbad2577e76;hp=7446f1002b6a1d084c872ea02e2b17aa223ad635;hpb=3977b71f1dfd04b6ac2c14e1405ce251c31a38aa;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index 7446f1002b..03edf0eb96 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,6 +1,6 @@ /* Implementation of the GDB variable objects API. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2016 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 @@ -16,7 +16,6 @@ along with this program. If not, see . */ #include "defs.h" -#include "exceptions.h" #include "value.h" #include "expression.h" #include "frame.h" @@ -24,9 +23,6 @@ #include "gdbcmd.h" #include "block.h" #include "valprint.h" - -#include "gdb_assert.h" -#include #include "gdb_regex.h" #include "varobj.h" @@ -54,7 +50,7 @@ show_varobjdebug (struct ui_file *file, int from_tty, /* String representations of gdb's format codes. */ char *varobj_format_string[] = - { "natural", "binary", "decimal", "hexadecimal", "octal" }; + { "natural", "binary", "decimal", "hexadecimal", "octal", "zero-hexadecimal" }; /* True if we want to allow Python-based pretty-printing. */ static int pretty_printing = 0; @@ -68,12 +64,12 @@ varobj_enable_pretty_printing (void) /* Data structures */ /* Every root variable has one of these structures saved in its - varobj. Members which must be free'd are noted. */ + varobj. */ struct varobj_root { - /* Alloc'd expression for this parent. */ - struct expression *exp; + /* The expression for this parent. */ + expression_up exp; /* Block for which this expression is valid. */ const struct block *valid_block; @@ -82,7 +78,7 @@ struct varobj_root not NULL. */ struct frame_id frame; - /* The thread ID that this varobj_root belong to. This field + /* The global thread ID that this varobj_root belongs to. This field is only valid if valid_block is not NULL. When not 0, indicates which thread 'frame' belongs to. When 0, indicates that the thread list was empty when the varobj_root @@ -140,12 +136,6 @@ struct varobj_dynamic varobj_item *saved_item; }; -struct cpstack -{ - char *name; - struct cpstack *next; -}; - /* A list of varobjs */ struct vlist @@ -158,16 +148,15 @@ struct vlist /* Helper functions for the above subcommands. */ -static int delete_variable (struct cpstack **, struct varobj *, int); +static int delete_variable (struct varobj *, int); -static void delete_variable_1 (struct cpstack **, int *, - struct varobj *, int, int); +static void delete_variable_1 (int *, struct varobj *, int, int); static int install_variable (struct varobj *); static void uninstall_variable (struct varobj *); -static struct varobj *create_child (struct varobj *, int, char *); +static struct varobj *create_child (struct varobj *, int, std::string &); static struct varobj * create_child_with_value (struct varobj *parent, int index, @@ -185,10 +174,6 @@ static struct cleanup *make_cleanup_free_variable (struct varobj *var); static enum varobj_display_formats variable_default_display (struct varobj *); -static void cppush (struct cpstack **pstack, char *name); - -static char *cppop (struct cpstack **pstack); - static int update_type_if_necessary (struct varobj *var, struct value *new_value); @@ -197,20 +182,20 @@ static int install_new_value (struct varobj *var, struct value *value, /* Language-specific routines. */ -static int number_of_children (struct varobj *); +static int number_of_children (const struct varobj *); -static char *name_of_variable (struct varobj *); +static std::string name_of_variable (const struct varobj *); -static char *name_of_child (struct varobj *, int); +static std::string name_of_child (struct varobj *, int); static struct value *value_of_root (struct varobj **var_handle, int *); -static struct value *value_of_child (struct varobj *parent, int index); +static struct value *value_of_child (const struct varobj *parent, int index); -static char *my_value_of_variable (struct varobj *var, - enum varobj_display_formats format); +static std::string my_value_of_variable (struct varobj *var, + enum varobj_display_formats format); -static int is_root_p (struct varobj *var); +static int is_root_p (const struct varobj *var); static struct varobj *varobj_add_child (struct varobj *var, struct varobj_item *item); @@ -218,13 +203,13 @@ static struct varobj *varobj_add_child (struct varobj *var, /* Private data */ /* Mappings of varobj_display_formats enums to gdb's format codes. */ -static int format_code[] = { 0, 't', 'd', 'x', 'o' }; +static int format_code[] = { 0, 't', 'd', 'x', 'o', 'z' }; /* Header of the list of root variable objects. */ static struct varobj_root *rootlist; /* Prime number indicating the number of buckets in the hash table. */ -/* A prime large enough to avoid too many colisions. */ +/* A prime large enough to avoid too many collisions. */ #define VAROBJ_TABLE_SIZE 227 /* Pointer to the varobj hash table (built at run time). */ @@ -234,7 +219,7 @@ static struct vlist **varobj_table; /* API Implementation */ static int -is_root_p (struct varobj *var) +is_root_p (const struct varobj *var) { return (var->root->rootvar == var); } @@ -243,15 +228,13 @@ is_root_p (struct varobj *var) /* Helper function to install a Python environment suitable for use during operations on VAR. */ struct cleanup * -varobj_ensure_python_env (struct varobj *var) +varobj_ensure_python_env (const struct varobj *var) { return ensure_python_env (var->root->exp->gdbarch, var->root->exp->language_defn); } #endif -/* Creates a varobj (not its children). */ - /* Return the full FRAME which corresponds to the given CORE_ADDR or NULL if no FRAME on the chain corresponds to CORE_ADDR. */ @@ -284,9 +267,11 @@ find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) return NULL; } +/* Creates a varobj (not its children). */ + struct varobj * -varobj_create (char *objname, - char *expression, CORE_ADDR frame, enum varobj_type type) +varobj_create (const char *objname, + const char *expression, CORE_ADDR frame, enum varobj_type type) { struct varobj *var; struct cleanup *old_chain; @@ -302,7 +287,6 @@ varobj_create (char *objname, const struct block *block; const char *p; struct value *value = NULL; - volatile struct gdb_exception except; CORE_ADDR pc; /* Parse and evaluate the expression, filling in as much of the @@ -342,16 +326,17 @@ varobj_create (char *objname, innermost_block = NULL; /* Wrap the call to parse expression, so we can return a sensible error. */ - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY { var->root->exp = parse_exp_1 (&p, pc, block, 0); } - if (except.reason < 0) + CATCH (except, RETURN_MASK_ERROR) { do_cleanups (old_chain); return NULL; } + END_CATCH /* Don't allow variables to be created for types. */ if (var->root->exp->elts[0].opcode == OP_TYPE @@ -366,9 +351,9 @@ varobj_create (char *objname, var->format = variable_default_display (var); var->root->valid_block = innermost_block; - var->name = xstrdup (expression); + var->name = expression; /* For a root var, the name and the expr are the same. */ - var->path_expr = xstrdup (expression); + var->path_expr = expression; /* When the frame is different from the current frame, we must select the appropriate frame before parsing @@ -384,7 +369,7 @@ varobj_create (char *objname, error (_("Failed to find the specified frame")); var->root->frame = get_frame_id (fi); - var->root->thread_id = pid_to_thread_id (inferior_ptid); + var->root->thread_id = ptid_to_global_thread_id (inferior_ptid); old_id = get_frame_id (get_selected_frame (NULL)); select_frame (fi); } @@ -392,27 +377,28 @@ varobj_create (char *objname, /* We definitely need to catch errors here. If evaluate_expression succeeds we got the value we wanted. But if it fails, we still go on with a call to evaluate_type(). */ - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY { - value = evaluate_expression (var->root->exp); + value = evaluate_expression (var->root->exp.get ()); } - - if (except.reason < 0) + CATCH (except, RETURN_MASK_ERROR) { /* Error getting the value. Try to at least get the right type. */ - struct value *type_only_value = evaluate_type (var->root->exp); + struct value *type_only_value = evaluate_type (var->root->exp.get ()); var->type = value_type (type_only_value); } - else - { - int real_type_found = 0; + END_CATCH - var->type = value_actual_type (value, 0, &real_type_found); - if (real_type_found) - value = value_cast (var->type, value); - } + if (value != NULL) + { + int real_type_found = 0; + + var->type = value_actual_type (value, 0, &real_type_found); + if (real_type_found) + value = value_cast (var->type, value); + } /* Set language info */ var->root->lang_ops = var->root->exp->language_defn->la_varobj_ops; @@ -432,7 +418,7 @@ varobj_create (char *objname, if ((var != NULL) && (objname != NULL)) { - var->obj_name = xstrdup (objname); + var->obj_name = objname; /* If a varobj name is duplicated, the install will fail so we must cleanup. */ @@ -466,7 +452,7 @@ varobj_gen_name (void) error if OBJNAME cannot be found. */ struct varobj * -varobj_get_handle (char *objname) +varobj_get_handle (const char *objname) { struct vlist *cv; const char *chp; @@ -479,7 +465,7 @@ varobj_get_handle (char *objname) } cv = *(varobj_table + index); - while ((cv != NULL) && (strcmp (cv->var->obj_name, objname) != 0)) + while (cv != NULL && cv->var->obj_name != objname) cv = cv->next; if (cv == NULL) @@ -490,64 +476,27 @@ varobj_get_handle (char *objname) /* Given the handle, return the name of the object. */ -char * -varobj_get_objname (struct varobj *var) +const char * +varobj_get_objname (const struct varobj *var) { - return var->obj_name; + return var->obj_name.c_str (); } -/* Given the handle, return the expression represented by the object. */ +/* Given the handle, return the expression represented by the + object. */ -char * -varobj_get_expression (struct varobj *var) +std::string +varobj_get_expression (const struct varobj *var) { return name_of_variable (var); } -/* Deletes a varobj and all its children if only_children == 0, - otherwise deletes only the children; returns a malloc'ed list of - all the (malloc'ed) names of the variables that have been deleted - (NULL terminated). */ +/* See varobj.h. */ int -varobj_delete (struct varobj *var, char ***dellist, int only_children) +varobj_delete (struct varobj *var, int only_children) { - int delcount; - int mycount; - struct cpstack *result = NULL; - char **cp; - - /* Initialize a stack for temporary results. */ - cppush (&result, NULL); - - if (only_children) - /* Delete only the variable children. */ - delcount = delete_variable (&result, var, 1 /* only the children */ ); - else - /* Delete the variable and all its children. */ - delcount = delete_variable (&result, var, 0 /* parent+children */ ); - - /* We may have been asked to return a list of what has been deleted. */ - if (dellist != NULL) - { - *dellist = xmalloc ((delcount + 1) * sizeof (char *)); - - cp = *dellist; - mycount = delcount; - *cp = cppop (&result); - while ((*cp != NULL) && (mycount > 0)) - { - mycount--; - cp++; - *cp = cppop (&result); - } - - if (mycount || (*cp != NULL)) - warning (_("varobj_delete: assertion failed - mycount(=%d) <> 0"), - mycount); - } - - return delcount; + return delete_variable (var, only_children); } #if HAVE_PYTHON @@ -584,6 +533,7 @@ varobj_set_display_format (struct varobj *var, case FORMAT_DECIMAL: case FORMAT_HEXADECIMAL: case FORMAT_OCTAL: + case FORMAT_ZHEXADECIMAL: var->format = format; break; @@ -594,7 +544,6 @@ varobj_set_display_format (struct varobj *var, if (varobj_value_is_changeable_p (var) && var->value && !value_lazy (var->value)) { - xfree (var->print_value); var->print_value = varobj_value_get_print_value (var->value, var->format, var); } @@ -603,15 +552,15 @@ varobj_set_display_format (struct varobj *var, } enum varobj_display_formats -varobj_get_display_format (struct varobj *var) +varobj_get_display_format (const struct varobj *var) { return var->format; } -char * -varobj_get_display_hint (struct varobj *var) +gdb::unique_xmalloc_ptr +varobj_get_display_hint (const struct varobj *var) { - char *result = NULL; + gdb::unique_xmalloc_ptr result; #if HAVE_PYTHON struct cleanup *back_to; @@ -633,7 +582,7 @@ varobj_get_display_hint (struct varobj *var) /* Return true if the varobj has items after TO, false otherwise. */ int -varobj_has_more (struct varobj *var, int to) +varobj_has_more (const struct varobj *var, int to) { if (VEC_length (varobj_p, var->children) > to) return 1; @@ -646,7 +595,7 @@ varobj_has_more (struct varobj *var, int to) inside that thread, returns GDB id of the thread -- which is always positive. Otherwise, returns -1. */ int -varobj_get_thread_id (struct varobj *var) +varobj_get_thread_id (const struct varobj *var) { if (var->root->valid_block && var->root->thread_id > 0) return var->root->thread_id; @@ -668,7 +617,7 @@ varobj_set_frozen (struct varobj *var, int frozen) } int -varobj_get_frozen (struct varobj *var) +varobj_get_frozen (const struct varobj *var) { return var->frozen; } @@ -704,7 +653,7 @@ static void install_dynamic_child (struct varobj *var, VEC (varobj_p) **changed, VEC (varobj_p) **type_changed, - VEC (varobj_p) **new, + VEC (varobj_p) **newobj, VEC (varobj_p) **unchanged, int *cchanged, int index, @@ -715,9 +664,9 @@ install_dynamic_child (struct varobj *var, /* There's no child yet. */ struct varobj *child = varobj_add_child (var, item); - if (new) + if (newobj) { - VEC_safe_push (varobj_p, *new, child); + VEC_safe_push (varobj_p, *newobj, child); *cchanged = 1; } } @@ -744,7 +693,7 @@ install_dynamic_child (struct varobj *var, #if HAVE_PYTHON static int -dynamic_varobj_has_child_method (struct varobj *var) +dynamic_varobj_has_child_method (const struct varobj *var) { struct cleanup *back_to; PyObject *printer = var->dynamic->pretty_printer; @@ -792,7 +741,7 @@ static int update_dynamic_varobj_children (struct varobj *var, VEC (varobj_p) **changed, VEC (varobj_p) **type_changed, - VEC (varobj_p) **new, + VEC (varobj_p) **newobj, VEC (varobj_p) **unchanged, int *cchanged, int update_children, @@ -853,7 +802,7 @@ update_dynamic_varobj_children (struct varobj *var, install_dynamic_child (var, can_mention ? changed : NULL, can_mention ? type_changed : NULL, - can_mention ? new : NULL, + can_mention ? newobj : NULL, can_mention ? unchanged : NULL, can_mention ? cchanged : NULL, i, item); @@ -876,7 +825,7 @@ update_dynamic_varobj_children (struct varobj *var, *cchanged = 1; for (j = i; j < VEC_length (varobj_p, var->children); ++j) - varobj_delete (VEC_index (varobj_p, var->children, j), NULL, 0); + varobj_delete (VEC_index (varobj_p, var->children, j), 0); VEC_truncate (varobj_p, var->children, i); } @@ -917,7 +866,6 @@ varobj_get_num_children (struct varobj *var) VEC (varobj_p)* varobj_list_children (struct varobj *var, int *from, int *to) { - char *name; int i, children_changed; var->dynamic->children_requested = 1; @@ -954,7 +902,7 @@ varobj_list_children (struct varobj *var, int *from, int *to) /* Either it's the first call to varobj_list_children for this variable object, and the child was never created, or it was explicitly deleted by the client. */ - name = name_of_child (var, i); + std::string name = name_of_child (var, i); existing = create_child (var, i, name); VEC_replace (varobj_p, var->children, i, existing); } @@ -976,16 +924,17 @@ varobj_add_child (struct varobj *var, struct varobj_item *item) } /* Obtain the type of an object Variable as a string similar to the one gdb - prints on the console. */ + prints on the console. The caller is responsible for freeing the string. + */ -char * +std::string varobj_get_type (struct varobj *var) { /* For the "fake" variables, do not return a type. (Its type is NULL, too.) Do not return a type for invalid variables as well. */ if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid) - return NULL; + return std::string (); return type_to_string (var->type); } @@ -993,7 +942,7 @@ varobj_get_type (struct varobj *var) /* Obtain the type of an object variable. */ struct type * -varobj_get_gdb_type (struct varobj *var) +varobj_get_gdb_type (const struct varobj *var) { return var->type; } @@ -1002,28 +951,28 @@ varobj_get_gdb_type (struct varobj *var) a valid path expression? */ static int -is_path_expr_parent (struct varobj *var) +is_path_expr_parent (const struct varobj *var) { - struct type *type; - - /* "Fake" children are not path_expr parents. */ - if (CPLUS_FAKE_CHILD (var)) - return 0; + gdb_assert (var->root->lang_ops->is_path_expr_parent != NULL); + return var->root->lang_ops->is_path_expr_parent (var); +} - type = varobj_get_value_type (var); +/* Is VAR a path expression parent, i.e., can it be used to construct + a valid path expression? By default we assume any VAR can be a path + parent. */ - /* Anonymous unions and structs are also not path_expr parents. */ - return !((TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) - && TYPE_NAME (type) == NULL); +int +varobj_default_is_path_expr_parent (const struct varobj *var) +{ + return 1; } /* Return the path expression parent for VAR. */ -struct varobj * -varobj_get_path_expr_parent (struct varobj *var) +const struct varobj * +varobj_get_path_expr_parent (const struct varobj *var) { - struct varobj *parent = var; + const struct varobj *parent = var; while (!is_root_p (parent) && !is_path_expr_parent (parent)) parent = parent->parent; @@ -1033,29 +982,32 @@ varobj_get_path_expr_parent (struct varobj *var) /* Return a pointer to the full rooted expression of varobj VAR. If it has not been computed yet, compute it. */ -char * -varobj_get_path_expr (struct varobj *var) + +const char * +varobj_get_path_expr (const struct varobj *var) { - if (var->path_expr != NULL) - return var->path_expr; - else + if (var->path_expr.empty ()) { /* For root varobjs, we initialize path_expr when creating varobj, so here it should be child varobj. */ + struct varobj *mutable_var = (struct varobj *) var; gdb_assert (!is_root_p (var)); - return (*var->root->lang_ops->path_expr_of_child) (var); + + mutable_var->path_expr = (*var->root->lang_ops->path_expr_of_child) (var); } + + return var->path_expr.c_str (); } const struct language_defn * -varobj_get_language (struct varobj *var) +varobj_get_language (const struct varobj *var) { return var->root->exp->language_defn; } int -varobj_get_attributes (struct varobj *var) +varobj_get_attributes (const struct varobj *var) { int attributes = 0; @@ -1069,19 +1021,19 @@ varobj_get_attributes (struct varobj *var) /* Return true if VAR is a dynamic varobj. */ int -varobj_is_dynamic_p (struct varobj *var) +varobj_is_dynamic_p (const struct varobj *var) { return var->dynamic->pretty_printer != NULL; } -char * +std::string varobj_get_formatted_value (struct varobj *var, enum varobj_display_formats format) { return my_value_of_variable (var, format); } -char * +std::string varobj_get_value (struct varobj *var) { return my_value_of_variable (var, var->format); @@ -1092,33 +1044,31 @@ varobj_get_value (struct varobj *var) /* Note: Invokes functions that can call error(). */ int -varobj_set_value (struct varobj *var, char *expression) +varobj_set_value (struct varobj *var, const char *expression) { struct value *val = NULL; /* Initialize to keep gcc happy. */ /* The argument "expression" contains the variable's new value. We need to first construct a legal expression for this -- ugh! */ /* Does this cover all the bases? */ - struct expression *exp; struct value *value = NULL; /* Initialize to keep gcc happy. */ int saved_input_radix = input_radix; const char *s = expression; - volatile struct gdb_exception except; gdb_assert (varobj_editable_p (var)); input_radix = 10; /* ALWAYS reset to decimal temporarily. */ - exp = parse_exp_1 (&s, 0, 0, 0); - TRY_CATCH (except, RETURN_MASK_ERROR) + expression_up exp = parse_exp_1 (&s, 0, 0, 0); + TRY { - value = evaluate_expression (exp); + value = evaluate_expression (exp.get ()); } - if (except.reason < 0) + CATCH (except, RETURN_MASK_ERROR) { /* We cannot proceed without a valid expression. */ - xfree (exp); return 0; } + END_CATCH /* All types that are editable must also be changeable. */ gdb_assert (varobj_value_is_changeable_p (var)); @@ -1137,13 +1087,16 @@ varobj_set_value (struct varobj *var, char *expression) /* The new value may be lazy. value_assign, or rather value_contents, will take care of this. */ - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY { val = value_assign (var->value, value); } - if (except.reason < 0) - return 0; + CATCH (except, RETURN_MASK_ERROR) + { + return 0; + } + END_CATCH /* If the value has changed, record it, so that next -var-update can report this change. If a variable had a value of '1', we've set it @@ -1291,18 +1244,17 @@ update_type_if_necessary (struct varobj *var, struct value *new_value) get_user_print_options (&opts); if (opts.objectprint) { - struct type *new_type; - char *curr_type_str, *new_type_str; + struct type *new_type = value_actual_type (new_value, 0, 0); + std::string new_type_str = type_to_string (new_type); + std::string curr_type_str = varobj_get_type (var); - new_type = value_actual_type (new_value, 0, 0); - new_type_str = type_to_string (new_type); - curr_type_str = varobj_get_type (var); - if (strcmp (curr_type_str, new_type_str) != 0) + /* Did the type name change? */ + if (curr_type_str != new_type_str) { var->type = new_type; /* This information may be not valid for a new type. */ - varobj_delete (var, NULL, 1); + varobj_delete (var, 1); VEC_free (varobj_p, var->children); var->num_children = -1; return 1; @@ -1333,7 +1285,6 @@ install_new_value (struct varobj *var, struct value *value, int initial) int need_to_fetch; int changed = 0; int intentionally_not_fetched = 0; - char *print_value = NULL; /* We need to know the varobj's type to decide if the value should be fetched or not. C++ fake children (public/protected/private) @@ -1373,7 +1324,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) will be lazy, which means we've lost that old value. */ if (need_to_fetch && value && value_lazy (value)) { - struct varobj *parent = var->parent; + const struct varobj *parent = var->parent; int frozen = var->frozen; for (; !frozen && parent; parent = parent->parent) @@ -1389,20 +1340,20 @@ install_new_value (struct varobj *var, struct value *value, int initial) } else { - volatile struct gdb_exception except; - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY { value_fetch_lazy (value); } - if (except.reason < 0) + CATCH (except, RETURN_MASK_ERROR) { /* Set the value to NULL, so that for the next -var-update, we don't try to compare the new value with this value, that we couldn't even read. */ value = NULL; } + END_CATCH } } @@ -1415,6 +1366,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) values. Don't get string rendering if the value is lazy -- if it is, the code above has decided that the value should not be fetched. */ + std::string print_value; if (value != NULL && !value_lazy (value) && var->dynamic->pretty_printer == NULL) print_value = varobj_value_get_print_value (value, var->format, var); @@ -1458,8 +1410,8 @@ install_new_value (struct varobj *var, struct value *value, int initial) gdb_assert (!value_lazy (var->value)); gdb_assert (!value_lazy (value)); - gdb_assert (var->print_value != NULL && print_value != NULL); - if (strcmp (var->print_value, print_value) != 0) + gdb_assert (!var->print_value.empty () && !print_value.empty ()); + if (var->print_value != print_value) changed = 1; } } @@ -1490,17 +1442,14 @@ install_new_value (struct varobj *var, struct value *value, int initial) to see if the variable changed. */ if (var->dynamic->pretty_printer != NULL) { - xfree (print_value); print_value = varobj_value_get_print_value (var->value, var->format, var); - if ((var->print_value == NULL && print_value != NULL) - || (var->print_value != NULL && print_value == NULL) - || (var->print_value != NULL && print_value != NULL - && strcmp (var->print_value, print_value) != 0)) - changed = 1; + if ((var->print_value.empty () && !print_value.empty ()) + || (!var->print_value.empty () && print_value.empty ()) + || (!var->print_value.empty () && !print_value.empty () + && var->print_value != print_value)) + changed = 1; } - if (var->print_value) - xfree (var->print_value); var->print_value = print_value; gdb_assert (!var->value || value_type (var->value)); @@ -1513,7 +1462,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) selected sub-range of VAR. If no range was selected using -var-set-update-range, then both will be -1. */ void -varobj_get_child_range (struct varobj *var, int *from, int *to) +varobj_get_child_range (const struct varobj *var, int *from, int *to) { *from = var->from; *to = var->to; @@ -1558,7 +1507,7 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer) Py_XDECREF (constructor); /* If there are any children now, wipe them. */ - varobj_delete (var, NULL, 1 /* children only */); + varobj_delete (var, 1 /* children only */); var->num_children = -1; do_cleanups (back_to); @@ -1575,7 +1524,7 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer) NEW_VALUE may be NULL, if the varobj is now out of scope. */ static int -varobj_value_has_mutated (struct varobj *var, struct value *new_value, +varobj_value_has_mutated (const struct varobj *var, struct value *new_value, struct type *new_type) { /* If we haven't previously computed the number of children in var, @@ -1616,11 +1565,11 @@ varobj_value_has_mutated (struct varobj *var, struct value *new_value, to point to the new varobj. */ VEC(varobj_update_result) * -varobj_update (struct varobj **varp, int explicit) +varobj_update (struct varobj **varp, int is_explicit) { int type_changed = 0; int i; - struct value *new; + struct value *newobj; VEC (varobj_update_result) *stack = NULL; VEC (varobj_update_result) *result = NULL; @@ -1629,7 +1578,7 @@ varobj_update (struct varobj **varp, int explicit) 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) + if (!is_explicit && (*varp)->frozen) return result; if (!(*varp)->root->is_valid) @@ -1654,15 +1603,15 @@ varobj_update (struct varobj **varp, int explicit) 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 (update_type_if_necessary(*varp, new)) + newobj = value_of_root (varp, &type_changed); + if (update_type_if_necessary(*varp, newobj)) type_changed = 1; r.varobj = *varp; r.type_changed = type_changed; - if (install_new_value ((*varp), new, type_changed)) + if (install_new_value ((*varp), newobj, type_changed)) r.changed = 1; - if (new == NULL) + if (newobj == NULL) r.status = VAROBJ_NOT_IN_SCOPE; r.value_installed = 1; @@ -1697,19 +1646,19 @@ varobj_update (struct varobj **varp, int explicit) { struct type *new_type; - new = value_of_child (v->parent, v->index); - if (update_type_if_necessary(v, new)) + newobj = value_of_child (v->parent, v->index); + if (update_type_if_necessary(v, newobj)) r.type_changed = 1; - if (new) - new_type = value_type (new); + if (newobj) + new_type = value_type (newobj); else new_type = v->root->lang_ops->type_of_child (v->parent, v->index); - if (varobj_value_has_mutated (v, new, new_type)) + if (varobj_value_has_mutated (v, newobj, new_type)) { /* The children are no longer valid; delete them now. Report the fact that its type changed as well. */ - varobj_delete (v, NULL, 1 /* only_children */); + varobj_delete (v, 1 /* only_children */); v->num_children = -1; v->to = -1; v->from = -1; @@ -1717,7 +1666,7 @@ varobj_update (struct varobj **varp, int explicit) r.type_changed = 1; } - if (install_new_value (v, new, r.type_changed)) + if (install_new_value (v, newobj, r.type_changed)) { r.changed = 1; v->updated = 0; @@ -1729,7 +1678,7 @@ varobj_update (struct varobj **varp, int explicit) if (varobj_is_dynamic_p (v)) { VEC (varobj_p) *changed = 0, *type_changed = 0, *unchanged = 0; - VEC (varobj_p) *new = 0; + VEC (varobj_p) *newobj = 0; int i, children_changed = 0; if (v->frozen) @@ -1761,14 +1710,14 @@ varobj_update (struct varobj **varp, int explicit) /* If update_dynamic_varobj_children returns 0, then we have a non-conforming pretty-printer, so we skip it. */ - if (update_dynamic_varobj_children (v, &changed, &type_changed, &new, + if (update_dynamic_varobj_children (v, &changed, &type_changed, &newobj, &unchanged, &children_changed, 1, v->from, v->to)) { - if (children_changed || new) + if (children_changed || newobj) { r.children_changed = 1; - r.new = new; + r.newobj = newobj; } /* Push in reverse order so that the first child is popped from the work stack first, and so will be @@ -1857,13 +1806,12 @@ varobj_update (struct varobj **varp, int explicit) */ static int -delete_variable (struct cpstack **resultp, struct varobj *var, - int only_children_p) +delete_variable (struct varobj *var, int only_children_p) { int delcount = 0; - delete_variable_1 (resultp, &delcount, var, - only_children_p, 1 /* remove_from_parent_p */ ); + delete_variable_1 (&delcount, var, only_children_p, + 1 /* remove_from_parent_p */ ); return delcount; } @@ -1873,8 +1821,7 @@ delete_variable (struct cpstack **resultp, struct varobj *var, and the parent is not removed we dump core. It must be always initially called with remove_from_parent_p set. */ static void -delete_variable_1 (struct cpstack **resultp, int *delcountp, - struct varobj *var, int only_children_p, +delete_variable_1 (int *delcountp, struct varobj *var, int only_children_p, int remove_from_parent_p) { int i; @@ -1888,7 +1835,7 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, continue; if (!remove_from_parent_p) child->parent = NULL; - delete_variable_1 (resultp, delcountp, child, 0, only_children_p); + delete_variable_1 (delcountp, child, 0, only_children_p); } VEC_free (varobj_p, var->children); @@ -1897,11 +1844,10 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, return; /* Otherwise, add it to the list of deleted ones and proceed to do so. */ - /* If the name is null, this is a temporary variable, that has not + /* If the name is empty, this is a temporary variable, that has not yet been installed, don't report it, it belongs to the caller... */ - if (var->obj_name != NULL) + if (!var->obj_name.empty ()) { - cppush (resultp, xstrdup (var->obj_name)); *delcountp = *delcountp + 1; } @@ -1915,7 +1861,7 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, VEC_replace (varobj_p, var->parent->children, var->index, NULL); } - if (var->obj_name != NULL) + if (!var->obj_name.empty ()) uninstall_variable (var); /* Free memory associated with this variable. */ @@ -1932,20 +1878,20 @@ install_variable (struct varobj *var) unsigned int index = 0; unsigned int i = 1; - for (chp = var->obj_name; *chp; chp++) + for (chp = var->obj_name.c_str (); *chp; chp++) { index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE; } cv = *(varobj_table + index); - while ((cv != NULL) && (strcmp (cv->var->obj_name, var->obj_name) != 0)) + while (cv != NULL && cv->var->obj_name != var->obj_name) cv = cv->next; if (cv != NULL) error (_("Duplicate variable object name")); /* Add varobj to hash table. */ - newvl = xmalloc (sizeof (struct vlist)); + newvl = XNEW (struct vlist); newvl->next = *(varobj_table + index); newvl->var = var; *(varobj_table + index) = newvl; @@ -1977,27 +1923,27 @@ uninstall_variable (struct varobj *var) unsigned int i = 1; /* Remove varobj from hash table. */ - for (chp = var->obj_name; *chp; chp++) + for (chp = var->obj_name.c_str (); *chp; chp++) { index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE; } cv = *(varobj_table + index); prev = NULL; - while ((cv != NULL) && (strcmp (cv->var->obj_name, var->obj_name) != 0)) + while (cv != NULL && cv->var->obj_name != var->obj_name) { prev = cv; cv = cv->next; } if (varobjdebug) - fprintf_unfiltered (gdb_stdlog, "Deleting %s\n", var->obj_name); + fprintf_unfiltered (gdb_stdlog, "Deleting %s\n", var->obj_name.c_str ()); if (cv == NULL) { warning ("Assertion failed: Could not find variable object \"%s\" to delete", - var->obj_name); + var->obj_name.c_str ()); return; } @@ -2027,7 +1973,7 @@ uninstall_variable (struct varobj *var) { warning (_("Assertion failed: Could not find " "varobj \"%s\" in root list"), - var->obj_name); + var->obj_name.c_str ()); return; } if (prer == NULL) @@ -2039,13 +1985,16 @@ uninstall_variable (struct varobj *var) } -/* Create and install a child of the parent of the given name. */ +/* Create and install a child of the parent of the given name. + + The created VAROBJ takes ownership of the allocated NAME. */ + static struct varobj * -create_child (struct varobj *parent, int index, char *name) +create_child (struct varobj *parent, int index, std::string &name) { struct varobj_item item; - item.name = name; + std::swap (item.name, name); item.value = value_of_child (parent, index); return create_child_with_value (parent, index, &item); @@ -2056,21 +2005,22 @@ create_child_with_value (struct varobj *parent, int index, struct varobj_item *item) { struct varobj *child; - char *childs_name; child = new_variable (); /* NAME is allocated by caller. */ - child->name = item->name; + std::swap (child->name, item->name); child->index = index; child->parent = parent; child->root = parent->root; if (varobj_is_anonymous_child (child)) - childs_name = xstrprintf ("%s.%d_anonymous", parent->obj_name, index); + child->obj_name = string_printf ("%s.%d_anonymous", + parent->obj_name.c_str (), index); else - childs_name = xstrprintf ("%s.%s", parent->obj_name, item->name); - child->obj_name = childs_name; + child->obj_name = string_printf ("%s.%s", + parent->obj_name.c_str (), + child->name.c_str ()); install_variable (child); @@ -2100,24 +2050,19 @@ new_variable (void) { struct varobj *var; - var = (struct varobj *) xmalloc (sizeof (struct varobj)); - var->name = NULL; - var->path_expr = NULL; - var->obj_name = NULL; + var = new varobj (); var->index = -1; var->type = NULL; var->value = NULL; var->num_children = -1; var->parent = NULL; var->children = NULL; - var->format = 0; + var->format = FORMAT_NATURAL; var->root = NULL; var->updated = 0; - var->print_value = NULL; var->frozen = 0; var->not_fetched = 0; - var->dynamic - = (struct varobj_dynamic *) xmalloc (sizeof (struct varobj_dynamic)); + var->dynamic = XNEW (struct varobj_dynamic); var->dynamic->children_requested = 0; var->from = -1; var->to = -1; @@ -2135,7 +2080,7 @@ new_root_variable (void) { struct varobj *var = new_variable (); - var->root = (struct varobj_root *) xmalloc (sizeof (struct varobj_root)); + var->root = new varobj_root (); var->root->lang_ops = NULL; var->root->exp = NULL; var->root->valid_block = NULL; @@ -2166,25 +2111,17 @@ free_variable (struct varobj *var) varobj_clear_saved_item (var->dynamic); value_free (var->value); - /* Free the expression if this is a root variable. */ if (is_root_p (var)) - { - xfree (var->root->exp); - xfree (var->root); - } + delete var->root; - xfree (var->name); - xfree (var->obj_name); - xfree (var->print_value); - xfree (var->path_expr); xfree (var->dynamic); - xfree (var); + delete var; } static void do_free_variable_cleanup (void *var) { - free_variable (var); + free_variable ((struct varobj *) var); } static struct cleanup * @@ -2205,7 +2142,7 @@ make_cleanup_free_variable (struct varobj *var) For example, top-level references are always stripped. */ struct type * -varobj_get_value_type (struct varobj *var) +varobj_get_value_type (const struct varobj *var) { struct type *type; @@ -2232,36 +2169,6 @@ variable_default_display (struct varobj *var) return FORMAT_NATURAL; } -/* FIXME: The following should be generic for any pointer. */ -static void -cppush (struct cpstack **pstack, char *name) -{ - struct cpstack *s; - - s = (struct cpstack *) xmalloc (sizeof (struct cpstack)); - s->name = name; - s->next = *pstack; - *pstack = s; -} - -/* FIXME: The following should be generic for any pointer. */ -static char * -cppop (struct cpstack **pstack) -{ - struct cpstack *s; - char *v; - - if ((*pstack)->name == NULL && (*pstack)->next == NULL) - return NULL; - - s = *pstack; - v = s->name; - *pstack = (*pstack)->next; - xfree (s); - - return v; -} - /* * Language-dependencies */ @@ -2274,22 +2181,22 @@ cppop (struct cpstack **pstack) is the number of children that the user will see in the variable display. */ static int -number_of_children (struct varobj *var) +number_of_children (const struct varobj *var) { return (*var->root->lang_ops->number_of_children) (var); } -/* What is the expression for the root varobj VAR? Returns a malloc'd - string. */ -static char * -name_of_variable (struct varobj *var) +/* What is the expression for the root varobj VAR? */ + +static std::string +name_of_variable (const struct varobj *var) { return (*var->root->lang_ops->name_of_variable) (var); } -/* What is the name of the INDEX'th child of VAR? Returns a malloc'd - string. */ -static char * +/* What is the name of the INDEX'th child of VAR? */ + +static std::string name_of_child (struct varobj *var, int index) { return (*var->root->lang_ops->name_of_child) (var, index); @@ -2299,7 +2206,7 @@ name_of_child (struct varobj *var, int index) to it and return 1. Otherwise, return 0. */ static int -check_scope (struct varobj *var) +check_scope (const struct varobj *var) { struct frame_info *fi; int scope; @@ -2350,8 +2257,9 @@ value_of_root_1 (struct varobj **var_handle) } else { - ptid_t ptid = thread_id_to_pid (var->root->thread_id); - if (in_thread_list (ptid)) + ptid_t ptid = global_thread_id_to_ptid (var->root->thread_id); + + if (!ptid_equal (minus_one_ptid, ptid)) { switch_to_thread (ptid); within_scope = check_scope (var); @@ -2360,14 +2268,17 @@ value_of_root_1 (struct varobj **var_handle) if (within_scope) { - volatile struct gdb_exception except; /* We need to catch errors here, because if evaluate expression fails we want to just return NULL. */ - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY + { + new_val = evaluate_expression (var->root->exp.get ()); + } + CATCH (except, RETURN_MASK_ERROR) { - new_val = evaluate_expression (var->root->exp); } + END_CATCH } do_cleanups (back_to); @@ -2403,17 +2314,16 @@ value_of_root (struct varobj **var_handle, int *type_changed) if (var->root->floating) { struct varobj *tmp_var; - char *old_type, *new_type; - tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0, + tmp_var = varobj_create (NULL, var->name.c_str (), (CORE_ADDR) 0, USE_SELECTED_FRAME); if (tmp_var == NULL) { return NULL; } - old_type = varobj_get_type (var); - new_type = varobj_get_type (tmp_var); - if (strcmp (old_type, new_type) == 0) + std::string old_type = varobj_get_type (var); + std::string new_type = varobj_get_type (tmp_var); + if (old_type == new_type) { /* The expression presently stored inside var->root->exp remembers the locations of local variables relatively to @@ -2421,28 +2331,23 @@ value_of_root (struct varobj **var_handle, int *type_changed) button, for example). Naturally, those locations are not correct in other frames, so update the expression. */ - struct expression *tmp_exp = var->root->exp; + std::swap (var->root->exp, tmp_var->root->exp); - var->root->exp = tmp_var->root->exp; - tmp_var->root->exp = tmp_exp; - - varobj_delete (tmp_var, NULL, 0); + varobj_delete (tmp_var, 0); *type_changed = 0; } else { - tmp_var->obj_name = xstrdup (var->obj_name); + tmp_var->obj_name = var->obj_name; tmp_var->from = var->from; tmp_var->to = var->to; - varobj_delete (var, NULL, 0); + varobj_delete (var, 0); install_variable (tmp_var); *var_handle = tmp_var; var = *var_handle; *type_changed = 1; } - xfree (old_type); - xfree (new_type); } else { @@ -2463,7 +2368,7 @@ value_of_root (struct varobj **var_handle, int *type_changed) /* The type has mutated, so the children are no longer valid. Just delete them, and tell our caller that the type has changed. */ - varobj_delete (var, NULL, 1 /* only_children */); + varobj_delete (var, 1 /* only_children */); var->num_children = -1; var->to = -1; var->from = -1; @@ -2475,7 +2380,7 @@ value_of_root (struct varobj **var_handle, int *type_changed) /* What is the ``struct value *'' for the INDEX'th child of PARENT? */ static struct value * -value_of_child (struct varobj *parent, int index) +value_of_child (const struct varobj *parent, int index) { struct value *value; @@ -2485,7 +2390,7 @@ value_of_child (struct varobj *parent, int index) } /* GDB already has a command called "value_of_variable". Sigh. */ -static char * +static std::string my_value_of_variable (struct varobj *var, enum varobj_display_formats format) { if (var->root->is_valid) @@ -2495,7 +2400,7 @@ my_value_of_variable (struct varobj *var, enum varobj_display_formats format) return (*var->root->lang_ops->value_of_variable) (var, format); } else - return NULL; + return std::string (); } void @@ -2507,30 +2412,29 @@ varobj_formatted_print_options (struct value_print_options *opts, opts->raw = 1; } -char * +std::string varobj_value_get_print_value (struct value *value, enum varobj_display_formats format, - struct varobj *var) + const struct varobj *var) { struct ui_file *stb; struct cleanup *old_chain; - char *thevalue = NULL; struct value_print_options opts; struct type *type = NULL; long len = 0; char *encoding = NULL; - struct gdbarch *gdbarch = NULL; /* Initialize it just to avoid a GCC false warning. */ CORE_ADDR str_addr = 0; int string_print = 0; if (value == NULL) - return NULL; + return std::string (); stb = mem_fileopen (); old_chain = make_cleanup_ui_file_delete (stb); - gdbarch = get_type_arch (value_type (value)); + std::string thevalue; + #if HAVE_PYTHON if (gdb_python_initialized) { @@ -2580,32 +2484,31 @@ varobj_value_get_print_value (struct value *value, string_print. Otherwise just return the extracted string as a value. */ - char *s = python_string_to_target_string (output); + gdb::unique_xmalloc_ptr s + = python_string_to_target_string (output); if (s) { - char *hint; + struct gdbarch *gdbarch; - hint = gdbpy_get_display_hint (value_formatter); + gdb::unique_xmalloc_ptr hint + = gdbpy_get_display_hint (value_formatter); if (hint) { - if (!strcmp (hint, "string")) + if (!strcmp (hint.get (), "string")) string_print = 1; - xfree (hint); } - len = strlen (s); - thevalue = xmemdup (s, len + 1, len + 1); + thevalue = std::string (s.get ()); + len = thevalue.size (); + gdbarch = get_type_arch (value_type (value)); type = builtin_type (gdbarch)->builtin_char; - xfree (s); if (!string_print) { do_cleanups (old_chain); return thevalue; } - - make_cleanup (xfree, thevalue); } else gdbpy_print_stack (); @@ -2624,8 +2527,9 @@ varobj_value_get_print_value (struct value *value, varobj_formatted_print_options (&opts, format); /* If the THEVALUE has contents, it is a regular string. */ - if (thevalue) - LA_PRINT_STRING (stb, type, (gdb_byte *) thevalue, len, encoding, 0, &opts); + if (!thevalue.empty ()) + LA_PRINT_STRING (stb, type, (gdb_byte *) thevalue.c_str (), + len, encoding, 0, &opts); else if (string_print) /* Otherwise, if string_print is set, and it is not a regular string, it is a lazy string. */ @@ -2634,14 +2538,14 @@ varobj_value_get_print_value (struct value *value, /* All other cases. */ common_val_print (value, stb, 0, &opts, current_language); - thevalue = ui_file_xstrdup (stb, NULL); + thevalue = ui_file_as_string (stb); do_cleanups (old_chain); return thevalue; } int -varobj_editable_p (struct varobj *var) +varobj_editable_p (const struct varobj *var) { struct type *type; @@ -2669,7 +2573,7 @@ varobj_editable_p (struct varobj *var) /* Call VAR's value_is_changeable_p language-specific callback. */ int -varobj_value_is_changeable_p (struct varobj *var) +varobj_value_is_changeable_p (const struct varobj *var) { return var->root->lang_ops->value_is_changeable_p (var); } @@ -2678,7 +2582,7 @@ varobj_value_is_changeable_p (struct varobj *var) selected frame, and not bound to thread/frame. Such variable objects are created using '@' as frame specifier to -var-create. */ int -varobj_floating_p (struct varobj *var) +varobj_floating_p (const struct varobj *var) { return var->root->floating; } @@ -2687,7 +2591,7 @@ varobj_floating_p (struct varobj *var) languages. */ int -varobj_default_value_is_changeable_p (struct varobj *var) +varobj_default_value_is_changeable_p (const struct varobj *var) { int r; struct type *type; @@ -2729,24 +2633,6 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data) (*func) (var_root->rootvar, data); } } - -extern void _initialize_varobj (void); -void -_initialize_varobj (void) -{ - int sizeof_table = sizeof (struct vlist *) * VAROBJ_TABLE_SIZE; - - varobj_table = xmalloc (sizeof_table); - memset (varobj_table, 0, sizeof_table); - - add_setshow_zuinteger_cmd ("varobj", class_maintenance, - &varobjdebug, - _("Set varobj debugging."), - _("Show varobj debugging."), - _("When non-zero, varobj debugging is enabled."), - NULL, show_varobjdebug, - &setdebuglist, &showdebuglist); -} /* Invalidate varobj VAR if it is tied to locals and re-create it if it is defined on globals. It is a helper for varobj_invalidate. @@ -2765,12 +2651,12 @@ varobj_invalidate_iter (struct varobj *var, void *unused) /* Try to create a varobj with same expression. If we succeed replace the old varobj, otherwise invalidate it. */ - tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0, + tmp_var = varobj_create (NULL, var->name.c_str (), (CORE_ADDR) 0, USE_CURRENT_FRAME); if (tmp_var != NULL) { - tmp_var->obj_name = xstrdup (var->obj_name); - varobj_delete (var, NULL, 0); + tmp_var->obj_name = var->obj_name; + varobj_delete (var, 0); install_variable (tmp_var); } else @@ -2789,3 +2675,18 @@ varobj_invalidate (void) { all_root_varobjs (varobj_invalidate_iter, NULL); } + +extern void _initialize_varobj (void); +void +_initialize_varobj (void) +{ + varobj_table = XCNEWVEC (struct vlist *, VAROBJ_TABLE_SIZE); + + add_setshow_zuinteger_cmd ("varobj", class_maintenance, + &varobjdebug, + _("Set varobj debugging."), + _("Show varobj debugging."), + _("When non-zero, varobj debugging is enabled."), + NULL, show_varobjdebug, + &setdebuglist, &showdebuglist); +}