public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA] New python module gdb.types
@ 2010-10-06 20:49 Doug Evans
  2010-10-06 21:04 ` Eli Zaretskii
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Doug Evans @ 2010-10-06 20:49 UTC (permalink / raw)
  To: gdb-patches

Hi.

This patch adds a new python module to gdb, gdb.types.
It contains a small collection of utilities that I've been using.

Ok to check in?

2010-10-06  Doug Evans  <dje@google.com>

	New python module gdb.types.
	* NEWS: Document it.
	* data-directory/Makefile.in (PYTHON_FILES): Add gdb/types.py.
	* python/lib/gdb/types.py: New file.

	testsuite/
	* lib/gdb-python.exp (gdb_check_python_config): New function.
	* gdb.python/Makefile.in (EXECUTABLES): Add lib-types.
	* gdb.python/lib-types.cc: New file.
	* gdb.python/lib-types.exp: New file.

	doc/
	* gdb.texinfo (Python): Add "Python modules".
	(Python modules): New node.

Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.406
diff -u -p -r1.406 NEWS
--- NEWS	28 Sep 2010 21:40:23 -0000	1.406
+++ NEWS	6 Oct 2010 20:32:43 -0000
@@ -12,6 +12,10 @@
 
      result = some_value (10,20)
 
+  ** Module gdb.types has been added.
+     It contains a collection of utilities for working with gdb.Types objects:
+     get_basic_type, has_field, make_enum_dict.
+
 * C++ Improvements:
 
   ** GDB now puts template parameters in scope when debugging in an
Index: data-directory/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/data-directory/Makefile.in,v
retrieving revision 1.1
diff -u -p -r1.1 Makefile.in
--- data-directory/Makefile.in	6 Oct 2010 16:02:44 -0000	1.1
+++ data-directory/Makefile.in	6 Oct 2010 20:32:43 -0000
@@ -51,7 +51,8 @@ SYSCALLS_FILES = \
 PYTHON_DIR = python
 PYTHON_INSTALL_DIR = $(DESTDIR)/$(GDB_DATADIR)/$(PYTHON_DIR)
 PYTHON_FILES = \
-	gdb/__init__.py
+	gdb/__init__.py \
+	gdb/types.py
 
 # Host-dependent makefile fragment comes in here.
 @host_makefile_frag@
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.767
diff -u -p -r1.767 gdb.texinfo
--- doc/gdb.texinfo	28 Sep 2010 21:40:23 -0000	1.767
+++ doc/gdb.texinfo	6 Oct 2010 20:32:43 -0000
@@ -20401,6 +20401,7 @@ the Python interpreter to locate all scr
 * Python Commands::             Accessing Python from @value{GDBN}.
 * Python API::                  Accessing @value{GDBN} from Python.
 * Auto-loading::                Automatically loading Python code.
+* Python modules::              Python modules provided by @value{GDBN}.
 @end menu
 
 @node Python Commands
@@ -22911,6 +22912,27 @@ cumbersome.  It may be easier to specify
 top of the source tree to the source search path.
 @end itemize
 
+@node Python modules
+@subsection Python modules
+@cindex Python modules
+
+@value{GDBN} comes with module @code{gdb.types}.
+It provides a collection of utilities for working with @code{gdb.Types}
+objects.
+
+@table @code
+@item get_basic_type (@var{type})
+Return @var{type} with const and volatile qualifiers, typedefs,
+and references stripped away.
+
+@item has_field (@var{type}, @var{field})
+Return @code{True} if @var{type}, assumed to be a type with fields
+(e.g., a class, structure, or union), has field @var{field}.
+
+@item make_enum_dict (@var{enum_type})
+Return a dictionary made from @var{enum_type}.
+@end table
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
Index: python/lib/gdb/types.py
===================================================================
RCS file: python/lib/gdb/types.py
diff -N python/lib/gdb/types.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ python/lib/gdb/types.py	6 Oct 2010 20:32:43 -0000
@@ -0,0 +1,58 @@
+# Type utilities.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import gdb
+
+# Given a type, return the same type with references, typedefs and qualifiers
+# (const, volatile) stripped away.
+
+def get_basic_type (typ):
+    """Return the 'basic' type of type TYP."""
+
+    if typ.code == gdb.TYPE_CODE_REF:
+        typ = typ.target ()
+    return typ.unqualified ().strip_typedefs ()
+
+# Return True if FIELD is in type TYP (spelled this way to avoid collision
+# with python's "type"), with extra handling so references, typedefs, and
+# subclasses "just work".
+
+def has_field (typ, field):
+    """Return True if type TYPE has the specified field."""
+
+    typ = get_basic_type (typ)
+    for f in typ.fields ():
+        if f.is_base_class:
+            if has_field (f.type, field):
+                return True
+        else:
+            # NOTE: f.name could be None
+            if f.name == field:
+                return True
+    return False
+
+# Create a dictionary out of an enum type.
+
+def make_enum_dict (enum_type):
+  """Build a dictionary from a program's enum type."""
+
+  if enum_type.code != gdb.TYPE_CODE_ENUM:
+    raise TypeError ("not an enum type")
+  enum_dict = {}
+  for field in enum_type.fields():
+    # The enum's value is stored in "bitpos".
+    enum_dict[field.name] = field.bitpos
+  return enum_dict
Index: testsuite/gdb.python/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/Makefile.in,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.in
--- testsuite/gdb.python/Makefile.in	19 Aug 2010 17:00:57 -0000	1.8
+++ testsuite/gdb.python/Makefile.in	6 Oct 2010 20:32:43 -0000
@@ -3,7 +3,7 @@ srcdir = @srcdir@
 
 EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
 		py-symbol py-mi py-breakpoint py-inferior py-infthread \
-		py-shared python
+		py-shared python lib-types
 
 MISCELLANEOUS = py-shared-sl.sl
 
Index: testsuite/gdb.python/lib-types.cc
===================================================================
RCS file: testsuite/gdb.python/lib-types.cc
diff -N testsuite/gdb.python/lib-types.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.cc	6 Oct 2010 20:32:43 -0000
@@ -0,0 +1,53 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+class class1
+{
+ public:
+  class1 (int _x) : x (_x) {}
+  int x;
+};
+
+class1 simple_class1 (42);
+const class1 const_class1 (42);
+volatile class1 volatile_class1 (42);
+const volatile class1 const_volatile_class1 (42);
+
+typedef class1 class2;
+
+class2 typedef_class1 (42);
+
+class1& ref_class1 (simple_class1);
+
+class subclass1 : public class1
+{
+ public:
+  subclass1 (int _x, int _y) : class1 (_x), y (_y) {}
+  int y;
+};
+
+subclass1 simple_subclass1 (42, 43);
+
+enum enum1 { A, B, C };
+
+enum1 simple_enum1 (A);
+
+int
+main ()
+{
+  return 0;
+}
Index: testsuite/gdb.python/lib-types.exp
===================================================================
RCS file: testsuite/gdb.python/lib-types.exp
diff -N testsuite/gdb.python/lib-types.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.exp	6 Oct 2010 20:32:43 -0000
@@ -0,0 +1,123 @@
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.
+# It tests the types.py module.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "lib-types"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+# Ensure sys.path, et.al. are initialized properly.
+gdb_check_python_config
+
+gdb_test_no_output "python import gdb.types"
+
+# test get_basic_type const stripping
+gdb_test_no_output "python const_class1 = gdb.parse_and_eval ('const_class1')"
+gdb_test_no_output "python basic_type_const_class1 = gdb.types.get_basic_type (const_class1.type)"
+gdb_test "python print str (const_class1.type)" "const class1"
+set test "const stripping"
+gdb_test_multiple "python print str (basic_type_const_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+gdb_test "python print str (basic_type_const_class1)" "class1"
+
+# test get_basic_type volatile stripping
+gdb_test_no_output "python volatile_class1 = gdb.parse_and_eval ('volatile_class1')"
+gdb_test_no_output "python basic_type_volatile_class1 = gdb.types.get_basic_type (volatile_class1.type)"
+gdb_test "python print str (volatile_class1.type)" "volatile class1"
+set test "volatile stripping"
+gdb_test_multiple "python print str (basic_type_volatile_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type volatile+const stripping
+gdb_test_no_output "python const_volatile_class1 = gdb.parse_and_eval ('const_volatile_class1')"
+gdb_test_no_output "python basic_type_const_volatile_class1 = gdb.types.get_basic_type (const_volatile_class1.type)"
+gdb_test "python print str (const_volatile_class1.type)" "const volatile class1"
+set test "volatile+const stripping"
+gdb_test_multiple "python print str (basic_type_const_volatile_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type typedef stripping
+gdb_test_no_output "python typedef_class1 = gdb.parse_and_eval ('typedef_class1')"
+gdb_test_no_output "python basic_type_typedef_class1 = gdb.types.get_basic_type (typedef_class1.type)"
+gdb_test "python print str (typedef_class1.type)" "class2"
+set test "typedef stripping"
+gdb_test_multiple "python print str (basic_type_typedef_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type reference stripping
+gdb_test_no_output "python ref_class1 = gdb.parse_and_eval ('ref_class1')"
+gdb_test_no_output "python basic_type_ref_class1 = gdb.types.get_basic_type (ref_class1.type)"
+gdb_test "python print str (ref_class1.type)" "class1 &"
+set test "reference stripping"
+gdb_test_multiple "python print str (basic_type_ref_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test has_field on simple class
+gdb_test_no_output "python simple_class1 = gdb.parse_and_eval ('simple_class1')"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'x')" "True"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'nope')" "False"
+
+# test has_field in base class
+gdb_test_no_output "python simple_subclass1 = gdb.parse_and_eval ('simple_subclass1')"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'x')" "True"
+
+# test make_enum_dict
+gdb_test_no_output "python simple_enum1 = gdb.parse_and_eval ('simple_enum1')"
+gdb_test_no_output "python enum1_dict = gdb.types.make_enum_dict (simple_enum1.type)"
+gdb_test_no_output "python enum1_list = enum1_dict.items ()"
+gdb_test_no_output "python enum1_list.sort ()"
+gdb_test "python print enum1_list" {\[\('A', 0L\), \('B', 1L\), \('C', 2L\)\]}
Index: testsuite/lib/gdb-python.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb-python.exp,v
retrieving revision 1.1
diff -u -p -r1.1 gdb-python.exp
--- testsuite/lib/gdb-python.exp	1 Oct 2010 17:03:50 -0000	1.1
+++ testsuite/lib/gdb-python.exp	6 Oct 2010 20:32:43 -0000
@@ -45,3 +45,21 @@ proc gdb_py_test_multiple { name args } 
     }
     return 0
 }
+
+# Establish various python configuration parameters if necessary.
+# E.g. sys.path.
+
+proc gdb_check_python_config { } {
+    global USE_INSTALLED_TREE
+    # If we're running an installed version of gdb, and we want to test the
+    # installed versions of the python support scripts, then we don't want
+    # to point data-directory at the build tree.
+    if { [info exists USE_INSTALLED_TREE] && "$USE_INSTALLED_TREE" == "yes" } {
+	verbose -log "Assuming system config already installed."
+    } else {
+	verbose -log "Installing system config from build tree."
+	set gdb_data_dir "[pwd]/../data-directory"
+	gdb_test_no_output "set data-directory $gdb_data_dir"
+	gdb_test_no_output "python GdbSetPythonDirectory ('$gdb_data_dir/python')"
+    }
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-06 20:49 [RFA] New python module gdb.types Doug Evans
@ 2010-10-06 21:04 ` Eli Zaretskii
  2010-10-08 22:19   ` Doug Evans
  2010-10-06 21:12 ` Joel Brobecker
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Eli Zaretskii @ 2010-10-06 21:04 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

