- /* Interface between gdb and its extension languages.
- Copyright (C) 2014-2015 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/>. */
- /* Note: With few exceptions, external functions and variables in this file
- have "ext_lang" in the name, and no other symbol in gdb does. */
- #include "defs.h"
- #include <signal.h>
- #include "auto-load.h"
- #include "breakpoint.h"
- #include "event-top.h"
- #include "extension.h"
- #include "extension-priv.h"
- #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.
- This does not include GDB's own scripting language. */
- #define ALL_EXTENSION_LANGUAGES(i, extlang) \
- for (/*int*/ i = 0, extlang = extension_languages[0]; \
- extlang != NULL; \
- extlang = extension_languages[++i])
- /* Iterate over all external extension languages that are supported.
- This does not include GDB's own scripting language. */
- #define ALL_ENABLED_EXTENSION_LANGUAGES(i, extlang) \
- for (/*int*/ i = 0, extlang = extension_languages[0]; \
- extlang != NULL; \
- extlang = extension_languages[++i]) \
- if (extlang->ops != NULL)
- static script_sourcer_func source_gdb_script;
- static objfile_script_sourcer_func source_gdb_objfile_script;
- /* GDB's own scripting language.
- This exists, in part, to support auto-loading ${prog}-gdb.gdb scripts. */
- static const struct extension_language_script_ops
- extension_language_gdb_script_ops =
- {
- source_gdb_script,
- source_gdb_objfile_script,
- auto_load_gdb_scripts_enabled
- };
- const struct extension_language_defn extension_language_gdb =
- {
- EXT_LANG_GDB,
- "gdb",
- "GDB",
- /* We fall back to interpreting a script as a GDB script if it doesn't
- match the other scripting languages, but for consistency's sake
- give it a formal suffix. */
- ".gdb",
- "-gdb.gdb",
- /* cli_control_type: This is never used: GDB's own scripting language
- has a variety of control types (if, while, etc.). */
- commands_control,
- &extension_language_gdb_script_ops,
- /* The rest of the extension language interface isn't supported by GDB's own
- extension/scripting language. */
- NULL
- };
- /* NULL-terminated table of all external (non-native) extension languages.
- The order of appearance in the table is important.
- When multiple extension languages provide the same feature, for example
- a pretty-printer for a particular type, which one gets used?
- The algorithm employed here is "the first one wins". For example, in
- the case of pretty-printers this means the first one to provide a
- pretty-printed value is the one that is used. This algorithm is employed
- throughout. */
- 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
- };
- /* Return a pointer to the struct extension_language_defn object of
- extension language LANG.
- This always returns a non-NULL pointer, even if support for the language
- is not compiled into this copy of GDB. */
- const struct extension_language_defn *
- get_ext_lang_defn (enum extension_language lang)
- {
- int i;
- const struct extension_language_defn *extlang;
- gdb_assert (lang != EXT_LANG_NONE);
- if (lang == EXT_LANG_GDB)
- return &extension_language_gdb;
- ALL_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->language == lang)
- return extlang;
- }
- gdb_assert_not_reached ("unable to find extension_language_defn");
- }
- /* Return TRUE if FILE has extension EXTENSION. */
- static int
- has_extension (const char *file, const char *extension)
- {
- int file_len = strlen (file);
- int extension_len = strlen (extension);
- return (file_len > extension_len
- && strcmp (&file[file_len - extension_len], extension) == 0);
- }
- /* Return the extension language of FILE, or NULL if
- the extension language of FILE is not recognized.
- This is done by looking at the file's suffix. */
- const struct extension_language_defn *
- get_ext_lang_of_file (const char *file)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_EXTENSION_LANGUAGES (i, extlang)
- {
- if (has_extension (file, extlang->suffix))
- return extlang;
- }
- return NULL;
- }
- /* Return non-zero if support for the specified extension language
- is compiled in. */
- int
- ext_lang_present_p (const struct extension_language_defn *extlang)
- {
- return extlang->script_ops != NULL;
- }
- /* Return non-zero if the specified extension language has successfully
- initialized. */
- int
- ext_lang_initialized_p (const struct extension_language_defn *extlang)
- {
- if (extlang->ops != NULL)
- {
- /* This method is required. */
- gdb_assert (extlang->ops->initialized != NULL);
- return extlang->ops->initialized (extlang);
- }
- return 0;
- }
- /* Throw an error indicating EXTLANG is not supported in this copy of GDB. */
- void
- throw_ext_lang_unsupported (const struct extension_language_defn *extlang)
- {
- error (_("Scripting in the \"%s\" language is not supported"
- " in this copy of GDB."),
- ext_lang_capitalized_name (extlang));
- }
- /* Methods for GDB's own extension/scripting language. */
- /* The extension_language_script_ops.script_sourcer "method". */
- static void
- source_gdb_script (const struct extension_language_defn *extlang,
- FILE *stream, const char *file)
- {
- script_from_file (stream, file);
- }
- /* The extension_language_script_ops.objfile_script_sourcer "method". */
- static void
- source_gdb_objfile_script (const struct extension_language_defn *extlang,
- struct objfile *objfile,
- FILE *stream, const char *file)
- {
- script_from_file (stream, file);
- }
- /* Accessors for "public" attributes of struct extension_language. */
- /* Return the "name" field of EXTLANG. */
- const char *
- ext_lang_name (const struct extension_language_defn *extlang)
- {
- return extlang->name;
- }
- /* Return the "capitalized_name" field of EXTLANG. */
- const char *
- ext_lang_capitalized_name (const struct extension_language_defn *extlang)
- {
- return extlang->capitalized_name;
- }
- /* Return the "suffix" field of EXTLANG. */
- const char *
- ext_lang_suffix (const struct extension_language_defn *extlang)
- {
- return extlang->suffix;
- }
- /* Return the "auto_load_suffix" field of EXTLANG. */
- const char *
- ext_lang_auto_load_suffix (const struct extension_language_defn *extlang)
- {
- return extlang->auto_load_suffix;
- }
- /* extension_language_script_ops wrappers. */
- /* Return the script "sourcer" function for EXTLANG.
- This is the function that loads and processes a script.
- If support for this language isn't compiled in, NULL is returned. */
- script_sourcer_func *
- ext_lang_script_sourcer (const struct extension_language_defn *extlang)
- {
- if (extlang->script_ops == NULL)
- return NULL;
- /* The extension language is required to implement this function. */
- gdb_assert (extlang->script_ops->script_sourcer != NULL);
- return extlang->script_ops->script_sourcer;
- }
- /* Return the objfile script "sourcer" function for EXTLANG.
- This is the function that loads and processes a script for a particular
- objfile.
- If support for this language isn't compiled in, NULL is returned. */
- objfile_script_sourcer_func *
- ext_lang_objfile_script_sourcer (const struct extension_language_defn *extlang)
- {
- if (extlang->script_ops == NULL)
- return NULL;
- /* The extension language is required to implement this function. */
- gdb_assert (extlang->script_ops->objfile_script_sourcer != NULL);
- return extlang->script_ops->objfile_script_sourcer;
- }
- /* Return non-zero if auto-loading of EXTLANG scripts is enabled.
- Zero is returned if support for this language isn't compiled in. */
- int
- ext_lang_auto_load_enabled (const struct extension_language_defn *extlang)
- {
- if (extlang->script_ops == NULL)
- return 0;
- /* The extension language is required to implement this function. */
- gdb_assert (extlang->script_ops->auto_load_enabled != NULL);
- return extlang->script_ops->auto_load_enabled (extlang);
- }
- /* Functions that iterate over all extension languages.
- These only iterate over external extension languages, not including
- GDB's own extension/scripting language, unless otherwise indicated. */
- /* Wrapper to call the extension_language_ops.finish_initialization "method"
- for each compiled-in extension language. */
- void
- finish_ext_lang_initialization (void)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->ops->finish_initialization != NULL)
- extlang->ops->finish_initialization (extlang);
- }
- }
- /* Invoke the appropriate extension_language_ops.eval_from_control_command
- method to perform CMD, which is a list of commands in an extension language.
- This function is what implements, for example:
- python
- print 42
- end
- in a GDB script. */
- void
- eval_ext_lang_from_control_command (struct command_line *cmd)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->cli_control_type == cmd->control_type)
- {
- if (extlang->ops != NULL
- && extlang->ops->eval_from_control_command != NULL)
- {
- extlang->ops->eval_from_control_command (extlang, cmd);
- return;
- }
- /* The requested extension language is not supported in this GDB. */
- throw_ext_lang_unsupported (extlang);
- }
- }
- gdb_assert_not_reached ("unknown extension language in command_line");
- }
- /* Search for and load scripts for OBJFILE written in extension languages.
- This includes GDB's own scripting language.
- This function is what implements the loading of OBJFILE-gdb.py and
- OBJFILE-gdb.gdb. */
- void
- auto_load_ext_lang_scripts_for_objfile (struct objfile *objfile)
- {
- int i;
- const struct extension_language_defn *extlang;
- extlang = &extension_language_gdb;
- if (ext_lang_auto_load_enabled (extlang))
- auto_load_objfile_script (objfile, extlang);
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (ext_lang_auto_load_enabled (extlang))
- auto_load_objfile_script (objfile, extlang);
- }
- }
- /* Interface to type pretty-printers implemented in an extension language. */
- /* Call this at the start when preparing to pretty-print a type.
- The result is a pointer to an opaque object (to the caller) to be passed
- to apply_ext_lang_type_printers and free_ext_lang_type_printers.
- We don't know in advance which extension language will provide a
- pretty-printer for the type, so all are initialized. */
- struct ext_lang_type_printers *
- start_ext_lang_type_printers (void)
- {
- struct ext_lang_type_printers *printers
- = XCNEW (struct ext_lang_type_printers);
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->ops->start_type_printers != NULL)
- extlang->ops->start_type_printers (extlang, printers);
- }
- return printers;
- }
- /* Iteratively try the type pretty-printers specified by PRINTERS
- according to the standard search order (specified by extension_languages),
- returning the result of the first one that succeeds.
- If there was an error, or if no printer succeeds, then NULL is returned. */
- char *
- apply_ext_lang_type_printers (struct ext_lang_type_printers *printers,
- struct type *type)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- char *result = NULL;
- enum ext_lang_rc rc;
- if (extlang->ops->apply_type_printers == NULL)
- continue;
- rc = extlang->ops->apply_type_printers (extlang, printers, type,
- &result);
- switch (rc)
- {
- case EXT_LANG_RC_OK:
- gdb_assert (result != NULL);
- return result;
- case EXT_LANG_RC_ERROR:
- return NULL;
- case EXT_LANG_RC_NOP:
- break;
- default:
- gdb_assert_not_reached ("bad return from apply_type_printers");
- }
- }
- return NULL;
- }
- /* Call this after pretty-printing a type to release all memory held
- by PRINTERS. */
- void
- free_ext_lang_type_printers (struct ext_lang_type_printers *printers)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->ops->free_type_printers != NULL)
- extlang->ops->free_type_printers (extlang, printers);
- }
- xfree (printers);
- }
- /* Try to pretty-print a value of type TYPE located at VALADDR
- + EMBEDDED_OFFSET, which came from the inferior at address ADDRESS
- + EMBEDDED_OFFSET, onto stdio stream STREAM according to OPTIONS.
- VAL is the whole object that came from ADDRESS. VALADDR must point to
- the head of VAL's contents buffer.
- Returns non-zero if the value was successfully pretty-printed.
- Extension languages are tried in the order specified by
- extension_languages. The first one to provide a pretty-printed
- value "wins".
- If an error is encountered in a pretty-printer, no further extension
- languages are tried.
- Note: This is different than encountering a memory error trying to read a
- value for pretty-printing. Here we're referring to, e.g., programming
- errors that trigger an exception in the extension language. */
- int
- apply_ext_lang_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
- int embedded_offset, CORE_ADDR address,
- struct ui_file *stream, int recurse,
- const struct value *val,
- const struct value_print_options *options,
- const struct language_defn *language)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- enum ext_lang_rc rc;
- if (extlang->ops->apply_val_pretty_printer == NULL)
- continue;
- rc = extlang->ops->apply_val_pretty_printer (extlang, type, valaddr,
- embedded_offset, address,
- stream, recurse, val,
- options, language);
- switch (rc)
- {
- case EXT_LANG_RC_OK:
- return 1;
- case EXT_LANG_RC_ERROR:
- return 0;
- case EXT_LANG_RC_NOP:
- break;
- default:
- gdb_assert_not_reached ("bad return from apply_val_pretty_printer");
- }
- }
- return 0;
- }
- /* GDB access to the "frame filter" feature.
- FRAME is the source frame to start frame-filter invocation. FLAGS is an
- integer holding the flags for printing. The following elements of
- the FRAME_FILTER_FLAGS enum denotes the make-up of FLAGS:
- PRINT_LEVEL is a flag indicating whether to print the frame's
- relative level in the output. PRINT_FRAME_INFO is a flag that
- indicates whether this function should print the frame
- information, PRINT_ARGS is a flag that indicates whether to print
- frame arguments, and PRINT_LOCALS, likewise, with frame local
- variables. ARGS_TYPE is an enumerator describing the argument
- format, OUT is the output stream to print. FRAME_LOW is the
- beginning of the slice of frames to print, and FRAME_HIGH is the
- upper limit of the frames to count. Returns EXT_LANG_BT_ERROR on error,
- or EXT_LANG_BT_COMPLETED on success.
- Extension languages are tried in the order specified by
- extension_languages. The first one to provide a filter "wins".
- If there is an error (EXT_LANG_BT_ERROR) it is reported immediately
- rather than trying filters in other extension languages. */
- enum ext_lang_bt_status
- apply_ext_lang_frame_filter (struct frame_info *frame, int flags,
- enum ext_lang_frame_args args_type,
- struct ui_out *out,
- int frame_low, int frame_high)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- enum ext_lang_bt_status status;
- if (extlang->ops->apply_frame_filter == NULL)
- continue;
- status = extlang->ops->apply_frame_filter (extlang, frame, flags,
- args_type, out,
- frame_low, frame_high);
- /* We use the filters from the first extension language that has
- applicable filters. Also, an error is reported immediately
- rather than continue trying. */
- if (status != EXT_LANG_BT_NO_FILTERS)
- return status;
- }
- return EXT_LANG_BT_NO_FILTERS;
- }
- /* Update values held by the extension language when OBJFILE is discarded.
- New global types must be created for every such value, which must then be
- updated to use the new types.
- The function typically just iterates over all appropriate values and
- calls preserve_one_value for each one.
- COPIED_TYPES is used to prevent cycles / duplicates and is passed to
- preserve_one_value. */
- void
- preserve_ext_lang_values (struct objfile *objfile, htab_t copied_types)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->ops->preserve_values != NULL)
- extlang->ops->preserve_values (extlang, objfile, copied_types);
- }
- }
- /* If there is a stop condition implemented in an extension language for
- breakpoint B, return a pointer to the extension language's definition.
- Otherwise return NULL.
- If SKIP_LANG is not EXT_LANG_NONE, skip checking this language.
- This is for the case where we're setting a new condition: Only one
- condition is allowed, so when setting a condition for any particular
- extension language, we need to check if any other extension language
- already has a condition set. */
- const struct extension_language_defn *
- get_breakpoint_cond_ext_lang (struct breakpoint *b,
- enum extension_language skip_lang)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->language != skip_lang
- && extlang->ops->breakpoint_has_cond != NULL
- && extlang->ops->breakpoint_has_cond (extlang, b))
- return extlang;
- }
- return NULL;
- }
- /* Return whether a stop condition for breakpoint B says to stop.
- True is also returned if there is no stop condition for B. */
- int
- breakpoint_ext_lang_cond_says_stop (struct breakpoint *b)
- {
- int i;
- const struct extension_language_defn *extlang;
- enum ext_lang_bp_stop stop = EXT_LANG_BP_STOP_UNSET;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- /* There is a rule that a breakpoint can have at most one of any of a
- CLI or extension language condition. However, Python hacks in "finish
- breakpoints" on top of the "stop" check, so we have to call this for
- every language, even if we could first determine whether a "stop"
- method exists. */
- if (extlang->ops->breakpoint_cond_says_stop != NULL)
- {
- enum ext_lang_bp_stop this_stop
- = extlang->ops->breakpoint_cond_says_stop (extlang, b);
- if (this_stop != EXT_LANG_BP_STOP_UNSET)
- {
- /* Even though we have to check every extension language, only
- one of them can return yes/no (because only one of them
- can have a "stop" condition). */
- gdb_assert (stop == EXT_LANG_BP_STOP_UNSET);
- stop = this_stop;
- }
- }
- }
- return stop == EXT_LANG_BP_STOP_NO ? 0 : 1;
- }
- /* ^C/SIGINT support.
- This requires cooperation with the extension languages so the support
- is defined here. */
- /* This flag tracks quit requests when we haven't called out to an
- extension language. it also holds quit requests when we transition to
- an extension language that doesn't have cooperative SIGINT handling. */
- static int quit_flag;
- /* The current extension language we've called out to, or
- extension_language_gdb if there isn't one.
- This must be set everytime we call out to an extension language, and reset
- to the previous value when it returns. Note that the previous value may
- be a different (or the same) extension language. */
- static const struct extension_language_defn *active_ext_lang
- = &extension_language_gdb;
- /* Return the currently active extension language. */
- const struct extension_language_defn *
- get_active_ext_lang (void)
- {
- return active_ext_lang;
- }
- /* Install a SIGINT handler. */
- static void
- install_sigint_handler (const struct signal_handler *handler_state)
- {
- gdb_assert (handler_state->handler_saved);
- signal (SIGINT, handler_state->handler);
- }
- /* Install GDB's SIGINT handler, storing the previous version in *PREVIOUS.
- As a simple optimization, if the previous version was GDB's SIGINT handler
- then mark the previous handler as not having been saved, and thus it won't
- be restored. */
- static void
- install_gdb_sigint_handler (struct signal_handler *previous)
- {
- /* Save here to simplify comparison. */
- RETSIGTYPE (*handle_sigint_for_compare) () = handle_sigint;
- previous->handler = signal (SIGINT, handle_sigint);
- if (previous->handler != handle_sigint_for_compare)
- previous->handler_saved = 1;
- else
- previous->handler_saved = 0;
- }
- /* Set the currently active extension language to NOW_ACTIVE.
- The result is a pointer to a malloc'd block of memory to pass to
- restore_active_ext_lang.
- N.B. This function must be called every time we call out to an extension
- language, and the result must be passed to restore_active_ext_lang
- afterwards.
- If there is a pending SIGINT it is "moved" to the now active extension
- language, if it supports cooperative SIGINT handling (i.e., it provides
- {clear,set,check}_quit_flag methods). If the extension language does not
- support cooperative SIGINT handling, then the SIGINT is left queued and
- we require the non-cooperative extension language to call check_quit_flag
- at appropriate times.
- It is important for the extension language to call check_quit_flag if it
- installs its own SIGINT handler to prevent the situation where a SIGINT
- is queued on entry, extension language code runs for a "long" time possibly
- serving one or more SIGINTs, and then returns. Upon return, if
- check_quit_flag is not called, the original SIGINT will be thrown.
- Non-cooperative extension languages are free to install their own SIGINT
- handler but the original must be restored upon return, either itself
- or via restore_active_ext_lang. */
- struct active_ext_lang_state *
- set_active_ext_lang (const struct extension_language_defn *now_active)
- {
- struct active_ext_lang_state *previous
- = XCNEW (struct active_ext_lang_state);
- previous->ext_lang = active_ext_lang;
- active_ext_lang = now_active;
- /* If the newly active extension language uses cooperative SIGINT handling
- then ensure GDB's SIGINT handler is installed. */
- if (now_active->language == EXT_LANG_GDB
- || now_active->ops->check_quit_flag != NULL)
- install_gdb_sigint_handler (&previous->sigint_handler);
- /* If there's a SIGINT recorded in the cooperative extension languages,
- move it to the new language, or save it in GDB's global flag if the newly
- active extension language doesn't use cooperative SIGINT handling. */
- if (check_quit_flag ())
- set_quit_flag ();
- return previous;
- }
- /* Restore active extension language from PREVIOUS. */
- void
- restore_active_ext_lang (struct active_ext_lang_state *previous)
- {
- const struct extension_language_defn *current = active_ext_lang;
- active_ext_lang = previous->ext_lang;
- /* Restore the previous SIGINT handler if one was saved. */
- if (previous->sigint_handler.handler_saved)
- install_sigint_handler (&previous->sigint_handler);
- /* If there's a SIGINT recorded in the cooperative extension languages,
- move it to the new language, or save it in GDB's global flag if the newly
- active extension language doesn't use cooperative SIGINT handling. */
- if (check_quit_flag ())
- set_quit_flag ();
- xfree (previous);
- }
- /* Clear the quit flag.
- The flag is cleared in all extension languages,
- not just the currently active one. */
- void
- clear_quit_flag (void)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->ops->clear_quit_flag != NULL)
- extlang->ops->clear_quit_flag (extlang);
- }
- quit_flag = 0;
- }
- /* Set the quit flag.
- This only sets the flag in the currently active extension language.
- If the currently active extension language does not have cooperative
- SIGINT handling, then GDB's global flag is set, and it is up to the
- extension language to call check_quit_flag. The extension language
- is free to install its own SIGINT handler, but we still need to handle
- the transition. */
- void
- set_quit_flag (void)
- {
- if (active_ext_lang->ops != NULL
- && active_ext_lang->ops->set_quit_flag != NULL)
- active_ext_lang->ops->set_quit_flag (active_ext_lang);
- else
- quit_flag = 1;
- }
- /* Return true if the quit flag has been set, false otherwise.
- Note: The flag is cleared as a side-effect.
- The flag is checked in all extension languages that support cooperative
- SIGINT handling, not just the current one. This simplifies transitions. */
- int
- check_quit_flag (void)
- {
- int i, result = 0;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- if (extlang->ops->check_quit_flag != NULL)
- if (extlang->ops->check_quit_flag (extlang) != 0)
- result = 1;
- }
- /* This is written in a particular way to avoid races. */
- if (quit_flag)
- {
- quit_flag = 0;
- result = 1;
- }
- return result;
- }
- /* 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;
- }
- /* 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);
- }
- /* 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,
- and no further languages are tried. */
- static void
- ext_lang_before_prompt (const char *current_gdb_prompt)
- {
- int i;
- const struct extension_language_defn *extlang;
- ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
- {
- enum ext_lang_rc rc;
- if (extlang->ops->before_prompt == NULL)
- continue;
- rc = extlang->ops->before_prompt (extlang, current_gdb_prompt);
- switch (rc)
- {
- case EXT_LANG_RC_OK:
- case EXT_LANG_RC_ERROR:
- return;
- case EXT_LANG_RC_NOP:
- break;
- default:
- gdb_assert_not_reached ("bad return from before_prompt");
- }
- }
- }
- extern initialize_file_ftype _initialize_extension;
- void
- _initialize_extension (void)
- {
- observer_attach_before_prompt (ext_lang_before_prompt);
- }