This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] PR python/10807 API for macros.


In the gdb.Macro class,  I didn't used methods instead of attributes,
because the values are lazily computed/can return different objects if
called multiple times, thus attributes seemed weird, even though I
think the Macro methods are fairly attribute like.  so if anyone has
any opinion here on attributes vs methods.

contains one unrelated change, to stpy_dealloc which seemed to leak.

its missing macro expansion, user defined macros, a sal/scoped version
of the macros() method
and whatever else anyone can think of, will save that for another time.

2011-08-15  Matt Rice  <ratmice@gmail.com>

        PR python/10807

        * NEWS: Mention new macro api.
        * Makefile.in: Add py-macro.c.
        * python/py-macro.c: New file.
        * python/py-objfile.c (objfpy_symtab): New function.
        (objfile_getset): Add symtab attribute.
        * python/py-symtab.c (add_macro_to_list, stpy_macros,
        salpy_macro_named): New functions.
        (stpy_dealloc): Free the PyObject.
        (symtab_object_methods): Add macros method.
        (sal_object_methods): Add macro_named method.
        * python/py-symtab.h: New File:
        (symtab_to_symtab_object): Make public.
        * python/python.h: Add gdb_initialize_macros.
        * python/python.c: Call gdb_initialize_macros.

2011-08-15  Matt Rice  <ratmice@gmail.com>

        * gdb.python/py-macro.c: New file.
        * gdb.python/py-macro.exp: Ditto.

2011-08-15  Matt Rice  <ratmice@gmail.com>

        * gdb.texinfo (Macros In Python): New section.
        (Symbols In Python): Add macro_named, and macros methods.
        (Objfiles In Python): Add symtab attribute.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index bd00644..71389a6 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -289,6 +289,7 @@ SUBDIR_PYTHON_OBS = \
 	py-inferior.o \
 	py-infthread.o \
 	py-lazy-string.o \
+	py-macro.o \
 	py-objfile.o \
 	py-param.o \
 	py-prettyprint.o \
@@ -319,6 +320,7 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-inferior.c \
 	python/py-infthread.c \
 	python/py-lazy-string.c \
+	python/py-macro.c \
 	python/py-objfile.c \
 	python/py-param.c \
 	python/py-prettyprint.c \
@@ -2110,6 +2112,10 @@ py-lazy-string.o: $(srcdir)/python/py-lazy-string.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-lazy-string.c
 	$(POSTCOMPILE)
 
+py-macro.o: $(srcdir)/python/py-macro.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-macro.c
+	$(POSTCOMPILE)
+
 py-objfile.o: $(srcdir)/python/py-objfile.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
 	$(POSTCOMPILE)
diff --git a/gdb/NEWS b/gdb/NEWS
index 089e6ce..a6c2d11 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -30,6 +30,13 @@
 
   ** Symbols now provide the "type" attribute, the type of the symbol.
 
+  ** Objfiles now provide a "symtab" attribute.
+
+  ** The Macro object is now available for representing preprocessor macros.
+     The following objects now have methods for macro lookup.
+     - Symtab_and_line now has a "macro_named" method
+     - Symtab now has a "macros" method.
+
 * libthread-db-search-path now supports two special values: $sdir and $pdir.
   $sdir specifies the default system locations of shared libraries.
   $pdir specifies the directory where the libpthread used by the application
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b477cf3..db74e67 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -20955,6 +20955,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 * Blocks In Python::            Accessing frame blocks from Python.
 * Symbols In Python::           Python representation of symbols.
 * Symbol Tables In Python::     Python representation of symbol tables.
+* Macros In Python::            Python representation of preprocessor macros.
 * Lazy Strings In Python::      Python representation of lazy strings.
 * Breakpoints In Python::       Manipulating breakpoints using Python.
 @end menu
@@ -22945,6 +22946,10 @@ which is used to format the value.  @xref{Pretty Printing API}, for more
 information.
 @end defivar
 
+@defivar Objfile symtab
+The objfile's symbol table represented as a @code{gdb.Symtab} object.
+@end defivar
+
 A @code{gdb.Objfile} object has the following methods:
 
 @defmethod Objfile is_valid
@@ -23415,6 +23420,11 @@ exist in @value{GDBN} any longer.  All other
 @code{gdb.Symtab_and_line} methods will throw an exception if it is
 invalid at the time the method is called.
 @end defmethod
+
+@defmethod Symtab_and_line macro_named @r{[}name@r{]}
+Returns a @code{gdb.Macro} object, for the macro
+with the given name.
+@end defmethod
 @end table
 
 A @code{gdb.Symtab} object has the following attributes:
@@ -23444,8 +23454,48 @@ if it is invalid at the time the method is called.
 @defmethod Symtab fullname
 Return the symbol table's source absolute file name.
 @end defmethod
