Share regcache function regcache_raw_read_unsigned
[deliverable/binutils-gdb.git] / gdb / extension.c
index 4392dec225046247bb7d56ae64c99c3f50957ddf..1b5365a1d66d65be565fb5e8a71f0cfcf0256235 100644 (file)
@@ -1,6 +1,6 @@
 /* Interface between gdb and its extension languages.
 
-   Copyright (C) 2013 Free Software Foundation, Inc.
+   Copyright (C) 2014-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -30,6 +30,7 @@
 #include "observer.h"
 #include "cli/cli-script.h"
 #include "python/python.h"
+#include "guile/guile.h"
 
 /* Iterate over all external extension languages, regardless of whether the
    support has been compiled in or not.
@@ -60,6 +61,7 @@ static const struct extension_language_script_ops
 {
   source_gdb_script,
   source_gdb_objfile_script,
+  NULL, /* objfile_script_executor */
   auto_load_gdb_scripts_enabled
 };
 
@@ -100,6 +102,7 @@ static const struct extension_language_defn * const extension_languages[] =
 {
   /* To preserve existing behaviour, python should always appear first.  */
   &extension_language_python,
+  &extension_language_guile,
   NULL
 };
 
@@ -284,6 +287,21 @@ ext_lang_objfile_script_sourcer (const struct extension_language_defn *extlang)
   return extlang->script_ops->objfile_script_sourcer;
 }
 
+/* Return the objfile script "executor" function for EXTLANG.
+   This is the function that executes a script for a particular objfile.
+   If support for this language isn't compiled in, NULL is returned.
+   The extension language is not required to implement this function.  */
+
+objfile_script_executor_func *
+ext_lang_objfile_script_executor
+  (const struct extension_language_defn *extlang)
+{
+  if (extlang->script_ops == NULL)
+    return NULL;
+
+  return extlang->script_ops->objfile_script_executor;
+}
+
 /* Return non-zero if auto-loading of EXTLANG scripts is enabled.
    Zero is returned if support for this language isn't compiled in.  */
 
