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