From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 75611 invoked by alias); 18 Mar 2019 09:22:43 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 75252 invoked by uid 89); 18 Mar 2019 09:22:43 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=HX-Languages-Length:376, H*c:HHHH, H*c:HHHHHHHH X-HELO: mail-wm1-f67.google.com Received: from mail-wm1-f67.google.com (HELO mail-wm1-f67.google.com) (209.85.128.67) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 18 Mar 2019 09:22:41 +0000 Received: by mail-wm1-f67.google.com with SMTP id v14so3383284wmf.2 for ; Mon, 18 Mar 2019 02:22:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=undo-io.20150623.gappssmtp.com; s=20150623; h=from:message-id:mime-version:subject:date:in-reply-to:cc:to :references; bh=4UHSXtcPL0MKzI6+p3OFnNkuiAGCJzcijsmYEM5I0A8=; b=1abe7t49qOzxkYMQLVZSKor/3BpJFg6saCfifGE+9hI9SxLfGOVJZjsPDFyja3doZN 1VB27GdK87HfXJpzPEC7mQcg6VFXZUbXvRy+LDVlmFL5h2BDVGjLLeHqIIN9vNaqxULc R2lPjdZb/EiM33g3Q2ZitFY2+IVhxdIxOYx70LI1GhCQSUqV8RmEVB4qKoj8ooM+I5SR 72Ll2yjj1iuHd0jDNFGIm6WjQ+Mpi52NxxbuTdOT3APQ/FtK4EtU+r/+/SDdEnoIXlxM nxeYly1JlOCWqEvZIaLs9lncKpznxfKbFR1dD3lYws9bvq9zdBjhe6bCHIOMoisv1Su9 JdlQ== Return-Path: Received: from [192.168.0.109] (cpc91242-cmbg18-2-0-cust276.5-4.cable.virginm.net. [82.8.129.21]) by smtp.gmail.com with ESMTPSA id c10sm8337998wrr.1.2019.03.18.02.22.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Mar 2019 02:22:37 -0700 (PDT) From: Marco Barisione Message-Id: Content-Type: multipart/mixed; boundary="Apple-Mail=_6710A3BB-88E6-4AF5-930F-5640220A865E" Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\)) Subject: Re: [PATCH v2] Add gdb.Value.format_string () Date: Mon, 18 Mar 2019 09:22:00 -0000 In-Reply-To: <20190317135023.2e51944d@f29-4.lan> Cc: Kevin Buettner To: gdb-patches@sourceware.org References: <20190317135023.2e51944d@f29-4.lan> X-IsSubscribed: yes X-SW-Source: 2019-03/txt/msg00366.txt.bz2 --Apple-Mail=_6710A3BB-88E6-4AF5-930F-5640220A865E Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Content-length: 324 Hello, Here=E2=80=99s my updated patch fixing Kevin=E2=80=99s review comments. Thanks again for your review! > On 17 Mar 2019, at 20:50, Kevin Buettner wrote: > A period is needed at the end of this ChangeLog entry. Fixed. > Why not use a bool return type to indicate success or failure? Fixed. --Apple-Mail=_6710A3BB-88E6-4AF5-930F-5640220A865E Content-Disposition: attachment; filename=0001-Add-gdb.Value.format_string.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-Add-gdb.Value.format_string.patch" Content-Transfer-Encoding: quoted-printable Content-length: 57981 >From 004d2c324676852d55e3d466ac78f76deaa0ee55 Mon Sep 17 00:00:00 2001=0A= From: Marco Barisione =0A= Date: Mon, 18 Mar 2019 09:15:13 +0000=0A= Subject: [PATCH] Add gdb.Value.format_string ()=0A= =0A= The str () function, called on a gdb.Value instance, produces a string=0A= representation similar to what can be achieved with the print command,=0A= but it doesn't allow to specify additional formatting settings, for=0A= instance disabling pretty printers.=0A= =0A= This patch introduces a new format_string () method to gdb.Value which=0A= allows specifying more formatting options, thus giving access to more=0A= features provided by the internal C function common_val_print ().=0A= =0A= gdb/ChangeLog:=0A= =0A= 2019-03-18 Marco Barisione =0A= =0A= Add gdb.Value.format_string ().=0A= * python/py-value.c (copy_py_bool_obj):=0A= (valpy_format_string): Add gdb.Value.format_string ().=0A= * NEWS: Document the addition of gdb.Value.format_string ().=0A= =0A= gdb/doc/ChangeLog:=0A= =0A= 2019-03-18 Marco Barisione =0A= =0A= * python.texi: Document gdb.Value.format_string ().=0A= =0A= gdb/testsuite/ChangeLog:=0A= =0A= 2019-03-18 Marco Barisione =0A= =0A= Test gdb.Value.format_string ().=0A= * gdb.python/py-format-string.exp: New test.=0A= * gdb.python/py-format-string.c: New file.=0A= * gdb.python/py-format-string.py: New file.=0A= ---=0A= gdb/NEWS | 6 +=0A= gdb/doc/python.texi | 79 ++=0A= gdb/python/py-value.c | 162 +++=0A= gdb/testsuite/gdb.python/py-format-string.c | 118 +++=0A= gdb/testsuite/gdb.python/py-format-string.exp | 958 ++++++++++++++++++=0A= gdb/testsuite/gdb.python/py-format-string.py | 49 +=0A= 6 files changed, 1372 insertions(+)=0A= create mode 100644 gdb/testsuite/gdb.python/py-format-string.c=0A= create mode 100644 gdb/testsuite/gdb.python/py-format-string.exp=0A= create mode 100644 gdb/testsuite/gdb.python/py-format-string.py=0A= =0A= diff --git a/gdb/NEWS b/gdb/NEWS=0A= index c45b313406..e4d9ae0fea 100644=0A= --- a/gdb/NEWS=0A= +++ b/gdb/NEWS=0A= @@ -231,6 +231,12 @@ before Windows XP.=0A= ** The gdb.Value type has a new constructor, which is used to construct = a=0A= gdb.Value from a Python buffer object and a gdb.Type.=0A= =20=0A= + ** The gdb.Value type has a new method 'format_string' which returns a= =0A= + string representing the value. The formatting is controlled by the= =0A= + optional keyword arguments: 'raw', 'pretty_arrays', 'pretty_structs',= =0A= + 'array_indexes', 'symbols', 'unions', 'deref_refs', 'actual_objects',= =0A= + 'static_members', 'max_elements', 'repeat_threshold', and 'format'.= =0A= +=0A= * Configure changes=0A= =20=0A= --enable-ubsan=0A= diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi=0A= index b02a154ce1..71d6d344fb 100644=0A= --- a/gdb/doc/python.texi=0A= +++ b/gdb/doc/python.texi=0A= @@ -864,6 +864,85 @@ Like @code{Value.cast}, but works as if the C@t{++} @c= ode{reinterpret_cast}=0A= operator were used. Consult a C@t{++} reference for details.=0A= @end defun=0A= =20=0A= +@defun Value.format_string (...)=0A= +Convert a @code{gdb.Value} to a string, similarly to what the @code{print}= =0A= +command does. Invoked with no arguments, this is equivalent to calling=0A= +the @code{str} function on the @code{gdb.Value}. The representation of=0A= +the same value may change across different versions of @value{GDBN}, so=0A= +you shouldn't, for instance, parse the strings returned by this method.=0A= +=0A= +All the arguments are keyword only. If an argument is not specified, the= =0A= +current global default setting is used.=0A= +=0A= +@table @code=0A= +@item raw=0A= +@code{True} if pretty-printers (@pxref{Pretty Printing}) should not be=0A= +used to format the value. @code{False} if enabled pretty-printers=0A= +matching the type represented by the @code{gdb.Value} should be used to=0A= +format it.=0A= +=0A= +@item pretty_arrays=0A= +@code{True} if arrays should be pretty printed to be more convenient to=0A= +read, @code{False} if they shouldn't (see @code{set print array} in=0A= +@ref{Print Settings}).=0A= +=0A= +@item pretty_structs=0A= +@code{True} if structs should be pretty printed to be more convenient to= =0A= +read, @code{False} if they shouldn't (see @code{set print pretty} in=0A= +@ref{Print Settings}).=0A= +=0A= +@item array_indexes=0A= +@code{True} if array indexes should be included in the string=0A= +representation of arrays, @code{False} if they shouldn't (see @code{set=0A= +print array-indexes} in @ref{Print Settings}).=0A= +=0A= +@item symbols=0A= +@code{True} if the string representation of a pointer should include the= =0A= +corresponding symbol name (if one exists), @code{False} if it shouldn't=0A= +(see @code{set print symbol} in @ref{Print Settings}).=0A= +=0A= +@item unions=0A= +@code{True} if unions which are contained in other structures or unions=0A= +should be expanded, @code{False} if they shouldn't (see @code{set print=0A= +union} in @ref{Print Settings}).=0A= +=0A= +@item deref_refs=0A= +@code{True} if C++ references should be resolved to the value they refer= =0A= +to, @code{False} (the default) if they shouldn't. Note that, unlike for= =0A= +the @code{print} command, references are not automatically expanded when= =0A= +using the @code{format_string ()} method or the @code{str ()} function.=0A= +There is no global @code{print} setting to change the default behaviour.= =0A= +=0A= +@item actual_objects=0A= +@code{True} if the representation of a pointer to an object should=0A= +identify the @emph{actual} (derived) type of the object rather than the=0A= +@emph{declared} type, using the virtual function table. @code{False} if= =0A= +the @emph{declared} type should be used. (See @code{set print object} in= =0A= +@ref{Print Settings}).=0A= +=0A= +@item static_fields=0A= +@code{True} if static members should be included in the string=0A= +representation of a C++ object, @code{False} if they shouldn't (see=0A= +@code{set print static-members} in @ref{Print Settings}).=0A= +=0A= +@item max_elements=0A= +Number of array elements to print, or @code{0} to print an unlimited=0A= +number of elements (see @code{set print elements} in @ref{Print=0A= +Settings}).=0A= +=0A= +@item repeat_threshold=0A= +Set the threshold for suppressing display of repeated array elements, or= =0A= +@code{0} to represent all elements, even if repeated. (See @code{set=0A= +print repeats} in @ref{Print Settings}).=0A= +=0A= +@item format=0A= +A string containing a single character representing the format to use for= =0A= +the returned string. For instance, @code{'x'} is equivalent to using the= =0A= +@value{GDBN} command @code{print} with the @code{/x} option and formats=0A= +the value as a hexadecimal number.=0A= +@end table=0A= +@end defun=0A= +=0A= @defun Value.string (@r{[}encoding@r{[}, errors@r{[}, length@r{]]]})=0A= If this @code{gdb.Value} represents a string, then this method=0A= converts the contents to a Python string. Otherwise, this method will=0A= diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c=0A= index dd6a536b6a..17f85d97d5 100644=0A= --- a/gdb/python/py-value.c=0A= +++ b/gdb/python/py-value.c=0A= @@ -588,6 +588,163 @@ valpy_string (PyObject *self, PyObject *args, PyObjec= t *kw)=0A= encoding, errors);=0A= }=0A= =20=0A= +/* Given a Python object, copy its truth value to a C int (the value=0A= + pointed by dest).=0A= + If src_obj is NULL, then *dest is not modified.=0A= +=0A= + Return true in case of success (including src_obj being NULL), false=0A= + in case of error. */=0A= +=0A= +static bool=0A= +copy_py_bool_obj (int *dest, PyObject *src_obj)=0A= +{=0A= + if (src_obj)=0A= + {=0A= + int cmp =3D PyObject_IsTrue (src_obj);=0A= + if (cmp < 0)=0A= + return false;=0A= + *dest =3D cmp;=0A= + }=0A= +=0A= + return true;=0A= +}=0A= +=0A= +/* Implementation of gdb.Value.format_string (...) -> string.=0A= + Return Unicode string with value contents formatted using the=0A= + keyword-only arguments. */=0A= +=0A= +static PyObject *=0A= +valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)=0A= +{=0A= + static const char *keywords[] =3D {=0A= + /* Basic C/C++ options. */=0A= + "raw", /* See the /r option to print. */=0A= + "pretty_arrays", /* See set print array on|off. */=0A= + "pretty_structs", /* See set print pretty on|off. */=0A= + "array_indexes", /* See set print array-indexes on|off. */=0A= + "symbols", /* See set print symbol on|off. */=0A= + "unions", /* See set print union on|off. */=0A= + /* C++ options. */=0A= + "deref_refs", /* No corresponding setting. */=0A= + "actual_objects", /* See set print object on|off. */=0A= + "static_members", /* See set print static-members on|off. */=0A= + /* C non-bool options. */=0A= + "max_elements", /* See set print elements N. */=0A= + "repeat_threshold", /* See set print repeats. */=0A= + "format", /* The format passed to the print command. */=0A= + NULL };=0A= +=0A= + /* This function has too many arguments to be useful as positionals, so= =0A= + the user should specify them all as keyword arguments.=0A= + Python 3.3 and later have a way to specify it (both in C and Python= =0A= + itself), but we could be compiled with older versions, so we just=0A= + check that the args tuple is empty. */=0A= + Py_ssize_t positional_count =3D PyObject_Length (args);=0A= + if (positional_count < 0)=0A= + return NULL;=0A= + else if (positional_count > 0)=0A= + {=0A= + /* This matches the error message that Python 3.3 raises when=0A= + passing positionals to functions expecting keyword-only=0A= + arguments. */=0A= + PyErr_Format (PyExc_TypeError,=0A= + "format_string() takes 0 positional arguments but %zu were given",= =0A= + positional_count);=0A= + return NULL;=0A= + }=0A= +=0A= + struct value_print_options opts;=0A= + get_user_print_options (&opts);=0A= + opts.deref_ref =3D 0;=0A= +=0A= + /* We need objects for booleans as the "p" flag for bools is new in=0A= + Python 3.3. */=0A= + PyObject *raw_obj =3D NULL;=0A= + PyObject *pretty_arrays_obj =3D NULL;=0A= + PyObject *pretty_structs_obj =3D NULL;=0A= + PyObject *array_indexes_obj =3D NULL;=0A= + PyObject *symbols_obj =3D NULL;=0A= + PyObject *unions_obj =3D NULL;=0A= + PyObject *deref_refs_obj =3D NULL;=0A= + PyObject *actual_objects_obj =3D NULL;=0A= + PyObject *static_members_obj =3D NULL;=0A= + char *format =3D NULL;=0A= + if (!gdb_PyArg_ParseTupleAndKeywords (args,=0A= + kw,=0A= + "|O!O!O!O!O!O!O!O!O!IIs",=0A= + keywords,=0A= + &PyBool_Type, &raw_obj,=0A= + &PyBool_Type, &pretty_arrays_obj,=0A= + &PyBool_Type, &pretty_structs_obj,=0A= + &PyBool_Type, &array_indexes_obj,=0A= + &PyBool_Type, &symbols_obj,=0A= + &PyBool_Type, &unions_obj,=0A= + &PyBool_Type, &deref_refs_obj,=0A= + &PyBool_Type, &actual_objects_obj,=0A= + &PyBool_Type, &static_members_obj,=0A= + &opts.print_max,=0A= + &opts.repeat_count_threshold,=0A= + &format))=0A= + return NULL;=0A= +=0A= + /* Set boolean arguments. */=0A= + if (!copy_py_bool_obj (&opts.raw, raw_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.prettyformat_arrays, pretty_arrays_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.prettyformat_structs, pretty_structs_obj))= =0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.print_array_indexes, array_indexes_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.symbol_print, symbols_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.unionprint, unions_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.deref_ref, deref_refs_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.objectprint, actual_objects_obj))=0A= + return NULL;=0A= + if (!copy_py_bool_obj (&opts.static_field_print, static_members_obj))=0A= + return NULL;=0A= +=0A= + /* Numeric arguments for which 0 means unlimited (which we represent as= =0A= + UINT_MAX). */=0A= + if (opts.print_max =3D=3D 0)=0A= + opts.print_max =3D UINT_MAX;=0A= + if (opts.repeat_count_threshold =3D=3D 0)=0A= + opts.repeat_count_threshold =3D UINT_MAX;=0A= +=0A= + /* Other arguments. */=0A= + if (format !=3D NULL)=0A= + {=0A= + if (strlen (format) =3D=3D 1)=0A= + opts.format =3D format[0];=0A= + else=0A= + {=0A= + /* Mimic the message on standard Python ones for similar=0A= + errors. */=0A= + PyErr_SetString (PyExc_ValueError,=0A= + "a single character is required");=0A= + return NULL;=0A= + }=0A= + }=0A= +=0A= + string_file stb;=0A= +=0A= + TRY=0A= + {=0A= + common_val_print (((value_object *) self)->value, &stb, 0,=0A= + &opts, python_language);=0A= + }=0A= + CATCH (except, RETURN_MASK_ALL)=0A= + {=0A= + GDB_PY_HANDLE_EXCEPTION (except);=0A= + }=0A= + END_CATCH=0A= +=0A= + return PyUnicode_Decode (stb.c_str (), stb.size (), host_charset (), NUL= L);=0A= +}=0A= +=0A= /* A helper function that implements the various cast operators. */=0A= =20=0A= static PyObject *=0A= @@ -1944,6 +2101,11 @@ Return a lazy string representation of the value." }= ,=0A= Return Unicode string representation of the value." },=0A= { "fetch_lazy", valpy_fetch_lazy, METH_NOARGS,=0A= "Fetches the value from the inferior, if it was lazy." },=0A= + { "format_string", (PyCFunction) valpy_format_string,=0A= + METH_VARARGS | METH_KEYWORDS,=0A= + "format_string (...) -> string\n\=0A= +Return a string representation of the value using the specified\n\=0A= +formatting options" },=0A= {NULL} /* Sentinel */=0A= };=0A= =20=0A= diff --git a/gdb/testsuite/gdb.python/py-format-string.c b/gdb/testsuite/gd= b.python/py-format-string.c=0A= new file mode 100644=0A= index 0000000000..120ecce989=0A= --- /dev/null=0A= +++ b/gdb/testsuite/gdb.python/py-format-string.c=0A= @@ -0,0 +1,118 @@=0A= +/* This testcase is part of GDB, the GNU debugger.=0A= +=0A= + Copyright 2019 Free Software Foundation, Inc.=0A= +=0A= + This program is free software; you can redistribute it and/or modify=0A= + it under the terms of the GNU General Public License as published by=0A= + the Free Software Foundation; either version 3 of the License, or=0A= + (at your option) any later version.=0A= +=0A= + This program is distributed in the hope that it will be useful,=0A= + but WITHOUT ANY WARRANTY; without even the implied warranty of=0A= + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A= + GNU General Public License for more details.=0A= +=0A= + You should have received a copy of the GNU General Public License=0A= + along with this program. If not, see . = */=0A= +=0A= +typedef struct point=0A= +{=0A= + int x;=0A= + int y;=0A= +} point_t;=0A= +=0A= +typedef union=0A= +{=0A= + int an_int;=0A= + char a_char;=0A= +} union_t;=0A= +=0A= +typedef struct=0A= +{=0A= + union_t the_union;=0A= +} struct_union_t;=0A= +=0A= +typedef enum=0A= +{=0A= + ENUM_FOO,=0A= + ENUM_BAR,=0A= +} enum_t;=0A= +=0A= +typedef void (*function_t) (int);=0A= +=0A= +static void=0A= +my_function(int n)=0A= +{=0A= +}=0A= +=0A= +#ifdef __cplusplus=0A= +=0A= +struct Base=0A= +{=0A= + Base (int a_) : a (a_) {}=0A= +=0A= + virtual int get_number () { return a; }=0A= +=0A= + int a;=0A= +=0A= + static int a_static_member;=0A= +};=0A= +=0A= +int Base::a_static_member =3D 2019;=0A= +=0A= +struct Deriv : Base=0A= +{=0A= + Deriv (int b_) : Base (42), b (b_) {}=0A= +=0A= + virtual int get_number () { return b; }=0A= +=0A= + int b;=0A= +};=0A= +=0A= +#endif=0A= +=0A= +int global_symbol =3D 42;=0A= +=0A= +int=0A= +main ()=0A= +{=0A= + point_t a_point_t =3D { 42, 12 };=0A= + point_t *a_point_t_pointer =3D &a_point_t;=0A= +#ifdef __cplusplus=0A= + point_t &a_point_t_ref =3D a_point_t;=0A= +#endif=0A= + struct point another_point =3D { 123, 456 };=0A= +=0A= + struct_union_t a_struct_with_union;=0A= + a_struct_with_union.the_union.an_int =3D 42;=0A= +=0A= + enum_t an_enum =3D ENUM_BAR;=0A= +=0A= + const char *a_string =3D "hello world";=0A= + const char *a_binary_string =3D "hello\0world";=0A= + const char a_binary_string_array[] =3D "hello\0world";=0A= +=0A= + const int letters_repeat =3D 10;=0A= + char a_big_string[26 * letters_repeat + 1];=0A= + a_big_string[26 * letters_repeat] =3D '\0';=0A= + for (int i =3D 0; i < letters_repeat; i++)=0A= + for (char c =3D 'A'; c <=3D 'Z'; c++)=0A= + a_big_string[i * 26 + c - 'A'] =3D c;=0A= +=0A= + int an_array[] =3D { 2, 3, 5 };=0A= +=0A= + int an_array_with_repetition[] =3D {=0A= + 1, /* 1 time. */=0A= + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 12 times. */=0A= + 5, 5, 5, /* 3 times */=0A= + };=0A= +=0A= + int *a_symbol_pointer =3D &global_symbol;=0A= +=0A= +#ifdef __cplusplus=0A= + Deriv a_deriv (123);=0A= + Base &a_base_ref =3D a_deriv;=0A= +#endif=0A= +=0A= + return 0; /* break here */=0A= +}=0A= diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/= gdb.python/py-format-string.exp=0A= new file mode 100644=0A= index 0000000000..4dbe3f80fa=0A= --- /dev/null=0A= +++ b/gdb/testsuite/gdb.python/py-format-string.exp=0A= @@ -0,0 +1,958 @@=0A= +# Copyright (C) 2009-2019 Free Software Foundation, Inc.=0A= +=0A= +# This program is free software; you can redistribute it and/or modify=0A= +# it under the terms of the GNU General Public License as published by=0A= +# the Free Software Foundation; either version 3 of the License, or=0A= +# (at your option) any later version.=0A= +#=0A= +# This program is distributed in the hope that it will be useful,=0A= +# but WITHOUT ANY WARRANTY; without even the implied warranty of=0A= +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A= +# GNU General Public License for more details.=0A= +#=0A= +# You should have received a copy of the GNU General Public License=0A= +# along with this program. If not, see .=0A= +=0A= +# This file is part of the GDB testsuite. It tests the=0A= +# gdb.Value.format_string () method.=0A= +=0A= +load_lib gdb-python.exp=0A= +=0A= +standard_testfile=0A= +=0A= +if [get_compiler_info c++] {=0A= + return -1=0A= +}=0A= +=0A= +# Build inferior to language specification.=0A= +proc build_inferior {exefile lang} {=0A= + global srcdir subdir srcfile testfile hex=0A= +=0A= + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${exefile}" executab= le "debug $lang"] !=3D "" } {=0A= + untested "failed to compile in $lang mode"=0A= + return -1=0A= + }=0A= +=0A= + return 0=0A= +}=0A= +=0A= +# Restart GDB.=0A= +proc prepare_gdb {exefile} {=0A= + global srcdir subdir srcfile testfile hex=0A= +=0A= + gdb_exit=0A= + gdb_start=0A= + gdb_reinitialize_dir $srcdir/$subdir=0A= + gdb_load ${exefile}=0A= +=0A= + # Skip all tests if Python scripting is not enabled.=0A= + if { [skip_python_tests] } { continue }=0A= +=0A= + if ![runto_main] then {=0A= + perror "couldn't run to breakpoint"=0A= + return=0A= + }=0A= +=0A= + # Load the pretty printer.=0A= + set remote_python_file \=0A= + [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]=0A= + gdb_test_no_output "source ${remote_python_file}" "load python file"=0A= +=0A= + runto_bp "break here"=0A= +}=0A= +=0A= +# Set breakpoint and run to that breakpoint.=0A= +proc runto_bp {bp} {=0A= + gdb_breakpoint [gdb_get_line_number $bp]=0A= + gdb_continue_to_breakpoint $bp=0A= +}=0A= +=0A= +# Set an option using the GDB command in $set_cmd, execute $body, and then= =0A= +# restore the option using the GDB command in $unset_cmd.=0A= +proc with_temp_option { set_cmd unset_cmd body } {=0A= + with_test_prefix $set_cmd {=0A= + gdb_test "$set_cmd" ".*"=0A= + uplevel 1 $body=0A= + gdb_test "$unset_cmd" ".*"=0A= + }=0A= +}=0A= +=0A= +# A regular expression for a pointer.=0A= +set default_pointer_regexp "0x\[a-fA-F0-9\]+"=0A= +=0A= +# A regular expression for a non-expanded C++ reference.=0A= +#=0A= +# Stringifying a C++ reference produces an address preceeded by a "@" in= =0A= +# Python, but, by default, the C++ reference/class is expanded by the=0A= +# GDB print command.=0A= +set default_ref_regexp "@${default_pointer_regexp}"=0A= +=0A= +# The whole content of the C variable a_big_string, i.e. the whole English= =0A= +# alphabet repeated 10 times.=0A= +set whole_big_string ""=0A= +set alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ"=0A= +for {set i 0} {$i < 10} {incr i} {=0A= + append whole_big_string $alphabet=0A= +}=0A= +unset alphabet=0A= +=0A= +# Produces a potentially cut down version of $whole_big_string like GDB=0A= +# would represent it.=0A= +# $max is the maximum number of characters allowed in the string (but=0A= +# the return value may contain more to accound for the extra quotes and=0A= +# "..." added by GDB).=0A= +proc get_cut_big_string { max } {=0A= + global whole_big_string=0A= +=0A= + set whole_size [string length $whole_big_string]=0A= + if { $max > $whole_size } {=0A= + return "\"${whole_big_string}\""=0A= + }=0A= +=0A= + set cut_string [string range $whole_big_string 0 [expr $max - 1]]=0A= + return "\"${cut_string}\"..."=0A= +}=0A= +=0A= +# A dictionary mapping from C variable names to their default string=0A= +# representation when using str () or gdb.Value.format_string () with=0A= +# no arguments.=0A= +# This usually matches what the print command prints if used with no=0A= +# options, except for C++ references which are not expanded by=0A= +# default in Python. See the comment above $default_ref_regexp.=0A= +set default_regexp_dict [dict create \=0A= + "a_point_t" "Pretty Point \\(42, 12\\)" \=0A= + "a_point_t_pointer" $default_pointer_regexp \=0A= + "a_point_t_ref" "Pretty Point \\(42, 12\\)" \=0A= + "another_point" "Pretty Point \\(123, 456\\)" \=0A= + "a_struct_with_union" "\\{the_union =3D \\{an_int =3D 42, a_char =3D 42= '\\*'\\}\\}" \=0A= + "an_enum" "ENUM_BAR" \=0A= + "a_string" "${default_pointer_regexp} \"hello world\"" \=0A= + "a_binary_string" "${default_pointer_regexp} \"hello\"" \=0A= + "a_binary_string_array" "\"hello\\\\000world\"" \=0A= + "a_big_string" [get_cut_big_string 200] \=0A= + "an_array" "\\{2, 3, 5\\}" \=0A= + "an_array_with_repetition" "\\{1, 3 , 5, 5, 5\\}" \=0A= + "a_symbol_pointer" "${default_pointer_regexp} " \=0A= + "a_base_ref" "${default_ref_regexp}" \=0A= + ]=0A= +=0A= +# A sentinel value to pass to function to get them to use a default value= =0A= +# instead.=0A= +# Note that we cannot use $undefined for default arguments in function=0A= +# definitions as we would just get the literal "$undefined" string, so=0A= +# we need to repeat the string.=0A= +set undefined "\000UNDEFINED\000"=0A= +=0A= +# Return $value if it's not $undefined, otherwise return the default value= =0A= +# (from $default_regexp_dict) for the variable $var.=0A= +proc get_value_or_default { var value } {=0A= + global undefined=0A= + if { $value !=3D $undefined } {=0A= + return $value=0A= + }=0A= +=0A= + global default_regexp_dict=0A= + return [dict get $default_regexp_dict $var]=0A= +}=0A= +=0A= +# Check that using gdb.Value.format_string on the value representing the= =0A= +# variable $var produces $expected.=0A= +proc check_format_string {=0A= + var=0A= + opts=0A= + { expected "\000UNDEFINED\000" }=0A= + { name "\000UNDEFINED\000" }=0A= + } {=0A= + global undefined=0A= +=0A= + set expected [get_value_or_default $var $expected]=0A= + if { $name =3D=3D $undefined } {=0A= + set name "${var} with option ${opts}"=0A= + }=0A= +=0A= + gdb_test \=0A= + "python print (gdb.parse_and_eval ('${var}').format_string (${opts}))"= \=0A= + $expected \=0A= + $name=0A= +}=0A= +=0A= +# Check that printing $var with no options set, produces the expected=0A= +# output.=0A= +proc check_var_with_no_opts {=0A= + var=0A= + { expected "\000UNDEFINED\000" }=0A= + } {=0A= + set expected [get_value_or_default $var $expected]=0A= +=0A= + with_test_prefix "${var}" {=0A= + check_format_string \=0A= + $var \=0A= + "" \=0A= + $expected \=0A= + "no opts"=0A= + # str () should behave like gdb.Value.format_string () with no args.= =0A= + gdb_test \=0A= + "python print (str (gdb.parse_and_eval ('${var}')))" \=0A= + $expected \=0A= + "str"=0A= + }=0A= +}=0A= +=0A= +# Check that printing $var with $opt set to True and set to False,=0A= +# produces the expected output.=0A= +proc check_var_with_bool_opt {=0A= + opt=0A= + var=0A= + { true_expected "\000UNDEFINED\000" }=0A= + { false_expected "\000UNDEFINED\000" }=0A= + } {=0A= + set true_expected [get_value_or_default $var $true_expected]=0A= + set false_expected [get_value_or_default $var $false_expected]=0A= +=0A= + with_test_prefix "${var} with option ${opt}" {=0A= + # Option set to True.=0A= + check_format_string \=0A= + $var \=0A= + "${opt}=3DTrue" \=0A= + $true_expected \=0A= + "${opt}=3Dtrue"=0A= + # Option set to False.=0A= + check_format_string \=0A= + $var \=0A= + "${opt}=3DFalse" \=0A= + $false_expected \=0A= + "${opt}=3Dfalse"=0A= + }=0A= +}=0A= +=0A= +# Test gdb.Value.format_string with no options.=0A= +proc test_no_opts {} {=0A= + global current_lang=0A= +=0A= + check_var_with_no_opts "a_point_t"=0A= + check_var_with_no_opts "a_point_t_pointer"=0A= + check_var_with_no_opts "another_point"=0A= + check_var_with_no_opts "a_struct_with_union"=0A= + check_var_with_no_opts "an_enum"=0A= + check_var_with_no_opts "a_string"=0A= + check_var_with_no_opts "a_binary_string"=0A= + check_var_with_no_opts "a_binary_string_array"=0A= + check_var_with_no_opts "a_big_string"=0A= + check_var_with_no_opts "an_array"=0A= + check_var_with_no_opts "an_array_with_repetition"=0A= + check_var_with_no_opts "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + # Nothing changes in all of the C++ tests because deref_refs is not=0A= + # True.=0A= + check_var_with_no_opts "a_point_t_ref"=0A= + check_var_with_no_opts "a_base_ref"=0A= + }=0A= +}=0A= +=0A= +# Test the raw option for gdb.Value.format_string.=0A= +proc test_raw {} {=0A= + global current_lang=0A= + global default_ref_regexp=0A= +=0A= + check_var_with_bool_opt "raw" "a_point_t" \=0A= + "{x =3D 42, y =3D 12}"=0A= + check_var_with_bool_opt "raw" "a_point_t_pointer"=0A= + check_var_with_bool_opt "raw" "another_point" \=0A= + "{x =3D 123, y =3D 456}"=0A= + check_var_with_bool_opt "raw" "a_struct_with_union"=0A= + check_var_with_bool_opt "raw" "an_enum"=0A= + check_var_with_bool_opt "raw" "a_string"=0A= + check_var_with_bool_opt "raw" "a_binary_string"=0A= + check_var_with_bool_opt "raw" "a_binary_string_array"=0A= + check_var_with_bool_opt "raw" "a_big_string"=0A= + check_var_with_bool_opt "raw" "an_array"=0A= + check_var_with_bool_opt "raw" "an_array_with_repetition"=0A= + check_var_with_bool_opt "raw" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "raw" "a_point_t_ref" \=0A= + ${default_ref_regexp}=0A= + check_var_with_bool_opt "raw" "a_base_ref"=0A= + }=0A= +=0A= + with_temp_option \=0A= + "disable pretty-printer '' test_lookup_function" \=0A= + "enable pretty-printer '' test_lookup_function" {=0A= + check_var_with_no_opts "a_point_t" \=0A= + "{x =3D 42, y =3D 12}"=0A= + check_var_with_bool_opt "raw" "a_point_t" \=0A= + "{x =3D 42, y =3D 12}" \=0A= + "{x =3D 42, y =3D 12}"=0A= + }=0A= +}=0A= +=0A= +# Test the pretty_arrays option for gdb.Value.format_string.=0A= +proc test_pretty_arrays {} {=0A= + global current_lang=0A= +=0A= + set an_array_pretty " \\{2,\[\r\n\]+ 3,\[\r\n\]+ 5\\}"=0A= + set an_array_with_repetition_pretty \=0A= + " \\{1,\[\r\n\]+ 3 ,\[\r\n\]+ 5,\[\r\n\]+ 5,\[\r= \n\]+ 5\\}"=0A= +=0A= + check_var_with_bool_opt "pretty_arrays" "a_point_t"=0A= + check_var_with_bool_opt "pretty_arrays" "a_point_t_pointer"=0A= + check_var_with_bool_opt "pretty_arrays" "another_point"=0A= + check_var_with_bool_opt "pretty_arrays" "a_struct_with_union"=0A= + check_var_with_bool_opt "pretty_arrays" "an_enum"=0A= + check_var_with_bool_opt "pretty_arrays" "a_string"=0A= + check_var_with_bool_opt "pretty_arrays" "a_binary_string"=0A= + check_var_with_bool_opt "pretty_arrays" "a_binary_string_array"=0A= + check_var_with_bool_opt "pretty_arrays" "a_big_string"=0A= + check_var_with_bool_opt "pretty_arrays" "an_array" \=0A= + $an_array_pretty=0A= + check_var_with_bool_opt "pretty_arrays" "an_array_with_repetition" \=0A= + $an_array_with_repetition_pretty=0A= + check_var_with_bool_opt "pretty_arrays" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "pretty_arrays" "a_point_t_ref"=0A= + check_var_with_bool_opt "pretty_arrays" "a_base_ref"=0A= + }=0A= +=0A= + with_temp_option "set print array on" "set print array off" {=0A= + check_var_with_no_opts "an_array" \=0A= + $an_array_pretty=0A= + check_var_with_bool_opt "pretty_arrays" "an_array" \=0A= + $an_array_pretty=0A= +=0A= + check_var_with_no_opts "an_array_with_repetition" \=0A= + $an_array_with_repetition_pretty=0A= + check_var_with_bool_opt "pretty_arrays" "an_array_with_repetition" \= =0A= + $an_array_with_repetition_pretty=0A= + }=0A= +}=0A= +=0A= +# Test the pretty_structs option for gdb.Value.format_string.=0A= +proc test_pretty_structs {} {=0A= + global current_lang=0A= +=0A= + set a_struct_with_union_pretty \=0A= + "\\{\[\r\n\]+ the_union =3D \\{\[\r\n\]+ an_int =3D 42, \[\r\n\]+ = a_char =3D 42 '\\*'\[\r\n\]+ \\}\[\r\n\]+\\}"=0A= + # Note the space after the colon! ^ here=0A= +=0A= + check_var_with_bool_opt "pretty_structs" "a_point_t"=0A= + check_var_with_bool_opt "pretty_structs" "a_point_t_pointer"=0A= + check_var_with_bool_opt "pretty_structs" "another_point"=0A= + check_var_with_bool_opt "pretty_structs" "a_struct_with_union" \=0A= + $a_struct_with_union_pretty=0A= + check_var_with_bool_opt "pretty_structs" "an_enum"=0A= + check_var_with_bool_opt "pretty_structs" "a_string"=0A= + check_var_with_bool_opt "pretty_structs" "a_binary_string"=0A= + check_var_with_bool_opt "pretty_structs" "a_binary_string_array"=0A= + check_var_with_bool_opt "pretty_structs" "a_big_string"=0A= + check_var_with_bool_opt "pretty_structs" "an_array"=0A= + check_var_with_bool_opt "pretty_structs" "an_array_with_repetition"=0A= + check_var_with_bool_opt "pretty_structs" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "pretty_structs" "a_point_t_ref"=0A= + check_var_with_bool_opt "pretty_structs" "a_base_ref"=0A= + }=0A= +=0A= + with_temp_option "set print structs on" "set print structs off" {=0A= + check_var_with_no_opts "a_struct_with_union"=0A= + check_var_with_bool_opt "pretty_structs" "a_struct_with_union" \=0A= + $a_struct_with_union_pretty=0A= + }=0A= +=0A= + # point_t is usually printed through the pretty printer.=0A= + # Try disabling it.=0A= + with_temp_option \=0A= + "disable pretty-printer '' test_lookup_function" \=0A= + "enable pretty-printer '' test_lookup_function" {=0A= + check_var_with_no_opts "a_point_t" \=0A= + "{x =3D 42, y =3D 12}"=0A= + check_var_with_bool_opt "pretty_structs" "a_point_t" \=0A= + "\\{\[\r\n\]+ x =3D 42, *\[\r\n\]+ y =3D 12\[\r\n\]+\\}" \=0A= + "{x =3D 42, y =3D 12}" \=0A= + }=0A= +}=0A= +=0A= +# Test the array_indexes option for gdb.Value.format_string.=0A= +proc test_array_indexes {} {=0A= + global current_lang=0A= +=0A= + set an_array_with_indexes "\\{\\\[0\\\] =3D 2, \\\[1\\\] =3D 3, \\\[2\\\= ] =3D 5\\}"=0A= + set an_array_with_repetition_with_indexes \=0A= + "\\{\\\[0\\\] =3D 1, \\\[1\\\] =3D 3 , \\\[13\\\] = =3D 5, \\\[14\\\] =3D 5, \\\[15\\\] =3D 5\\}"=0A= +=0A= + check_var_with_bool_opt "array_indexes" "a_point_t"=0A= + check_var_with_bool_opt "array_indexes" "a_point_t_pointer"=0A= + check_var_with_bool_opt "array_indexes" "another_point"=0A= + check_var_with_bool_opt "array_indexes" "a_struct_with_union"=0A= + check_var_with_bool_opt "array_indexes" "an_enum"=0A= + check_var_with_bool_opt "array_indexes" "a_string"=0A= + check_var_with_bool_opt "array_indexes" "a_binary_string"=0A= + check_var_with_bool_opt "array_indexes" "a_binary_string_array"=0A= + check_var_with_bool_opt "array_indexes" "a_big_string"=0A= + check_var_with_bool_opt "array_indexes" "an_array" \=0A= + $an_array_with_indexes=0A= + check_var_with_bool_opt "array_indexes" "an_array_with_repetition" \=0A= + $an_array_with_repetition_with_indexes=0A= + check_var_with_bool_opt "array_indexes" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "array_indexes" "a_point_t_ref"=0A= + check_var_with_bool_opt "array_indexes" "a_base_ref"=0A= + }=0A= +=0A= + with_temp_option \=0A= + "set print array-indexes on" \=0A= + "set print array-indexes off" {=0A= + check_var_with_no_opts "an_array" \=0A= + $an_array_with_indexes=0A= + check_var_with_bool_opt "array_indexes" "an_array" \=0A= + $an_array_with_indexes=0A= +=0A= + check_var_with_no_opts "an_array_with_repetition" \=0A= + $an_array_with_repetition_with_indexes=0A= + check_var_with_bool_opt "array_indexes" "an_array_with_repetition" \= =0A= + $an_array_with_repetition_with_indexes=0A= + }=0A= +}=0A= +=0A= +# Test the symbols option for gdb.Value.format_string.=0A= +proc test_symbols {} {=0A= + global undefined=0A= + global current_lang=0A= + global default_pointer_regexp=0A= +=0A= + check_var_with_bool_opt "symbols" "a_point_t"=0A= + check_var_with_bool_opt "symbols" "a_point_t_pointer"=0A= + check_var_with_bool_opt "symbols" "another_point"=0A= + check_var_with_bool_opt "symbols" "a_struct_with_union"=0A= + check_var_with_bool_opt "symbols" "an_enum"=0A= + check_var_with_bool_opt "symbols" "a_string"=0A= + check_var_with_bool_opt "symbols" "a_binary_string"=0A= + check_var_with_bool_opt "symbols" "a_binary_string_array"=0A= + check_var_with_bool_opt "symbols" "a_big_string"=0A= + check_var_with_bool_opt "symbols" "an_array"=0A= + check_var_with_bool_opt "symbols" "an_array_with_repetition"=0A= + check_var_with_bool_opt "symbols" "a_symbol_pointer" \=0A= + $undefined \=0A= + $default_pointer_regexp=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "symbols" "a_point_t_ref"=0A= + check_var_with_bool_opt "symbols" "a_base_ref"=0A= + }=0A= +=0A= + with_temp_option "set print symbol off" "set print symbol on" {=0A= + check_var_with_no_opts "a_symbol_pointer" \=0A= + $default_pointer_regexp=0A= + check_var_with_bool_opt "symbols" "a_symbol_pointer" \=0A= + $undefined \=0A= + $default_pointer_regexp=0A= + }=0A= +}=0A= +=0A= +# Test the unions option for gdb.Value.format_string.=0A= +proc test_unions {} {=0A= + global undefined=0A= + global current_lang=0A= +=0A= + check_var_with_bool_opt "unions" "a_point_t"=0A= + check_var_with_bool_opt "unions" "a_point_t_pointer"=0A= + check_var_with_bool_opt "unions" "another_point"=0A= + check_var_with_bool_opt "unions" "a_struct_with_union" \=0A= + $undefined \=0A= + "\\{the_union =3D \\{...\\}\\}"=0A= + check_var_with_bool_opt "unions" "an_enum"=0A= + check_var_with_bool_opt "unions" "a_string"=0A= + check_var_with_bool_opt "unions" "a_binary_string"=0A= + check_var_with_bool_opt "unions" "a_binary_string_array"=0A= + check_var_with_bool_opt "unions" "a_big_string"=0A= + check_var_with_bool_opt "unions" "an_array"=0A= + check_var_with_bool_opt "unions" "an_array_with_repetition"=0A= + check_var_with_bool_opt "unions" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "unions" "a_point_t_ref"=0A= + check_var_with_bool_opt "unions" "a_base_ref"=0A= + }=0A= +=0A= + with_temp_option "set print union off" "set print union on" {=0A= + check_var_with_no_opts "a_struct_with_union" \=0A= + "\\{the_union =3D \\{...\\}\\}"=0A= + check_var_with_bool_opt "unions" "a_struct_with_union" \=0A= + $undefined \=0A= + "\\{the_union =3D \\{...\\}\\}"=0A= + }=0A= +}=0A= +=0A= +# Test the deref_refs option for gdb.Value.format_string.=0A= +proc test_deref_refs {} {=0A= + global current_lang=0A= + global default_pointer_regexp=0A= + global default_ref_regexp=0A= +=0A= + check_var_with_bool_opt "deref_refs" "a_point_t"=0A= + check_var_with_bool_opt "deref_refs" "a_point_t_pointer"=0A= + check_var_with_bool_opt "deref_refs" "another_point"=0A= + check_var_with_bool_opt "deref_refs" "a_struct_with_union"=0A= + check_var_with_bool_opt "deref_refs" "an_enum"=0A= + check_var_with_bool_opt "deref_refs" "a_string"=0A= + check_var_with_bool_opt "deref_refs" "a_binary_string"=0A= + check_var_with_bool_opt "deref_refs" "a_binary_string_array"=0A= + check_var_with_bool_opt "deref_refs" "a_big_string"=0A= + check_var_with_bool_opt "deref_refs" "an_array"=0A= + check_var_with_bool_opt "deref_refs" "an_array_with_repetition"=0A= + check_var_with_bool_opt "deref_refs" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_var_with_bool_opt "deref_refs" "a_point_t_ref"=0A= + check_var_with_bool_opt "deref_refs" "a_base_ref" \=0A= + "${default_ref_regexp}: \\{_vptr\\.Base =3D ${default_pointer_regexp= } , a =3D 42, static a_static_member =3D 2019\\}"=0A= + }=0A= +}=0A= +=0A= +# Test the actual_objects option for gdb.Value.format_string.=0A= +proc test_actual_objects {} {=0A= + global current_lang=0A= +=0A= + check_var_with_bool_opt "actual_objects" "a_point_t"=0A= + check_var_with_bool_opt "actual_objects" "a_point_t_pointer"=0A= + check_var_with_bool_opt "actual_objects" "another_point"=0A= + check_var_with_bool_opt "actual_objects" "a_struct_with_union"=0A= + check_var_with_bool_opt "actual_objects" "an_enum"=0A= + check_var_with_bool_opt "actual_objects" "a_string"=0A= + check_var_with_bool_opt "actual_objects" "a_binary_string"=0A= + check_var_with_bool_opt "actual_objects" "a_binary_string_array"=0A= + check_var_with_bool_opt "actual_objects" "a_big_string"=0A= + check_var_with_bool_opt "actual_objects" "an_array"=0A= + check_var_with_bool_opt "actual_objects" "an_array_with_repetition"=0A= + check_var_with_bool_opt "actual_objects" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + # Nothing changes in all of the C++ tests because deref_refs is not=0A= + # True.=0A= + check_var_with_bool_opt "actual_objects" "a_point_t_ref"=0A= + check_var_with_bool_opt "actual_objects" "a_base_ref"=0A= +=0A= + with_temp_option "set print object on" "set print object off" {=0A= + check_var_with_no_opts "a_point_t_ref"=0A= + check_var_with_bool_opt "actual_objects" "a_point_t_ref"=0A= +=0A= + check_var_with_no_opts "a_base_ref"=0A= + check_var_with_bool_opt "actual_objects" "a_base_ref"=0A= + }=0A= + }=0A= +}=0A= +=0A= +# Test the static_members option for gdb.Value.format_string.=0A= +proc test_static_members {} {=0A= + global current_lang=0A= +=0A= + check_var_with_bool_opt "static_members" "a_point_t"=0A= + check_var_with_bool_opt "static_members" "a_point_t_pointer"=0A= + check_var_with_bool_opt "static_members" "another_point"=0A= + check_var_with_bool_opt "static_members" "a_struct_with_union"=0A= + check_var_with_bool_opt "static_members" "an_enum"=0A= + check_var_with_bool_opt "static_members" "a_string"=0A= + check_var_with_bool_opt "static_members" "a_binary_string"=0A= + check_var_with_bool_opt "static_members" "a_binary_string_array"=0A= + check_var_with_bool_opt "static_members" "a_big_string"=0A= + check_var_with_bool_opt "static_members" "an_array"=0A= + check_var_with_bool_opt "static_members" "an_array_with_repetition"=0A= + check_var_with_bool_opt "static_members" "a_symbol_pointer"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + # Nothing changes in all of the C++ tests because deref_refs is not=0A= + # True.=0A= + check_var_with_bool_opt "static_members" "a_point_t_ref"=0A= + check_var_with_bool_opt "static_members" "a_base_ref"=0A= +=0A= + with_temp_option \=0A= + "set print static-members off" \=0A= + "set print static-members on" {=0A= + check_var_with_no_opts "a_point_t_ref"=0A= + check_var_with_bool_opt "static_members" "a_point_t_ref"=0A= +=0A= + check_var_with_no_opts "a_base_ref"=0A= + check_var_with_bool_opt "static_members" "a_base_ref"=0A= + }=0A= + }=0A= +}=0A= +=0A= +# Test the max_elements option for gdb.Value.format_string.=0A= +proc test_max_elements {} {=0A= + global current_lang=0A= + global default_pointer_regexp=0A= +=0A= + # 200 is the default maximum number of elements, so setting it should=0A= + # not change the output.=0A= + set opts "max_elements=3D200"=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts=0A= + check_format_string "a_binary_string" $opts=0A= + check_format_string "a_binary_string_array" $opts=0A= + check_format_string "a_big_string" $opts=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +=0A= + set opts "max_elements=3D3"=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts \=0A= + "${default_pointer_regexp} \"hel\"..."=0A= + check_format_string "a_binary_string" $opts \=0A= + "${default_pointer_regexp} \"hel\"..."=0A= + # This will print four characters instead of three, see=0A= + # .=0A= + check_format_string "a_binary_string_array" $opts \=0A= + "\"hell\"..."=0A= + check_format_string "a_big_string" $opts \=0A= + [get_cut_big_string 3]=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts \=0A= + "\\{1, 3 ...\\}"=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +=0A= + # Both 1,000 (we don't have that many elements) and 0 (unlimited) should= =0A= + # mean no truncation.=0A= + foreach opts { "max_elements=3D1000" "max_elements=3D0" } {=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts=0A= + check_format_string "a_binary_string" $opts=0A= + check_format_string "a_binary_string_array" $opts=0A= + check_format_string "a_big_string" $opts \=0A= + [get_cut_big_string 1000]=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= + }=0A= +=0A= + with_temp_option "set print elements 4" "set print elements 200" {=0A= + check_format_string "a_string" "" \=0A= + "${default_pointer_regexp} \"hell\"..."=0A= + check_format_string "a_binary_string" "" \=0A= + "${default_pointer_regexp} \"hell\"..."=0A= + check_format_string "a_binary_string_array" "" \=0A= + "\"hell\"..."=0A= + check_format_string "an_array_with_repetition" "" \=0A= + "\\{1, 3 ...\\}"=0A= + }=0A= +}=0A= +=0A= +# Test the repeat_threshold option for gdb.Value.format_string.=0A= +proc test_repeat_threshold {} {=0A= + global current_lang=0A= + global default_pointer_regexp=0A= +=0A= + # 10 is the default threshold for repeated items, so setting it should= =0A= + # not change the output.=0A= + set opts "repeat_threshold=3D10"=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts=0A= + check_format_string "a_binary_string" $opts=0A= + check_format_string "a_binary_string_array" $opts=0A= + check_format_string "a_big_string" $opts=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +=0A= + set opts "repeat_threshold=3D1"=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts \=0A= + "${default_pointer_regexp} \"he\", 'l' , \"o world\= ""=0A= + check_format_string "a_binary_string" $opts \=0A= + "${default_pointer_regexp} \"he\", 'l' , \"o\""=0A= + check_format_string "a_binary_string_array" $opts \=0A= + "\"he\", 'l' , \"o\\\\000world\""=0A= + check_format_string "a_big_string" $opts=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts \=0A= + "\\{1, 3 , 5 \\}"=0A= +=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +=0A= + set opts "repeat_threshold=3D3"=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts=0A= + check_format_string "a_binary_string" $opts=0A= + check_format_string "a_binary_string_array" $opts=0A= + check_format_string "a_big_string" $opts=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +=0A= + # Both 100 (we don't have that many repeated elements) and 0 (unlimited)= =0A= + # should mean no truncation.=0A= + foreach opts { "repeat_threshold=3D100" "repeat_threshold=3D0" } {=0A= + with_test_prefix $opts {=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts=0A= + check_format_string "an_enum" $opts=0A= + check_format_string "a_string" $opts=0A= + check_format_string "a_binary_string" $opts=0A= + check_format_string "a_binary_string_array" $opts=0A= + check_format_string "a_big_string" $opts=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts \=0A= + "\\{1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5\\}"=0A= + check_format_string "a_symbol_pointer" $opts=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= + }=0A= +=0A= + with_temp_option "set print repeats 1" "set print repeats 10" {=0A= + check_format_string "an_array_with_repetition" "" \=0A= + "\\{1, 3 , 5 \\}"=0A= + }=0A= +}=0A= +=0A= +# Test the format option for gdb.Value.format_string.=0A= +proc test_format {} {=0A= + global current_lang=0A= + global default_pointer_regexp=0A= +=0A= + # Hexadecimal.=0A= + set opts "format=3D'x'"=0A= + with_test_prefix $opts {=0A= + gdb_test "python print (gdb.Value (42).format_string (${opts}))" \=0A= + "0x2a" \=0A= + "42 with option ${opts}"=0A= +=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts \=0A= + "\\{the_union =3D \\{an_int =3D 0x2a, a_char =3D 0x2a\\}\\}"=0A= + check_format_string "an_enum" $opts \=0A= + "0x1"=0A= + check_format_string "a_string" $opts \=0A= + $default_pointer_regexp=0A= + check_format_string "a_binary_string" $opts \=0A= + $default_pointer_regexp=0A= + check_format_string "a_binary_string_array" $opts \=0A= + "\\{0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0, 0x77, 0x6f, 0x72, 0x6c, 0x64,= 0x0\\}"=0A= + check_format_string "a_big_string" $opts \=0A= + "\\{0x41, 0x42, 0x43, 0x44, 0x45, \[, x0-9a-f\]+\.\.\.\\}"=0A= + check_format_string "an_array" $opts \=0A= + "\\{0x2, 0x3, 0x5\\}"=0A= + check_format_string "an_array_with_repetition" $opts \=0A= + "\\{0x1, 0x3 , 0x5, 0x5, 0x5\\}"=0A= + check_format_string "a_symbol_pointer" $opts \=0A= + $default_pointer_regexp=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +=0A= + # Decimal.=0A= + set opts "format=3D'd'"=0A= + with_test_prefix $opts {=0A= + set decimal_pointer_regexp "\[0-9\]+"=0A= + gdb_test "python print (gdb.Value (0x2a).format_string (${opts}))" \= =0A= + "42" \=0A= + "0x2a with option ${opts}"=0A= +=0A= + check_format_string "a_point_t" $opts=0A= + check_format_string "a_point_t_pointer" $opts \=0A= + $decimal_pointer_regexp=0A= + check_format_string "another_point" $opts=0A= + check_format_string "a_struct_with_union" $opts \=0A= + "\\{the_union =3D \\{an_int =3D 42, a_char =3D 42\\}\\}"=0A= + check_format_string "an_enum" $opts \=0A= + "1"=0A= + check_format_string "a_string" $opts \=0A= + $decimal_pointer_regexp=0A= + check_format_string "a_binary_string" $opts \=0A= + $decimal_pointer_regexp=0A= + check_format_string "a_binary_string_array" $opts \=0A= + "\\{104, 101, 108, 108, 111, 0, 119, 111, 114, 108, 100, 0\\}"=0A= + check_format_string "a_big_string" $opts \=0A= + "\\{65, 66, 67, 68, 69, \[, 0-9\]+\.\.\.\\}"=0A= + check_format_string "an_array" $opts=0A= + check_format_string "an_array_with_repetition" $opts=0A= + check_format_string "a_symbol_pointer" $opts \=0A= + $decimal_pointer_regexp=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" $opts=0A= + check_format_string "a_base_ref" $opts=0A= + }=0A= + }=0A= +}=0A= +=0A= +# Test mixing options.=0A= +proc test_mixed {} {=0A= + global current_lang=0A= + global default_ref_regexp=0A= + global default_pointer_regexp=0A= +=0A= + check_format_string "a_point_t" \=0A= + "raw=3DTrue, format=3D'x'" \=0A= + "\\{x =3D 0x2a, y =3D 0xc\\}"=0A= +=0A= + check_format_string "an_array" \=0A= + "array_indexes=3DTrue, pretty_arrays=3DTrue" \=0A= + " \\{\\\[0\\\] =3D 2,\[\r\n\]+ \\\[1\\\] =3D 3,\[\r\n\]+ \\\[2\\\] = =3D 5\\}"=0A= +=0A= + check_format_string "a_struct_with_union" \=0A= + "pretty_structs=3DTrue, unions=3DFalse" \=0A= + "\\{\[\r\n\]+ the_union =3D \\{\.\.\.\\}\[\r\n\]+\\}"=0A= +=0A= + check_format_string "a_symbol_pointer" \=0A= + "symbols=3DFalse, format=3D'd'" \=0A= + "\[0-9\]+"=0A= +=0A= + if { $current_lang =3D=3D "c++" } {=0A= + check_format_string "a_point_t_ref" \=0A= + "deref_refs=3DTrue, actual_objects=3DTrue, raw=3DTrue" \=0A= + "${default_ref_regexp}: \\{x =3D 42, y =3D 12\\}"=0A= +=0A= + check_format_string "a_base_ref" \=0A= + "deref_refs=3DTrue, static_members=3DFalse" \=0A= + "${default_ref_regexp}: \\{_vptr\\.Base =3D ${default_pointer_regexp= } , a =3D 42\\}"=0A= + }=0A= +}=0A= +=0A= +# Test passing invalid arguments to gdb.Value.format_string.=0A= +proc test_invalid_args {} {=0A= + check_format_string \=0A= + "a_point_t" \=0A= + "12" \=0A= + "TypeError: format_string\\(\\) takes 0 positional arguments but 1 wer= e given.*"=0A= +=0A= + check_format_string \=0A= + "a_point_t" \=0A= + "invalid=3DTrue" \=0A= + "TypeError: 'invalid' is an invalid keyword argument for this function= .*"=0A= +=0A= + check_format_string \=0A= + "a_point_t" \=0A= + "raw=3D'hello'" \=0A= + "TypeError: argument 1 must be bool, not str.*"=0A= +=0A= + check_format_string \=0A= + "a_point_t" \=0A= + "format=3D'xd'" \=0A= + "ValueError: a single character is required.*"=0A= +}=0A= +=0A= +# Run all the tests in common for both C and C++.=0A= +proc test_all_common {} {=0A= + # No options.=0A= + test_no_opts=0A= + # Single options set to True/False.=0A= + test_raw=0A= + test_pretty_arrays=0A= + test_pretty_structs=0A= + test_array_indexes=0A= + test_symbols=0A= + test_unions=0A= + test_deref_refs=0A= + test_actual_objects=0A= + test_static_members=0A= + test_max_elements=0A= + test_repeat_threshold=0A= + test_format=0A= + # Multiple options mixed together.=0A= + test_mixed=0A= + # Various error conditions.=0A= + test_invalid_args=0A= +}=0A= +=0A= +# The current language ("c" or "c++" while running tests).=0A= +set current_lang ""=0A= +=0A= +with_test_prefix "format_string" {=0A= + # Perform C Tests.=0A= + if { [build_inferior "${binfile}" "c"] =3D=3D 0 } {=0A= + with_test_prefix "lang_c" {=0A= + set current_lang "c"=0A= + prepare_gdb "${binfile}"=0A= + test_all_common=0A= + }=0A= + }=0A= +=0A= + # Perform C++ Tests.=0A= + if { [build_inferior "${binfile}-cxx" "c++"] =3D=3D 0 } {=0A= + with_test_prefix "lang_cpp" {=0A= + set current_lang "c++"=0A= + prepare_gdb "${binfile}-cxx"=0A= + test_all_common=0A= + }=0A= + }=0A= +}=0A= diff --git a/gdb/testsuite/gdb.python/py-format-string.py b/gdb/testsuite/g= db.python/py-format-string.py=0A= new file mode 100644=0A= index 0000000000..c2ad88e862=0A= --- /dev/null=0A= +++ b/gdb/testsuite/gdb.python/py-format-string.py=0A= @@ -0,0 +1,49 @@=0A= +# Copyright (C) 2008-2019 Free Software Foundation, Inc.=0A= +=0A= +# This program is free software; you can redistribute it and/or modify=0A= +# it under the terms of the GNU General Public License as published by=0A= +# the Free Software Foundation; either version 3 of the License, or=0A= +# (at your option) any later version.=0A= +#=0A= +# This program is distributed in the hope that it will be useful,=0A= +# but WITHOUT ANY WARRANTY; without even the implied warranty of=0A= +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A= +# GNU General Public License for more details.=0A= +#=0A= +# You should have received a copy of the GNU General Public License=0A= +# along with this program. If not, see .=0A= +=0A= +# This file is part of the GDB testsuite. It tests python pretty=0A= +# printers.=0A= +=0A= +import gdb=0A= +=0A= +class PointPrinter (object):=0A= + def __init__ (self, val):=0A= + self.val =3D val=0A= +=0A= + def to_string (self):=0A= + return 'Pretty Point (%s, %s)' % (self.val['x'], self.val['y'])=0A= +=0A= +def test_lookup_function (val):=0A= + "Look-up and return a pretty-printer that can print val."=0A= +=0A= + # Get the type.=0A= + type =3D val.type=0A= +=0A= + # If it points to a reference, get the reference.=0A= + if type.code =3D=3D gdb.TYPE_CODE_REF:=0A= + type =3D type.target ()=0A= +=0A= + # Get the unqualified type, stripped of typedefs.=0A= + type =3D type.unqualified ().strip_typedefs ()=0A= +=0A= + # Get the type name.=0A= + typename =3D type.tag=0A= +=0A= + if typename =3D=3D 'point':=0A= + return PointPrinter (val)=0A= +=0A= + return None=0A= +=0A= +gdb.pretty_printers.append (test_lookup_function)=0A= --=20=0A= 2.19.2=0A= =0A= --Apple-Mail=_6710A3BB-88E6-4AF5-930F-5640220A865E Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii Content-length: 23 -- Marco Barisione --Apple-Mail=_6710A3BB-88E6-4AF5-930F-5640220A865E--