aboutsummaryrefslogtreecommitdiff
path: root/gdb/value.c
diff options
context:
space:
mode:
authorThiago Jung Bauermann <bauerman@br.ibm.com>2009-03-21 03:03:56 +0000
committerThiago Jung Bauermann <bauerman@br.ibm.com>2009-03-21 03:03:56 +0000
commitbc3b79fd1ac12e5432ef017d81064427d04a2d71 (patch)
tree2ebe34d96ed81c86dd3fef2a0944a4712dbc8357 /gdb/value.c
parentc6dd29cec2aa072966e6ebccc56db0c5dbf636ee (diff)
downloadgdb-bc3b79fd1ac12e5432ef017d81064427d04a2d71.zip
gdb-bc3b79fd1ac12e5432ef017d81064427d04a2d71.tar.gz
gdb-bc3b79fd1ac12e5432ef017d81064427d04a2d71.tar.bz2
gdb/
2009-03-05 Tom Tromey <tromey@redhat.com> Add support for convenience functions in Python. * Makefile.in (SUBDIR_PYTHON_OBS): Add python-function.o. (SUBDIR_PYTHON_SRCS): Add python-function.c. (python-function.o): New target. * eval.c: Include "python/python.h" and <ctype.h>. (evaluate_subexp_standard): Handle values of type TYPE_CODE_INTERNAL_FUNCTION. * gdbtypes.h (type_code): Add TYPE_CODE_INTERNAL_FUNCTION. * parse.c (write_exp_string): Remove duplicate word in comment. * python/python-function.c: New file. * python/python-internal.h (gdbpy_initialize_functions): Add prototype. * python/python.c (_initialize_python): Call gdbpy_initialize_functions. * valprint.c (value_check_printable): Handle values of type TYPE_CODE_INTERNAL_FUNCTION. * value.c: Include "cli/cli-decode.h". (internal_function): New struct. (functionlist, internal_fn_type): New static variables. (lookup_only_internalvar, lookup_internalvar): Add const qualifier to name argument. (create_internalvar): Likewise. Initialize new field. (set_internal_var): Fix typo in comment. Don't allow assignment to canonical variable. (value_create_internal_function, value_internal_function_name, call_internal_function, function_command, function_destroyer, add_internal_function): New functions. (_initialize_values): Create `function' placeholder command. Initialize internal_fn_type. * value.h (lookup_only_internalvar, create_internalvar, lookup_internalvar): Add const qualifier to name argument. (internal_function_fn, add_internal_function, call_internal_function, value_internal_function_name): Add prototypes. (struct internalvar) <canonical>: New field. gdb/doc/ 2008-03-05 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Convenience Vars): Document convenience functions. (Functions In Python): New node. (Python API): Update. gdb/testsuite/ 2009-03-05 Thiago Jung Bauermann <bauerman@br.ibm.com> * gdb.python/python-function.exp: New file.
Diffstat (limited to 'gdb/value.c')
-rw-r--r--gdb/value.c113
1 files changed, 109 insertions, 4 deletions
diff --git a/gdb/value.c b/gdb/value.c
index 4d4329e..9c08a41 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -37,6 +37,7 @@
#include "dfp.h"
#include "objfiles.h"
#include "valprint.h"
+#include "cli/cli-decode.h"
#include "python/python.h"
@@ -44,6 +45,23 @@
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;
+};
+
+static struct cmd_list_element *functionlist;
+
struct value
{
/* Type of value; either not an lval, or one of the various
@@ -203,6 +221,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)
@@ -878,7 +900,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;
@@ -894,7 +916,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));
@@ -902,6 +924,7 @@ create_internalvar (char *name)
var->value = allocate_value (builtin_type_void);
var->endian = gdbarch_byte_order (current_gdbarch);
var->make_value = NULL;
+ var->canonical = 0;
release_value (var->value);
var->next = internalvars;
internalvars = var;
@@ -934,7 +957,7 @@ create_internalvar_type_lazy (char *name, internalvar_make_value fun)
one is created, with a void value. */
struct internalvar *
-lookup_internalvar (char *name)
+lookup_internalvar (const char *name)
{
struct internalvar *var;
@@ -1031,6 +1054,9 @@ set_internalvar (struct internalvar *var, struct value *val)
{
struct value *newval;
+ if (var->canonical)
+ error (_("Cannot overwrite convenience function %s"), var->name);
+
newval = value_copy (val);
newval->modifiable = 1;
@@ -1042,7 +1068,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. */
@@ -1059,6 +1085,76 @@ internalvar_name (struct internalvar *var)
return var->name;
}
+static struct value *
+value_create_internal_function (const char *name,
+ internal_function_fn handler,
+ void *cookie)
+{
+ struct value *result = allocate_value (internal_fn_type);
+ gdb_byte *addr = value_contents_writeable (result);
+ struct internal_function **fnp = (struct internal_function **) addr;
+ struct internal_function *ifn = XNEW (struct internal_function);
+ ifn->name = xstrdup (name);
+ ifn->handler = handler;
+ ifn->cookie = cookie;
+ *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". */
+void
+add_internal_function (const char *name, const char *doc,
+ internal_function_fn handler, void *cookie)
+{
+ struct cmd_list_element *cmd;
+ struct internalvar *var = lookup_internalvar (name);
+ struct value *fnval = value_create_internal_function (name, handler, cookie);
+ set_internalvar (var, fnval);
+ var->canonical = 1;
+
+ 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. */
@@ -1944,4 +2040,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>";
}