xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp (revision 9357b5d08497326a1895cab6c1d712bf12a34519)
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
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     char *ret = (char *)PyMem_RawMalloc(1);
53     if (ret != NULL)
54       *ret = '\0';
55     return ret;
56   }
57   if (*line)
58     add_history(line);
59   int n = strlen(line);
60   char *ret = (char *)PyMem_RawMalloc(n + 2);
61   if (ret) {
62     strncpy(ret, line, n);
63     free(line);
64     ret[n] = '\n';
65     ret[n + 1] = '\0';
66   }
67   return ret;
68 }
69 
70 PyMODINIT_FUNC initlldb_readline(void) {
71   PyOS_ReadlineFunctionPointer = simple_readline;
72 
73 #if PY_MAJOR_VERSION >= 3
74   return PyModule_Create(&readline_module);
75 #else
76   Py_InitModule4("lldb_readline", moduleMethods, moduleDocumentation,
77                  static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
78 #endif
79 }
80 #endif
81