> Date: Wed,  6 Oct 2010 13:44:34 -0700 (PDT)
> From: dje@google.com (Doug Evans)
> 
> This patch adds a new python module to gdb, gdb.types.
> It contains a small collection of utilities that I've been using.

Thanks.

> +  ** Module gdb.types has been added.
> +     It contains a collection of utilities for working with gdb.Types objects:
> +     get_basic_type, has_field, make_enum_dict.

This part is okay.

> +@cindex Python modules

Index entries should use lower-case letters only (to avoid problems
with sorting them in certain locales).

> +@item get_basic_type (@var{type})
> +Return @var{type} with const and volatile qualifiers, typedefs,
> +and references stripped away.

This is quite cryptic.  I can understand what it means to remove
const, volatile, etc. qualifiers (what about `static', btw?), but what
does it mean to "strip" a typedef or a reference?  At the very least
please give a few examples, if this cannot be explained easily.

> +@item make_enum_dict (@var{enum_type})
> +Return a dictionary made from @var{enum_type}.

Same here: at the very least we should say what is a "dictionary" in
this context.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-06 20:49 [RFA] New python module gdb.types Doug Evans
  2010-10-06 21:04 ` Eli Zaretskii
@ 2010-10-06 21:12 ` Joel Brobecker
  2010-10-06 22:12 ` Tom Tromey
  2010-10-08 23:08 ` Doug Evans
  3 siblings, 0 replies; 11+ messages in thread
From: Joel Brobecker @ 2010-10-06 21:12 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

> This patch adds a new python module to gdb, gdb.types.
> It contains a small collection of utilities that I've been using.

I'm excited to seem more Python stuff being contributed!

> +def get_basic_type (typ):
> +    """Return the 'basic' type of type TYP."""
> +
> +    if typ.code == gdb.TYPE_CODE_REF:
> +        typ = typ.target ()
> +    return typ.unqualified ().strip_typedefs ()

The python style is to not have a space before the opening parenthesis.
For instance:

    def get_basic_type(typ):
        """Return the 'basic' type of type TYP."""
    
        if typ.code == gdb.TYPE_CODE_REF:
            typ = typ.target()
        return typ.unqualified().strip_typedefs()

It looks really ugly at first, but it's not so bad after a while.
I think we should try to follow the Python style because it makes it
easier for Python users to read our code.

> +# Return True if FIELD is in type TYP (spelled this way to avoid collision
> +# with python's "type"), with extra handling so references, typedefs, and
> +# subclasses "just work".

Just a thought - I think it would useful to mention how we handle
the case where the type has no fields (we return False, if I read
the code right).

And should we mention that, unlike module `gdb' which is already
imported, module `gdb.types' isn't?


-- 
Joel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-06 20:49 [RFA] New python module gdb.types Doug Evans
  2010-10-06 21:04 ` Eli Zaretskii
  2010-10-06 21:12 ` Joel Brobecker
@ 2010-10-06 22:12 ` Tom Tromey
  2010-10-06 23:44   ` Doug Evans
  2010-10-08 23:08 ` Doug Evans
  3 siblings, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2010-10-06 22:12 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

>>>>> "Doug" == Doug Evans <dje@google.com> writes:

Doug> This patch adds a new python module to gdb, gdb.types.
Doug> It contains a small collection of utilities that I've been using.

Doug> Ok to check in?

It seems reasonable to me.

I wouldn't mind if has_field were made a method on Type, but of course
that can be done at any time.

I think the documentation would be a little improved if the gdb.Type
documentation had an xref to the new module's documentation.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-06 22:12 ` Tom Tromey
@ 2010-10-06 23:44   ` Doug Evans
  0 siblings, 0 replies; 11+ messages in thread
From: Doug Evans @ 2010-10-06 23:44 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Wed, Oct 6, 2010 at 3:11 PM, Tom Tromey <tromey@redhat.com> wrote:
> I wouldn't mind if has_field were made a method on Type, but of course
> that can be done at any time.

It could, but there are design issues.
E.g., the has_field function calls get_basic_type and traverses base
types (instead of treating base types as a field which is what the
current gdb.Type API does.  It's an internal implementation detail of
gdb that got exposed.  Maybe it's reasonable to keep, I don't know).
Whether Type.has_field should do that ... I'm not sure.
It felt safer to see what works as a separate function before
expanding gdb.Type.

> I think the documentation would be a little improved if the gdb.Type
> documentation had an xref to the new module's documentation.

Thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-06 21:04 ` Eli Zaretskii
@ 2010-10-08 22:19   ` Doug Evans
  2010-10-08 22:21     ` Doug Evans
  2010-10-09  9:14     ` Eli Zaretskii
  0 siblings, 2 replies; 11+ messages in thread
From: Doug Evans @ 2010-10-08 22:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Wed, Oct 6, 2010 at 2:04 PM, Eli Zaretskii <eliz@gnu.org> wrote:
>> +@item get_basic_type (@var{type})
>> +Return @var{type} with const and volatile qualifiers, typedefs,
>> +and references stripped away.
>
> This is quite cryptic.  I can understand what it means to remove
> const, volatile, etc. qualifiers (what about `static', btw?), but what
> does it mean to "strip" a typedef or a reference?  At the very least
> please give a few examples, if this cannot be explained easily.

static isn't an attribute of a type.

What if it said the following instead?

Return @var{type} with const and volatile qualifiers stripped,
and with typedefs and references converted to the underlying type.

>> +@item make_enum_dict (@var{enum_type})
>> +Return a dictionary made from @var{enum_type}.
>
> Same here: at the very least we should say what is a "dictionary" in
> this context.

The context is python and in the python context "dictionary" is quite
specific, it's a builtin type.

What if it said the following instead?

Return a python dictionary made from @var{enum_type}.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-08 22:19   ` Doug Evans
@ 2010-10-08 22:21     ` Doug Evans
  2010-10-09  9:14     ` Eli Zaretskii
  1 sibling, 0 replies; 11+ messages in thread
From: Doug Evans @ 2010-10-08 22:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Fri, Oct 8, 2010 at 3:18 PM, Doug Evans <dje@google.com> wrote:
>>> +@item make_enum_dict (@var{enum_type})
>>> +Return a dictionary made from @var{enum_type}.
>>
>> Same here: at the very least we should say what is a "dictionary" in
>> this context.
>
> The context is python and in the python context "dictionary" is quite
> specific, it's a builtin type.
>
> What if it said the following instead?
>
> Return a python dictionary made from @var{enum_type}.

Or rather

Return a Python dictionary made from @var{enum_type}.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-06 20:49 [RFA] New python module gdb.types Doug Evans
                   ` (2 preceding siblings ...)
  2010-10-06 22:12 ` Tom Tromey
@ 2010-10-08 23:08 ` Doug Evans
  3 siblings, 0 replies; 11+ messages in thread
From: Doug Evans @ 2010-10-08 23:08 UTC (permalink / raw)
  To: gdb-patches, Eli Zaretskii, Joel Brobecker, Tom Tromey

[-- Attachment #1: Type: text/plain, Size: 896 bytes --]

On Wed, Oct 6, 2010 at 1:44 PM, Doug Evans <dje@google.com> wrote:
> Hi.
>
> This patch adds a new python module to gdb, gdb.types.
> It contains a small collection of utilities that I've been using.

Here's the current version of the patch.

Ok to check in?


2010-10-08  Doug Evans  <dje@google.com>

        New python module gdb.types.
        * NEWS: Document it.
        * data-directory/Makefile.in (PYTHON_FILES): Add gdb/types.py.
        * python/lib/gdb/types.py: New file.

        testsuite/
        * lib/gdb-python.exp (gdb_check_python_config): New function.
        * gdb.python/Makefile.in (EXECUTABLES): Add lib-types.
        * gdb.python/lib-types.cc: New file.
        * gdb.python/lib-types.exp: New file.

        doc/
        * gdb.texinfo (Python): Add "Python modules".
        (Types in Python): Add reference to gdb.types section.
        (Python modules): New node.

[-- Attachment #2: gdb-101008-types-module-2.patch.txt --]
[-- Type: text/plain, Size: 15368 bytes --]

2010-10-08  Doug Evans  <dje@google.com>

	New python module gdb.types.
	* NEWS: Document it.
	* data-directory/Makefile.in (PYTHON_FILES): Add gdb/types.py.
	* python/lib/gdb/types.py: New file.

	testsuite/
	* lib/gdb-python.exp (gdb_check_python_config): New function.
	* gdb.python/Makefile.in (EXECUTABLES): Add lib-types.
	* gdb.python/lib-types.cc: New file.
	* gdb.python/lib-types.exp: New file.

	doc/
	* gdb.texinfo (Python): Add "Python modules".
	(Types in Python): Add reference to gdb.types section.
	(Python modules): New node.

Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.406
diff -u -p -r1.406 NEWS
--- NEWS	28 Sep 2010 21:40:23 -0000	1.406
+++ NEWS	8 Oct 2010 23:03:28 -0000
@@ -12,6 +12,10 @@
 
      result = some_value (10,20)
 
+  ** Module gdb.types has been added.
+     It contains a collection of utilities for working with gdb.Types objects:
+     get_basic_type, has_field, make_enum_dict.
+
 * C++ Improvements:
 
   ** GDB now puts template parameters in scope when debugging in an
Index: data-directory/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/data-directory/Makefile.in,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile.in
--- data-directory/Makefile.in	7 Oct 2010 00:18:22 -0000	1.2
+++ data-directory/Makefile.in	8 Oct 2010 23:03:28 -0000
@@ -51,7 +51,8 @@ SYSCALLS_FILES = \
 PYTHON_DIR = python
 PYTHON_INSTALL_DIR = $(DESTDIR)/$(GDB_DATADIR)/$(PYTHON_DIR)
 PYTHON_FILES = \
-	gdb/__init__.py
+	gdb/__init__.py \
+	gdb/types.py
 
 .PHONY: all
 all: stamp-syscalls stamp-python
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.767
diff -u -p -r1.767 gdb.texinfo
--- doc/gdb.texinfo	28 Sep 2010 21:40:23 -0000	1.767
+++ doc/gdb.texinfo	8 Oct 2010 23:03:28 -0000
@@ -20401,6 +20401,7 @@ the Python interpreter to locate all scr
 * Python Commands::             Accessing Python from @value{GDBN}.
 * Python API::                  Accessing @value{GDBN} from Python.
 * Auto-loading::                Automatically loading Python code.
+* Python modules::              Python modules provided by @value{GDBN}.
 @end menu
 
 @node Python Commands
@@ -20789,7 +20790,7 @@ this value, thus it is not available for
 
 @defivar Value type
 The type of this @code{gdb.Value}.  The value of this attribute is a
-@code{gdb.Type} object.
+@code{gdb.Type} object (@pxref{Types In Python}).
 @end defivar
 
 @defivar Value dynamic_type
@@ -21245,6 +21246,9 @@ A function internal to @value{GDBN}.  Th
 convenience functions.
 @end table
 
+Further support for types is provided in the @code{gdb.types}
+Python module (@pxref{gdb.types}).
+
 @node Pretty Printing API
 @subsubsection Pretty Printing API
 
@@ -22911,6 +22915,37 @@ cumbersome.  It may be easier to specify
 top of the source tree to the source search path.
 @end itemize
 
+@node Python modules
+@subsection Python modules
+@cindex python modules
+
+@c It is assumed that at least one more module will be added before
+@c the next release of gdb.
+@value{GDBN} comes with a module to assist writing Python code.
+
+@menu
+* gdb.types::          Utilities for working with types.
+@end menu
+
+@node gdb.types
+@subsubsection gdb.types
+
+This module provides a collection of utilities for working with
+@code{gdb.Types} objects.
+
+@table @code
+@item get_basic_type (@var{type})
+Return @var{type} with const and volatile qualifiers stripped,
+and with typedefs and references converted to the underlying type.
+
+@item has_field (@var{type}, @var{field})
+Return @code{True} if @var{type}, assumed to be a type with fields
+(e.g., a structure or union), has field @var{field}.
+
+@item make_enum_dict (@var{enum_type})
+Return a Python dictionary made from @var{enum_type}.
+@end table
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
Index: python/lib/gdb/types.py
===================================================================
RCS file: python/lib/gdb/types.py
diff -N python/lib/gdb/types.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ python/lib/gdb/types.py	8 Oct 2010 23:03:28 -0000
@@ -0,0 +1,77 @@
+# Type utilities.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Utilities for working with gdb.Types."""
+
+import gdb
+
+
+def get_basic_type(type_):
+    """Return the "basic" type of a type.
+
+    Arguments:
+        type_: The type to reduce to its basic type.
+
+    Returns:
+        type_ with const/volatile is stripped away, and typedefs/references
+        are converted to the original type.
+    """
+
+    if type_.code == gdb.TYPE_CODE_REF:
+        type_ = type_.target()
+    return type_.unqualified().strip_typedefs()
+
+
+def has_field(type_, field):
+    """Return True if a type has the specified field.
+
+    Arguments:
+        type_: The type to examine.
+            It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION.
+        field: The name of the field to look up.
+
+    Returns:
+        True if the field is present either in type_ or any baseclass.
+
+    Raises:
+        TypeError: The type is not a struct or union.
+    """
+
+    type_ = get_basic_type(type_)
+    if (type_.code != gdb.TYPE_CODE_STRUCT and
+        type_.code != gdb.TYPE_CODE_UNION):
+        raise TypeError("not a struct or union")
+    for f in type_.fields():
+        if f.is_base_class:
+            if has_field(f.type, field):
+                return True
+        else:
+            # NOTE: f.name could be None
+            if f.name == field:
+                return True
+    return False
+
+
+def make_enum_dict(enum_type):
+    """Return a dictionary from a program's enum type."""
+
+    if enum_type.code != gdb.TYPE_CODE_ENUM:
+        raise TypeError("not an enum type")
+    enum_dict = {}
+    for field in enum_type.fields():
+        # The enum's value is stored in "bitpos".
+        enum_dict[field.name] = field.bitpos
+    return enum_dict
Index: testsuite/gdb.python/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/Makefile.in,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.in
--- testsuite/gdb.python/Makefile.in	19 Aug 2010 17:00:57 -0000	1.8
+++ testsuite/gdb.python/Makefile.in	8 Oct 2010 23:03:28 -0000
@@ -3,7 +3,7 @@ srcdir = @srcdir@
 
 EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
 		py-symbol py-mi py-breakpoint py-inferior py-infthread \
-		py-shared python
+		py-shared python lib-types
 
 MISCELLANEOUS = py-shared-sl.sl
 
Index: testsuite/gdb.python/lib-types.cc
===================================================================
RCS file: testsuite/gdb.python/lib-types.cc
diff -N testsuite/gdb.python/lib-types.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.cc	8 Oct 2010 23:03:28 -0000
@@ -0,0 +1,53 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+class class1
+{
+ public:
+  class1 (int _x) : x (_x) {}
+  int x;
+};
+
+class1 simple_class1 (42);
+const class1 const_class1 (42);
+volatile class1 volatile_class1 (42);
+const volatile class1 const_volatile_class1 (42);
+
+typedef class1 class2;
+
+class2 typedef_class1 (42);
+
+class1& ref_class1 (simple_class1);
+
+class subclass1 : public class1
+{
+ public:
+  subclass1 (int _x, int _y) : class1 (_x), y (_y) {}
+  int y;
+};
+
+subclass1 simple_subclass1 (42, 43);
+
+enum enum1 { A, B, C };
+
+enum1 simple_enum1 (A);
+
+int
+main ()
+{
+  return 0;
+}
Index: testsuite/gdb.python/lib-types.exp
===================================================================
RCS file: testsuite/gdb.python/lib-types.exp
diff -N testsuite/gdb.python/lib-types.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.exp	8 Oct 2010 23:03:28 -0000
@@ -0,0 +1,123 @@
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.
+# It tests the types.py module.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "lib-types"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+# Ensure sys.path, et.al. are initialized properly.
+gdb_check_python_config
+
+gdb_test_no_output "python import gdb.types"
+
+# test get_basic_type const stripping
+gdb_test_no_output "python const_class1 = gdb.parse_and_eval ('const_class1')"
+gdb_test_no_output "python basic_type_const_class1 = gdb.types.get_basic_type (const_class1.type)"
+gdb_test "python print str (const_class1.type)" "const class1"
+set test "const stripping"
+gdb_test_multiple "python print str (basic_type_const_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+gdb_test "python print str (basic_type_const_class1)" "class1"
+
+# test get_basic_type volatile stripping
+gdb_test_no_output "python volatile_class1 = gdb.parse_and_eval ('volatile_class1')"
+gdb_test_no_output "python basic_type_volatile_class1 = gdb.types.get_basic_type (volatile_class1.type)"
+gdb_test "python print str (volatile_class1.type)" "volatile class1"
+set test "volatile stripping"
+gdb_test_multiple "python print str (basic_type_volatile_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type volatile+const stripping
+gdb_test_no_output "python const_volatile_class1 = gdb.parse_and_eval ('const_volatile_class1')"
+gdb_test_no_output "python basic_type_const_volatile_class1 = gdb.types.get_basic_type (const_volatile_class1.type)"
+gdb_test "python print str (const_volatile_class1.type)" "const volatile class1"
+set test "volatile+const stripping"
+gdb_test_multiple "python print str (basic_type_const_volatile_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type typedef stripping
+gdb_test_no_output "python typedef_class1 = gdb.parse_and_eval ('typedef_class1')"
+gdb_test_no_output "python basic_type_typedef_class1 = gdb.types.get_basic_type (typedef_class1.type)"
+gdb_test "python print str (typedef_class1.type)" "class2"
+set test "typedef stripping"
+gdb_test_multiple "python print str (basic_type_typedef_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type reference stripping
+gdb_test_no_output "python ref_class1 = gdb.parse_and_eval ('ref_class1')"
+gdb_test_no_output "python basic_type_ref_class1 = gdb.types.get_basic_type (ref_class1.type)"
+gdb_test "python print str (ref_class1.type)" "class1 &"
+set test "reference stripping"
+gdb_test_multiple "python print str (basic_type_ref_class1)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test has_field on simple class
+gdb_test_no_output "python simple_class1 = gdb.parse_and_eval ('simple_class1')"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'x')" "True"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'nope')" "False"
+
+# test has_field in base class
+gdb_test_no_output "python simple_subclass1 = gdb.parse_and_eval ('simple_subclass1')"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'x')" "True"
+
+# test make_enum_dict
+gdb_test_no_output "python simple_enum1 = gdb.parse_and_eval ('simple_enum1')"
+gdb_test_no_output "python enum1_dict = gdb.types.make_enum_dict (simple_enum1.type)"
+gdb_test_no_output "python enum1_list = enum1_dict.items ()"
+gdb_test_no_output "python enum1_list.sort ()"
+gdb_test "python print enum1_list" {\[\('A', 0L\), \('B', 1L\), \('C', 2L\)\]}
Index: testsuite/lib/gdb-python.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb-python.exp,v
retrieving revision 1.1
diff -u -p -r1.1 gdb-python.exp
--- testsuite/lib/gdb-python.exp	1 Oct 2010 17:03:50 -0000	1.1
+++ testsuite/lib/gdb-python.exp	8 Oct 2010 23:03:28 -0000
@@ -45,3 +45,21 @@ proc gdb_py_test_multiple { name args } 
     }
     return 0
 }
