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
22 PyDoc_STRVAR(moduleDocumentation,
23 "Simple readline module implementation based on libedit.");
24
25 #if PY_MAJOR_VERSION >= 3
26 static 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
38 static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
39 #endif
40
41 static char *
42 #if PY_MAJOR_VERSION >= 3
simple_readline(FILE * stdin,FILE * stdout,const char * prompt)43 simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
44 #else
45 simple_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 memcpy(ret, line, n);
71 free(line);
72 ret[n] = '\n';
73 ret[n + 1] = '\0';
74 }
75 return ret;
76 }
77
initlldb_readline(void)78 PyMODINIT_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