xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1  #include "PythonReadline.h"
2  
3  #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
4  
5  #include <cstdio>
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  static struct PyModuleDef readline_module = {
26      PyModuleDef_HEAD_INIT, // m_base
27      "lldb_editline",       // m_name
28      moduleDocumentation,   // m_doc
29      -1,                    // m_size
30      nullptr,               // m_methods
31      nullptr,               // m_reload
32      nullptr,               // m_traverse
33      nullptr,               // m_clear
34      nullptr,               // m_free
35  };
36  
37  static char *simple_readline(FILE *stdin, FILE *stdout, const char *prompt) {
38    rl_instream = stdin;
39    rl_outstream = stdout;
40    char *line = readline(prompt);
41    if (!line) {
42      char *ret = (char *)PyMem_RawMalloc(1);
43      if (ret != nullptr)
44        *ret = '\0';
45      return ret;
46    }
47    if (*line)
48      add_history(line);
49    int n = strlen(line);
50    char *ret = (char *)PyMem_RawMalloc(n + 2);
51    if (ret) {
52      memcpy(ret, line, n);
53      free(line);
54      ret[n] = '\n';
55      ret[n + 1] = '\0';
56    }
57    return ret;
58  }
59  
60  PyMODINIT_FUNC initlldb_readline(void) {
61    PyOS_ReadlineFunctionPointer = simple_readline;
62  
63    return PyModule_Create(&readline_module);
64  }
65  #endif
66