xref: /src/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1706b4fc4SDimitry Andric #include "PythonReadline.h"
2706b4fc4SDimitry Andric 
3706b4fc4SDimitry Andric #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
4706b4fc4SDimitry Andric 
5344a3780SDimitry Andric #include <cstdio>
6706b4fc4SDimitry Andric 
7706b4fc4SDimitry Andric #include <editline/readline.h>
8706b4fc4SDimitry Andric 
9706b4fc4SDimitry Andric // Simple implementation of the Python readline module using libedit.
10706b4fc4SDimitry Andric // In the event that libedit is excluded from the build, this turns
11706b4fc4SDimitry Andric // back into a null implementation that blocks the module from pulling
12706b4fc4SDimitry Andric // in the GNU readline shared lib, which causes linkage confusion when
13706b4fc4SDimitry Andric // both readline and libedit's readline compatibility symbols collide.
14706b4fc4SDimitry Andric //
15706b4fc4SDimitry Andric // Currently it only installs a PyOS_ReadlineFunctionPointer, without
16706b4fc4SDimitry Andric // implementing any of the readline module methods. This is meant to
17706b4fc4SDimitry Andric // work around LLVM pr18841 to avoid seg faults in the stock Python
18706b4fc4SDimitry Andric // readline.so linked against GNU readline.
19706b4fc4SDimitry Andric //
20706b4fc4SDimitry Andric // Bug on the cpython side: https://bugs.python.org/issue38634
21706b4fc4SDimitry Andric 
22706b4fc4SDimitry Andric PyDoc_STRVAR(moduleDocumentation,
23706b4fc4SDimitry Andric              "Simple readline module implementation based on libedit.");
24706b4fc4SDimitry Andric 
25706b4fc4SDimitry Andric static struct PyModuleDef readline_module = {
26706b4fc4SDimitry Andric     PyModuleDef_HEAD_INIT, // m_base
27706b4fc4SDimitry Andric     "lldb_editline",       // m_name
28706b4fc4SDimitry Andric     moduleDocumentation,   // m_doc
29706b4fc4SDimitry Andric     -1,                    // m_size
30706b4fc4SDimitry Andric     nullptr,               // m_methods
31706b4fc4SDimitry Andric     nullptr,               // m_reload
32706b4fc4SDimitry Andric     nullptr,               // m_traverse
33706b4fc4SDimitry Andric     nullptr,               // m_clear
34706b4fc4SDimitry Andric     nullptr,               // m_free
35706b4fc4SDimitry Andric };
36706b4fc4SDimitry Andric 
simple_readline(FILE * stdin,FILE * stdout,const char * prompt)37145449b1SDimitry Andric static char *simple_readline(FILE *stdin, FILE *stdout, const char *prompt) {
38706b4fc4SDimitry Andric   rl_instream = stdin;
39706b4fc4SDimitry Andric   rl_outstream = stdout;
40706b4fc4SDimitry Andric   char *line = readline(prompt);
41706b4fc4SDimitry Andric   if (!line) {
42706b4fc4SDimitry Andric     char *ret = (char *)PyMem_RawMalloc(1);
43e3b55780SDimitry Andric     if (ret != nullptr)
44706b4fc4SDimitry Andric       *ret = '\0';
45706b4fc4SDimitry Andric     return ret;
46706b4fc4SDimitry Andric   }
47706b4fc4SDimitry Andric   if (*line)
48706b4fc4SDimitry Andric     add_history(line);
49706b4fc4SDimitry Andric   int n = strlen(line);
50706b4fc4SDimitry Andric   char *ret = (char *)PyMem_RawMalloc(n + 2);
51706b4fc4SDimitry Andric   if (ret) {
52706b4fc4SDimitry Andric     memcpy(ret, line, n);
53706b4fc4SDimitry Andric     free(line);
54706b4fc4SDimitry Andric     ret[n] = '\n';
55706b4fc4SDimitry Andric     ret[n + 1] = '\0';
56706b4fc4SDimitry Andric   }
57706b4fc4SDimitry Andric   return ret;
58706b4fc4SDimitry Andric }
59706b4fc4SDimitry Andric 
initlldb_readline(void)60706b4fc4SDimitry Andric PyMODINIT_FUNC initlldb_readline(void) {
61706b4fc4SDimitry Andric   PyOS_ReadlineFunctionPointer = simple_readline;
62706b4fc4SDimitry Andric 
63706b4fc4SDimitry Andric   return PyModule_Create(&readline_module);
64706b4fc4SDimitry Andric }
65706b4fc4SDimitry Andric #endif
66