+
+# Establish various python configuration parameters if necessary.
+# E.g. sys.path.
+
+proc gdb_check_python_config { } {
+    global USE_INSTALLED_TREE
+    # If we're running an installed version of gdb, and we want to test the
+    # installed versions of the python support scripts, then we don't want
+    # to point data-directory at the build tree.
+    if { [info exists USE_INSTALLED_TREE] && "$USE_INSTALLED_TREE" == "yes" } {
+	verbose -log "Assuming system config already installed."
+    } else {
+	verbose -log "Installing system config from build tree."
+	set gdb_data_dir "[pwd]/../data-directory"
+	gdb_test_no_output "set data-directory $gdb_data_dir"
+	gdb_test_no_output "python GdbSetPythonDirectory ('$gdb_data_dir/python')"
+    }
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-08 22:19   ` Doug Evans
  2010-10-08 22:21     ` Doug Evans
@ 2010-10-09  9:14     ` Eli Zaretskii
  2010-10-13 18:42       ` Doug Evans
  1 sibling, 1 reply; 11+ messages in thread
From: Eli Zaretskii @ 2010-10-09  9:14 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

> Date: Fri, 8 Oct 2010 15:18:45 -0700
> From: Doug Evans <dje@google.com>
> Cc: gdb-patches@sourceware.org
> 
> Return @var{type} with const and volatile qualifiers stripped,
> and with typedefs and references converted to the underlying type.

If the conversion of typedefs is recursive, then I think "to the
underlying primitive data type" is more accurate.

This takes care of typedefs.  I'm still unclear regarding the
"references" part.  What does it mean? removing the "pointer to" part,
like in "int *" -> "int"?

I still maintain that examples go a long way towards explaining such
abstract descriptions.

> >> +@item make_enum_dict (@var{enum_type})
> >> +Return a dictionary made from @var{enum_type}.
> >
> > Same here: at the very least we should say what is a "dictionary" in
> > this context.
> 
> The context is python and in the python context "dictionary" is quite
> specific, it's a builtin type.

Well, you used it as a simple word, which makes it hard to guess to
someone like me, for whom Python is a read-only language.

> What if it said the following instead?
> 
> Return a python dictionary made from @var{enum_type}.

How about

  Return a Python @code{dictionary} type produced from @var{enum_type}.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-09  9:14     ` Eli Zaretskii
@ 2010-10-13 18:42       ` Doug Evans
  2010-10-13 18:49         ` Eli Zaretskii
  0 siblings, 1 reply; 11+ messages in thread
From: Doug Evans @ 2010-10-13 18:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2049 bytes --]

On Sat, Oct 9, 2010 at 2:14 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>> Date: Fri, 8 Oct 2010 15:18:45 -0700
>> From: Doug Evans <dje@google.com>
>> Cc: gdb-patches@sourceware.org
>>
>> Return @var{type} with const and volatile qualifiers stripped,
>> and with typedefs and references converted to the underlying type.
>
> If the conversion of typedefs is recursive, then I think "to the
> underlying primitive data type" is more accurate.
>
> This takes care of typedefs.  I'm still unclear regarding the
> "references" part.  What does it mean? removing the "pointer to" part,
> like in "int *" -> "int"?
>
> I still maintain that examples go a long way towards explaining such
> abstract descriptions.
>
>> >> +@item make_enum_dict (@var{enum_type})
>> >> +Return a dictionary made from @var{enum_type}.
>> >
>> > Same here: at the very least we should say what is a "dictionary" in
>> > this context.
>>
>> The context is python and in the python context "dictionary" is quite
>> specific, it's a builtin type.
>
> Well, you used it as a simple word, which makes it hard to guess to
> someone like me, for whom Python is a read-only language.
>
>> What if it said the following instead?
>>
>> Return a python dictionary made from @var{enum_type}.
>
> How about
>
>  Return a Python @code{dictionary} type produced from @var{enum_type}.

How about this?

2010-10-13  Doug Evans  <dje@google.com>

        New python module gdb.types.
        * NEWS: Document it.
        * data-directory/Makefile.in (PYTHON_FILES): Add gdb/types.py.
        * python/lib/gdb/types.py: New file.

        testsuite/
        * lib/gdb-python.exp (gdb_check_python_config): New function.
        * gdb.python/Makefile.in (EXECUTABLES): Add lib-types.
        * gdb.python/lib-types.cc: New file.
        * gdb.python/lib-types.exp: New file.

        doc/
        * gdb.texinfo (Python): Add "Python modules".
        (Types in Python): Add reference to gdb.types section.
        (Python modules): New node.

[-- Attachment #2: gdb-101013-types-module-3.patch.txt --]
[-- Type: text/plain, Size: 17447 bytes --]

2010-10-13  Doug Evans  <dje@google.com>

	New python module gdb.types.
	* NEWS: Document it.
	* data-directory/Makefile.in (PYTHON_FILES): Add gdb/types.py.
	* python/lib/gdb/types.py: New file.

	testsuite/
	* lib/gdb-python.exp (gdb_check_python_config): New function.
	* gdb.python/Makefile.in (EXECUTABLES): Add lib-types.
	* gdb.python/lib-types.cc: New file.
	* gdb.python/lib-types.exp: New file.

	doc/
	* gdb.texinfo (Python): Add "Python modules".
	(Types in Python): Add reference to gdb.types section.
	(Python modules): New node.

Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.406
diff -u -p -r1.406 NEWS
--- NEWS	28 Sep 2010 21:40:23 -0000	1.406
+++ NEWS	13 Oct 2010 18:26:34 -0000
@@ -12,6 +12,10 @@
 
      result = some_value (10,20)
 
+  ** Module gdb.types has been added.
+     It contains a collection of utilities for working with gdb.Types objects:
+     get_basic_type, has_field, make_enum_dict.
+
 * C++ Improvements:
 
   ** GDB now puts template parameters in scope when debugging in an
Index: data-directory/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/data-directory/Makefile.in,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile.in
--- data-directory/Makefile.in	7 Oct 2010 00:18:22 -0000	1.2
+++ data-directory/Makefile.in	13 Oct 2010 18:26:34 -0000
@@ -51,7 +51,8 @@ SYSCALLS_FILES = \
 PYTHON_DIR = python
 PYTHON_INSTALL_DIR = $(DESTDIR)/$(GDB_DATADIR)/$(PYTHON_DIR)
 PYTHON_FILES = \
-	gdb/__init__.py
+	gdb/__init__.py \
+	gdb/types.py
 
 .PHONY: all
 all: stamp-syscalls stamp-python
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.768
diff -u -p -r1.768 gdb.texinfo
--- doc/gdb.texinfo	11 Oct 2010 15:46:09 -0000	1.768
+++ doc/gdb.texinfo	13 Oct 2010 18:26:34 -0000
@@ -20401,6 +20401,7 @@ the Python interpreter to locate all scr
 * Python Commands::             Accessing Python from @value{GDBN}.
 * Python API::                  Accessing @value{GDBN} from Python.
 * Auto-loading::                Automatically loading Python code.
+* Python modules::              Python modules provided by @value{GDBN}.
 @end menu
 
 @node Python Commands
@@ -21245,6 +21246,9 @@ A function internal to @value{GDBN}.  Th
 convenience functions.
 @end table
 
+Further support for types is provided in the @code{gdb.types}
+Python module (@pxref{gdb.types}).
+
 @node Pretty Printing API
 @subsubsection Pretty Printing API
 
@@ -22911,6 +22915,56 @@ cumbersome.  It may be easier to specify
 top of the source tree to the source search path.
 @end itemize
 
+@node Python modules
+@subsection Python modules
+@cindex python modules
+
+@c It is assumed that at least one more module will be added before
+@c the next release of gdb.  Thus we use a menu here.
+@value{GDBN} comes with a module to assist writing Python code.
+
+@menu
+* gdb.types::          Utilities for working with types.
+@end menu
+
+@node gdb.types
+@subsubsection gdb.types
+
+This module provides a collection of utilities for working with
+@code{gdb.Types} objects.
+
+@table @code
+@item get_basic_type (@var{type})
+Return @var{type} with const and volatile qualifiers stripped,
+and with typedefs and C++ references converted to the underlying type.
+
+C++ example:
+
+@smallexample
+typedef const int const_int;
+const_int foo (3);
+const_int& foo_ref (foo);
+int main () { return 0; }
+@end smallexample
+
+Then in gdb:
+
+@smallexample
+(gdb) start
+(gdb) python import gdb.types
+(gdb) python foo_ref = gdb.parse_and_eval("foo_ref")
+(gdb) python print gdb.types.get_basic_type(foo_ref.type)
+int
+@end smallexample
+
+@item has_field (@var{type}, @var{field})
+Return @code{True} if @var{type}, assumed to be a type with fields
+(e.g., a structure or union), has field @var{field}.
+
+@item make_enum_dict (@var{enum_type})
+Return a Python @code{dictionary} type produced from @var{enum_type}.
+@end table
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
Index: python/lib/gdb/types.py
===================================================================
RCS file: python/lib/gdb/types.py
diff -N python/lib/gdb/types.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ python/lib/gdb/types.py	13 Oct 2010 18:40:00 -0000
@@ -0,0 +1,91 @@
+# Type utilities.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Utilities for working with gdb.Types."""
+
+import gdb
+
+
+def get_basic_type(type_):
+    """Return the "basic" type of a type.
+
+    Arguments:
+        type_: The type to reduce to its basic type.
+
+    Returns:
+        type_ with const/volatile is stripped away,
+        and typedefs/references converted to the underlying type.
+    """
+
+    while (type_.code == gdb.TYPE_CODE_REF or
+           type_.code == gdb.TYPE_CODE_TYPEDEF):
+        if type_.code == gdb.TYPE_CODE_REF:
+            type_ = type_.target()
+        else:
+            type_ = type_.strip_typedefs()
+    return type_.unqualified()
+
+
+def has_field(type_, field):
+    """Return True if a type has the specified field.
+
+    Arguments:
+        type_: The type to examine.
+            It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION.
+        field: The name of the field to look up.
+
+    Returns:
+        True if the field is present either in type_ or any baseclass.
+
+    Raises:
+        TypeError: The type is not a struct or union.
+    """
+
+    type_ = get_basic_type(type_)
+    if (type_.code != gdb.TYPE_CODE_STRUCT and
+        type_.code != gdb.TYPE_CODE_UNION):
+        raise TypeError("not a struct or union")
+    for f in type_.fields():
+        if f.is_base_class:
+            if has_field(f.type, field):
+                return True
+        else:
+            # NOTE: f.name could be None
+            if f.name == field:
+                return True
+    return False
+
+
+def make_enum_dict(enum_type):
+    """Return a dictionary from a program's enum type.
+
+    Arguments:
+        enum_type: The enum to compute the dictionary for.
+
+    Returns:
+        The dictionary of the enum.
+
+    Raises:
+        TypeError: The type is not an enum.
+    """
+
+    if enum_type.code != gdb.TYPE_CODE_ENUM:
+        raise TypeError("not an enum type")
+    enum_dict = {}
+    for field in enum_type.fields():
+        # The enum's value is stored in "bitpos".
+        enum_dict[field.name] = field.bitpos
+    return enum_dict
Index: testsuite/gdb.python/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/Makefile.in,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.in
--- testsuite/gdb.python/Makefile.in	19 Aug 2010 17:00:57 -0000	1.8
+++ testsuite/gdb.python/Makefile.in	13 Oct 2010 18:26:35 -0000
@@ -3,7 +3,7 @@ srcdir = @srcdir@
 
 EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
 		py-symbol py-mi py-breakpoint py-inferior py-infthread \
-		py-shared python
+		py-shared python lib-types
 
 MISCELLANEOUS = py-shared-sl.sl
 
Index: testsuite/gdb.python/lib-types.cc
===================================================================
RCS file: testsuite/gdb.python/lib-types.cc
diff -N testsuite/gdb.python/lib-types.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.cc	13 Oct 2010 18:26:35 -0000
@@ -0,0 +1,61 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+class class1
+{
+ public:
+  class1 (int _x) : x (_x) {}
+  int x;
+};
+
+class1 class1_obj (42);
+const class1 const_class1_obj (42);
+volatile class1 volatile_class1_obj (42);
+const volatile class1 const_volatile_class1_obj (42);
+
+typedef class1 typedef_class1;
+
+typedef_class1 typedef_class1_obj (42);
+
+class1& class1_ref_obj (class1_obj);
+
+typedef const typedef_class1 typedef_const_typedef_class1;
+
+typedef_const_typedef_class1 typedef_const_typedef_class1_obj (42);
+
+typedef typedef_const_typedef_class1& typedef_const_typedef_class1_ref;
+
+typedef_const_typedef_class1_ref typedef_const_typedef_class1_ref_obj (typedef_const_typedef_class1_obj);
+
+class subclass1 : public class1
+{
+ public:
+  subclass1 (int _x, int _y) : class1 (_x), y (_y) {}
+  int y;
+};
+
+subclass1 subclass1_obj (42, 43);
+
+enum enum1 { A, B, C };
+
+enum1 enum1_obj (A);
+
+int
+main ()
+{
+  return 0;
+}
Index: testsuite/gdb.python/lib-types.exp
===================================================================
RCS file: testsuite/gdb.python/lib-types.exp
diff -N testsuite/gdb.python/lib-types.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.exp	13 Oct 2010 18:26:35 -0000
@@ -0,0 +1,143 @@
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.
+# It tests the types.py module.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "lib-types"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+# Ensure sys.path, et.al. are initialized properly.
+gdb_check_python_config
+
+gdb_test_no_output "python import gdb.types"
+
+# test get_basic_type const stripping
+gdb_test_no_output "python const_class1_obj = gdb.parse_and_eval ('const_class1_obj')"
+gdb_test_no_output "python basic_type_const_class1_obj = gdb.types.get_basic_type (const_class1_obj.type)"
+gdb_test "python print str (const_class1_obj.type)" "const class1"
+set test "const stripping"
+gdb_test_multiple "python print str (basic_type_const_class1_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type volatile stripping
+gdb_test_no_output "python volatile_class1_obj = gdb.parse_and_eval ('volatile_class1_obj')"
+gdb_test_no_output "python basic_type_volatile_class1_obj = gdb.types.get_basic_type (volatile_class1_obj.type)"
+gdb_test "python print str (volatile_class1_obj.type)" "volatile class1"
+set test "volatile stripping"
+gdb_test_multiple "python print str (basic_type_volatile_class1_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type volatile+const stripping
+gdb_test_no_output "python const_volatile_class1_obj = gdb.parse_and_eval ('const_volatile_class1_obj')"
+gdb_test_no_output "python basic_type_const_volatile_class1_obj = gdb.types.get_basic_type (const_volatile_class1_obj.type)"
+gdb_test "python print str (const_volatile_class1_obj.type)" "const volatile class1"
+set test "volatile+const stripping"
+gdb_test_multiple "python print str (basic_type_const_volatile_class1_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type typedef stripping
+gdb_test_no_output "python typedef_class1_obj = gdb.parse_and_eval ('typedef_class1_obj')"
+gdb_test_no_output "python basic_type_typedef_class1_obj = gdb.types.get_basic_type (typedef_class1_obj.type)"
+gdb_test "python print str (typedef_class1_obj.type)" "typedef_class1"
+set test "typedef stripping"
+gdb_test_multiple "python print str (basic_type_typedef_class1_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test get_basic_type reference stripping
+gdb_test_no_output "python class1_ref_obj = gdb.parse_and_eval ('class1_ref_obj')"
+gdb_test_no_output "python basic_type_class1_ref_obj = gdb.types.get_basic_type (class1_ref_obj.type)"
+gdb_test "python print str (class1_ref_obj.type)" "class1 &"
+set test "reference stripping"
+gdb_test_multiple "python print str (basic_type_class1_ref_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test nested typedef stripping
+gdb_test_no_output "python typedef_const_typedef_class1_obj = gdb.parse_and_eval ('typedef_const_typedef_class1_obj')"
+gdb_test_no_output "python basic_type_typedef_const_typedef_class1_obj = gdb.types.get_basic_type (typedef_const_typedef_class1_obj.type)"
+gdb_test "python print str (typedef_class1_obj.type)" "typedef_class1"
+set test "nested typedef stripping"
+gdb_test_multiple "python print str (basic_type_typedef_const_typedef_class1_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test nested typedef/reference stripping
+gdb_test_no_output "python typedef_const_typedef_class1_ref_obj = gdb.parse_and_eval ('typedef_const_typedef_class1_ref_obj')"
+gdb_test_no_output "python basic_type_typedef_const_typedef_class1_ref_obj = gdb.types.get_basic_type (typedef_const_typedef_class1_ref_obj.type)"
+gdb_test "python print str (typedef_const_typedef_class1_ref_obj.type)" "const typedef_const_typedef_class1_ref"
+set test "nested typedef/ref stripping"
+gdb_test_multiple "python print str (basic_type_typedef_const_typedef_class1_ref_obj)" $test {
+    -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# test has_field on simple class
+gdb_test_no_output "python class1_obj = gdb.parse_and_eval ('class1_obj')"
+gdb_test "python print gdb.types.has_field (class1_obj.type, 'x')" "True"
+gdb_test "python print gdb.types.has_field (class1_obj.type, 'nope')" "False"
+
+# test has_field in base class
+gdb_test_no_output "python subclass1_obj = gdb.parse_and_eval ('subclass1_obj')"
+gdb_test "python print gdb.types.has_field (subclass1_obj.type, 'x')" "True"
+
+# test make_enum_dict
+gdb_test_no_output "python enum1_obj = gdb.parse_and_eval ('enum1_obj')"
+gdb_test_no_output "python enum1_dict = gdb.types.make_enum_dict (enum1_obj.type)"
+gdb_test_no_output "python enum1_list = enum1_dict.items ()"
+gdb_test_no_output "python enum1_list.sort ()"
+gdb_test "python print enum1_list" {\[\('A', 0L\), \('B', 1L\), \('C', 2L\)\]}
Index: testsuite/lib/gdb-python.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb-python.exp,v
retrieving revision 1.1
diff -u -p -r1.1 gdb-python.exp
--- testsuite/lib/gdb-python.exp	1 Oct 2010 17:03:50 -0000	1.1
+++ testsuite/lib/gdb-python.exp	13 Oct 2010 18:26:35 -0000
@@ -45,3 +45,21 @@ proc gdb_py_test_multiple { name args } 
     }
     return 0
 }
+
+# Establish various python configuration parameters if necessary.
+# E.g. sys.path.
+
+proc gdb_check_python_config { } {
+    global USE_INSTALLED_TREE
+    # If we're running an installed version of gdb, and we want to test the
+    # installed versions of the python support scripts, then we don't want
+    # to point data-directory at the build tree.
+    if { [info exists USE_INSTALLED_TREE] && "$USE_INSTALLED_TREE" == "yes" } {
+	verbose -log "Assuming system config already installed."
+    } else {
+	verbose -log "Installing system config from build tree."
+	set gdb_data_dir "[pwd]/../data-directory"
+	gdb_test_no_output "set data-directory $gdb_data_dir"
+	gdb_test_no_output "python GdbSetPythonDirectory ('$gdb_data_dir/python')"
+    }
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFA] New python module gdb.types
  2010-10-13 18:42       ` Doug Evans
@ 2010-10-13 18:49         ` Eli Zaretskii
  0 siblings, 0 replies; 11+ messages in thread
From: Eli Zaretskii @ 2010-10-13 18:49 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

> Date: Wed, 13 Oct 2010 11:42:39 -0700
> From: Doug Evans <dje@google.com>
> Cc: gdb-patches@sourceware.org
> 
> How about this?

Thanks.

> +and with typedefs and C++ references converted to the underlying type.
                         ^^^
We use C@t{++} in the manual.

Okay with that change.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-10-13 18:49 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-06 20:49 [RFA] New python module gdb.types Doug Evans
2010-10-06 21:04 ` Eli Zaretskii
2010-10-08 22:19   ` Doug Evans
2010-10-08 22:21     ` Doug Evans
2010-10-09  9:14     ` Eli Zaretskii
2010-10-13 18:42       ` Doug Evans
2010-10-13 18:49         ` Eli Zaretskii
2010-10-06 21:12 ` Joel Brobecker
2010-10-06 22:12 ` Tom Tromey
2010-10-06 23:44   ` Doug Evans
2010-10-08 23:08 ` Doug Evans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).