diff options
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp')
-rw-r--r-- | lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp new file mode 100644 index 000000000000..674ec9b6140a --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp @@ -0,0 +1,88 @@ +#include "PythonReadline.h" + +#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE + +#include <stdio.h> + +#include <editline/readline.h> + +// Simple implementation of the Python readline module using libedit. +// In the event that libedit is excluded from the build, this turns +// back into a null implementation that blocks the module from pulling +// in the GNU readline shared lib, which causes linkage confusion when +// both readline and libedit's readline compatibility symbols collide. +// +// Currently it only installs a PyOS_ReadlineFunctionPointer, without +// implementing any of the readline module methods. This is meant to +// work around LLVM pr18841 to avoid seg faults in the stock Python +// readline.so linked against GNU readline. +// +// Bug on the cpython side: https://bugs.python.org/issue38634 + +PyDoc_STRVAR(moduleDocumentation, + "Simple readline module implementation based on libedit."); + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef readline_module = { + PyModuleDef_HEAD_INIT, // m_base + "lldb_editline", // m_name + moduleDocumentation, // m_doc + -1, // m_size + nullptr, // m_methods + nullptr, // m_reload + nullptr, // m_traverse + nullptr, // m_clear + nullptr, // m_free +}; +#else +static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}}; +#endif + +static char * +#if PY_MAJOR_VERSION >= 3 +simple_readline(FILE *stdin, FILE *stdout, const char *prompt) +#else +simple_readline(FILE *stdin, FILE *stdout, char *prompt) +#endif +{ + rl_instream = stdin; + rl_outstream = stdout; + char *line = readline(prompt); + if (!line) { +#if PY_MAJOR_VERSION >= 3 + char *ret = (char *)PyMem_RawMalloc(1); +#else + char *ret = (char *)PyMem_Malloc(1); +#endif + if (ret != NULL) + *ret = '\0'; + return ret; + } + if (*line) + add_history(line); + int n = strlen(line); +#if PY_MAJOR_VERSION >= 3 + char *ret = (char *)PyMem_RawMalloc(n + 2); +#else + char *ret = (char *)PyMem_Malloc(n + 2); +#endif + if (ret) { + strncpy(ret, line, n); + free(line); + ret[n] = '\n'; + ret[n + 1] = '\0'; + } + return ret; +} + +PyMODINIT_FUNC initlldb_readline(void) { + PyOS_ReadlineFunctionPointer = simple_readline; + +#if PY_MAJOR_VERSION >= 3 + return PyModule_Create(&readline_module); +#else + Py_InitModule4("readline", moduleMethods, moduleDocumentation, + static_cast<PyObject *>(NULL), PYTHON_API_VERSION); +#endif +} +#endif |