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