This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH v1 02/13] script language API for GDB: scripting.[ch]
- From: xdje42 at gmail dot com
- To: gdb-patches at sourceware dot org
- Date: Thu, 05 Dec 2013 21:52:14 -0800
- Subject: [PATCH v1 02/13] script language API for GDB: scripting.[ch]
- Authentication-results: sourceware.org; auth=none
This patch adds scripting.h, scripting.c and scripting-priv.h.
scripting.h provides the public API.
The enums that were in python.h have been moved here and any py_,PY_ part
of the name has been replaced to be non-python-specific.
scripting-priv.h provides the "private" API.
This is what Python exports to GDB.
scripting.c defines script_language_gdb for GDB's own scripting language,
and provides the functions GDB calls to call into a scripting language.
2013-12-05 Doug Evans <xdje42@gmail.com>
* Makefile.in (SFILES): Add scripting.c.
(HFILES_NO_SRCDIR): Add scripting.h.
(COMMON_OBS): Add scripting.o.
* scripting.h: New file.
* scripting-priv.h: New file.
* scripting.c: New file.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index be30dfd..a859ffc 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -757,7 +757,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
proc-service.list progspace.c \
prologue-value.c psymtab.c \
regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c reverse.c \
- sentinel-frame.c \
+ scripting.c sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
stabsread.c stack.c probe.c stap-probe.c std-regs.c \
@@ -842,6 +842,7 @@ config/nm-nto.h config/sparc/nm-sol2.h config/nm-linux.h \
top.h bsd-kvm.h gdb-stabs.h reggroups.h \
annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \
remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
+scripting.h scripting-priv.h \
sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \
gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h \
psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \
@@ -934,6 +935,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
go-lang.o go-valprint.o go-typeprint.o \
jv-lang.o jv-valprint.o jv-typeprint.o jv-varobj.o \
m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \
+ scripting.o \
sentinel-frame.o \
complaints.o typeprint.o \
ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
diff --git a/gdb/scripting-priv.h b/gdb/scripting-priv.h
new file mode 100644
index 0000000..f839d8c
--- /dev/null
+++ b/gdb/scripting-priv.h
@@ -0,0 +1,191 @@
+/* Private implementation details of interface between gdb and its
+ scripting languages.
+
+ Copyright (C) 2013 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/>. */
+
+#ifndef SCRIPTING_PRIV_H
+#define SCRIPTING_PRIV_H
+
+#include "scripting.h"
+
+/* High level description of a scripting language.
+ An entry for each is compiled into GDB regardless of whether the support
+ is present. This is done so that we can issue meaningful errors if the
+ support is not compiled in. */
+
+struct script_language_defn
+{
+ /* Enum of the scripting language. */
+ enum script_language language;
+
+ /* The name of the scripting language, lowercase. E.g., python. */
+ const char *name;
+
+ /* The capitalized name of the scripting language. E.g., Python. */
+ const char *capitalized_name;
+
+ /* The file suffix for this scripting language. E.g., ".py". */
+ const char *suffix;
+
+ /* The suffix of per-objfile scripts to auto-load scripts.
+ E.g., When the program loads libfoo.so, look for libfoo.so-gdb.py. */
+ const char *auto_load_suffix;
+
+ /* We support embedding external scripting language code in GDB's own
+ scripting language. We do this by having a special command that begins
+ the external language snippet, and terminate it with "end".
+ This specifies the control type used to implement this. */
+ enum command_control_type cli_control_type;
+
+ /* A pointer to the "methods" to load scripts in this language,
+ or NULL if the support is not compiled into GDB. */
+ const struct script_language_script_ops *script_ops;
+
+ /* Either a pointer to the "methods" of the scripting language interface
+ or NULL if the support is not compiled into GDB.
+ This is also NULL for GDB's own scripting language which is relatively
+ primitive, and doesn't provide these features. */
+ const struct script_language_ops *ops;
+};
+
+/* The interface for loading scripts from external scripting languages,
+ as well as GDB's own scripting language. */
+
+struct script_language_script_ops
+{
+ /* Load a script. This is called, e.g., via the "source" command. */
+ script_sourcer_func *script_sourcer;
+
+ /* Load a script attached to an objfile. */
+ objfile_script_sourcer_func *objfile_script_sourcer;
+
+ /* Return non-zero if auto-loading scripts in this scripting language
+ is enabled. */
+ int (*auto_load_enabled) (const struct script_language_defn *);
+};
+
+/* The interface for making calls from GDB to an external scripting
+ language. This is for non-script-loading related functionality,
+ like pretty-printing, etc. The reason these are separated out as
+ GDB's own scripting language makes use of script_language_script_opts,
+ but it makes no use of these. There is no (current) intention to split
+ script_language_ops up any further. */
+
+struct script_language_ops
+{
+ /* Called at the end of gdb initialization to give the scripting language
+ an opportunity to finish up. This is useful for things like adding
+ new commands where one has to wait until gdb itself is initialized. */
+ void (*finish_initialization) (const struct script_language_defn *);
+
+ /* Return non-zero if the scripting language successfully initialized. */
+ int (*initialized) (const struct script_language_defn *);
+
+ /* Process a sequence of commands embedded in gdb's own scripting language.
+ E.g.,
+ python
+ print 42
+ end */
+ void (*eval_from_control_command) (const struct script_language_defn *,
+ struct command_line *);
+
+ /* Called before printing a type. */
+ void (*start_type_printers) (const struct script_language_defn *,
+ struct script_type_printers *);
+
+ /* Try to pretty-print TYPE. If successful the pretty-printed type is
+ returned. Otherwise NULL is returned.
+ This function has a bit of a funny name, since it actually applies
+ recognizers, but this seemed clearer given the start_type_printers
+ and free_type_printers functions. */
+ char *(*apply_type_printers) (const struct script_language_defn *,
+ const struct script_type_printers *,
+ struct type *);
+
+ /* Called after a type has been printed to give the type pretty-printer
+ mechanism an opportunity to clean up. */
+ void (*free_type_printers) (const struct script_language_defn *,
+ struct script_type_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. */
+ int (*apply_val_pretty_printer)
+ (const struct script_language_defn *,
+ 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);
+
+ /* 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 SCR_BT_ERROR on error,
+ or SCR_BT_COMPLETED on success. */
+ enum script_bt_status (*apply_frame_filter)
+ (const struct script_language_defn *,
+ struct frame_info *frame, int flags, enum script_frame_args args_type,
+ struct ui_out *out, int frame_low, int frame_high);
+
+ /* Update values held by the scripting 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_values) (const struct script_language_defn *,
+ struct objfile *objfile, htab_t copied_types);
+
+ /* Return non-zero if there is a stop condition for the breakpoint. */
+ int (*breakpoint_has_cond) (const struct script_language_defn *,
+ struct breakpoint *);
+
+ /* Return non-zero if there is a stop condition for the breakpoint,
+ and it indicates the program should stop. */
+ enum scr_bp_stop (*breakpoint_cond_says_stop)
+ (const struct script_language_defn *, struct breakpoint *);
+
+ /* The next three are used to connect gdb's SIGINT handling with the
+ scripting language's. */
+
+ /* Clear the SIGINT indicator. */
+ void (*clear_quit_flag) (const struct script_language_defn *);
+
+ /* Set the SIGINT indicator. */
+ void (*set_quit_flag) (const struct script_language_defn *);
+
+ /* Return non-zero if a SIGINT has occurred.
+ This is expected to also clear the indicator. */
+ int (*check_quit_flag) (const struct script_language_defn *);
+};
+
+#endif /* SCRIPTING_PRIV_H */
diff --git a/gdb/scripting.c b/gdb/scripting.c
new file mode 100644
index 0000000..f63edf8
--- /dev/null
+++ b/gdb/scripting.c
@@ -0,0 +1,621 @@
+/* Interface between gdb and its scripting languages.
+
+ Copyright (C) 2013 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 "script" in the name, and no other symbol in gdb does. */
+
+#include "defs.h"
+#include "auto-load.h"
+#include "breakpoint.h"
+#include "scripting.h"
+#include "scripting-priv.h"
+#include "cli/cli-script.h"
+#include "python/python.h"
+
+/* Iterate over all external scripting languages, regardless of whether the
+ support has been compiled in or not. */
+#define ALL_EXT_SCRIPTING_LANGUAGES(i, slang) \
+ for (/*int*/ i = 0, slang = external_scripting_languages[0]; \
+ slang != NULL; \
+ slang = external_scripting_languages[++i])
+
+/* Iterate over all external scripting languages that are supported. */
+#define ALL_ENABLED_EXT_SCRIPTING_LANGUAGES(i, slang) \
+ for (/*int*/ i = 0, slang = external_scripting_languages[0]; \
+ slang != NULL; \
+ slang = external_scripting_languages[++i]) \
+ if (slang->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 script_language_script_ops script_lang_gdb_script_ops =
+{
+ source_gdb_script,
+ source_gdb_objfile_script,
+ auto_load_gdb_scripts_enabled
+};
+
+const struct script_language_defn script_language_gdb =
+{
+ SCRIPT_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,
+
+ &script_lang_gdb_script_ops,
+
+ /* The rest of the scripting interface isn't supported by GDB's own
+ scripting language. */
+ NULL
+};
+
+/* Table of all external (non-native) scripting languages. */
+
+static const struct script_language_defn * const
+ external_scripting_languages[] =
+{
+ &script_language_python,
+ NULL
+};
+
+/* Methods for GDB's own scripting language. */
+
+/* The script_language_script_ops.script_sourcer "method". */
+
+static void
+source_gdb_script (const struct script_language_defn *slang,
+ FILE *stream, const char *file)
+{
+ script_from_file (stream, file);
+}
+
+/* The script_language_script_ops.objfile_script_sourcer "method". */
+
+static void
+source_gdb_objfile_script (const struct script_language_defn *slang,
+ struct objfile *objfile,
+ FILE *stream, const char *file)
+{
+ script_from_file (stream, file);
+}
+
+/* Accessors for "public" attributes of struct script_language.
+
+ IWBN if we could use slang_foo here and elsewhere, but we can't for fear of
+ confusing someone into thinking we might be referring to the Slang
+ programming language. */
+
+/* Return the "name" field of SLANG. */
+
+const char *
+script_lang_name (const struct script_language_defn *slang)
+{
+ return slang->name;
+}
+
+/* Return the "capitalized_name" field of SLANG. */
+
+const char *
+script_lang_capitalized_name (const struct script_language_defn *slang)
+{
+ return slang->capitalized_name;
+}
+
+/* Return the "suffix" field of SLANG. */
+
+const char *
+script_lang_suffix (const struct script_language_defn *slang)
+{
+ return slang->suffix;
+}
+
+/* Return the "auto_load_suffix" field of SLANG. */
+
+const char *
+script_lang_auto_load_suffix (const struct script_language_defn *slang)
+{
+ return slang->auto_load_suffix;
+}
+
+/* script_language_script_ops wrappers. */
+
+static void
+throw_unsupported (const struct script_language_defn *slang)
+{
+ throw_error (UNSUPPORTED_ERROR,
+ _("Scripting in the \"%s\" language is not supported"
+ " in this copy of GDB."),
+ slang->capitalized_name);
+}
+
+/* Throw UNSUPPORTED_ERROR if called.
+ This is used to implement script_ext_{soft,hard}. */
+
+static void
+source_script_unsupported (const struct script_language_defn *slang,
+ FILE *stream, const char *file)
+{
+ throw_unsupported (slang);
+}
+
+/* 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 a function to load FILE.
+ If FILE specifies a scripting language we support then the script language
+ definition is stored in *SLANG_PTR.
+ If FILE specifies a scripting language we support but which is not
+ enabled then return a function that throws UNSUPPORTED_ERROR.
+ Otherwise return NULL.
+
+ Note: This could be a lot cleaner if not for script_ext_soft. */
+
+script_sourcer_func *
+get_script_sourcer (const char *file,
+ const struct script_language_defn **slang_ptr)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ *slang_ptr = NULL;
+
+ ALL_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (has_extension (file, slang->suffix))
+ {
+ script_sourcer_func *func = script_lang_sourcer (slang);
+
+ *slang_ptr = slang;
+ if (func != NULL)
+ return func;
+ return source_script_unsupported;
+ }
+ }
+
+ return NULL;
+}
+
+/* Return the script "sourcer" function for SLANG.
+ This is the function that loads and processes a script. */
+
+script_sourcer_func *
+script_lang_sourcer (const struct script_language_defn *slang)
+{
+ if (slang->script_ops == NULL)
+ return NULL;
+ return slang->script_ops->script_sourcer;
+}
+
+/* Return the objfile script "sourcer" function for SLANG.
+ This is the function that loads and processes a script for a particular
+ objfile. */
+
+objfile_script_sourcer_func *
+script_lang_objfile_sourcer (const struct script_language_defn *slang)
+{
+ if (slang->script_ops == NULL)
+ return NULL;
+ return slang->script_ops->objfile_script_sourcer;
+}
+
+/* Return non-zero if auto-loading of SLANG scripts is enabled. */
+
+int
+script_lang_auto_load_enabled (const struct script_language_defn *slang)
+{
+ if (slang->script_ops == NULL)
+ return 0;
+ return slang->script_ops->auto_load_enabled (slang);
+}
+
+/* Functions that iterate over all (external) scripting languages. */
+
+/* Wrapper to call the script_language_ops.finish_initialization "method"
+ for each compiled-in scripting language. */
+
+void
+finish_script_initialization (void)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->finish_initialization != NULL)
+ slang->ops->finish_initialization (slang);
+ }
+}
+
+/* Return the scripting language specified by CMD.
+ Note the difference between this function and
+ eval_script_from_control_command is that we loop on
+ ALL_EXT_SCRIPTING_LANGUAGES whereas the latter loops on
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES. */
+
+static const struct script_language_defn *
+script_lang_from_control_command (struct command_line *cmd)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->cli_control_type == cmd->control_type)
+ return slang;
+ }
+
+ gdb_assert_not_reached ("invalid scripting language in cli command");
+}
+
+/* Evaluate the commands in CMD, which specifies a sequence of commands
+ in an external scripting language. */
+
+void
+eval_script_from_control_command (struct command_line *cmd)
+{
+ int i;
+ const struct script_language_defn *slang;
+ const char *script_lang_name;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->cli_control_type == cmd->control_type
+ && slang->ops->eval_from_control_command != NULL)
+ {
+ slang->ops->eval_from_control_command (slang, cmd);
+ return;
+ }
+ }
+
+ /* The requested scripting language is not supported in this GDB. */
+ throw_unsupported (script_lang_from_control_command (cmd));
+}
+
+/* Load scripts for OBJFILE written in external languages. */
+
+void
+auto_load_scripts_for_objfile (struct objfile *objfile)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ slang = &script_language_gdb;
+ if (script_lang_auto_load_enabled (slang))
+ auto_load_objfile_script (objfile, slang);
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (script_lang_auto_load_enabled (slang))
+ auto_load_objfile_script (objfile, slang);
+ }
+}
+
+/* Interface to type pretty-printers implemented in an external
+ scripting 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_script_type_printers and free_script_type_printers. */
+
+struct script_type_printers *
+start_script_type_printers (void)
+{
+ struct script_type_printers *printers
+ = XZALLOC (struct script_type_printers);
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->start_type_printers != NULL)
+ slang->ops->start_type_printers (slang, printers);
+ }
+
+ return printers;
+}
+
+/* Iteratively try the type pretty-printers specified by PRINTERS,
+ returning the result of the first one that succeeds. If no printer
+ succeeds then NULL is returned. */
+
+char *
+apply_script_type_printers (struct script_type_printers *printers,
+ struct type *type)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ char *result = NULL;
+
+ if (slang->ops->apply_type_printers != NULL)
+ result = slang->ops->apply_type_printers (slang, printers, type);
+
+ if (result != NULL)
+ return result;
+ }
+
+ return NULL;
+}
+
+/* Call this after pretty-printing a type to release all memory held
+ by PRINTERS. */
+
+void
+free_script_type_printers (struct script_type_printers *printers)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->free_type_printers != NULL)
+ slang->ops->free_type_printers (slang, 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. */
+
+int
+apply_val_script_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 script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->apply_val_pretty_printer (slang, type, valaddr,
+ embedded_offset, address,
+ stream, recurse, val,
+ options, language))
+ return 1;
+ }
+
+ 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 SCR_BT_ERROR on error,
+ or SCR_BT_COMPLETED on success. */
+
+enum script_bt_status
+apply_script_frame_filter (struct frame_info *frame, int flags,
+ enum script_frame_args args_type,
+ struct ui_out *out,
+ int frame_low, int frame_high)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ enum script_bt_status status;
+
+ if (slang->ops->apply_frame_filter == NULL)
+ continue;
+ status = slang->ops->apply_frame_filter (slang, frame, flags,
+ args_type, out,
+ frame_low, frame_high);
+ /* We use the filters from the first scripting language that has
+ applicable filters. */
+ if (status != SCR_BT_NO_FILTERS)
+ return status;
+ }
+
+ return SCR_BT_NO_FILTERS;
+}
+
+/* Update values held by the scripting 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_script_values (struct objfile *objfile, htab_t copied_types)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->preserve_values != NULL)
+ slang->ops->preserve_values (slang, objfile, copied_types);
+ }
+}
+
+/* Return non-zero if there is a stop condition for the breakpoint.
+ If SKIP_LANG is not SCRIPT_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
+ scripting language, we need to check if any other already has a
+ condition set. */
+
+int
+breakpoint_has_script_cond (struct breakpoint *b,
+ enum script_language skip_lang)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->language != skip_lang
+ && slang->ops->breakpoint_has_cond != NULL
+ && slang->ops->breakpoint_has_cond (slang, b))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* 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_script_cond_says_stop (struct breakpoint *b)
+{
+ int i;
+ const struct script_language_defn *slang;
+ enum scr_bp_stop stop = SCR_BP_STOP_UNSET;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ /* There is a rule that a breakpoint can have at most one of any of a
+ CLI or script 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 (slang->ops->breakpoint_cond_says_stop != NULL)
+ {
+ enum scr_bp_stop this_stop
+ = slang->ops->breakpoint_cond_says_stop (slang, b);
+
+ if (this_stop != SCR_BP_STOP_UNSET)
+ {
+ /* Even though we have to check every scripting language, only
+ one of them can return yes/no (because only one of them
+ can have a "stop" condition. */
+ gdb_assert (stop == SCR_BP_STOP_UNSET);
+ stop = this_stop;
+ }
+ }
+ }
+
+ return stop == SCR_BP_STOP_NO ? 0 : 1;
+}
+
+/* ^C/SIGINT support.
+ This requires cooperation with the scripting languages so the support
+ is defined here.
+ The prototypes for these are in defs.h. */
+
+/* Nonzero means a quit has been requested.
+ This flag tracks quit requests but it's only used if the scripting language
+ doesn't provide the necessary support. */
+static int quit_flag;
+
+/* Clear the quit flag. */
+
+void
+clear_quit_flag (void)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->clear_quit_flag != NULL)
+ slang->ops->clear_quit_flag (slang);
+ }
+
+ quit_flag = 0;
+}
+
+/* Set the quit flag. */
+
+void
+set_quit_flag (void)
+{
+ int i;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->set_quit_flag != NULL)
+ slang->ops->set_quit_flag (slang);
+ }
+
+ quit_flag = 1;
+}
+
+/* Return true if the quit flag has been set, false otherwise.
+ Scripting languages may need their own control over whether SIGINT has
+ been seen. */
+
+int
+check_quit_flag (void)
+{
+ int i, result = 0;
+ const struct script_language_defn *slang;
+
+ ALL_ENABLED_EXT_SCRIPTING_LANGUAGES (i, slang)
+ {
+ if (slang->ops->check_quit_flag != NULL)
+ if (slang->ops->check_quit_flag (slang) != 0)
+ result = 1;
+ }
+
+ /* This is written in a particular way to avoid races. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/gdb/scripting.h b/gdb/scripting.h
new file mode 100644
index 0000000..4307bb0
--- /dev/null
+++ b/gdb/scripting.h
@@ -0,0 +1,204 @@
+/* Interface between gdb and its scripting languages.
+
+ Copyright (C) 2013 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/>. */
+
+#ifndef SCRIPTING_H
+#define SCRIPTING_H
+
+#include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc. */
+
+struct breakpoint;
+struct command_line;
+struct frame_info;
+struct language_defn;
+struct objfile;
+struct script_language_defn;
+struct type;
+struct ui_file;
+struct ui_out;
+struct value;
+struct value_print_options;
+
+/* A function to load and process a script file.
+ The file has been opened and is ready to be read from the beginning.
+ Any exceptions are not caught, and are passed to the caller. */
+typedef void script_sourcer_func (const struct script_language_defn *,
+ FILE *, const char *);
+
+/* A function to load and process a script for an objfile.
+ The file has been opened and is ready to be read from the beginning.
+ Any exceptions are not caught, and are passed to the caller. */
+typedef void objfile_script_sourcer_func (const struct script_language_defn *,
+ struct objfile *,
+ FILE *, const char *);
+
+/* Enum of each scripting language. */
+
+enum script_language
+ {
+ SCRIPT_LANG_NONE,
+ SCRIPT_LANG_GDB,
+ SCRIPT_LANG_PYTHON
+ };
+
+/* Script frame-filter status return values. */
+
+enum script_bt_status
+ {
+ /* Return when an error has occurred in processing frame filters,
+ or when printing the stack. */
+ SCR_BT_ERROR = -1,
+
+ /* Return from internal routines to indicate that the function
+ succeeded. */
+ SCR_BT_OK = 1,
+
+ /* Return when the frame filter process is complete, and all
+ operations have succeeded. */
+ SCR_BT_COMPLETED = 2,
+
+ /* Return when the frame filter process is complete, but there
+ were no filter registered and enabled to process. */
+ SCR_BT_NO_FILTERS = 3
+ };
+
+/* Flags to pass to apply_frame_filter. */
+
+enum frame_filter_flags
+ {
+ /* Set this flag if frame level is to be printed. */
+ PRINT_LEVEL = 1,
+
+ /* Set this flag if frame information is to be printed. */
+ PRINT_FRAME_INFO = 2,
+
+ /* Set this flag if frame arguments are to be printed. */
+ PRINT_ARGS = 4,
+
+ /* Set this flag if frame locals are to be printed. */
+ PRINT_LOCALS = 8,
+ };
+
+/* A choice of the different frame argument printing strategies that
+ can occur in different cases of frame filter instantiation. */
+
+enum script_frame_args
+ {
+ /* Print no values for arguments when invoked from the MI. */
+ NO_VALUES = PRINT_NO_VALUES,
+
+ MI_PRINT_ALL_VALUES = PRINT_ALL_VALUES,
+
+ /* Print only simple values (what MI defines as "simple") for
+ arguments when invoked from the MI. */
+ MI_PRINT_SIMPLE_VALUES = PRINT_SIMPLE_VALUES,
+
+ /* Print only scalar values for arguments when invoked from the CLI. */
+ CLI_SCALAR_VALUES,
+
+ /* Print all values for arguments when invoked from the CLI. */
+ CLI_ALL_VALUES
+ };
+
+/* The possible results of script_language_ops.breakpoint_cond_says_stop. */
+
+enum scr_bp_stop
+ {
+ /* No "stop" condition is set. */
+ SCR_BP_STOP_UNSET,
+
+ /* A "stop" condition is set, and it says "don't stop". */
+ SCR_BP_STOP_NO,
+
+ /* A "stop" condition is set, and it says "stop". */
+ SCR_BP_STOP_YES
+ };
+
+/* Table of type printers associated with the global typedef table. */
+
+struct script_type_printers
+{
+ /* Type-printers from Python. */
+ void *py_type_printers;
+};
+
+/* The interface for gdb's own scripting language. */
+extern const struct script_language_defn script_language_gdb;
+
+/* Accessors for "public" attributes of the scripting language definition. */
+
+extern enum script_language script_lang_kind
+ (const struct script_language_defn *);
+
+extern const char *script_lang_name (const struct script_language_defn *);
+
+extern const char *script_lang_capitalized_name
+ (const struct script_language_defn *);
+
+extern const char *script_lang_suffix (const struct script_language_defn *);
+
+extern const char *script_lang_auto_load_suffix
+ (const struct script_language_defn *);
+
+extern script_sourcer_func *script_lang_sourcer
+ (const struct script_language_defn *);
+
+extern objfile_script_sourcer_func *script_lang_objfile_sourcer
+ (const struct script_language_defn *);
+
+extern int script_lang_auto_load_enabled (const struct script_language_defn *);
+
+/* Return the function that can load(source) FILE. */
+extern script_sourcer_func *get_script_sourcer
+ (const char *file, const struct script_language_defn **slang_ptr);
+
+/* Wrappers for each scripting API function that iterate over all
+ (external) scripting languages. */
+
+extern void finish_script_initialization (void);
+
+extern void eval_script_from_control_command (struct command_line *cmd);
+
+extern void auto_load_scripts_for_objfile (struct objfile *);
+
+extern struct script_type_printers *start_script_type_printers (void);
+
+extern char *apply_script_type_printers (struct script_type_printers *,
+ struct type *);
+
+extern void free_script_type_printers (struct script_type_printers *);
+
+extern int apply_val_script_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);
+
+extern enum script_bt_status apply_script_frame_filter
+ (struct frame_info *frame, int flags, enum script_frame_args args_type,
+ struct ui_out *out, int frame_low, int frame_high);
+
+extern void preserve_script_values (struct objfile *, htab_t copied_types);
+
+extern int breakpoint_has_script_cond (struct breakpoint *b,
+ enum script_language skip_lang);
+
+extern int breakpoint_script_cond_says_stop (struct breakpoint *);
+
+#endif /* SCRIPTING_H */