+
+@defmethod Symtab macros
+Return all of the macros contained in the symbol table.
+@end defmethod
 @end table
 
+
+@node Macros In Python
+@subsubsection Python representation of preprocessor macros.
+
+@cindex macros in python
+@tindex gdb.macro
+
+Python code can query information about preprocessor macros using the
+@code{gdb.macro} class.  For obtaining a @code{gdb.macro} object see
+@xref{Symbol Tables In Python}.
+
+@defmethod Macro name
+Returns the name of the macro.
+@end defmethod
+
+@defmethod Macro definition
+Returns a string with the definition of the macro.
+@end defmethod
+
+@defmethod Macro is_function_like
+Returns @code{true} If the macro is function like.
+@end defmethod
+
+@defmethod Macro argv
+Returns a list of the macros arguments if the macro is function like.
+If the macro is not function like, returns @code{None}
+@end defmethod
+
+@defmethod Macro include_trail
+Returns a list of tuples containing the filenames, and line numbers
+of header and source files that correspond to the include directives
+and file location that caused the macro to be defined.
+The list is sorted starting with the place of definition,
+and ending with the first include directive.
+@end defmethod
+
 @node Breakpoints In Python
 @subsubsection Manipulating breakpoints using Python
 
diff --git a/gdb/python/py-macro.c b/gdb/python/py-macro.c
new file mode 100644
index 0000000..4b2f385
--- /dev/null
+++ b/gdb/python/py-macro.c
@@ -0,0 +1,463 @@
+/* Python interface to macros.
+
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "defs.h"
+#include "python-internal.h"
+#include "macrotab.h"
+#include "macroexp.h"
+#include "macroscope.h"
+#include "charset.h"
+
+typedef struct
+{
+  PyObject_HEAD;
+  const char *name;
+  struct macro_source_file *src_file;
+  int src_line;
+} macro_object;
+
+static PyTypeObject macro_object_type;
+
+static PyObject *
+definition_to_py (struct macro_definition *macro)
+{
+  if (macro->replacement)
+    return PyString_FromString (macro->replacement);
+  else
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+is_function_like_to_py (struct macro_definition *macro)
+{
+  if (macro->kind == macro_function_like)
+    Py_RETURN_TRUE;
+  else
+    Py_RETURN_FALSE;
+}
+
+static PyObject *
+argv_to_py (struct macro_definition *macro)
+{
+  PyObject *ret = NULL;
+
+  if (macro->kind == macro_function_like)
+    {
+      Py_ssize_t i;
+      PyObject *ret = PyList_New (macro->argc);
+
+      if (ret == NULL)
+	return NULL;
+
+      for (i = 0; i < macro->argc; i++)
+        {
+	  PyObject *item = PyString_FromString (macro->argv[i]);
+
+	  if (!item)
+	    goto err_ret;
+
+	  if (PyList_SetItem (ret, i, item) != 0)
+            goto err_ret;
+        }
+
+      return ret;
+    }
+
+  Py_RETURN_NONE;
+
+  err_ret:
+    Py_XDECREF (ret);
+    return NULL;
+}
+
+
+static PyObject *
+include_trail_to_py(struct macro_definition *macro,
+		   const char *name,
+		   struct macro_source_file *src_file,
+		   int src_line)
+{
+  PyObject *tuple = PyTuple_New (2);
+  PyObject *result = PyList_New (0);
+  PyObject *tmp;
+  struct macro_source_file *file;
+  int line;
+
+  if (!tuple || !result)
+    goto err_exit;
+
+  file = macro_definition_location (src_file, src_line, name, &line);
+  if (!file)
+    goto err_exit;
+
+  tmp = PyString_FromString (file->filename);
+  if (!tmp)
+    goto err_exit;
+  PyTuple_SetItem (tuple, 0, tmp);
+
+  tmp = PyInt_FromLong (line);
+  if (!tmp)
+    goto err_exit;
+  if (PyTuple_SetItem (tuple, 1, tmp) != 0)
+    goto err_exit;
+  if (PyList_Append (result, tuple) != 0)
+    goto err_exit;
+  Py_DECREF (tuple);
+
+  while (file->included_by)
+    {
+      tuple = PyTuple_New (2);
+
+      if (!tuple)
+        goto err_exit;
+
+      tmp = PyString_FromString (file->included_by->filename);
+      if (!tmp)
+        goto err_exit;
+      if (PyTuple_SetItem (tuple, 0, tmp) != 0)
+        goto err_exit;
+
+      tmp = PyInt_FromLong (file->included_at_line);
+      if (!tmp)
+        goto err_exit;
+      if (PyTuple_SetItem (tuple, 1, tmp) != 0)
+        goto err_exit;
+
+      if (PyList_Append (result, tuple) != 0)
+	goto err_exit;
+      Py_DECREF (tuple);
+
+      file = file->included_by;
+    }
+
+  return result;
+
+  err_exit:
+    Py_XDECREF (tuple);
+    Py_DECREF (result);
+    return NULL;
+}
+
+/* Create a new macro (gdb.Macro) object that encapsulates the
+   macro_definition structure from GDB.  */
+PyObject *
+macropy_object_create (struct macro_definition *macro,
+		       const char *name,
+		       struct macro_source_file *ms,
+		       int line)
+{
+  macro_object *macro_obj;
+
+  macro_obj = PyObject_New (macro_object, &macro_object_type);
+  if (macro_obj)
+    {
+      /* Save enough to lookup the macro again in the methods.
+	 Then do a lookup and lazily copy things into PyObjects.
+         Consecutive lookups should be OK, because of the splay tree.
+         We cannot save a macro definition due to inconsistent memory
+	 management.  We rely on the fact that the macro_source_file
+         is not released until exit.
+
+	 It seems we may need to move to using a 'macro_scope'
+	 if we want a python api for user-defined macros. */
+      macro_obj->src_file = ms;
+      macro_obj->src_line = line;
+      macro_obj->name = xstrdup (name);
+    }
+
+  return (PyObject *) macro_obj;
+}
+
+static void
+macropy_dealloc (PyObject *obj)
+{
+  macro_object *macro_obj = (macro_object *) obj;
+
+  xfree ((void *) macro_obj->name);
+  obj->ob_type->tp_free (obj);
+}
+
+static PyObject *
+macropy_name_method (PyObject *self, PyObject *args)
+{
+  macro_object *me = (macro_object *) self;
+
+  return PyString_Decode (me->name, strlen (me->name), host_charset (), NULL);
+}
+
+static PyObject *
+macropy_definition_method (PyObject *self, PyObject *args)
+{
+  macro_object *me = (macro_object *) self;
+  struct macro_definition *macro;
+
+  macro = macro_lookup_definition (me->src_file, me->src_line, me->name);
+  return definition_to_py (macro);
+}
+
+static PyObject *
+macropy_is_function_like_method (PyObject *self, PyObject *args)
+{
+  macro_object *me = (macro_object *) self;
+  struct macro_definition *macro;
+
+  macro = macro_lookup_definition (me->src_file, me->src_line, me->name);
+  return is_function_like_to_py (macro);
+}
+
+static PyObject *
+macropy_argv_method (PyObject *self, PyObject *args)
+{
+  macro_object *me = (macro_object *) self;
+  struct macro_definition *macro;
+
+  macro = macro_lookup_definition (me->src_file, me->src_line, me->name);
+  return argv_to_py (macro);
+}
+
+static PyObject *
+macropy_include_trail_method (PyObject *self, PyObject *args)
+{
+  macro_object *me = (macro_object *) self;
+  struct macro_definition *macro;
+
+  macro = macro_lookup_definition (me->src_file, me->src_line, me->name);
+  return include_trail_to_py (macro, me->name, me->src_file, me->src_line);
+}
+
+static int
+concat_chars (PyObject **result, const char *stuff)
+{
+  PyObject *tmp = PyString_FromString (stuff);
+
+  if (!tmp)
+    return -1;
+
+  PyString_ConcatAndDel (result, tmp);
+  if (*result == NULL)
+    return -1;
+
+  return 0;
+}
+
+static int
+concat_py_obj (PyObject **result, PyObject *stuff)
+{
+  PyObject *tmp = PyObject_Str (stuff);
+
+  if (!tmp)
+    return -1;
+
+  PyString_ConcatAndDel (result, tmp);
+  if (*result == NULL)
+    return -1;
+
+  return 0;
+}
+
+static PyObject *
+macropy_str (PyObject *self)
+{
+  PyObject *result = PyString_FromString ("<gdb.Macro ");
+  macro_object *me = (macro_object *) self;
+  struct macro_definition *macro;
+  PyObject *argv = macropy_argv_method (self, Py_None);
+  PyObject *definition = macropy_definition_method (self, Py_None);
+  PyObject *include_trail = macropy_include_trail_method (self, Py_None);
+  PyObject *is_function_like = macropy_is_function_like_method (self, Py_None);
+  PyObject *name = PyString_FromString (me->name);
+
+  if (!definition || !is_function_like || !argv
+      || !include_trail || !name || !result)
+    goto err_ret;
+
+  if (concat_py_obj (&result, name) != 0)
+    goto err_ret;
+
+  if (is_function_like == Py_True)
+    {
+      Py_ssize_t sz = PyList_Size (argv);
+      Py_ssize_t i;
+
+      if (concat_chars (&result, "(") != 0)
+        goto err_ret;
+
+      for (i = 0; i < sz; i++)
+        {
+				      /* borrowed */
+	  if (concat_py_obj (&result, PyList_GetItem (argv, i)) != 0)
+	    goto err_ret;
+
+	  if (i < sz - 1)
+            if (concat_chars (&result, ", ") != 0)
+	      goto err_ret;
+        }
+
+      if (concat_chars (&result, ")") != 0)
+	goto err_ret;
+    }
+
+  if (definition != Py_None && PyString_Size (definition))
+    {
+      if (concat_chars (&result, "=") != 0)
+        goto err_ret;
+
+      if (concat_py_obj (&result, definition) != 0)
+	goto err_ret;
+    }
+
+  if (concat_chars (&result, " ") != 0)
+    goto err_ret;
+  if (concat_chars (&result, "include_trail=") != 0)
+    goto err_ret;
+  if (concat_py_obj (&result, include_trail) != 0)
+    goto err_ret;
+
+  if (concat_chars (&result, ">") != 0)
+    goto err_ret;
+
+  goto normal_ret;
+
+  err_ret:
+    Py_XDECREF (result);
+    result = NULL;
+    /* fall-through */
+  normal_ret:
+    Py_XDECREF (argv);
+    Py_XDECREF (definition);
+    Py_XDECREF (include_trail);
+    Py_XDECREF (is_function_like);
+    Py_XDECREF (name);
+    return result;
+}
+
+static int
+macropy_compare (PyObject *self, PyObject *o2)
+{
+  PyObject *my_str = macropy_str (self);
+  int result;
+
+  if (!my_str)
+    return -1;
+
+  if (PyObject_TypeCheck (o2, &macro_object_type))
+    {
+      PyObject *other_str = macropy_str (o2);
+
+      if (other_str)
+        result = PyObject_Compare (my_str, other_str);
+      else
+	result = -1;
+
+      Py_DECREF (my_str);
+      Py_XDECREF (other_str);
+      return result;
+    }
+
+  result = PyObject_Compare (my_str, o2);
+
+  Py_DECREF (my_str);
+  return result;
+}
+
+static long
+macropy_hash(PyObject *o)
+{
+  long result;
+  PyObject *my_str = macropy_str (o);
+
+  if (!my_str)
+    return -1;
+
+  result = PyObject_Hash (my_str);
+  Py_DECREF (my_str);
+  return result;
+}
+
+void
+gdbpy_initialize_macros (void)
+{
+  macro_object_type.tp_new = PyType_GenericNew;
+
+  if (PyType_Ready (&macro_object_type) < 0)
+    return;
+
+  Py_INCREF (&macro_object_type);
+  PyModule_AddObject (gdb_module, "Macro",
+		      (PyObject *) &macro_object_type);
+}
+
+static PyGetSetDef macro_object_getset[] = {
+  {NULL}  /* Sentinel */
+};
+
+static PyMethodDef macro_object_methods[] = {
+  { "argv", macropy_argv_method, METH_NOARGS,
+    "argv () -> List.\n\
+Return a list containing the names of the arguments for a function like \
+macro." },
+  { "definition", macropy_definition_method, METH_NOARGS,
+    "definition () -> String.\n\
+Return the macro's definition." },
+  { "include_trail", macropy_include_trail_method, METH_NOARGS,
+    "include_trail () -> List.\n\
+Return a list containing tuples with the filename and line number describing \
+how and where this macro came to be defined." },
+  { "is_function_like", macropy_is_function_like_method, METH_NOARGS,
+    "is_function_like () -> Bool.\n\
+Return True if the macro is function like, False otherwise." },
+  { "name", macropy_name_method, METH_NOARGS,
+    "name () -> String.\n\
+Return the macro's name." },
+  {NULL}  /* Sentinel */
+};
+
+static PyTypeObject macro_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Macro",			  /*tp_name*/
+  sizeof (macro_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  macropy_dealloc,		  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  macropy_compare,		  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  macropy_hash,			  /*tp_hash */
+  0,				  /*tp_call*/
+  macropy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB macro object",		  /*tp_doc */
+  0,				  /*tp_traverse */
+  0,				  /*tp_clear */
+  0,				  /*tp_richcompare */
+  0,				  /*tp_weaklistoffset */
+  0,				  /*tp_iter */
+  0,				  /*tp_iternext */
+  macro_object_methods,		  /*tp_methods */
+  0,				  /*tp_members */
+  macro_object_getset,		  /*tp_getset */
+};
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index f9821f5..2697218 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -22,6 +22,7 @@
 #include "charset.h"
 #include "objfiles.h"
 #include "language.h"