@@ -340,7 +358,8 @@ eval_ext_lang_from_control_command (struct command_line *cmd)
     {
       if (extlang->cli_control_type == cmd->control_type)
        {
-         if (extlang->ops->eval_from_control_command != NULL)
+         if (extlang->ops != NULL
+             && extlang->ops->eval_from_control_command != NULL)
            {
              extlang->ops->eval_from_control_command (extlang, cmd);
              return;
@@ -688,7 +707,7 @@ static void
 install_gdb_sigint_handler (struct signal_handler *previous)
 {
   /* Save here to simplify comparison.  */
-  RETSIGTYPE (*handle_sigint_for_compare) () = handle_sigint;
+  sighandler_t handle_sigint_for_compare = handle_sigint;
 
   previous->handler = signal (SIGINT, handle_sigint);
   if (previous->handler != handle_sigint_for_compare)
@@ -831,6 +850,185 @@ check_quit_flag (void)
   return result;
 }
 \f
+/* xmethod support.  */
+
+/* The xmethod API routines do not have "ext_lang" in the name because
+   the name "xmethod" implies that this routine deals with extension
+   languages.  Plus some of the methods take a xmethod_foo * "self/this"
+   arg, not an extension_language_defn * arg.  */
+
+/* Returns a new xmethod_worker with EXTLANG and DATA.  Space for the
+   result must be freed with free_xmethod_worker.  */
+
+struct xmethod_worker *
+new_xmethod_worker (const struct extension_language_defn *extlang, void *data)
+{
+  struct xmethod_worker *worker = XCNEW (struct xmethod_worker);
+
+  worker->extlang = extlang;
+  worker->data = data;
+  worker->value = NULL;
+
+  return worker;
+}
+
+/* Clones WORKER and returns a new but identical worker.
+   The function get_matching_xmethod_workers (see below), returns a
+   vector of matching workers.  If a particular worker is selected by GDB
+   to invoke a method, then this function can help in cloning the
+   selected worker and freeing up the vector via a cleanup.
+
+   Space for the result must be freed with free_xmethod_worker.  */
+
+struct xmethod_worker *
+clone_xmethod_worker (struct xmethod_worker *worker)
+{
+  struct xmethod_worker *new_worker;
+  const struct extension_language_defn *extlang = worker->extlang;
+
+  gdb_assert (extlang->ops->clone_xmethod_worker_data != NULL);
+
+  new_worker = new_xmethod_worker
+    (extlang,
+     extlang->ops->clone_xmethod_worker_data (extlang, worker->data));
+
+  return new_worker;
+}
+
+/* If a method with name METHOD_NAME is to be invoked on an object of type
+   TYPE, then all entension languages are searched for implementations of
+   methods with name METHOD.  All matches found are returned as a vector
+   of 'xmethod_worker_ptr' objects.  If no matching methods are
+   found, NULL is returned.  */
+
+VEC (xmethod_worker_ptr) *
+get_matching_xmethod_workers (struct type *type, const char *method_name)
+{
+  VEC (xmethod_worker_ptr) *workers = NULL;
+  int i;
+  const struct extension_language_defn *extlang;
+
+  ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
+    {
+      VEC (xmethod_worker_ptr) *lang_workers, *new_vec;
+      enum ext_lang_rc rc;
+
+      /* If an extension language does not support xmethods, ignore
+        it.  */
+      if (extlang->ops->get_matching_xmethod_workers == NULL)
+       continue;
+
+      rc = extlang->ops->get_matching_xmethod_workers (extlang,
+                                                      type, method_name,
+                                                      &lang_workers);
+      if (rc == EXT_LANG_RC_ERROR)
+       {
+         free_xmethod_worker_vec (workers);
+         error (_("Error while looking for matching xmethod workers "
+                  "defined in %s."), extlang->capitalized_name);
+       }
+
+      new_vec = VEC_merge (xmethod_worker_ptr, workers, lang_workers);
+      /* Free only the vectors and not the elements as NEW_VEC still
+        contains them.  */
+      VEC_free (xmethod_worker_ptr, workers);
+      VEC_free (xmethod_worker_ptr, lang_workers);
+      workers = new_vec;
+    }
+
+  return workers;
+}
+
+/* Return the arg types of the xmethod encapsulated in WORKER.
+   An array of arg types is returned.  The length of the array is returned in
+   NARGS.  The type of the 'this' object is returned as the first element of
+   array.  */
+
+struct type **
+get_xmethod_arg_types (struct xmethod_worker *worker, int *nargs)
+{
+  enum ext_lang_rc rc;
+  struct type **type_array = NULL;
+  const struct extension_language_defn *extlang = worker->extlang;
+
+  gdb_assert (extlang->ops->get_xmethod_arg_types != NULL);
+
+  rc = extlang->ops->get_xmethod_arg_types (extlang, worker, nargs,
+                                           &type_array);
+  if (rc == EXT_LANG_RC_ERROR)
+    {
+      error (_("Error while looking for arg types of a xmethod worker "
+              "defined in %s."), extlang->capitalized_name);
+    }
+
+  return type_array;
+}
+
+/* Return the type of the result of the xmethod encapsulated in WORKER.
+   OBJECT, ARGS, NARGS are the same as for invoke_xmethod.  */
+
+struct type *
+get_xmethod_result_type (struct xmethod_worker *worker,
+                        struct value *object, struct value **args, int nargs)
+{
+  enum ext_lang_rc rc;
+  struct type *result_type;
+  const struct extension_language_defn *extlang = worker->extlang;
+
+  gdb_assert (extlang->ops->get_xmethod_arg_types != NULL);
+
+  rc = extlang->ops->get_xmethod_result_type (extlang, worker,
+                                             object, args, nargs,
+                                             &result_type);
+  if (rc == EXT_LANG_RC_ERROR)
+    {
+      error (_("Error while fetching result type of an xmethod worker "
+              "defined in %s."), extlang->capitalized_name);
+    }
+
+  return result_type;
+}
+
+/* Invokes the xmethod encapsulated in WORKER and returns the result.
+   The method is invoked on OBJ with arguments in the ARGS array.  NARGS is
+   the length of the this array.  */
+
+struct value *
+invoke_xmethod (struct xmethod_worker *worker, struct value *obj,
+                    struct value **args, int nargs)
+{
+  gdb_assert (worker->extlang->ops->invoke_xmethod != NULL);
+
+  return worker->extlang->ops->invoke_xmethod (worker->extlang, worker,
+                                              obj, args, nargs);
+}
+
+/* Frees the xmethod worker WORKER.  */
+
+void
+free_xmethod_worker (struct xmethod_worker *worker)
+{
+  gdb_assert (worker->extlang->ops->free_xmethod_worker_data != NULL);
+  worker->extlang->ops->free_xmethod_worker_data (worker->extlang,
+                                                 worker->data);
+  xfree (worker);
+}
+
+/* Frees a vector of xmethod_workers VEC.  */
+
+void
+free_xmethod_worker_vec (void *vec)
+{
+  int i;
+  struct xmethod_worker *worker;
+  VEC (xmethod_worker_ptr) *v = (VEC (xmethod_worker_ptr) *) vec;
+
+  for (i = 0; VEC_iterate (xmethod_worker_ptr, v, i, worker); i++)
+    free_xmethod_worker (worker);
+
+  VEC_free (xmethod_worker_ptr, v);
+}
+\f
 /* Called via an observer before gdb prints its prompt.
    Iterate over the extension languages giving them a chance to
    change the prompt.  The first one to change the prompt wins,
This page took 0.026768 seconds and 4 git commands to generate.