diff options
author | Tom Tromey <tromey@adacore.com> | 2022-06-06 09:54:45 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2022-07-15 09:25:33 -0600 |
commit | c4a3dbaf1132105586586617a59d0e7566eefd41 (patch) | |
tree | 60fdbcc109b1a55a76ce8070f6b4b7c81dc6c38f /gdb/python | |
parent | aa63b0a77e193b5181390f19465f33c314d0490e (diff) | |
download | fsf-binutils-gdb-c4a3dbaf1132105586586617a59d0e7566eefd41.zip fsf-binutils-gdb-c4a3dbaf1132105586586617a59d0e7566eefd41.tar.gz fsf-binutils-gdb-c4a3dbaf1132105586586617a59d0e7566eefd41.tar.bz2 |
Expose current 'print' settings to Python
PR python/17291 asks for access to the current print options. While I
think this need is largely satisfied by the existence of
Value.format_string, it seemed to me that a bit more could be done.
First, while Value.format_string uses the user's settings, it does not
react to temporary settings such as "print/x". This patch changes
this.
Second, there is no good way to examine the current settings (in
particular the temporary ones in effect for just a single "print").
This patch adds this as well.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17291
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/py-prettyprint.c | 98 | ||||
-rw-r--r-- | gdb/python/py-value.c | 4 | ||||
-rw-r--r-- | gdb/python/py-varobj.c | 25 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 13 | ||||
-rw-r--r-- | gdb/python/python.c | 4 |
5 files changed, 133 insertions, 11 deletions
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c index a25a1b6..4ef45b2 100644 --- a/gdb/python/py-prettyprint.c +++ b/gdb/python/py-prettyprint.c @@ -39,6 +39,10 @@ enum gdbpy_string_repr_result string_repr_ok }; +/* If non-null, points to options that are in effect while + printing. */ +const struct value_print_options *gdbpy_current_print_options; + /* Helper function for find_pretty_printer which iterates over a list, calls each function and inspects output. This will return a printer object if one recognizes VALUE. If no printer is found, it @@ -604,6 +608,9 @@ gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang, if (printer == Py_None) return EXT_LANG_RC_NOP; + scoped_restore set_options = make_scoped_restore (&gdbpy_current_print_options, + options); + /* If we are printing a map, we want some special formatting. */ gdb::unique_xmalloc_ptr<char> hint (gdbpy_get_display_hint (printer.get ())); @@ -632,8 +639,12 @@ gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang, gdbpy_ref<> apply_varobj_pretty_printer (PyObject *printer_obj, struct value **replacement, - struct ui_file *stream) + struct ui_file *stream, + const value_print_options *opts) { + scoped_restore set_options = make_scoped_restore (&gdbpy_current_print_options, + opts); + *replacement = NULL; gdbpy_ref<> py_str = pretty_print_one_value (printer_obj, replacement); @@ -688,3 +699,88 @@ gdbpy_default_visualizer (PyObject *self, PyObject *args) return find_pretty_printer (val_obj).release (); } + +/* Helper function to set a boolean in a dictionary. */ +static int +set_boolean (PyObject *dict, const char *name, bool val) +{ + gdbpy_ref<> val_obj (PyBool_FromLong (val)); + if (val_obj == nullptr) + return -1; + return PyDict_SetItemString (dict, name, val_obj.get ()); +} + +/* Helper function to set an integer in a dictionary. */ +static int +set_unsigned (PyObject *dict, const char *name, unsigned int val) +{ + gdbpy_ref<> val_obj = gdb_py_object_from_ulongest (val); + if (val_obj == nullptr) + return -1; + return PyDict_SetItemString (dict, name, val_obj.get ()); +} + +/* Implement gdb.print_options. */ +PyObject * +gdbpy_print_options (PyObject *unused1, PyObject *unused2) +{ + gdbpy_ref<> result (PyDict_New ()); + if (result == nullptr) + return nullptr; + + value_print_options opts; + gdbpy_get_print_options (&opts); + + if (set_boolean (result.get (), "raw", + opts.raw) < 0 + || set_boolean (result.get (), "pretty_arrays", + opts.prettyformat_arrays) < 0 + || set_boolean (result.get (), "pretty_structs", + opts.prettyformat_structs) < 0 + || set_boolean (result.get (), "array_indexes", + opts.print_array_indexes) < 0 + || set_boolean (result.get (), "symbols", + opts.symbol_print) < 0 + || set_boolean (result.get (), "unions", + opts.unionprint) < 0 + || set_boolean (result.get (), "address", + opts.addressprint) < 0 + || set_boolean (result.get (), "deref_refs", + opts.deref_ref) < 0 + || set_boolean (result.get (), "actual_objects", + opts.objectprint) < 0 + || set_boolean (result.get (), "static_members", + opts.static_field_print) < 0 + || set_boolean (result.get (), "deref_refs", + opts.deref_ref) < 0 + || set_unsigned (result.get (), "max_elements", + opts.print_max) < 0 + || set_unsigned (result.get (), "max_depth", + opts.max_depth) < 0 + || set_unsigned (result.get (), "repeat_threshold", + opts.repeat_count_threshold) < 0) + return nullptr; + + if (opts.format != 0) + { + char str[2] = { (char) opts.format, 0 }; + gdbpy_ref<> fmtstr = host_string_to_python_string (str); + if (fmtstr == nullptr) + return nullptr; + if (PyDict_SetItemString (result.get (), "format", fmtstr.get ()) < 0) + return nullptr; + } + + return result.release (); +} + +/* Helper function that either finds the prevailing print options, or + calls get_user_print_options. */ +void +gdbpy_get_print_options (value_print_options *opts) +{ + if (gdbpy_current_print_options != nullptr) + *opts = *gdbpy_current_print_options; + else + get_user_print_options (opts); +} diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 12e9562..93cb9b9 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -673,7 +673,7 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw) } struct value_print_options opts; - get_user_print_options (&opts); + gdbpy_get_print_options (&opts); opts.deref_ref = 0; /* We need objects for booleans as the "p" flag for bools is new in @@ -1163,7 +1163,7 @@ valpy_str (PyObject *self) { struct value_print_options opts; - get_user_print_options (&opts); + gdbpy_get_print_options (&opts); opts.deref_ref = 0; string_file stb; diff --git a/gdb/python/py-varobj.c b/gdb/python/py-varobj.c index 372c911..9e4fb6c 100644 --- a/gdb/python/py-varobj.c +++ b/gdb/python/py-varobj.c @@ -17,13 +17,15 @@ #include "python-internal.h" #include "varobj.h" #include "varobj-iter.h" +#include "valprint.h" /* A dynamic varobj iterator "class" for python pretty-printed varobjs. This inherits struct varobj_iter. */ struct py_varobj_iter : public varobj_iter { - py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter); + py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter, + const value_print_options *opts); ~py_varobj_iter () override; std::unique_ptr<varobj_item> next () override; @@ -41,6 +43,9 @@ private: /* The python iterator returned by the printer's 'children' method, or NULL if not available. */ PyObject *m_iter; + + /* The print options to use. */ + value_print_options m_opts; }; /* Implementation of the 'dtor' method of pretty-printed varobj @@ -67,6 +72,9 @@ py_varobj_iter::next () gdbpy_enter_varobj enter_py (m_var); + scoped_restore set_options = make_scoped_restore (&gdbpy_current_print_options, + &m_opts); + gdbpy_ref<> item (PyIter_Next (m_iter)); if (item == NULL) @@ -124,9 +132,11 @@ py_varobj_iter::next () whose children the iterator will be iterating over. PYITER is the python iterator actually responsible for the iteration. */ -py_varobj_iter::py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter) +py_varobj_iter::py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter, + const value_print_options *opts) : m_var (var), - m_iter (pyiter.release ()) + m_iter (pyiter.release ()), + m_opts (*opts) { } @@ -134,13 +144,17 @@ py_varobj_iter::py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter) over VAR's children. */ std::unique_ptr<varobj_iter> -py_varobj_get_iterator (struct varobj *var, PyObject *printer) +py_varobj_get_iterator (struct varobj *var, PyObject *printer, + const value_print_options *opts) { gdbpy_enter_varobj enter_py (var); if (!PyObject_HasAttr (printer, gdbpy_children_cst)) return NULL; + scoped_restore set_options = make_scoped_restore (&gdbpy_current_print_options, + opts); + gdbpy_ref<> children (PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, NULL)); if (children == NULL) @@ -157,5 +171,6 @@ py_varobj_get_iterator (struct varobj *var, PyObject *printer) } return std::unique_ptr<varobj_iter> (new py_varobj_iter (var, - std::move (iter))); + std::move (iter), + opts)); } diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 5d296a7..551438c 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -746,11 +746,16 @@ int gdbpy_is_value_object (PyObject *obj); other pretty-printer functions, because they refer to PyObject. */ gdbpy_ref<> apply_varobj_pretty_printer (PyObject *print_obj, struct value **replacement, - struct ui_file *stream); + struct ui_file *stream, + const value_print_options *opts); gdbpy_ref<> gdbpy_get_varobj_pretty_printer (struct value *value); gdb::unique_xmalloc_ptr<char> gdbpy_get_display_hint (PyObject *printer); PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args); +PyObject *gdbpy_print_options (PyObject *self, PyObject *args); +void gdbpy_get_print_options (value_print_options *opts); +extern const struct value_print_options *gdbpy_current_print_options; + void bpfinishpy_pre_stop_hook (struct gdbpy_breakpoint_object *bp_obj); void bpfinishpy_post_stop_hook (struct gdbpy_breakpoint_object *bp_obj); @@ -784,8 +789,10 @@ int gdb_pymodule_addobject (PyObject *module, const char *name, struct varobj_iter; struct varobj; -std::unique_ptr<varobj_iter> py_varobj_get_iterator (struct varobj *var, - PyObject *printer); +std::unique_ptr<varobj_iter> py_varobj_get_iterator + (struct varobj *var, + PyObject *printer, + const value_print_options *opts); /* Deleter for Py_buffer unique_ptr specialization. */ diff --git a/gdb/python/python.c b/gdb/python/python.c index 2f1a00e..c75896d 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -2560,6 +2560,10 @@ the returned string is 'ADDRESS <SYMBOL+OFFSET>' without the quotes." }, "current_language () -> string\n\ Return the name of the currently selected language." }, + { "print_options", gdbpy_print_options, METH_NOARGS, + "print_options () -> dict\n\ +Return the current print options." }, + {NULL, NULL, 0, NULL} }; |