xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp (revision 76e47d4887f456878c0e2f20ebfae36267006cd7)
19357b5d0Sserge-sans-paille #include "PythonReadline.h"
29357b5d0Sserge-sans-paille 
39357b5d0Sserge-sans-paille #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
49357b5d0Sserge-sans-paille 
5*76e47d48SRaphael Isemann #include <cstdio>
69357b5d0Sserge-sans-paille 
79357b5d0Sserge-sans-paille #include <editline/readline.h>
89357b5d0Sserge-sans-paille 
99357b5d0Sserge-sans-paille // Simple implementation of the Python readline module using libedit.
109357b5d0Sserge-sans-paille // In the event that libedit is excluded from the build, this turns
119357b5d0Sserge-sans-paille // back into a null implementation that blocks the module from pulling
129357b5d0Sserge-sans-paille // in the GNU readline shared lib, which causes linkage confusion when
139357b5d0Sserge-sans-paille // both readline and libedit's readline compatibility symbols collide.
149357b5d0Sserge-sans-paille //
159357b5d0Sserge-sans-paille // Currently it only installs a PyOS_ReadlineFunctionPointer, without
169357b5d0Sserge-sans-paille // implementing any of the readline module methods. This is meant to
179357b5d0Sserge-sans-paille // work around LLVM pr18841 to avoid seg faults in the stock Python
189357b5d0Sserge-sans-paille // readline.so linked against GNU readline.
199357b5d0Sserge-sans-paille //
209357b5d0Sserge-sans-paille // Bug on the cpython side: https://bugs.python.org/issue38634
219357b5d0Sserge-sans-paille 
229357b5d0Sserge-sans-paille PyDoc_STRVAR(moduleDocumentation,
239357b5d0Sserge-sans-paille              "Simple readline module implementation based on libedit.");
249357b5d0Sserge-sans-paille 
259357b5d0Sserge-sans-paille #if PY_MAJOR_VERSION >= 3
269357b5d0Sserge-sans-paille static struct PyModuleDef readline_module = {
279357b5d0Sserge-sans-paille     PyModuleDef_HEAD_INIT, // m_base
289357b5d0Sserge-sans-paille     "lldb_editline",       // m_name
299357b5d0Sserge-sans-paille     moduleDocumentation,   // m_doc
309357b5d0Sserge-sans-paille     -1,                    // m_size
319357b5d0Sserge-sans-paille     nullptr,               // m_methods
329357b5d0Sserge-sans-paille     nullptr,               // m_reload
339357b5d0Sserge-sans-paille     nullptr,               // m_traverse
349357b5d0Sserge-sans-paille     nullptr,               // m_clear
359357b5d0Sserge-sans-paille     nullptr,               // m_free
369357b5d0Sserge-sans-paille };
379357b5d0Sserge-sans-paille #else
389357b5d0Sserge-sans-paille static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
399357b5d0Sserge-sans-paille #endif
409357b5d0Sserge-sans-paille 
419357b5d0Sserge-sans-paille static char *
429357b5d0Sserge-sans-paille #if PY_MAJOR_VERSION >= 3
439357b5d0Sserge-sans-paille simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
449357b5d0Sserge-sans-paille #else
459357b5d0Sserge-sans-paille simple_readline(FILE *stdin, FILE *stdout, char *prompt)
469357b5d0Sserge-sans-paille #endif
479357b5d0Sserge-sans-paille {
489357b5d0Sserge-sans-paille   rl_instream = stdin;
499357b5d0Sserge-sans-paille   rl_outstream = stdout;
509357b5d0Sserge-sans-paille   char *line = readline(prompt);
519357b5d0Sserge-sans-paille   if (!line) {
52d5904988Sserge-sans-paille #if PY_MAJOR_VERSION >= 3
539357b5d0Sserge-sans-paille     char *ret = (char *)PyMem_RawMalloc(1);
54d5904988Sserge-sans-paille #else
55d5904988Sserge-sans-paille     char *ret = (char *)PyMem_Malloc(1);
56d5904988Sserge-sans-paille #endif
579357b5d0Sserge-sans-paille     if (ret != NULL)
589357b5d0Sserge-sans-paille       *ret = '\0';
599357b5d0Sserge-sans-paille     return ret;
609357b5d0Sserge-sans-paille   }
619357b5d0Sserge-sans-paille   if (*line)
629357b5d0Sserge-sans-paille     add_history(line);
639357b5d0Sserge-sans-paille   int n = strlen(line);
64d5904988Sserge-sans-paille #if PY_MAJOR_VERSION >= 3
659357b5d0Sserge-sans-paille   char *ret = (char *)PyMem_RawMalloc(n + 2);
66d5904988Sserge-sans-paille #else
67d5904988Sserge-sans-paille   char *ret = (char *)PyMem_Malloc(n + 2);
68d5904988Sserge-sans-paille #endif
699357b5d0Sserge-sans-paille   if (ret) {
701805d1f8SPavel Labath     memcpy(ret, line, n);
719357b5d0Sserge-sans-paille     free(line);
729357b5d0Sserge-sans-paille     ret[n] = '\n';
739357b5d0Sserge-sans-paille     ret[n + 1] = '\0';
749357b5d0Sserge-sans-paille   }
759357b5d0Sserge-sans-paille   return ret;
769357b5d0Sserge-sans-paille }
779357b5d0Sserge-sans-paille 
789357b5d0Sserge-sans-paille PyMODINIT_FUNC initlldb_readline(void) {
799357b5d0Sserge-sans-paille   PyOS_ReadlineFunctionPointer = simple_readline;
809357b5d0Sserge-sans-paille 
819357b5d0Sserge-sans-paille #if PY_MAJOR_VERSION >= 3
829357b5d0Sserge-sans-paille   return PyModule_Create(&readline_module);
839357b5d0Sserge-sans-paille #else
84d5904988Sserge-sans-paille   Py_InitModule4("readline", moduleMethods, moduleDocumentation,
859357b5d0Sserge-sans-paille                  static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
869357b5d0Sserge-sans-paille #endif
879357b5d0Sserge-sans-paille }
889357b5d0Sserge-sans-paille #endif
89