[PATCH 3/7] [python] API for macros: Add gdb.Macro class.

matt rice
2011-08-24T15:12:00Z

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

PR python/10807
* Makefile.in: Add python/py-macro.c.
* python/py-macro.c: New file.
* python/py-macro.h: Ditto.
* python/python-internal.h: Declare gdbpy_initialize_macros.
* python/python.c (_initialize_python): Call gdbpy_initialize_macros.
---
gdb/Makefile.in | 6 +
gdb/python/py-macro.c | 782 ++++++++++++++++++++++++++++++++++++++++++
gdb/python/py-macro.h | 62 ++++
gdb/python/python-internal.h | 1 +
gdb/python/python.c | 1 +
5 files changed, 852 insertions(+), 0 deletions(-)
create mode 100644 gdb/python/py-macro.c
create mode 100644 gdb/python/py-macro.h

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/python/py-macro.c b/gdb/python/py-macro.c
new file mode 100644
index 0000000..184be02
--- /dev/null
+++ b/gdb/python/py-macro.c
@@ -0,0 +1,782 @@
+/* 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 "py-macro.h"
+#include "macrotab.h"
+#include "bcache.h"
+#include "objfiles.h"
+
+/* The macro_object_validator type has the ability to detect when an object
+ has been invalidated and nothing more. The more featured validation
+ methods of pyst, pysal, provide no benefit for macros because once
+ we have been invalidated, we have no way to know what macro the object
+ once represented. */
+typedef struct
+{
+ PyObject_HEAD;
+ int is_valid;
+ struct objfile *objfile;
+} macro_validator_object;
+
+typedef struct
+{
+ PyObject_HEAD;
+
+ /* A macro definition object representing this macro. */
+ const struct macro_definition *def;
+ /* The name of the macro */
+ const char *name;
+ /* The file where the macro resides and its include trail. */
+ struct macro_source_file *src;
+ /* the line location in the 'SRC' file. */
+ int line;
+ /* This is used to tell us if the macro has been invalidated
+ The objfile who's obstack and bcache the mdef, and src, and name
+ fields reside in is stored here. Those fields may be dangling
+ pointers if the objfile is NULL.
+ An invalid macro cannot become valid once again. */
+ macro_validator_object *objfile_validator;
+} macro_object;
+
+static const struct objfile_data *macropy_objfile_data_key;
+
+static PyTypeObject macro_object_type;
+static PyTypeObject macro_validator_object_type;
+
+\f
+
+/* Internal methods for converting macros to python objects. */
+
+static PyObject *
+macropy__definition_to_py (const struct macro_definition *macro)
+{
+ if (macro->replacement)
+ return PyString_FromString (macro->replacement);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+macropy__is_function_like_to_py (const struct macro_definition *macro)
+{
+ if (macro->kind == macro_function_like)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+macropy__argv_to_py (const struct macro_definition *macro)
+{
+ PyObject *ret;
+
+ if (macro->kind == macro_function_like)
+ {
+ Py_ssize_t i;
+ ret = PyList_New (macro->argc);
+
+ if (ret == NULL)
+ goto err_ret;
+
+ 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 *
+macropy__include_trail_to_py (const struct macro_definition *macro,
+ struct macro_source_file *file,
+ int line)
+{
+ PyObject *tuple = NULL;
+ PyObject *result;
+ PyObject *tmp;
+
+ result = PyList_New (0);
+ if (!result)
+ goto err_ret;
+
+ tuple = PyTuple_New (2);
+ if (!tuple)
+ goto err_ret;
+
+ tmp = PyString_FromString (file->filename);
+ if (!tmp)
+ goto err_ret;
+ if (PyTuple_SetItem (tuple, 0, tmp) != 0)
+ goto err_ret;
+
+ tmp = PyInt_FromLong (line);
+ if (!tmp)
+ goto err_ret;
+ if (PyTuple_SetItem (tuple, 1, tmp) != 0)
+ goto err_ret;
+
+ if (PyList_Append (result, tuple) != 0)
+ goto err_ret;
+ Py_DECREF (tuple);
+
+ while (file->included_by)
+ {
+ tuple = PyTuple_New (2);
+
+ if (!tuple)
+ goto err_ret;
+
+ tmp = PyString_FromString (file->included_by->filename);
+ if (!tmp)
+ goto err_ret;
+ if (PyTuple_SetItem (tuple, 0, tmp) != 0)
+ goto err_ret;
+
+ tmp = PyInt_FromLong (file->included_at_line);
+ if (!tmp)
+ goto err_ret;
+ if (PyTuple_SetItem (tuple, 1, tmp) != 0)
+ goto err_ret;
+
+ if (PyList_Append (result, tuple) != 0)
+ goto err_ret;
+ Py_DECREF (tuple);
+
+ file = file->included_by;
+ }
+
+ return result;
+
+ err_ret:
+ Py_XDECREF (tuple);
+ Py_XDECREF (result);
+ return NULL;
+}
+
+static PyObject *
+macropy__name_to_py (const char *name)
+{
+ return PyString_FromString (name);
+}
+
+\f
+
+/* Publicly declared functions. */
+
+/* A macro_callback_fn for use with macro_foreach that adds
+ the macro to a python list. */
+enum macro_walk_status
+pymacro_add_macro_to_list (const char *name,
+ const struct macro_definition *definition,
+ struct macro_source_file *source,
+ int line,
+ void *user_data)
+{
+ PyObject *tmp = NULL;
+ struct macropy_user_data *mud = user_data;
+ PyObject *list = (PyObject *) mud->list;
+
+ if (! PyObject_TypeCheck (list, &PyList_Type))
+ goto fail;
+
+ tmp = macropy_object_create (mud->objfile, name, definition, source, line);
+ if (!tmp)
+ goto fail;
+
+ if (PyList_Append (list, tmp) != 0)
+ goto fail;
+
+ Py_DECREF (tmp);
+ return macro_walk_continue;
+
+ fail:
+ Py_XDECREF (tmp);
+ return macro_walk_abort;
+}
+
+/* Create a new macro (gdb.Macro) object that encapsulates
+ the gdb macro representation. */
+PyObject *
+macropy_object_create (struct objfile *objfile,
+ const char *name,
+ const struct macro_definition *def,
+ struct macro_source_file *src,
+ int line)
+{
+ macro_object *macro_obj;
+
+ macro_obj = PyObject_New (macro_object, &macro_object_type);
+
+ if (macro_obj)
+ {
+ macro_validator_object *validator;
+
+ macro_obj->objfile_validator = NULL;
+
+ /* check our arguments, Don't check line because 0 is a valid line. */
+ if (!objfile)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Invalid objfile initializing gdb.Macro"));
+ goto err_ret;
+ }
+
+ if (!name)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Invalid macro name initializing gdb.Macro"));
+ goto err_ret;
+ }
+
+ if (!def)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Invalid macro definition initializing gdb.Macro"));
+ goto err_ret;
+ }
+
+ if (!src)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Invalid macro source file initializing gdb.Macro"));
+ goto err_ret;
+ }
+
+ validator = objfile_data (objfile, macropy_objfile_data_key);
+ if (!validator)
+ {
+ validator = PyObject_New (macro_validator_object,
+ &macro_validator_object_type);
+ if (!validator)
+ goto err_ret;
+
+ validator->is_valid = 1;
+ validator->objfile = objfile;
+ set_objfile_data (objfile, macropy_objfile_data_key, validator);
+ }
+ else
+ Py_INCREF (validator);
+
+ macro_obj->name = bcache (name, strlen (name) + 1, objfile->macro_cache);
+ macro_obj->objfile_validator = validator;
+ macro_obj->def = def;
+ macro_obj->src = src;
+ macro_obj->line = line;
+
+ return (PyObject *) macro_obj;
+
+ err_ret:
+ Py_DECREF (macro_obj);
+ return NULL;
+ }
+ return NULL;
+}
+
+static void
+macropy_dealloc (PyObject *obj)
+{
+ macro_object *me = (macro_object *) obj;
+
+ Py_XDECREF (me->objfile_validator);
+
+ obj->ob_type->tp_free (obj);
+}
+
+static void
+macropy_validator_dealloc (PyObject *obj)
+{
+ macro_validator_object *me = (macro_validator_object *) obj;
+
+ if (me->objfile)
+ set_objfile_data (me->objfile, macropy_objfile_data_key, NULL);
+
+ obj->ob_type->tp_free (obj);
+}
+
+static void
+del_objfile_macro (struct objfile *objfile, void *datum)
+{
+ macro_validator_object *validator = datum;
+
+ if (validator)
+ {
+ validator->is_valid = 0;
+ validator->objfile = NULL;
+ }
+ else
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Internal inconsistency invalidating objfile macros."));
+}
+
+\f
+
+/* Helper function for macro validation */
+
+static inline macro_object *
+macropy__validate_self (PyObject *self)
+{
+ macro_object *me;
+
+ if (! PyObject_TypeCheck (self, &macro_object_type))
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Typecheck failure converting macro."));
+ return NULL;
+ }
+
+ me = (macro_object *) self;
+
+ if (me->objfile_validator->is_valid == 0)
+ {
+ PyErr_SetString (PyExc_RuntimeError, _("Macro is invalid."));
+ return NULL;
+ }
+
+ return me;
+}
+
+/* Macro object methods */
+
+static PyObject *
+macropy_name_method (PyObject *self, PyObject *args)
+{
+ macro_object *me = macropy__validate_self (self);
+
+ if (!me)
+ return NULL;
+
+ return macropy__name_to_py (me->name);
+}
+
+static PyObject *
+macropy_definition_method (PyObject *self, PyObject *args)
+{
+ macro_object *me = macropy__validate_self (self);
+
+ if (!me)
+ return NULL;
+
+ return macropy__definition_to_py (me->def);
+}
+
+static PyObject *
+macropy_is_function_like_method (PyObject *self, PyObject *args)
+{
+ macro_object *me = macropy__validate_self (self);
+
+ if (!me)
+ return NULL;
+
+ return macropy__is_function_like_to_py (me->def);
+}
+
+static PyObject *
+macropy_argv_method (PyObject *self, PyObject *args)
+{
+ macro_object *me = macropy__validate_self (self);
+
+ if (!me)
+ return NULL;
+
+ return macropy__argv_to_py (me->def);
+}
+
+static PyObject *
+macropy_include_trail_method (PyObject *self, PyObject *args)
+{
+ macro_object *me = macropy__validate_self (self);
+
+ if (!me)
+ return NULL;
+
+ return macropy__include_trail_to_py (me->def, me->src, me->line);
+}
+
+/* For future API compatibility. */
+static PyObject *
+macropy_is_valid_method (PyObject *self, PyObject *args)
+{
+ macro_object *me = (macro_object *) self;
+
+ if (!me)
+ return NULL;
+
+ if (me->objfile_validator->is_valid)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+/* Helpers for the macropy_str method. */
+static int
+macropy__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
+macropy__concat_py_obj (PyObject **result, PyObject *stuff)
+{
+ PyObject *tmp;
+
+ if (PyObject_TypeCheck (stuff, &PyString_Type))
+ {
+ PyString_Concat (result, stuff);
+ return *result ? 0 : -1;
+ }
+
+ tmp = PyObject_Str (stuff);
+ if (!tmp)
+ return -1;
+
+ PyString_ConcatAndDel (result, tmp);
+ return *result ? 0 : -1;
+}
+
+static PyObject *
+macropy_str (PyObject *self)
+{
+ PyObject *result = NULL;
+ PyObject *argv = NULL;
+ PyObject *definition = NULL;
+ PyObject *include_trail = NULL;
+ PyObject *is_function_like = NULL;
+ PyObject *name = NULL;
+ macro_object *me = macropy__validate_self (self);
+
+ if (!me)
+ goto err_ret;
+
+ result = PyString_FromString ("<gdb.Macro ");
+ if (!result)
+ goto err_ret;
+
+ argv = macropy__argv_to_py (me->def);
+ if (!argv)
+ goto err_ret;
+
+ definition = macropy__definition_to_py (me->def);
+ if (!definition)
+ goto err_ret;
+
+ include_trail = macropy__include_trail_to_py (me->def, me->src, me->line);
+ if (!include_trail)
+ goto err_ret;
+
+ is_function_like = macropy__is_function_like_to_py (me->def);
+ if (!is_function_like)
+ goto err_ret;
+
+ name = macropy__name_to_py (me->name);
+ if (!name)
+ goto err_ret;
+
+ if (macropy__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 (macropy__concat_chars (&result, "(") != 0)
+ goto err_ret;
+
+ for (i = 0; i < sz; i++)
+ {
+ /* borrowed */
+ if (macropy__concat_py_obj (&result, PyList_GetItem (argv, i)) != 0)
+ goto err_ret;
+
+ if (i < sz - 1)
+ if (macropy__concat_chars (&result, ", ") != 0)
+ goto err_ret;
+ }
+
+ if (macropy__concat_chars (&result, ")") != 0)
+ goto err_ret;
+ }
+
+ if (definition != Py_None && PyString_Size (definition))
+ {
+ if (macropy__concat_chars (&result, "=") != 0)
+ goto err_ret;
+
+ if (macropy__concat_py_obj (&result, definition) != 0)
+ goto err_ret;
+ }
+
+ if (macropy__concat_chars (&result, " ") != 0)
+ goto err_ret;
+ if (macropy__concat_chars (&result, "include_trail=") != 0)
+ goto err_ret;
+ if (macropy__concat_py_obj (&result, include_trail) != 0)
+ goto err_ret;
+
+ if (macropy__concat_chars (&result, ">") != 0)
+ goto err_ret;
+
+ goto normal_ret;
+
+ err_ret:
+ Py_XDECREF (result);
+ result = NULL;
+ 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);
+ PyObject *other_str = NULL;
+ PyObject *an_error;
+ int err_code = -1;
+ int comparison_result = -1;
+
+ if (!my_str)
+ goto check_for_errors_and_return;
+
+ if (PyObject_TypeCheck (o2, &macro_object_type))
+ {
+ other_str = macropy_str (o2);
+ if (!other_str)
+ goto check_for_errors_and_return;
+
+ err_code = PyObject_Cmp (my_str, other_str, &comparison_result);
+ }
+ else
+ {
+ err_code = PyObject_Cmp (my_str, o2, &comparison_result);
+ }
+
+ check_for_errors_and_return:
+ Py_XDECREF (my_str);
+ Py_XDECREF (other_str);
+
+ /* Because -1 is also Less Than we cannot use gdbpy_print_stack ()
+ which clears the error if set python print-stack is off.
+ Which would lead to (gdb) python print x == x
+ returning False with no error message displayed.
+
+ alternately if an error is set and the return value is not 1,
+ python will complain.
+
+ Thus if there is an error, we must normalize it
+ making sure that both an error and the return
+ value are -1. Should we encounter one. */
+ an_error = PyErr_Occurred ();
+ if (an_error == NULL && err_code != -1)
+ {
+ /* a valid comparison */
+ return comparison_result;
+ }
+ else if (an_error == NULL && err_code == -1)
+ {
+ /* an unknown error */
+ PyErr_SetString (PyExc_RuntimeError,
+ _("mystery error during macro comparison."));
+ return -1;
+ }
+ else /* a known error */
+ return -1;
+}
+
+static long
+macropy_hash (PyObject *o)
+{
+ long result = -1;
+ PyObject *my_str = macropy_str (o);
+
+ if (my_str)
+ result = PyObject_Hash (my_str);
+
+ /* The docs say PyObject_Hash should return -1 on error,
+ Don't believe it because it is not always true,
+ The exception gets raised regardless of return value,
+ But we should follow the documented return strategy of -1 on error.
+
+ gdbpy_print_stack () clears the error if set python print-stack is off,
+ which would cause python later to complain that we returned -1
+ without an error set. We don't want that. */
+ if (PyErr_Occurred ())
+ result = -1;
+ Py_XDECREF (my_str);
+ return result;
+}
+
+\f
+
+void
+gdbpy_initialize_macros (void)
+{
+ macro_object_type.tp_new = PyType_GenericNew;
+ macro_validator_object_type.tp_new = PyType_GenericNew;
+
+ if (PyType_Ready (&macro_validator_object_type) < 0)
+ return;
+
+ if (PyType_Ready (&macro_object_type) < 0)
+ return;
+
+ macropy_objfile_data_key
+ = register_objfile_data_with_cleanup (NULL, del_objfile_macro);
+
+ Py_INCREF (&macro_object_type);
+ PyModule_AddObject (gdb_module, "Macro",
+ (PyObject *) &macro_object_type);
+
+ Py_INCREF (&macro_validator_object_type);
+ PyModule_AddObject (gdb_module, "MacroValidator",
+ (PyObject *) &macro_validator_object_type);
+}
+
+static PyGetSetDef macro_validator_object_getset[] = {
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef macro_validator_object_methods[] = {
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject macro_validator_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.MacroValidator", /*tp_name*/
+ sizeof (macro_validator_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ macropy_validator_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB macro validator object", /*tp_doc */
+ 0, /*tp_traverse */
+ 0, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ 0, /*tp_iter */
+ 0, /*tp_iternext */
+ macro_validator_object_methods, /*tp_methods */
+ 0, /*tp_members */
+ macro_validator_object_getset, /*tp_getset */
+};
+
+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." },
+ { "is_valid", macropy_is_valid_method, METH_NOARGS,
+ "is_valid () -> Bool.\n\
+Return whether the macro is valid." },
+ {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-macro.h b/gdb/python/py-macro.h
new file mode 100644
index 0000000..46b0293
--- /dev/null
+++ b/gdb/python/py-macro.h
@@ -0,0 +1,62 @@
+/* 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/>. */
+
+#ifndef GDB_PY_MACRO_H
+#define GDB_PY_MACRO_H
+
+#include "objfiles.h"
+#include "macrotab.h"
+
+struct macropy_user_data {
+ PyObject *list;
+ struct objfile *objfile;
+};
+
+/* A macro_callback_fn for use with macro_foreach and friends that adds
+ a gdb.Macro object to the python list USER_DATA->LIST.
+ USER_DATA should be of type struct macropy_user_data.
+
+ A null USER_DATA->OBJFILE is currently be considered an error,
+ this is subject to change.
+
+ Aborts the iteration on error, and forces the macro iterator function
+ to return macro_walk_aborted check the iterators macro_walk_result.
+ On error it is the callers responsibility to dispose of the USER_DATA
+ structure and its contents. The appropriate python exception
+ that caused the error has already been set.
+*/
+enum macro_walk_status
+pymacro_add_macro_to_list (const char *name,
+ const struct macro_definition *definition,
+ struct macro_source_file *source,
+ int line,
+ void *user_data);
+
+/* Create a new macro (gdb.Macro) object that encapsulates
+ the gdb macro representation. OBJFILE is the objfile that contains
+ the macro table. NAME is the name of the macro. DEF the macros definition
+ SRC the source file containing the macro. LINE definitions location. */
+PyObject *
+macropy_object_create (struct objfile *objfile,
+ const char *name,
+ const struct macro_definition *def,
+ struct macro_source_file *src,
+ int line);
+
+#endif /* GDB_PY_MACRO_H */
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 ();
--
1.7.4.4