| |   |
| 259 | 259 | # |
| 260 | 260 | SUBDIR_PYTHON_OBS = \ |
| 261 | 261 | python.o \ |
| 262 | python-function.o \ |
| 262 | 263 | python-hooks.o \ |
| 263 | 264 | python-utils.o \ |
| 264 | 265 | python-value.o |
| 265 | 266 | SUBDIR_PYTHON_SRCS = \ |
| 266 | 267 | python/python.c \ |
| 268 | python/python-function.c \ |
| 267 | 269 | python/python-hooks.c \ |
| 268 | 270 | python/python-utils.c \ |
| 269 | 271 | python/python-value.c |
| … | … | |
| 2126 | 2126 | $(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \ |
| 2127 | 2127 | $(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \ |
| 2128 | 2128 | $(parser_defs_h) $(cp_support_h) $(gdb_assert_h) $(exceptions_h) \ |
| 2129 | | $(uiout_h) $(regcache_h) |
| 2129 | $(uiout_h) $(regcache_h) $(python_h) |
| 2130 | 2130 | event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \ |
| 2131 | 2131 | $(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h) |
| 2132 | 2132 | event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \ |
| … | … | |
| 3001 | 3001 | $(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \ |
| 3002 | 3002 | $(language_h) $(demangle_h) $(doublest_h) \ |
| 3003 | 3003 | $(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h) $(objfiles_h) \ |
| 3004 | | $(python_h) |
| 3004 | $(python_h) $(cli_decode_h) |
| 3005 | 3005 | varobj.o: varobj.c $(defs_h) $(exceptions_h) $(value_h) $(expression_h) \ |
| 3006 | 3006 | $(frame_h) $(language_h) $(wrapper_h) $(gdbcmd_h) $(block_h) \ |
| 3007 | 3007 | $(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h) $(gdbthread_h) \ |
| … | … | |
| 3431 | 3431 | $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \ |
| 3432 | 3432 | $(ui_out_h) $(target_h) $(gdbthread_h) |
| 3433 | 3433 | $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c |
| 3434 | python-function.o: $(srcdir)/python/python-function.c $(defs_h) $(python_h) \ |
| 3435 | $(python_internal_h) $(frame_h) $(exceptions_h) $(symtab_h) \ |
| 3436 | $(charset_h) $(stack_h) $(value_h) |
| 3437 | $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \ |
| 3438 | $(srcdir)/python/python-function.c -o python-function.o |
| 3434 | 3439 | python-hooks.o: $(srcdir)/python/python-hooks.c $(defs_h) $(cli_decode_h) \ |
| 3435 | 3440 | $(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h) \ |
| 3436 | 3441 | $(observer_h) |
| toggle raw diff |
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -259,11 +259,13 @@ SUBDIR_TUI_CFLAGS= \
#
SUBDIR_PYTHON_OBS = \
python.o \
+ python-function.o \
python-hooks.o \
python-utils.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
+ python/python-function.c \
python/python-hooks.c \
python/python-utils.c \
python/python-value.c
@@ -2124,7 +2126,7 @@ eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
$(parser_defs_h) $(cp_support_h) $(gdb_assert_h) $(exceptions_h) \
- $(uiout_h) $(regcache_h)
+ $(uiout_h) $(regcache_h) $(python_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@@ -2999,7 +3001,7 @@ value.o: value.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \
$(language_h) $(demangle_h) $(doublest_h) \
$(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h) $(objfiles_h) \
- $(python_h)
+ $(python_h) $(cli_decode_h)
varobj.o: varobj.c $(defs_h) $(exceptions_h) $(value_h) $(expression_h) \
$(frame_h) $(language_h) $(wrapper_h) $(gdbcmd_h) $(block_h) \
$(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h) $(gdbthread_h) \
@@ -3429,6 +3431,11 @@ python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
$(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
$(ui_out_h) $(target_h) $(gdbthread_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-function.o: $(srcdir)/python/python-function.c $(defs_h) $(python_h) \
+ $(python_internal_h) $(frame_h) $(exceptions_h) $(symtab_h) \
+ $(charset_h) $(stack_h) $(value_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/python-function.c -o python-function.o
python-hooks.o: $(srcdir)/python/python-hooks.c $(defs_h) $(cli_decode_h) \
$(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h) \
$(observer_h) |
| |   |
| 1 | /* gdb commands implemented in Python |
| 2 | |
| 3 | Copyright (C) 2008 Free Software Foundation, Inc. |
| 4 | |
| 5 | This file is part of GDB. |
| 6 | |
| 7 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 3 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 19 | |
| 20 | |
| 21 | #include "defs.h" |
| 22 | #include "value.h" |
| 23 | #include "exceptions.h" |
| 24 | #include "python-internal.h" |
| 25 | #include "charset.h" |
| 26 | #include "gdbcmd.h" |
| 27 | #include "cli/cli-decode.h" |
| 28 | #include "completer.h" |
| 29 | #include "expression.h" |
| 30 | |
| 31 | static PyTypeObject fnpy_object_type = |
| 32 | { |
| 33 | PyObject_HEAD_INIT (NULL) |
| 34 | 0, /*ob_size*/ |
| 35 | "gdb.Function", /*tp_name*/ |
| 36 | sizeof (PyObject), /*tp_basicsize*/ |
| 37 | 0, /*tp_itemsize*/ |
| 38 | 0, /*tp_dealloc*/ |
| 39 | 0, /*tp_print*/ |
| 40 | 0, /*tp_getattr*/ |
| 41 | 0, /*tp_setattr*/ |
| 42 | 0, /*tp_compare*/ |
| 43 | 0, /*tp_repr*/ |
| 44 | 0, /*tp_as_number*/ |
| 45 | 0, /*tp_as_sequence*/ |
| 46 | 0, /*tp_as_mapping*/ |
| 47 | 0, /*tp_hash */ |
| 48 | 0, /*tp_call*/ |
| 49 | 0, /*tp_str*/ |
| 50 | 0, /*tp_getattro*/ |
| 51 | 0, /*tp_setattro*/ |
| 52 | 0, /*tp_as_buffer*/ |
| 53 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ |
| 54 | "GDB function object", /* tp_doc */ |
| 55 | 0, /* tp_traverse */ |
| 56 | 0, /* tp_clear */ |
| 57 | 0, /* tp_richcompare */ |
| 58 | 0, /* tp_weaklistoffset */ |
| 59 | 0, /* tp_iter */ |
| 60 | 0, /* tp_iternext */ |
| 61 | 0 /* tp_methods */ |
| 62 | }; |
| 63 | |
| 64 | |
| 65 | |
| 66 | static PyObject * |
| 67 | convert_values_to_python (int argc, struct value **argv) |
| 68 | { |
| 69 | int i; |
| 70 | PyObject *result = PyTuple_New (argc); |
| 71 | for (i = 0; i < argc; ++i) |
| 72 | { |
| 73 | PyObject *elt = value_to_value_object (argv[i]); |
| 74 | if (! elt) |
| 75 | { |
| 76 | Py_DECREF (result); |
| 77 | error ("could not convert value to Python object"); |
| 78 | } |
| 79 | PyTuple_SetItem (result, i, elt); |
| 80 | } |
| 81 | return result; |
| 82 | } |
| 83 | |
| 84 | /* Call a Python function object's invoke method. */ |
| 85 | |
| 86 | static struct value * |
| 87 | fnpy_call (void *cookie, int argc, struct value **argv) |
| 88 | { |
| 89 | int i; |
| 90 | struct value *value; |
| 91 | PyObject *result, *callable, *args; |
| 92 | volatile struct gdb_exception except; |
| 93 | |
| 94 | args = convert_values_to_python (argc, argv); |
| 95 | |
| 96 | callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke"); |
| 97 | if (! callable) |
| 98 | { |
| 99 | Py_DECREF (args); |
| 100 | error ("no method named 'invoke' in object"); |
| 101 | } |
| 102 | |
| 103 | result = PyObject_Call (callable, args, NULL); |
| 104 | Py_DECREF (callable); |
| 105 | Py_DECREF (args); |
| 106 | |
| 107 | if (!result) |
| 108 | return NULL; |
| 109 | |
| 110 | TRY_CATCH (except, RETURN_MASK_ALL) |
| 111 | { |
| 112 | value = convert_value_from_python (result); |
| 113 | } |
| 114 | if (except.reason < 0) |
| 115 | { |
| 116 | Py_DECREF (result); |
| 117 | gdbpy_print_stack (); |
| 118 | throw_exception (except); |
| 119 | } |
| 120 | |
| 121 | Py_DECREF (result); |
| 122 | |
| 123 | return value; |
| 124 | } |
| 125 | |
| 126 | /* Called when destroying a struct internal_function. */ |
| 127 | |
| 128 | static void |
| 129 | fnpy_destroy (void *cookie) |
| 130 | { |
| 131 | Py_DECREF ((PyObject *) cookie); |
| 132 | } |
| 133 | |
| 134 | /* Initializer for a Function object. It takes one argument, the name |
| 135 | of the function. */ |
| 136 | |
| 137 | static int |
| 138 | fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) |
| 139 | { |
| 140 | char *name, *docstring = NULL; |
| 141 | if (! PyArg_ParseTuple (args, "s", &name)) |
| 142 | return -1; |
| 143 | Py_INCREF (self); |
| 144 | |
| 145 | if (PyObject_HasAttrString (self, "__doc__")) |
| 146 | { |
| 147 | PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__"); |
| 148 | if (ds_obj && PyString_Check (ds_obj)) |
| 149 | docstring = PyString_AsString (ds_obj); |
| 150 | } |
| 151 | if (! docstring) |
| 152 | docstring = "This command is not documented."; |
| 153 | |
| 154 | add_internal_function (name, docstring, fnpy_call, self, fnpy_destroy); |
| 155 | return 0; |
| 156 | } |
| 157 | |
| 158 | /* Initialize internal function support. */ |
| 159 | |
| 160 | void |
| 161 | gdbpy_initialize_functions (void) |
| 162 | { |
| 163 | fnpy_object_type.tp_new = PyType_GenericNew; |
| 164 | fnpy_object_type.tp_init = fnpy_init; |
| 165 | if (PyType_Ready (&fnpy_object_type) < 0) |
| 166 | return; |
| 167 | Py_INCREF (&fnpy_object_type); |
| 168 | PyModule_AddObject (gdb_module, "Function", (PyObject *) &fnpy_object_type); |
| 169 | } |
| toggle raw diff |
--- /dev/null
+++ b/gdb/python/python-function.c
@@ -0,0 +1,169 @@
+/* gdb commands implemented in Python
+
+ Copyright (C) 2008 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 "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "gdbcmd.h"
+#include "cli/cli-decode.h"
+#include "completer.h"
+#include "expression.h"
+
+static PyTypeObject fnpy_object_type =
+{
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Function", /*tp_name*/
+ sizeof (PyObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*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 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ "GDB function object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0 /* tp_methods */
+};
+
+
+
+static PyObject *
+convert_values_to_python (int argc, struct value **argv)
+{
+ int i;
+ PyObject *result = PyTuple_New (argc);
+ for (i = 0; i < argc; ++i)
+ {
+ PyObject *elt = value_to_value_object (argv[i]);
+ if (! elt)
+ {
+ Py_DECREF (result);
+ error ("could not convert value to Python object");
+ }
+ PyTuple_SetItem (result, i, elt);
+ }
+ return result;
+}
+
+/* Call a Python function object's invoke method. */
+
+static struct value *
+fnpy_call (void *cookie, int argc, struct value **argv)
+{
+ int i;
+ struct value *value;
+ PyObject *result, *callable, *args;
+ volatile struct gdb_exception except;
+
+ args = convert_values_to_python (argc, argv);
+
+ callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke");
+ if (! callable)
+ {
+ Py_DECREF (args);
+ error ("no method named 'invoke' in object");
+ }
+
+ result = PyObject_Call (callable, args, NULL);
+ Py_DECREF (callable);
+ Py_DECREF (args);
+
+ if (!result)
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ value = convert_value_from_python (result);
+ }
+ if (except.reason < 0)
+ {
+ Py_DECREF (result);
+ gdbpy_print_stack ();
+ throw_exception (except);
+ }
+
+ Py_DECREF (result);
+
+ return value;
+}
+
+/* Called when destroying a struct internal_function. */
+
+static void
+fnpy_destroy (void *cookie)
+{
+ Py_DECREF ((PyObject *) cookie);
+}
+
+/* Initializer for a Function object. It takes one argument, the name
+ of the function. */
+
+static int
+fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
+{
+ char *name, *docstring = NULL;
+ if (! PyArg_ParseTuple (args, "s", &name))
+ return -1;
+ Py_INCREF (self);
+
+ if (PyObject_HasAttrString (self, "__doc__"))
+ {
+ PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__");
+ if (ds_obj && PyString_Check (ds_obj))
+ docstring = PyString_AsString (ds_obj);
+ }
+ if (! docstring)
+ docstring = "This command is not documented.";
+
+ add_internal_function (name, docstring, fnpy_call, self, fnpy_destroy);
+ return 0;
+}
+
+/* Initialize internal function support. */
+
+void
+gdbpy_initialize_functions (void)
+{
+ fnpy_object_type.tp_new = PyType_GenericNew;
+ fnpy_object_type.tp_init = fnpy_init;
+ if (PyType_Ready (&fnpy_object_type) < 0)
+ return;
+ Py_INCREF (&fnpy_object_type);
+ PyModule_AddObject (gdb_module, "Function", (PyObject *) &fnpy_object_type);
+} |
| |   |
| 36 | 36 | #include "block.h" |
| 37 | 37 | #include "dfp.h" |
| 38 | 38 | #include "objfiles.h" |
| 39 | #include "cli/cli-decode.h" |
| 39 | 40 | |
| 40 | 41 | #include "python/python.h" |
| 41 | 42 | |
| … | … | |
| 44 | 44 | |
| 45 | 45 | void _initialize_values (void); |
| 46 | 46 | |
| 47 | /* Definition of a user function. */ |
| 48 | struct internal_function |
| 49 | { |
| 50 | /* The name of the function. It is a bit odd to have this in the |
| 51 | function itself -- the user might use a differently-named |
| 52 | convenience variable to hold the function. */ |
| 53 | char *name; |
| 54 | |
| 55 | /* The handler. */ |
| 56 | internal_function_fn handler; |
| 57 | |
| 58 | /* User data for the handler. */ |
| 59 | void *cookie; |
| 60 | |
| 61 | /* Function called to destroy the cookie when the function object is |
| 62 | destroyed. */ |
| 63 | void (*destroyer) (void *cookie); |
| 64 | }; |
| 65 | |
| 66 | static struct cmd_list_element *functionlist; |
| 67 | |
| 47 | 68 | struct value |
| 48 | 69 | { |
| 49 | 70 | /* Type of value; either not an lval, or one of the various |
| … | … | |
| 227 | 227 | static struct value_history_chunk *value_history_chain; |
| 228 | 228 | |
| 229 | 229 | static int value_history_count; /* Abs number of last entry stored */ |
| 230 | |
| 231 | /* The type of internal functions. */ |
| 232 | |
| 233 | static struct type *internal_fn_type; |
| 230 | 234 | |
| 231 | 235 | /* List of all value objects currently allocated |
| 232 | 236 | (except for those released by calls to release_value) |
| … | … | |
| 267 | 267 | return val; |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | /* Deallocate a value and run destructors if needed. */ |
| 271 | |
| 272 | void |
| 273 | value_free (struct value *value) |
| 274 | { |
| 275 | xfree (value); |
| 276 | } |
| 277 | |
| 270 | 278 | /* Allocate a value that has the correct length |
| 271 | 279 | for COUNT repetitions of type TYPE. */ |
| 272 | 280 | |
| … | … | |
| 808 | 808 | the return value is NULL. */ |
| 809 | 809 | |
| 810 | 810 | struct internalvar * |
| 811 | | lookup_only_internalvar (char *name) |
| 811 | lookup_only_internalvar (const char *name) |
| 812 | 812 | { |
| 813 | 813 | struct internalvar *var; |
| 814 | 814 | |
| … | … | |
| 824 | 824 | NAME should not normally include a dollar sign. */ |
| 825 | 825 | |
| 826 | 826 | struct internalvar * |
| 827 | | create_internalvar (char *name) |
| 827 | create_internalvar (const char *name) |
| 828 | 828 | { |
| 829 | 829 | struct internalvar *var; |
| 830 | 830 | var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); |
| … | … | |
| 845 | 845 | one is created, with a void value. */ |
| 846 | 846 | |
| 847 | 847 | struct internalvar * |
| 848 | | lookup_internalvar (char *name) |
| 848 | lookup_internalvar (const char *name) |
| 849 | 849 | { |
| 850 | 850 | struct internalvar *var; |
| 851 | 851 | |
| … | … | |
| 932 | 932 | |
| 933 | 933 | /* Begin code which must not call error(). If var->value points to |
| 934 | 934 | something free'd, an error() obviously leaves a dangling pointer. |
| 935 | | But we also get a danling pointer if var->value points to |
| 935 | But we also get a dangling pointer if var->value points to |
| 936 | 936 | something in the value chain (i.e., before release_value is |
| 937 | 937 | called), because after the error free_all_values will get called before |
| 938 | 938 | long. */ |
| … | … | |
| 949 | 949 | return var->name; |
| 950 | 950 | } |
| 951 | 951 | |
| 952 | static struct value * |
| 953 | value_create_internal_function (const char *name, |
| 954 | internal_function_fn handler, |
| 955 | void *cookie, |
| 956 | void (*destroyer) (void *)) |
| 957 | { |
| 958 | struct value *result = allocate_value (internal_fn_type); |
| 959 | gdb_byte *addr = value_contents_writeable (result); |
| 960 | struct internal_function **fnp = (struct internal_function **) addr; |
| 961 | /* The internal_function object is leaked here -- to make it truly |
| 962 | deletable, we would have to reference count it and add special |
| 963 | code to value_free and value_copy. The setup here is a bit odd |
| 964 | in general. It would be better to have a special case in |
| 965 | help_command. */ |
| 966 | struct internal_function *ifn = XNEW (struct internal_function); |
| 967 | ifn->name = xstrdup (name); |
| 968 | ifn->handler = handler; |
| 969 | ifn->cookie = cookie; |
| 970 | ifn->destroyer = destroyer; |
| 971 | *fnp = ifn; |
| 972 | return result; |
| 973 | } |
| 974 | |
| 975 | char * |
| 976 | value_internal_function_name (struct value *val) |
| 977 | { |
| 978 | gdb_byte *addr = value_contents_writeable (val); |
| 979 | struct internal_function *ifn = * (struct internal_function **) addr; |
| 980 | return ifn->name; |
| 981 | } |
| 982 | |
| 983 | struct value * |
| 984 | call_internal_function (struct value *func, int argc, struct value **argv) |
| 985 | { |
| 986 | gdb_byte *addr = value_contents_writeable (func); |
| 987 | struct internal_function *ifn = * (struct internal_function **) addr; |
| 988 | return (*ifn->handler) (ifn->cookie, argc, argv); |
| 989 | } |
| 990 | |
| 991 | /* The 'function' command. This does nothing -- it is just a |
| 992 | placeholder to let "help function NAME" work. This is also used as |
| 993 | the implementation of the sub-command that is created when |
| 994 | registering an internal function. */ |
| 995 | static void |
| 996 | function_command (char *command, int from_tty) |
| 997 | { |
| 998 | /* Do nothing. */ |
| 999 | } |
| 1000 | |
| 1001 | /* Clean up if an internal function's command is destroyed. */ |
| 1002 | static void |
| 1003 | function_destroyer (struct cmd_list_element *self, void *ignore) |
| 1004 | { |
| 1005 | xfree (self->name); |
| 1006 | xfree (self->doc); |
| 1007 | } |
| 1008 | |
| 1009 | /* Add a new internal function. NAME is the name of the function; DOC |
| 1010 | is a documentation string describing the function. HANDLER is |
| 1011 | called when the function is invoked. COOKIE is an arbitrary |
| 1012 | pointer which is passed to HANDLER and is intended for "user data". |
| 1013 | DESTROYER is invoked when the function is destroyed. */ |
| 1014 | void |
| 1015 | add_internal_function (const char *name, const char *doc, |
| 1016 | internal_function_fn handler, |
| 1017 | void *cookie, void (*destroyer) (void *)) |
| 1018 | { |
| 1019 | struct cmd_list_element *cmd; |
| 1020 | struct internalvar *var = lookup_internalvar (name); |
| 1021 | struct value *fnval = value_create_internal_function (name, handler, cookie, |
| 1022 | destroyer); |
| 1023 | release_value (fnval); |
| 1024 | set_internalvar (var, fnval); |
| 1025 | |
| 1026 | cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc, |
| 1027 | &functionlist); |
| 1028 | cmd->destroyer = function_destroyer; |
| 1029 | } |
| 1030 | |
| 952 | 1031 | /* Update VALUE before discarding OBJFILE. COPIED_TYPES is used to |
| 953 | 1032 | prevent cycles / duplicates. */ |
| 954 | 1033 | |
| … | … | |
| 1924 | 1924 | Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\ |
| 1925 | 1925 | exist or does not contain a value. The EXPRESSION is not evaluated if the\n\ |
| 1926 | 1926 | VARIABLE is already initialized.")); |
| 1927 | |
| 1928 | add_prefix_cmd ("function", no_class, function_command, _("\ |
| 1929 | Placeholder command for showing help on convenience functions."), |
| 1930 | &functionlist, "function ", 0, &cmdlist); |
| 1931 | |
| 1932 | internal_fn_type = alloc_type (NULL); |
| 1933 | TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION; |
| 1934 | TYPE_LENGTH (internal_fn_type) = sizeof (struct internal_function *); |
| 1935 | TYPE_NAME (internal_fn_type) = "<internal function>"; |
| 1927 | 1936 | } |
| toggle raw diff |
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -36,6 +36,7 @@
#include "block.h"
#include "dfp.h"
#include "objfiles.h"
+#include "cli/cli-decode.h"
#include "python/python.h"
@@ -43,6 +44,27 @@
void _initialize_values (void);
+/* Definition of a user function. */
+struct internal_function
+{
+ /* The name of the function. It is a bit odd to have this in the
+ function itself -- the user might use a differently-named
+ convenience variable to hold the function. */
+ char *name;
+
+ /* The handler. */
+ internal_function_fn handler;
+
+ /* User data for the handler. */
+ void *cookie;
+
+ /* Function called to destroy the cookie when the function object is
+ destroyed. */
+ void (*destroyer) (void *cookie);
+};
+
+static struct cmd_list_element *functionlist;
+
struct value
{
/* Type of value; either not an lval, or one of the various
@@ -205,6 +227,10 @@ struct value_history_chunk
static struct value_history_chunk *value_history_chain;
static int value_history_count; /* Abs number of last entry stored */
+
+/* The type of internal functions. */
+
+static struct type *internal_fn_type;
/* List of all value objects currently allocated
(except for those released by calls to release_value)
@@ -241,6 +267,14 @@ allocate_value (struct type *type)
return val;
}
+/* Deallocate a value and run destructors if needed. */
+
+void
+value_free (struct value *value)
+{
+ xfree (value);
+}
+
/* Allocate a value that has the correct length
for COUNT repetitions of type TYPE. */
@@ -774,7 +808,7 @@ init_if_undefined_command (char* args, int from_tty)
the return value is NULL. */
struct internalvar *
-lookup_only_internalvar (char *name)
+lookup_only_internalvar (const char *name)
{
struct internalvar *var;
@@ -790,7 +824,7 @@ lookup_only_internalvar (char *name)
NAME should not normally include a dollar sign. */
struct internalvar *
-create_internalvar (char *name)
+create_internalvar (const char *name)
{
struct internalvar *var;
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
@@ -811,7 +845,7 @@ create_internalvar (char *name)
one is created, with a void value. */
struct internalvar *
-lookup_internalvar (char *name)
+lookup_internalvar (const char *name)
{
struct internalvar *var;
@@ -898,7 +932,7 @@ set_internalvar (struct internalvar *var, struct value *val)
/* Begin code which must not call error(). If var->value points to
something free'd, an error() obviously leaves a dangling pointer.
- But we also get a danling pointer if var->value points to
+ But we also get a dangling pointer if var->value points to
something in the value chain (i.e., before release_value is
called), because after the error free_all_values will get called before
long. */
@@ -915,6 +949,85 @@ internalvar_name (struct internalvar *var)
return var->name;
}
+static struct value *
+value_create_internal_function (const char *name,
+ internal_function_fn handler,
+ void *cookie,
+ void (*destroyer) (void *))
+{
+ struct value *result = allocate_value (internal_fn_type);
+ gdb_byte *addr = value_contents_writeable (result);
+ struct internal_function **fnp = (struct internal_function **) addr;
+ /* The internal_function object is leaked here -- to make it truly
+ deletable, we would have to reference count it and add special
+ code to value_free and value_copy. The setup here is a bit odd
+ in general. It would be better to have a special case in
+ help_command. */
+ struct internal_function *ifn = XNEW (struct internal_function);
+ ifn->name = xstrdup (name);
+ ifn->handler = handler;
+ ifn->cookie = cookie;
+ ifn->destroyer = destroyer;
+ *fnp = ifn;
+ return result;
+}
+
+char *
+value_internal_function_name (struct value *val)
+{
+ gdb_byte *addr = value_contents_writeable (val);
+ struct internal_function *ifn = * (struct internal_function **) addr;
+ return ifn->name;
+}
+
+struct value *
+call_internal_function (struct value *func, int argc, struct value **argv)
+{
+ gdb_byte *addr = value_contents_writeable (func);
+ struct internal_function *ifn = * (struct internal_function **) addr;
+ return (*ifn->handler) (ifn->cookie, argc, argv);
+}
+
+/* The 'function' command. This does nothing -- it is just a
+ placeholder to let "help function NAME" work. This is also used as
+ the implementation of the sub-command that is created when
+ registering an internal function. */
+static void
+function_command (char *command, int from_tty)
+{
+ /* Do nothing. */
+}
+
+/* Clean up if an internal function's command is destroyed. */
+static void
+function_destroyer (struct cmd_list_element *self, void *ignore)
+{
+ xfree (self->name);
+ xfree (self->doc);
+}
+
+/* Add a new internal function. NAME is the name of the function; DOC
+ is a documentation string describing the function. HANDLER is
+ called when the function is invoked. COOKIE is an arbitrary
+ pointer which is passed to HANDLER and is intended for "user data".
+ DESTROYER is invoked when the function is destroyed. */
+void
+add_internal_function (const char *name, const char *doc,
+ internal_function_fn handler,
+ void *cookie, void (*destroyer) (void *))
+{
+ struct cmd_list_element *cmd;
+ struct internalvar *var = lookup_internalvar (name);
+ struct value *fnval = value_create_internal_function (name, handler, cookie,
+ destroyer);
+ release_value (fnval);
+ set_internalvar (var, fnval);
+
+ cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc,
+ &functionlist);
+ cmd->destroyer = function_destroyer;
+}
+
/* Update VALUE before discarding OBJFILE. COPIED_TYPES is used to
prevent cycles / duplicates. */
@@ -1811,4 +1924,13 @@ init-if-undefined VARIABLE = EXPRESSION\n\
Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\
exist or does not contain a value. The EXPRESSION is not evaluated if the\n\
VARIABLE is already initialized."));
+
+ add_prefix_cmd ("function", no_class, function_command, _("\
+Placeholder command for showing help on convenience functions."),
+ &functionlist, "function ", 0, &cmdlist);
+
+ internal_fn_type = alloc_type (NULL);
+ TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION;
+ TYPE_LENGTH (internal_fn_type) = sizeof (struct internal_function *);
+ TYPE_NAME (internal_fn_type) = "<internal function>";
} |
| |   |
| 457 | 457 | int bitpos, int bitsize, |
| 458 | 458 | struct value *newvalue); |
| 459 | 459 | |
| 460 | | extern struct internalvar *lookup_only_internalvar (char *name); |
| 460 | extern struct internalvar *lookup_only_internalvar (const char *name); |
| 461 | 461 | |
| 462 | | extern struct internalvar *create_internalvar (char *name); |
| 462 | extern struct internalvar *create_internalvar (const char *name); |
| 463 | 463 | |
| 464 | | extern struct internalvar *lookup_internalvar (char *name); |
| 464 | extern struct internalvar *lookup_internalvar (const char *name); |
| 465 | 465 | |
| 466 | 466 | extern int value_equal (struct value *arg1, struct value *arg2); |
| 467 | 467 | |
| … | … | |
| 491 | 491 | |
| 492 | 492 | extern int destructor_name_p (const char *name, const struct type *type); |
| 493 | 493 | |
| 494 | | #define value_free(val) xfree (val) |
| 494 | extern void value_free (struct value *value); |
| 495 | 495 | |
| 496 | 496 | extern void free_all_values (void); |
| 497 | 497 | |
| … | … | |
| 576 | 576 | extern struct value *value_of_local (const char *name, int complain); |
| 577 | 577 | |
| 578 | 578 | extern struct value * value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound); |
| 579 | |
| 580 | /* User function handler. */ |
| 581 | |
| 582 | typedef struct value *(*internal_function_fn) (void *cookie, |
| 583 | int argc, |
| 584 | struct value **argv); |
| 585 | |
| 586 | void add_internal_function (const char *name, const char *doc, |
| 587 | internal_function_fn handler, |
| 588 | void *cookie, void (*destroyer) (void *)); |
| 589 | |
| 590 | struct value *call_internal_function (struct value *function, |
| 591 | int argc, struct value **argv); |
| 592 | |
| 593 | char *value_internal_function_name (struct value *); |
| 594 | |
| 579 | 595 | #endif /* !defined (VALUE_H) */ |
| toggle raw diff |
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -457,11 +457,11 @@ extern void set_internalvar_component (struct internalvar *var,
int bitpos, int bitsize,
struct value *newvalue);
-extern struct internalvar *lookup_only_internalvar (char *name);
+extern struct internalvar *lookup_only_internalvar (const char *name);
-extern struct internalvar *create_internalvar (char *name);
+extern struct internalvar *create_internalvar (const char *name);
-extern struct internalvar *lookup_internalvar (char *name);
+extern struct internalvar *lookup_internalvar (const char *name);
extern int value_equal (struct value *arg1, struct value *arg2);
@@ -491,7 +491,7 @@ extern int unop_user_defined_p (enum exp_opcode op, struct value *arg1);
extern int destructor_name_p (const char *name, const struct type *type);
-#define value_free(val) xfree (val)
+extern void value_free (struct value *value);
extern void free_all_values (void);
@@ -576,4 +576,20 @@ extern struct value *value_allocate_space_in_inferior (int);
extern struct value *value_of_local (const char *name, int complain);
extern struct value * value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound);
+
+/* User function handler. */
+
+typedef struct value *(*internal_function_fn) (void *cookie,
+ int argc,
+ struct value **argv);
+
+void add_internal_function (const char *name, const char *doc,
+ internal_function_fn handler,
+ void *cookie, void (*destroyer) (void *));
+
+struct value *call_internal_function (struct value *function,
+ int argc, struct value **argv);
+
+char *value_internal_function_name (struct value *);
+
#endif /* !defined (VALUE_H) */ |