PythonReadline.cpp revision 360661
1#include "PythonReadline.h"
2
3#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
4
5#include <stdio.h>
6
7#include <editline/readline.h>
8
9// Simple implementation of the Python readline module using libedit.
10// In the event that libedit is excluded from the build, this turns
11// back into a null implementation that blocks the module from pulling
12// in the GNU readline shared lib, which causes linkage confusion when
13// both readline and libedit's readline compatibility symbols collide.
14//
15// Currently it only installs a PyOS_ReadlineFunctionPointer, without
16// implementing any of the readline module methods. This is meant to
17// work around LLVM pr18841 to avoid seg faults in the stock Python
18// readline.so linked against GNU readline.
19//
20// Bug on the cpython side: https://bugs.python.org/issue38634
21
22PyDoc_STRVAR(moduleDocumentation,
23             "Simple readline module implementation based on libedit.");
24
25#if PY_MAJOR_VERSION >= 3
26static struct PyModuleDef readline_module = {
27    PyModuleDef_HEAD_INIT, // m_base
28    "lldb_editline",       // m_name
29    moduleDocumentation,   // m_doc
30    -1,                    // m_size
31    nullptr,               // m_methods
32    nullptr,               // m_reload
33    nullptr,               // m_traverse
34    nullptr,               // m_clear
35    nullptr,               // m_free
36};
37#else
38static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
39#endif
40
41static char *
42#if PY_MAJOR_VERSION >= 3
43simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
44#else
45simple_readline(FILE *stdin, FILE *stdout, char *prompt)
46#endif
47{
48  rl_instream = stdin;
49  rl_outstream = stdout;
50  char *line = readline(prompt);
51  if (!line) {
52#if PY_MAJOR_VERSION >= 3
53    char *ret = (char *)PyMem_RawMalloc(1);
54#else
55    char *ret = (char *)PyMem_Malloc(1);
56#endif
57    if (ret != NULL)
58      *ret = '\0';
59    return ret;
60  }
61  if (*line)
62    add_history(line);
63  int n = strlen(line);
64#if PY_MAJOR_VERSION >= 3
65  char *ret = (char *)PyMem_RawMalloc(n + 2);
66#else
67  char *ret = (char *)PyMem_Malloc(n + 2);
68#endif
69  if (ret) {
70    strncpy(ret, line, n);
71    free(line);
72    ret[n] = '\n';
73    ret[n + 1] = '\0';
74  }
75  return ret;
76}
77
78PyMODINIT_FUNC initlldb_readline(void) {
79  PyOS_ReadlineFunctionPointer = simple_readline;
80
81#if PY_MAJOR_VERSION >= 3
82  return PyModule_Create(&readline_module);
83#else
84  Py_InitModule4("readline", moduleMethods, moduleDocumentation,
85                 static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
86#endif
87}
88#endif
89