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