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