diff options
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/py-gdb-readline.c | 113 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 1 | ||||
-rw-r--r-- | gdb/python/python.c | 1 |
3 files changed, 115 insertions, 0 deletions
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c new file mode 100644 index 0000000..b5e0705 --- /dev/null +++ b/gdb/python/py-gdb-readline.c @@ -0,0 +1,113 @@ +/* Readline support for Python. + + Copyright (C) 2012 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/>. */ + +#include "defs.h" +#include "python-internal.h" +#include "exceptions.h" +#include "top.h" +#include "cli/cli-utils.h" +#include "gdb_string.h" + +#include <stddef.h> + +/* Readline function suitable for PyOS_ReadlineFunctionPointer, which + is used for Python's interactive parser and raw_input. In both + cases, sys_stdin and sys_stdout are always stdin and stdout + respectively, as far as I can tell; they are ignored and + command_line_input is used instead. */ + +static char * +gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout, + char *prompt) +{ + int n; + char *p = NULL, *p_start, *p_end, *q; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + p = command_line_input (prompt, 0, "python"); + + /* Detect user interrupt (Ctrl-C). */ + if (except.reason == RETURN_QUIT) + return NULL; + + /* Handle errors by raising Python exceptions. */ + if (except.reason < 0) + { + /* The thread state is nulled during gdbpy_readline_wrapper, + with the original value saved in the following undocumented + variable (see Python's Parser/myreadline.c and + Modules/readline.c). */ + PyEval_RestoreThread (_PyOS_ReadlineTState); + gdbpy_convert_exception (except); + PyEval_SaveThread (); + return NULL; + } + + /* Detect EOF (Ctrl-D). */ + if (p == NULL) + { + q = PyMem_Malloc (1); + if (q != NULL) + q[0] = '\0'; + return q; + } + + n = strlen (p); + + /* Copy the line to Python and return. */ + q = PyMem_Malloc (n + 2); + if (q != NULL) + { + strncpy (q, p, n); + q[n] = '\n'; + q[n + 1] = '\0'; + } + return q; +} + +/* Initialize Python readline support. */ + +void +gdbpy_initialize_gdb_readline (void) +{ + /* Python's readline module conflicts with GDB's use of readline + since readline is not reentrant. Ideally, a reentrant wrapper to + GDB's readline should be implemented to replace Python's readline + and prevent conflicts. For now, this file implements a + sys.meta_path finder that simply fails to import the readline + module. */ + PyRun_SimpleString ("\ +import sys\n\ +\n\ +class GdbRemoveReadlineFinder:\n\ + def find_module(self, fullname, path=None):\n\ + if fullname == 'readline' and path is None:\n\ + return self\n\ + return None\n\ +\n\ + def load_module(self, fullname):\n\ + raise ImportError('readline module disabled under GDB')\n\ +\n\ +sys.meta_path.append(GdbRemoveReadlineFinder())\n\ +"); + + PyOS_ReadlineFunctionPointer = gdbpy_readline_wrapper; +} + diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index bae61c2..aa3678b 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -232,6 +232,7 @@ struct symtab *symtab_object_to_symtab (PyObject *obj); struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); struct frame_info *frame_object_to_frame_info (PyObject *frame_obj); +void gdbpy_initialize_gdb_readline (void); void gdbpy_initialize_auto_load (void); void gdbpy_initialize_values (void); void gdbpy_initialize_frames (void); diff --git a/gdb/python/python.c b/gdb/python/python.c index ad735ce..1e59d1e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1389,6 +1389,7 @@ message == an error message without a stack will be printed."), gdbpy_gdberror_exc = PyErr_NewException ("gdb.GdbError", NULL, NULL); PyModule_AddObject (gdb_module, "GdbError", gdbpy_gdberror_exc); + gdbpy_initialize_gdb_readline (); gdbpy_initialize_auto_load (); gdbpy_initialize_values (); gdbpy_initialize_frames (); |