xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp (revision 5469a9953005a9a4d4aad7be88545d441622e9a0)
1  #include "PythonReadline.h"
2  
3  #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
4  
5  #include <stdio.h>
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  #if PY_MAJOR_VERSION >= 3
26  static struct PyModuleDef readline_module = {
27      PyModuleDef_HEAD_INIT, // m_base
28      "lldb_editline",       // m_name
29      moduleDocumentation,   // m_doc
30      -1,                    // m_size
31      nullptr,               // m_methods
32      nullptr,               // m_reload
33      nullptr,               // m_traverse
34      nullptr,               // m_clear
35      nullptr,               // m_free
36  };
37  #else
38  static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
39  #endif
40  
41  static char *
42  #if PY_MAJOR_VERSION >= 3
43  simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
44  #else
45  simple_readline(FILE *stdin, FILE *stdout, char *prompt)
46  #endif
47  {
48    rl_instream = stdin;
49    rl_outstream = stdout;
50    char *line = readline(prompt);
51    if (!line) {
52  #if PY_MAJOR_VERSION >= 3
53      char *ret = (char *)PyMem_RawMalloc(1);
54  #else
55      char *ret = (char *)PyMem_Malloc(1);
56  #endif
57      if (ret != NULL)
58        *ret = '\0';
59      return ret;
60    }
61    if (*line)
62      add_history(line);
63    int n = strlen(line);
64  #if PY_MAJOR_VERSION >= 3
65    char *ret = (char *)PyMem_RawMalloc(n + 2);
66  #else
67    char *ret = (char *)PyMem_Malloc(n + 2);
68  #endif
69    if (ret) {
70      memcpy(ret, line, n);
71      free(line);
72      ret[n] = '\n';
73      ret[n + 1] = '\0';
74    }
75    return ret;
76  }
77  
78  PyMODINIT_FUNC initlldb_readline(void) {
79    PyOS_ReadlineFunctionPointer = simple_readline;
80  
81  #if PY_MAJOR_VERSION >= 3
82    return PyModule_Create(&readline_module);
83  #else
84    Py_InitModule4("readline", moduleMethods, moduleDocumentation,
85                   static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
86  #endif
87  }
88  #endif
89