Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.1218 diff -u -p -r1.1218 Makefile.in --- Makefile.in 26 Nov 2012 19:23:50 -0000 1.1218 +++ Makefile.in 28 Nov 2012 14:04:16 -0000 @@ -289,6 +289,7 @@ SUBDIR_PYTHON_OBS = \ py-lazy-string.o \ py-newobjfileevent.o \ py-objfile.o \ + py-operator.o \ py-param.o \ py-prettyprint.o \ py-progspace.o \ @@ -322,6 +323,7 @@ SUBDIR_PYTHON_SRCS = \ python/py-lazy-string.c \ python/py-newobjfileevent.c \ python/py-objfile.c \ + python/py-operator.c \ python/py-param.c \ python/py-prettyprint.c \ python/py-progspace.c \ @@ -2113,6 +2115,10 @@ py-objfile.o: $(srcdir)/python/py-objfil $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c $(POSTCOMPILE) +py-operator.o: $(srcdir)/python/py-operator.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-operator.c + $(POSTCOMPILE) + py-param.o: $(srcdir)/python/py-param.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-param.c $(POSTCOMPILE) Index: valarith.c =================================================================== RCS file: /cvs/src/src/gdb/valarith.c,v retrieving revision 1.106 diff -u -p -r1.106 valarith.c --- valarith.c 14 Sep 2012 12:46:55 -0000 1.106 +++ valarith.c 28 Nov 2012 14:04:16 -0000 @@ -31,6 +31,7 @@ #include #include "infcall.h" #include "exceptions.h" +#include "python/python.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). */ @@ -353,6 +354,14 @@ value_x_binop (struct value *arg1, struc arg1 = coerce_ref (arg1); arg2 = coerce_ref (arg2); + if (py_use_debug_operators ()) + { + struct value *result = py_perform_binop (arg1, arg2, op); + + if (result) + return result; + } + /* now we know that what we have to do is construct our arg vector and find the right function to call it with. */ @@ -517,6 +526,14 @@ value_x_unop (struct value *arg1, enum e arg1 = coerce_ref (arg1); + if (py_use_debug_operators ()) + { + struct value *result = py_perform_unop (arg1, op); + + if (result) + return result; + } + /* now we know that what we have to do is construct our arg vector and find the right function to call it with. */ Index: data-directory/Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/data-directory/Makefile.in,v retrieving revision 1.13 diff -u -p -r1.13 Makefile.in --- data-directory/Makefile.in 12 Nov 2012 17:41:56 -0000 1.13 +++ data-directory/Makefile.in 28 Nov 2012 14:04:16 -0000 @@ -56,11 +56,13 @@ PYTHON_FILES = \ gdb/types.py \ gdb/printing.py \ gdb/prompt.py \ + gdb/operator.py \ gdb/command/__init__.py \ gdb/command/type_printers.py \ gdb/command/pretty_printers.py \ gdb/command/prompt.py \ gdb/command/explore.py \ + gdb/command/debug-operator.py \ gdb/function/__init__.py \ gdb/function/strfns.py Index: python/py-operator.c =================================================================== RCS file: python/py-operator.c diff -N python/py-operator.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ python/py-operator.c 28 Nov 2012 14:04:16 -0000 @@ -0,0 +1,201 @@ +/* Implementation of the support for Python debug operators. + + Copyright (C) 2012 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 . */ + + +#include "defs.h" +#include "arch-utils.h" +#include "symtab.h" +#include "language.h" +#include "python-internal.h" +#include "python.h" +#include "expression.h" + +static PyObject *binop_executor = NULL; +static PyObject *unop_executor = NULL; + +#define OPCODE(code) { code, #code } + +struct py_opcode_desc +{ + enum exp_opcode opcode; + const char *name; +}; + +static struct py_opcode_desc py_opcodes[] = +{ + OPCODE (BINOP_ADD), /* + */ + OPCODE (BINOP_SUB), /* - */ + OPCODE (BINOP_MUL), /* * */ + OPCODE (BINOP_DIV), /* / */ + OPCODE (BINOP_REM), /* % */ + OPCODE (BINOP_MOD), /* mod (Knuth 1.2.4) */ + OPCODE (BINOP_LSH), /* << */ + OPCODE (BINOP_RSH), /* >> */ + OPCODE (BINOP_LOGICAL_AND), /* && */ + OPCODE (BINOP_LOGICAL_OR), /* || */ + OPCODE (BINOP_BITWISE_AND), /* & */ + OPCODE (BINOP_BITWISE_IOR), /* | */ + OPCODE (BINOP_BITWISE_XOR), /* ^ */ + OPCODE (BINOP_EQUAL), /* == */ + OPCODE (BINOP_NOTEQUAL), /* != */ + OPCODE (BINOP_LESS), /* < */ + OPCODE (BINOP_GTR), /* > */ + OPCODE (BINOP_LEQ), /* <= */ + OPCODE (BINOP_GEQ), /* >= */ + OPCODE (BINOP_REPEAT), /* @ */ + OPCODE (BINOP_ASSIGN), /* = */ + OPCODE (BINOP_COMMA), /* , */ + OPCODE (BINOP_SUBSCRIPT), /* x[y] */ + OPCODE (BINOP_EXP), /* Exponentiation */ + + OPCODE (UNOP_NEG), /* Unary - */ + OPCODE (UNOP_LOGICAL_NOT), /* Unary ! */ + OPCODE (UNOP_COMPLEMENT), /* Unary ~ */ + OPCODE (UNOP_IND), /* Unary * */ + OPCODE (UNOP_ADDR), /* Unary & */ + OPCODE (UNOP_PREINCREMENT), /* ++ before an expression */ + OPCODE (UNOP_POSTINCREMENT), /* ++ after an expression */ + OPCODE (UNOP_PREDECREMENT), /* -- before an expression */ + OPCODE (UNOP_POSTDECREMENT), /* -- after an expression */ + + { OP_NULL, NULL } /* Delimiter */ +}; + +PyObject * +gdbpy_enable_debug_operators (PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + PyObject *temp1, *temp2; + + if (PyArg_ParseTuple (args, "OO", &temp1, &temp2)) + { + if (!PyCallable_Check (temp1) || !PyCallable_Check (temp2)) + { + printf_filtered ("ERROR: Unable to use debug operators!\n"); + return NULL; + } + + Py_XINCREF (temp1); + Py_XINCREF (temp2); + + Py_XDECREF (binop_executor); + Py_XDECREF (unop_executor); + + binop_executor = temp1; + unop_executor = temp2; + + Py_INCREF (Py_None); + result = Py_None; + } + + return result; +} + +struct value * +py_perform_binop (struct value *opr1, struct value *opr2, enum exp_opcode op) +{ + struct value *res_value = NULL; + PyObject *opr1_obj = value_to_value_object (opr1); + PyObject *opr2_obj = value_to_value_object (opr2); + PyObject *res_obj, *arg_tuple; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + arg_tuple = Py_BuildValue ("(iOO)", op, opr1_obj, opr2_obj); + if (!arg_tuple) + { + printf_filtered ("ERROR: Python error internal to GDB.\n"); + Py_XDECREF (opr1_obj); + Py_XDECREF (opr2_obj); + do_cleanups (cleanup); + return NULL; + } + + res_obj = PyObject_Call (binop_executor, arg_tuple, NULL); + + Py_DECREF (arg_tuple); + Py_XDECREF (opr1_obj); + Py_XDECREF (opr2_obj); + + if (!PyObject_TypeCheck (res_obj, Py_None->ob_type)) + res_value = convert_value_from_python (res_obj); + + Py_DECREF (res_obj); + + do_cleanups (cleanup); + return res_value; +} + +struct value * +py_perform_unop (struct value *opr, enum exp_opcode op) +{ + struct value *res_value = NULL; + PyObject *opr_obj = value_to_value_object (opr); + PyObject *res_obj, *arg_tuple; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + arg_tuple = Py_BuildValue ("(iO)", op, opr_obj); + if (!arg_tuple) + { + printf_filtered ("ERROR: Python error internal to GDB.\n"); + Py_XDECREF (opr_obj); + do_cleanups (cleanup); + return NULL; + } + + res_obj = PyObject_Call (unop_executor, arg_tuple, NULL); + + Py_DECREF (arg_tuple); + Py_XDECREF (opr_obj); + + if (!PyObject_TypeCheck (res_obj, Py_None->ob_type)) + res_value = convert_value_from_python (res_obj); + + Py_DECREF (res_obj); + + do_cleanups (cleanup); + return res_value; +} + +void +gdbpy_initialize_debug_operators (void) +{ + int i; + + for (i = 0; py_opcodes[i].opcode != OP_NULL; ++i) + { + if (PyModule_AddIntConstant (gdb_module, + /* Cast needed for Python 2.4. */ + (char *) py_opcodes[i].name, + py_opcodes[i].opcode) < 0) + return; + } +} + +int +py_use_debug_operators (void) +{ + if (binop_executor) + return 1; + else + return 0; +} Index: python/python-internal.h =================================================================== RCS file: /cvs/src/src/gdb/python/python-internal.h,v retrieving revision 1.59 diff -u -p -r1.59 python-internal.h --- python/python-internal.h 13 Sep 2012 21:49:31 -0000 1.59 +++ python/python-internal.h 28 Nov 2012 14:04:16 -0000 @@ -203,6 +203,7 @@ PyObject *gdbpy_parameter_value (enum va char *gdbpy_parse_command_name (const char *name, struct cmd_list_element ***base_list, struct cmd_list_element **start_list); +PyObject *gdbpy_enable_debug_operators (PyObject *self, PyObject *args); PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); PyObject *symtab_to_symtab_object (struct symtab *symtab); @@ -262,6 +263,7 @@ void gdbpy_initialize_continue_event (vo void gdbpy_initialize_exited_event (void); void gdbpy_initialize_thread_event (void); void gdbpy_initialize_new_objfile_event (void); +void gdbpy_initialize_debug_operators (void); struct cleanup *make_cleanup_py_decref (PyObject *py); Index: python/python.c =================================================================== RCS file: /cvs/src/src/gdb/python/python.c,v retrieving revision 1.101 diff -u -p -r1.101 python.c --- python/python.c 12 Nov 2012 19:24:14 -0000 1.101 +++ python/python.c 28 Nov 2012 14:04:16 -0000 @@ -1571,6 +1571,8 @@ message == an error message without a st gdbpy_initialize_thread_event (); gdbpy_initialize_new_objfile_event () ; + gdbpy_initialize_debug_operators (); + observer_attach_before_prompt (before_prompt_hook); gdbpy_to_string_cst = PyString_FromString ("to_string"); @@ -1729,6 +1731,10 @@ The first element contains any unparsed (or None if the string was fully parsed). The second element contains\n\ a tuple that contains all the locations that match, represented as\n\ gdb.Symtab_and_line objects (or None)."}, + { "enable_debug_operators", gdbpy_enable_debug_operators, METH_VARARGS, + "enable_debug_operators (Function, Function). Enables debug oeprators\n\ +implemented in python registering a binary operator executor and a unary\n\ +operator executor. NOTE: This is an internal function!"}, { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, "parse_and_eval (String) -> Value.\n\ Parse String as an expression, evaluate it, and return the result as a Value." Index: python/python.h =================================================================== RCS file: /cvs/src/src/gdb/python/python.h,v retrieving revision 1.20 diff -u -p -r1.20 python.h --- python/python.h 12 Nov 2012 17:41:57 -0000 1.20 +++ python/python.h 28 Nov 2012 14:04:16 -0000 @@ -49,6 +49,13 @@ int gdbpy_should_stop (struct breakpoint int gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj); +int py_use_debug_operators (void); + +struct value *py_perform_binop (struct value *opr1, struct value *opr2, + enum exp_opcode op); + +struct value *py_perform_unop (struct value *opr, enum exp_opcode opcode); + void *start_type_printers (void); char *apply_type_printers (void *, struct type *type); Index: python/lib/gdb/operator.py =================================================================== RCS file: python/lib/gdb/operator.py diff -N python/lib/gdb/operator.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ python/lib/gdb/operator.py 28 Nov 2012 14:04:16 -0000 @@ -0,0 +1,101 @@ +# Support for debug operators in GDB. +# Copyright (C) 2012 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 . + +"""Debug operator API.""" + +import gdb +import re + +BINARY_OPCODE_TO_OPERATOR_MAP = { } +UNARY_OPCODE_TO_OPERATOR_MAP = { } + +def register_binop(opcode, opr1_matcher, opr2_matcher, function): + if opcode in BINARY_OPCODE_TO_OPERATOR_MAP: + BINARY_OPCODE_TO_OPERATOR_MAP[opcode].append((opr1_matcher, + opr2_matcher, + function)) + else: + BINARY_OPCODE_TO_OPERATOR_MAP[opcode] = [(opr1_matcher, + opr2_matcher, + function)] + +def register_unop(opcode, opr_matcher, function): + if opcode in UNARY_OPCODE_TO_OPERATOR_MAP: + UNARY_OPCODE_TO_OPERATOR_MAP[opcode].append((opr_matcher, + function)) + else: + UNARY_OPCODE_TO_OPERATOR_MAP[opcode] = [(opr_matcher, + function)] + +def _get_dynamic_value(opr): + if opr.type != opr.dynamic_type: + return opr.cast(opr.dynamic_type) + else: + return opr + +def _get_matching_binop_function(opr1_type, opr2_type, opcode_matcher_list): + for opr1_matcher, opr2_matcher, function in opcode_matcher_list: + if (re.match(opr1_matcher, str(opr1_type)) and + re.match(opr2_matcher, str(opr2_type))): + return function + +def _def_matching_unop_function(opr_type, opcode_matcher_list): + for opr_matcher, function in opcode_matcher_list: + if re.match(opr_matcher, str(opr_type)): + return function + +def _get_is_a_types(gdbtype): + is_a_types = [gdbtype] + typedefee = gdbtype.strip_typedefs() + if str(typedefee) != str(gdbtype): + is_a_types.append(typedefee) + if typedefee.code != gdb.TYPE_CODE_STRUCT: + return is_a_types + for field in typedefee.fields(): + if field.is_base_class: + is_a_types.extend(_get_is_a_types(field.type)) + return is_a_types + +def _execute_binop(opcode, opr1, opr2): + opr1 = _get_dynamic_value(opr1) + opr2 = _get_dynamic_value(opr2) + opcode_matcher_list = BINARY_OPCODE_TO_OPERATOR_MAP.get(opcode) + if not opcode_matcher_list: + return None + opr1_is_a_list = _get_is_a_types(opr1.type) + opr2_is_a_list = _get_is_a_types(opr2.type) + for opr1_type in opr1_is_a_list: + for opr2_type in opr2_is_a_list: + op_function = _get_matching_binop_function(opr1_type, opr2_type, + opcode_matcher_list) + if op_function: + return op_function(opr1.cast(opr1_type), opr2.cast(opr2_type)) + +def _execute_unop(opcode, opr): + opr = _get_dynamic_value(opr) + opcode_matcher_list = UNARY_OPCODE_TO_OPERATOR_MAP.get(opcode) + if not opcode_matcher_list: + return None + opr_is_a_list = _get_is_a_types(opr.type) + for opr_type in opr_is_a_list: + op_function = _get_matching_unop_function(opr_type, + opcode_matcher_list) + if op_function: + return op_function(opr.cast(opr_type)) + +def enable_debug_operators(): + gdb.enable_debug_operators(gdb.operator._execute_binop, + gdb.operator._execute_unop) Index: python/lib/gdb/command/debug-operator.py =================================================================== RCS file: python/lib/gdb/command/debug-operator.py diff -N python/lib/gdb/command/debug-operator.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ python/lib/gdb/command/debug-operator.py 28 Nov 2012 14:04:16 -0000 @@ -0,0 +1,31 @@ +# Type utilities. +# Copyright (C) 2010-2012 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 . + +"""Implementation of the command 'enable debug-operators'.""" + +import gdb +import gdb.operator + +class EnableDebugOperators(gdb.Command): + def __init__(self): + super(EnableDebugOperators, self).__init__("enable debug-operators", + gdb.COMMAND_SUPPORT) + + def invoke(self, arg, from_tty): + gdb.operator.enable_debug_operators() + + +EnableDebugOperators()