PythonReadline.cpp revision 360661
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 22PyDoc_STRVAR(moduleDocumentation, 23 "Simple readline module implementation based on libedit."); 24 25#if PY_MAJOR_VERSION >= 3 26static 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 38static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}}; 39#endif 40 41static char * 42#if PY_MAJOR_VERSION >= 3 43simple_readline(FILE *stdin, FILE *stdout, const char *prompt) 44#else 45simple_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 strncpy(ret, line, n); 71 free(line); 72 ret[n] = '\n'; 73 ret[n + 1] = '\0'; 74 } 75 return ret; 76} 77 78PyMODINIT_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