diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6bbc5da2e7..0e804f6e90 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2010-01-18 Tom Tromey + Thiago Jung Bauermann + + Allow "source" to load python scripts. + * exceptions.h (enum errors): Add UNSUPPORTED_ERROR. + * python/python.c (source_python_script): New function. + * python/python.h (source_python_script): Add declaration. + * cli/cli-cmds.c: #include exceptions.h and python/python.h. + (script_ext_off, script_ext_soft, script_ext_strict) + (script_ext_enums, script_ext_mode): New static constants. + (show_script_ext_mode, find_and_open_script): New functions. + (source_script): Enhance to handle Python scripts. + (init_cli_cmds): Add set/show script-extension commands. + 2010-01-16 Stan Shebs * tracepoint.h (struct trace_status): Use unsigned long long diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index 483389848d..7400967375 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -19,6 +19,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "exceptions.h" #include "arch-utils.h" #include "readline/readline.h" #include "readline/tilde.h" @@ -47,6 +48,8 @@ extern void disconnect_or_stop_tracing (int from_tty); #include "cli/cli-setshow.h" #include "cli/cli-cmds.h" +#include "python/python.h" + #ifdef TUI #include "tui/tui.h" /* For tui_active et.al. */ #endif @@ -187,6 +190,21 @@ struct cmd_list_element *showchecklist; int source_verbose = 0; int trace_commands = 0; +/* 'script-extension' option support. */ + +static const char script_ext_off[] = "off"; +static const char script_ext_soft[] = "soft"; +static const char script_ext_strict[] = "strict"; + +static const char *script_ext_enums[] = { + script_ext_off, + script_ext_soft, + script_ext_strict, + NULL +}; + +static const char *script_ext_mode = script_ext_soft; + /* Utility used everywhere when at least one argument is needed and none is supplied. */ @@ -441,18 +459,25 @@ cd_command (char *dir, int from_tty) pwd_command ((char *) 0, 1); } -void -source_script (char *file, int from_tty) +/* Show the current value of the 'script-extension' option. */ + +static void +show_script_ext_mode (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) { - FILE *stream; - struct cleanup *old_cleanups; + fprintf_filtered (file, _("\ +Script filename extension recognition is \"%s\".\n"), + value); +} + +static int +find_and_open_script (int from_tty, char **filep, FILE **streamp, + struct cleanup **cleanupp) +{ + char *file = *filep; char *full_pathname = NULL; int fd; - - if (file == NULL || *file == 0) - { - error (_("source command requires file name of file to source.")); - } + struct cleanup *old_cleanups; file = tilde_expand (file); old_cleanups = make_cleanup (xfree, file); @@ -476,12 +501,58 @@ source_script (char *file, int from_tty) else { do_cleanups (old_cleanups); - return; + return 0; } } - stream = fdopen (fd, FOPEN_RT); - script_from_file (stream, file); + *streamp = fdopen (fd, FOPEN_RT); + *filep = file; + *cleanupp = old_cleanups; + + return 1; +} + +void +source_script (char *file, int from_tty) +{ + FILE *stream; + struct cleanup *old_cleanups; + + if (file == NULL || *file == 0) + { + error (_("source command requires file name of file to source.")); + } + + if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups)) + return; + + if (script_ext_mode != script_ext_off + && strlen (file) > 3 && !strcmp (&file[strlen (file) - 3], ".py")) + { + volatile struct gdb_exception e; + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + source_python_script (stream, file); + } + if (e.reason < 0) + { + /* Should we fallback to ye olde GDB script mode? */ + if (script_ext_mode == script_ext_soft + && e.reason == RETURN_ERROR && e.error == UNSUPPORTED_ERROR) + { + if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups)) + return; + + script_from_file (stream, file); + } + else + /* Nope, just punt. */ + throw_exception (e); + } + } + else + script_from_file (stream, file); do_cleanups (old_cleanups); } @@ -1314,6 +1385,19 @@ when GDB is started."), gdbinit); source_help_text, &cmdlist); set_cmd_completer (c, filename_completer); + add_setshow_enum_cmd ("script-extension", class_support, + script_ext_enums, &script_ext_mode, _("\ +Set mode for script filename extension recognition."), _("\ +Show mode for script filename extension recognition."), _("\ +off == no filename extension recognition (all sourced files are GDB scripts)\n\ +soft == evaluate script according to filename extension, fallback to GDB script" + "\n\ +strict == evaluate script according to filename extension, error if not supported" + ), + NULL, + show_script_ext_mode, + &setlist, &showlist); + add_com ("quit", class_support, quit_command, _("Exit gdb.")); c = add_com ("help", class_support, help_command, _("Print list of commands.")); diff --git a/gdb/exceptions.h b/gdb/exceptions.h index 84a9f0120b..6b3cbeb242 100644 --- a/gdb/exceptions.h +++ b/gdb/exceptions.h @@ -75,6 +75,9 @@ enum errors { /* Error accessing memory. */ MEMORY_ERROR, + /* Feature is not supported in this copy of GDB. */ + UNSUPPORTED_ERROR, + /* Add more errors here. */ NR_ERRORS }; diff --git a/gdb/python/python.c b/gdb/python/python.c index 827372c0cb..1f1ae729fb 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -343,6 +343,22 @@ gdbpy_parse_and_eval (PyObject *self, PyObject *args) return value_to_value_object (result); } +/* Read a file as Python code. STREAM is the input file; FILE is the + name of the file. */ + +void +source_python_script (FILE *stream, char *file) +{ + PyGILState_STATE state; + + state = PyGILState_Ensure (); + + PyRun_SimpleFile (stream, file); + + fclose (stream); + PyGILState_Release (state); +} + /* Printing. */ @@ -525,6 +541,14 @@ eval_python_from_control_command (struct command_line *cmd) error (_("Python scripting is not supported in this copy of GDB.")); } +void +source_python_script (FILE *stream, char *file) +{ + fclose (stream); + throw_error (UNSUPPORTED_ERROR, + _("Python scripting is not supported in this copy of GDB.")); +} + #endif /* HAVE_PYTHON */ diff --git a/gdb/python/python.h b/gdb/python/python.h index f35827bbbd..5d93f67962 100644 --- a/gdb/python/python.h +++ b/gdb/python/python.h @@ -24,6 +24,8 @@ void eval_python_from_control_command (struct command_line *); +void source_python_script (FILE *stream, char *file); + int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, int embedded_offset, CORE_ADDR address, struct ui_file *stream, int recurse,