+#include "py-symtab.h"
 
 typedef struct
 {
@@ -118,6 +119,17 @@ objfpy_set_printers (PyObject *o, PyObject *value, void *ignore)
   return 0;
 }
 
+static PyObject *
+objfpy_symtab (PyObject *self, void *ignore)
+{
+  objfile_object *obj = (objfile_object *) self;
+
+  if (! obj->objfile)
+    return Py_None;
+
+  return symtab_to_symtab_object (obj->objfile->symtabs);
+}
+
 /* Implementation of gdb.Objfile.is_valid (self) -> Boolean.
    Returns True if this object file still exists in GDB.  */
 
@@ -210,6 +222,8 @@ static PyGetSetDef objfile_getset[] =
     "The objfile's filename, or None.", NULL },
   { "pretty_printers", objfpy_get_printers, objfpy_set_printers,
     "Pretty printers.", NULL },
+  { "symtab", objfpy_symtab, NULL,
+    "The objfile's symtab, or None.", NULL },
   { NULL }
 };
 
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
index 107cdec..033a21d 100644
--- a/gdb/python/py-symtab.c
+++ b/gdb/python/py-symtab.c
@@ -22,6 +22,7 @@
 #include "symtab.h"
 #include "source.h"
 #include "python-internal.h"
+#include "py-macro.h"
 #include "objfiles.h"
 
 typedef struct stpy_symtab_object {
@@ -138,6 +139,66 @@ stpy_fullname (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
+struct macro_user_data {
+  PyObject *list;
+  int errors;
+};
+
+static void add_macro_to_list (const char *name,
+			       const struct macro_definition *definition,
+			       struct macro_source_file *source,
+			       int line,
+			       void *user_data)
+{
+  struct macro_user_data *mud = user_data;
+  PyObject *tmp;
+
+  if (! PyObject_TypeCheck (mud->list, &PyList_Type))
+    goto err_exit;
+
+  if (mud->errors != 0)
+    goto err_exit;
+
+  tmp = macropy_object_create (definition, name, source, line);
+  if (tmp)
+    {
+      if (PyList_Append (mud->list, tmp) != 0)
+	goto err_exit;
+      Py_DECREF (tmp);
+      return;
+    }
+
+  err_exit:
+    mud->errors = 1;
+    return;
+}
+
+static PyObject *
+stpy_macros (PyObject *self, PyObject *args)
+{
+  struct symtab *st = symtab_object_to_symtab (self);
+  struct macro_user_data mud;
+  PyObject *result;
+
+  STPY_REQUIRE_VALID (self, st);
+
+  result = PyList_New (0);
+  if (result == NULL)
+    return NULL;
+
+  mud.list = result;
+  mud.errors = 0;
+  macro_for_each (st->macro_table, add_macro_to_list, &mud);
+
+  if (mud.errors != 0)
+    {
+      Py_DECREF (result);
+      return NULL;
+    }
+
+  return result;
+}
+
 /* Implementation of gdb.Symtab.is_valid (self) -> Boolean.
    Returns True if this Symbol table still exists in GDB.  */
 
@@ -191,6 +252,7 @@ stpy_dealloc (PyObject *obj)
   if (symtab->next)
     symtab->next->prev = symtab->prev;
   symtab->symtab = NULL;
+  obj->ob_type->tp_free (obj);
 }
 
 
@@ -242,6 +304,39 @@ salpy_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+static PyObject *
+salpy_macro_named (PyObject *self, PyObject *args)
+{
+  struct symtab_and_line *sal;
+  struct macro_scope *ms;
+  struct macro_definition *mdef;
+  char *macro_name;
+  struct cleanup *cleanup_chain;
+  PyObject *result;
+
+  if (!PyArg_ParseTuple (args, "s", &macro_name))
+    return NULL;
+
+  SALPY_REQUIRE_VALID (self, sal);
+
+  ms = sal_macro_scope (*sal);
+  cleanup_chain = make_cleanup (free_current_contents, &ms);
+  if (ms == NULL)
+    goto none_exit;
+
+  mdef = macro_lookup_definition (ms->file, ms->line, macro_name);
+  if (mdef == NULL)
+    goto none_exit;
+
+  result = macropy_object_create (mdef, macro_name, ms->file, ms->line);
+  do_cleanups (cleanup_chain);
+  return result;
+
+  none_exit:
+    do_cleanups (cleanup_chain);
+    return Py_None;
+}
+
 static void
 salpy_dealloc (PyObject *self)
 {
@@ -477,6 +572,9 @@ Return true if this symbol table is valid, false if not." },
   { "fullname", stpy_fullname, METH_NOARGS,
     "fullname () -> String.\n\
 Return the symtab's full source filename." },
+  { "macros", stpy_macros, METH_NOARGS,
+    "macros () -> List.\n\
+Return a list of macros in the symtab." },
   {NULL}  /* Sentinel */
 };
 
@@ -526,6 +624,10 @@ static PyMethodDef sal_object_methods[] = {
   { "is_valid", salpy_is_valid, METH_NOARGS,
     "is_valid () -> Boolean.\n\
 Return true if this symbol table and line is valid, false if not." },
+  { "macro_named", salpy_macro_named, METH_VARARGS,
+    "macro_named (name) -> Macro.\n\
+Return the macro object for the given name, \
+or None if the macro cannot be found." },
   {NULL}  /* Sentinel */
 };
 
diff --git a/gdb/python/py-symtab.h b/gdb/python/py-symtab.h
new file mode 100644
index 0000000..911a051
--- /dev/null
+++ b/gdb/python/py-symtab.h
@@ -0,0 +1,7 @@
+#ifndef GDB_PY_SYMTAB_H
+#define GDB_PY_SYMTAB_H
+
+PyObject *
+symtab_to_symtab_object (struct symtab *symtab);
+
+#endif
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 996b23b..532552a 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -211,6 +211,7 @@ void gdbpy_initialize_breakpoint_event (void);
 void gdbpy_initialize_continue_event (void);
 void gdbpy_initialize_exited_event (void);
 void gdbpy_initialize_thread_event (void);
+void gdbpy_initialize_macros (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 03edce9..092b354 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1198,6 +1198,7 @@ Enables or disables printing of Python stack traces."),
   gdbpy_initialize_lazy_string ();
   gdbpy_initialize_thread ();
   gdbpy_initialize_inferior ();
+  gdbpy_initialize_macros ();
   gdbpy_initialize_events ();
 
   gdbpy_initialize_eventregistry ();
diff --git a/gdb/testsuite/gdb.python/py-macro.c b/gdb/testsuite/gdb.python/py-macro.c
new file mode 100644
index 0000000..8ac10e0
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-macro.c
@@ -0,0 +1,72 @@
+#ifdef DEF_MACROS
+
+  #ifdef ONE
+    #ifdef FOO
+    #undef FOO
+    #endif
+
+  #define FOO "hello"
+  #else
+    #undef FOO
+  #endif
+
+
+  #ifdef TWO
+    #ifdef FOO
+    #undef FOO
+    #endif
+  #define FOO " "
+  #endif
+
+  #ifdef THREE
+    #ifdef FOO
+    #undef FOO
+    #endif
+  #define FOO(a,b)
+  #endif
+
+  #ifdef FOUR
+    #ifdef FOO
+    #undef FOO
+    #endif
+    #define FOO(a) foo = a
+  #endif
+#else
+
+int main (int argc, const char **argv)
+{
+  char *foo;
+
+  #define DEF_MACROS
+  #define ONE
+  #include "py-macro.c"
+  foo = FOO;
+
+  #define TWO
+  #include "py-macro.c"
+  foo = FOO;
+
+  #define THREE
+  #include "py-macro.c"
+  foo = "world"FOO(0,1);
+
+  #undef THREE
+  #include "py-macro.c"
+  foo = FOO;
+
+  #undef TWO
+  #include "py-macro.c"
+  foo = FOO;
+
+  #undef ONE
+  #include "py-macro.c"
+  foo = (char *)0;
+
+  #define FOUR
+  #include "py-macro.c"
+  FOO ("the end.");
+
+  return 0;
+}
+#endif
+
diff --git a/gdb/testsuite/gdb.python/py-macro.exp b/gdb/testsuite/gdb.python/py-macro.exp
new file mode 100644
index 0000000..ccbabb6
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-macro.exp
@@ -0,0 +1,288 @@
+# Copyright (C) 2011 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 mechanism
+# exposing macros to Python.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "py-macro"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+get_compiler_info ${binfile}
+if [test_compiler_info gcc*] {
+    lappend options additional_flags=-g3
+} else {
+  untested ${testfile}.exp
+  return -1
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $options] } {
+    untested ${testfile}.exp
+    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 }
+
+gdb_py_test_multiple "setup macro test objects" \
+  "python" "" \
+  "def find_objfile():" "" \
+  "  for objfile in gdb.objfiles():" "" \
+  "    if objfile.filename == \"$binfile\":" "" \
+  "      print objfile.filename" "" \
+  "      return objfile" "" \
+  "def here_macro(name):" "" \
+  "  return gdb.decode_line(\"*\$pc\")\[1\]\[0\].macro_named(name)" "" \
+  "macros = list()" "" \
+  "end" ""
+
+gdb_test "python objfile = find_objfile()" "$binfile" "found objfile"
+gdb_test "python objfile.symtab.macros()" \
+	 "Symbol Table is invalid.*" "symtab is invalid"
+
+if ![runto_main] {
+    untested ${testfile}.exp
+    return -1
+}
+
+gdb_py_test_silent_cmd "python m = objfile.symtab.macros()" "get all macros" 1
+
+gdb_py_test_silent_cmd "python include_guard = here_macro(\"DEF_MACROS\")" \
+		       "get guard macro #1" \
+		       1
+
+gdb_test "python print include_guard.name() == \"DEF_MACROS\"" \
+	 "True" \
+	 "guard name"
+
+gdb_test "python print include_guard.is_function_like() == False" \
+	 "True" \
+	 "guard isnt function like"
+
+gdb_test "python print include_guard.argv() == None" \
+	 "True" \
+	 "guard has no args"
+
+gdb_test "python print 'foo' + include_guard.definition() + 'bar'" \
+	 "foobar" \
+	 "guard definition is empty"
+
+gdb_test "python print include_guard.include_trail()\[0\]\[0\]" \
+	 "$srcfile.*" \
+	 "guard trail has srcfile"
+
+#<gdb.Macro include_trail=[('./gdb.python/py-macro.c', 8), ('./gdb.python/py-macro.c', 43)] FOO="hello">
+gdb_test "python print include_guard" \
+"<gdb\.Macro DEF_MACROS include_trail=\\\[\\\('$srcdir/$subdir/$srcfile', \[0-9\]+\\\).*\\\]>" \
+"guard string rep"
+
+gdb_py_test_silent_cmd "python macros.append(include_guard)" \
+		       "add to macros list" \
+		       0
+
+gdb_py_test_silent_cmd "python foo = here_macro(\"FOO\")" \
+		       "get FOO macro #1" \
+		       1
+
+gdb_test "python print foo.name()" \
+	 "FOO" \
+	 "FOO macro #1 name"
+
+gdb_test "python print foo.is_function_like()" \
+	 "False" \
+	 "FOO macro #1 isnt function like"
+
+gdb_test "python print foo.argv()" \
+	 "None" \
+	 "FOO macro #1 has no args"
+
+gdb_test "python print foo.definition()" \
+	 "\"hello\"" \
+	 "FOO macro #1 definition is \"hello\""
+
+gdb_test "python print include_guard.include_trail()\[0\]\[0\]" \
+	 "$srcfile.*" \
+	 "FOO macro #1 has srcfile"
+
+gdb_test "python print foo" \
+"<gdb\.Macro FOO=\"hello\" include_trail=\\\[\\\('$srcdir/$subdir/$srcfile', \[0-9\]+\\\).*\\\]>" \
+"FOO macro #1 string rep"
+
+gdb_py_test_silent_cmd "python macros.append(foo)" \
+		       "add to macros list" \
+		       0
+
+gdb_test "next" "" ""
+gdb_py_test_silent_cmd "python foo = here_macro(\"FOO\")" \
+		       "get FOO macro #2" \
+		       1
+
+gdb_test "python print foo.name()" \
+	 "FOO" \
+	 "FOO macro #2 name"
+
+gdb_test "python print foo.is_function_like()" \
+	 "False" \
+	 "FOO macro #2 isnt function like"
+
+gdb_test "python print foo.argv()" \
+	 "None" \
+	 "FOO macro #2 has no args"
+
+gdb_test "python print foo.definition()" \
+	 "\" \"" \
+	 "FOO macro #2 definition is \" \""
+
+gdb_test "python print foo.include_trail()\[0\]\[0\]" \
+	 "$srcfile.*" \
+	 "FOO macro #2 has srcfile"
+
+gdb_test "python print foo" \
+"<gdb\.Macro FOO=\" \" include_trail=\\\[\\\('$srcdir/$subdir/$srcfile', \[0-9\]+\\\).*\\\]>" \
+"FOO macro #2 string rep"
+
+gdb_py_test_silent_cmd "python macros.append(foo)" \
+		       "add to macros list" \
+		       0
+
+gdb_test "next" "" ""
+gdb_py_test_silent_cmd "python foo = here_macro(\"FOO\")" \
+		       "get FOO macro #3" \
+		       1
+gdb_test "python print foo.name()" \
+	 "FOO" \
+	 "FOO macro #3 name"
+
+gdb_test "python print foo.is_function_like()" \
+	 "True" \
+	 "FOO macro #3 is function like"
+
+gdb_test "python print foo.argv()" \
+	 "\\\['a', 'b'\\\]" \
+	 "FOO macro #3 has args"
+
+gdb_test "python print 'foo' + foo.definition() + 'bar'" \
+	 "foobar" \
+	 "FOO macro #3 definition is empty"
+
+gdb_test "python print include_guard.include_trail()\[0\]\[0\]" \
+	 "$srcfile.*" \
+	 "FOO macro #3 has srcfile"
+
+gdb_test "python print foo" \
+"<gdb\.Macro FOO\\\(a, b\\\) include_trail=\\\[\\\('$srcdir/$subdir/$srcfile', \[0-9\]+\\\).*\\\]>" \
+"FOO macro #3 string rep"
+
+gdb_py_test_silent_cmd "python macros.append(foo)" \
+		       "add to macros list" \
+		       0
+gdb_test "next" "" ""
+gdb_test "next" "" ""
+gdb_test "next" "" ""
+gdb_py_test_silent_cmd "python foo = here_macro(\"FOO\")" \
+		       "get FOO macro #4" \
+		       1
+gdb_test "python print foo" \
+	 "None" \
+	 "there is no Foo macro #4"
+
+gdb_test "next" "" ""
+gdb_py_test_silent_cmd "python foo = here_macro(\"FOO\")" \
+		       "get FOO macro #5" \
+		       1
+
+gdb_test "python print foo.name()" \
+	 "" \
+	 "FOO macro #5 name"
+
+gdb_test "python print foo.is_function_like()" \
+	 "True" \
+	 "FOO macro #5 is function like"
+
+gdb_test "python print foo.argv()" \
+	 "\\\['a'\\\]" \
+	 "FOO macro #5 has args"
+
+gdb_test "python print foo.definition()" \
+	 "foo = a" \
+	 "FOO macro #5 definition ok"
+
+gdb_test "python print include_guard.include_trail()\[0\]\[0\]" \
+	 "$srcfile.*" \
+	 "FOO macro #5 has srcfile"
+
+gdb_test "python print foo" \
+"<gdb\.Macro FOO\\\(a\\\)=foo = a include_trail=\\\[\\\('$srcdir/$subdir/$srcfile', \[0-9\]+\\\).*\\\]>" \
+"FOO macro #5 string rep"
+gdb_py_test_silent_cmd "python macros.append(foo)" \
+		       "add to macros list" \
+		       0
+
+# this could find some ref count bugs if they were to happen for a singleton.
+gdb_py_test_multiple "run macros a couple of times" \
+  "python" "" \
+  "c = 0" "" \
+  "while c > 3:" "" \
+  "  c = c + 1" "" \
+  "  for macro in objfile.symtab.macros():" "" \
+  "    macro.name()" "" \
+  "    macro.is_function_like()" "" \
+  "    macro.argv()" "" \
+  "    macro.include_path()" "" \
+  "    macro.definition()" "" \
+  "    str(macro)" "" \
+  "    hash(macro)" "" \
+  "end" ""
+
+gdb_py_test_multiple "find selected macros in the big list of macros" \
+  "python" "" \
+  "set1 = set(objfile.symtab.macros())" "" \
+  "set2 = set(macros)" "" \
+  "intersect = (set1 & set2)" "" \
+  "set3 = set(filter(lambda(x): x.name() == \"FOO\", objfile.symtab.macros()))" "" \
+  "intersect2 = (set3 & set2)" "" \
+  "print \"set2\", map(lambda(x): x.name(), set2)" "" \
+  "print \"set3\", map(lambda(x): x.name(), set3)" "" \
+  "print \"intersect\", map(lambda(x): x.name(), intersect)" "" \
+  "print \"intersect2\", map(lambda(x): x.name(), intersect2)" "" \
+  "print \"set2 - intersect\", map(lambda(x): x.name(), set2 - intersect)" "" \
+  "print \"intersect - set2\", map(lambda(x): x.name(), intersect - set2)" "" \
+  "print \"set2 - intersect2\", map(lambda(x): x.name(), set2 - intersect2)" "" \
+  "print \"intersect2 - set2\", map(lambda(x): x.name(), intersect2 - set2)" "" \
+  "end" ""
+
+gdb_test "python print len(set2)" "5" "macro set length 5"
+gdb_test "python print len(set1) > len(set2)" "True" "all macros is longer."
+gdb_test "python print set1 >= set2" "True" "macro set2 is a subset"
+gdb_test "python print len(intersect - set2), len(set2 - intersect)" \
+	 "0 0" \
+	 "macro set intersection equality"
+gdb_test "python print len(intersect2 - set2)" \
+	 "0" \
+	 "macro set intersection equality 2"
+gdb_test "python print len(set2 - intersect2), (set2 - intersect2).pop()" \
+	 "1 <gdb.Macro DEF_MACROS.*>" \
+	 "macro set intersection 3"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]