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..5f6429f5cd0e --- /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) { +    memcpy(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 | 
