X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=7bd549d45c59d64eea6a3670e9b20066b94b2a2b;hb=6d580b635f8963183540b816b20bb9c240154497;hp=15eb90f8611e6f022233469ba1df0464da8c3686;hpb=f486487f558686c05d4f4d91a75638b9da399044;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index 15eb90f861..7bd549d45c 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,6 +1,6 @@ /* Implementation of the GDB variable objects API. - Copyright (C) 1999-2015 Free Software Foundation, Inc. + Copyright (C) 1999-2017 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 @@ -34,6 +34,7 @@ #if HAVE_PYTHON #include "python/python.h" #include "python/python-internal.h" +#include "python/py-ref.h" #else typedef int PyObject; #endif @@ -49,8 +50,8 @@ 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" }; +const char *varobj_format_string[] = + { "natural", "binary", "decimal", "hexadecimal", "octal", "zero-hexadecimal" }; /* True if we want to allow Python-based pretty-printing. */ static int pretty_printing = 0; @@ -64,12 +65,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; @@ -78,7 +79,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 @@ -136,12 +137,6 @@ struct varobj_dynamic varobj_item *saved_item; }; -struct cpstack -{ - char *name; - struct cpstack *next; -}; - /* A list of varobjs */ struct vlist @@ -154,16 +149,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, @@ -181,10 +175,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); @@ -195,16 +185,16 @@ static int install_new_value (struct varobj *var, struct value *value, static int number_of_children (const struct varobj *); -static char *name_of_variable (const 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 (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 (const struct varobj *var); @@ -214,13 +204,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). */ @@ -236,17 +226,14 @@ is_root_p (const struct varobj *var) } #ifdef HAVE_PYTHON -/* Helper function to install a Python environment suitable for - use during operations on VAR. */ -struct cleanup * -varobj_ensure_python_env (const struct varobj *var) + +/* See python-internal.h. */ +gdbpy_enter_varobj::gdbpy_enter_varobj (const struct varobj *var) +: gdbpy_enter (var->root->exp->gdbarch, var->root->exp->language_defn) { - return ensure_python_env (var->root->exp->gdbarch, - var->root->exp->language_defn); } -#endif -/* Creates a varobj (not its children). */ +#endif /* Return the full FRAME which corresponds to the given CORE_ADDR or NULL if no FRAME on the chain corresponds to CORE_ADDR. */ @@ -280,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; @@ -362,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 @@ -380,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); } @@ -390,13 +379,13 @@ varobj_create (char *objname, But if it fails, we still go on with a call to evaluate_type(). */ TRY { - value = evaluate_expression (var->root->exp); + value = evaluate_expression (var->root->exp.get ()); } 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); } @@ -429,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. */ @@ -463,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; @@ -476,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) @@ -487,66 +476,27 @@ varobj_get_handle (char *objname) /* Given the handle, return the name of the object. */ -char * +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. The - result must be freed by the caller. */ +/* Given the handle, return the expression represented by the + object. */ -char * +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. If DELLIST is non-NULL, it is - assigned a malloc'ed list of all the (malloc'ed) names of the variables - that have been deleted (NULL terminated). Returns the number of deleted - variables. */ +/* 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 @@ -583,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; @@ -593,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); } @@ -607,23 +557,19 @@ varobj_get_display_format (const struct varobj *var) return var->format; } -char * +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; - if (!gdb_python_initialized) return NULL; - back_to = varobj_ensure_python_env (var); + gdbpy_enter_varobj enter_py (var); if (var->dynamic->pretty_printer != NULL) result = gdbpy_get_display_hint (var->dynamic->pretty_printer); - - do_cleanups (back_to); #endif return result; @@ -745,17 +691,13 @@ install_dynamic_child (struct varobj *var, static int dynamic_varobj_has_child_method (const struct varobj *var) { - struct cleanup *back_to; PyObject *printer = var->dynamic->pretty_printer; - int result; if (!gdb_python_initialized) return 0; - back_to = varobj_ensure_python_env (var); - result = PyObject_HasAttr (printer, gdbpy_children_cst); - do_cleanups (back_to); - return result; + gdbpy_enter_varobj enter_py (var); + return PyObject_HasAttr (printer, gdbpy_children_cst); } #endif @@ -782,7 +724,7 @@ varobj_clear_saved_item (struct varobj_dynamic *var) if (var->saved_item != NULL) { value_free (var->saved_item->value); - xfree (var->saved_item); + delete var->saved_item; var->saved_item = NULL; } } @@ -857,7 +799,7 @@ update_dynamic_varobj_children (struct varobj *var, can_mention ? cchanged : NULL, i, item); - xfree (item); + delete item; } else { @@ -875,7 +817,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); } @@ -916,7 +858,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; @@ -953,7 +894,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); } @@ -978,14 +919,14 @@ varobj_add_child (struct varobj *var, struct varobj_item *item) 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); } @@ -1033,10 +974,11 @@ varobj_get_path_expr_parent (const struct varobj *var) /* Return a pointer to the full rooted expression of varobj VAR. If it has not been computed yet, compute it. */ -char * + +const char * varobj_get_path_expr (const struct varobj *var) { - if (var->path_expr == NULL) + if (var->path_expr.empty ()) { /* For root varobjs, we initialize path_expr when creating varobj, so here it should be @@ -1047,7 +989,7 @@ varobj_get_path_expr (const struct varobj *var) mutable_var->path_expr = (*var->root->lang_ops->path_expr_of_child) (var); } - return var->path_expr; + return var->path_expr.c_str (); } const struct language_defn * @@ -1076,14 +1018,14 @@ 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); @@ -1094,13 +1036,12 @@ 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; @@ -1108,16 +1049,15 @@ varobj_set_value (struct varobj *var, char *expression) gdb_assert (varobj_editable_p (var)); input_radix = 10; /* ALWAYS reset to decimal temporarily. */ - exp = parse_exp_1 (&s, 0, 0, 0); + expression_up exp = parse_exp_1 (&s, 0, 0, 0); TRY { - value = evaluate_expression (exp); + value = evaluate_expression (exp.get ()); } CATCH (except, RETURN_MASK_ERROR) { /* We cannot proceed without a valid expression. */ - xfree (exp); return 0; } END_CATCH @@ -1265,16 +1205,12 @@ install_new_value_visualizer (struct varobj *var) if (var->dynamic->constructor != Py_None && var->value != NULL) { - struct cleanup *cleanup; - - cleanup = varobj_ensure_python_env (var); + gdbpy_enter_varobj enter_py (var); if (var->dynamic->constructor == NULL) install_default_visualizer (var); else construct_visualizer (var, var->dynamic->constructor); - - do_cleanups (cleanup); } #else /* Do nothing. */ @@ -1296,23 +1232,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; - int type_name_changed; - - new_type = value_actual_type (new_value, 0, 0); - new_type_str = type_to_string (new_type); - curr_type_str = varobj_get_type (var); - type_name_changed = strcmp (curr_type_str, new_type_str) != 0; - xfree (curr_type_str); - xfree (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); - if (type_name_changed) + /* 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; @@ -1343,7 +1273,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) @@ -1425,6 +1354,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); @@ -1468,8 +1398,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; } } @@ -1500,17 +1430,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)); @@ -1543,35 +1470,31 @@ void varobj_set_visualizer (struct varobj *var, const char *visualizer) { #if HAVE_PYTHON - PyObject *mainmod, *globals, *constructor; - struct cleanup *back_to; + PyObject *mainmod; if (!gdb_python_initialized) return; - back_to = varobj_ensure_python_env (var); + gdbpy_enter_varobj enter_py (var); mainmod = PyImport_AddModule ("__main__"); - globals = PyModule_GetDict (mainmod); - Py_INCREF (globals); - make_cleanup_py_decref (globals); + gdbpy_ref<> globals (PyModule_GetDict (mainmod)); + Py_INCREF (globals.get ()); - constructor = PyRun_String (visualizer, Py_eval_input, globals, globals); + gdbpy_ref<> constructor (PyRun_String (visualizer, Py_eval_input, + globals.get (), globals.get ())); - if (! constructor) + if (constructor == NULL) { gdbpy_print_stack (); error (_("Could not evaluate visualizer expression: %s"), visualizer); } - construct_visualizer (var, constructor); - Py_XDECREF (constructor); + construct_visualizer (var, constructor.get ()); /* 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); #else error (_("Python support required")); #endif @@ -1719,7 +1642,7 @@ varobj_update (struct varobj **varp, int is_explicit) { /* 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; @@ -1867,13 +1790,12 @@ varobj_update (struct varobj **varp, int is_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; } @@ -1883,8 +1805,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; @@ -1898,7 +1819,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); @@ -1907,11 +1828,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; } @@ -1925,7 +1845,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. */ @@ -1942,20 +1862,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; @@ -1987,27 +1907,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; } @@ -2037,7 +1957,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) @@ -2054,11 +1974,11 @@ uninstall_variable (struct varobj *var) 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); @@ -2069,21 +1989,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); @@ -2113,10 +2034,7 @@ 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; @@ -2126,11 +2044,9 @@ new_variable (void) 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; @@ -2148,7 +2064,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; @@ -2167,11 +2083,10 @@ free_variable (struct varobj *var) #if HAVE_PYTHON if (var->dynamic->pretty_printer != NULL) { - struct cleanup *cleanup = varobj_ensure_python_env (var); + gdbpy_enter_varobj enter_py (var); Py_XDECREF (var->dynamic->constructor); Py_XDECREF (var->dynamic->pretty_printer); - do_cleanups (cleanup); } #endif @@ -2179,25 +2094,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 * @@ -2229,7 +2136,7 @@ varobj_get_value_type (const struct varobj *var) type = check_typedef (type); - if (TYPE_CODE (type) == TYPE_CODE_REF) + if (TYPE_IS_REFERENCE (type)) type = get_target_type (type); type = check_typedef (type); @@ -2245,36 +2152,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 */ @@ -2292,17 +2169,17 @@ 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 * +/* 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); @@ -2341,14 +2218,13 @@ value_of_root_1 (struct varobj **var_handle) struct value *new_val = NULL; struct varobj *var = *var_handle; int within_scope = 0; - struct cleanup *back_to; /* Only root variables can be updated... */ if (!is_root_p (var)) /* Not a root var. */ return NULL; - back_to = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; /* Determine whether the variable is still around. */ if (var->root->valid_block == NULL || var->root->floating) @@ -2363,8 +2239,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); @@ -2378,7 +2255,7 @@ value_of_root_1 (struct varobj **var_handle) expression fails we want to just return NULL. */ TRY { - new_val = evaluate_expression (var->root->exp); + new_val = evaluate_expression (var->root->exp.get ()); } CATCH (except, RETURN_MASK_ERROR) { @@ -2386,8 +2263,6 @@ value_of_root_1 (struct varobj **var_handle) END_CATCH } - do_cleanups (back_to); - return new_val; } @@ -2419,17 +2294,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 @@ -2437,28 +2311,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 { @@ -2479,7 +2348,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; @@ -2501,7 +2370,7 @@ value_of_child (const 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) @@ -2511,7 +2380,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 @@ -2523,69 +2392,57 @@ 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, 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; + gdb::unique_xmalloc_ptr encoding; /* 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); + string_file stb; + std::string thevalue; - gdbarch = get_type_arch (value_type (value)); #if HAVE_PYTHON if (gdb_python_initialized) { PyObject *value_formatter = var->dynamic->pretty_printer; - varobj_ensure_python_env (var); + gdbpy_enter_varobj enter_py (var); if (value_formatter) { /* First check to see if we have any children at all. If so, we simply return {...}. */ if (dynamic_varobj_has_child_method (var)) - { - do_cleanups (old_chain); - return xstrdup ("{...}"); - } + return "{...}"; if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst)) { struct value *replacement; - PyObject *output = NULL; - output = apply_varobj_pretty_printer (value_formatter, - &replacement, - stb); + gdbpy_ref<> output (apply_varobj_pretty_printer (value_formatter, + &replacement, + &stb)); /* If we have string like output ... */ - if (output) + if (output != NULL) { - make_cleanup_py_decref (output); - /* If this is a lazy string, extract it. For lazy strings we always print as a string, so set string_print. */ - if (gdbpy_is_lazy_string (output)) + if (gdbpy_is_lazy_string (output.get ())) { - gdbpy_extract_lazy_string (output, &str_addr, &type, - &len, &encoding); - make_cleanup (free_current_contents, &encoding); + gdbpy_extract_lazy_string (output.get (), &str_addr, + &type, &len, &encoding); string_print = 1; } else @@ -2596,32 +2453,28 @@ 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.get ()); 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); + return thevalue; } else gdbpy_print_stack (); @@ -2640,20 +2493,18 @@ 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.get (), 0, &opts); else if (string_print) /* Otherwise, if string_print is set, and it is not a regular string, it is a lazy string. */ - val_print_string (type, encoding, str_addr, len, stb, &opts); + val_print_string (type, encoding.get (), str_addr, len, &stb, &opts); else /* All other cases. */ - common_val_print (value, stb, 0, &opts, current_language); + common_val_print (value, &stb, 0, &opts, current_language); - thevalue = ui_file_xstrdup (stb, NULL); - - do_cleanups (old_chain); - return thevalue; + return std::move (stb.string ()); } int @@ -2763,12 +2614,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 @@ -2792,10 +2643,7 @@ 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); + varobj_table = XCNEWVEC (struct vlist *, VAROBJ_TABLE_SIZE); add_setshow_zuinteger_cmd ("varobj", class_maintenance, &varobjdebug,