17db96d56Sopenharmony_ci 27db96d56Sopenharmony_ci/* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c. 37db96d56Sopenharmony_ci By default, or when stdin is not a tty device, we have a super 47db96d56Sopenharmony_ci simple my_readline function using fgets. 57db96d56Sopenharmony_ci Optionally, we can use the GNU readline library. 67db96d56Sopenharmony_ci my_readline() has a different return value from GNU readline(): 77db96d56Sopenharmony_ci - NULL if an interrupt occurred or if an error occurred 87db96d56Sopenharmony_ci - a malloc'ed empty string if EOF was read 97db96d56Sopenharmony_ci - a malloc'ed string ending in \n normally 107db96d56Sopenharmony_ci*/ 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ci#include "Python.h" 137db96d56Sopenharmony_ci#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH 147db96d56Sopenharmony_ci#include "pycore_pystate.h" // _PyThreadState_GET() 157db96d56Sopenharmony_ci#ifdef MS_WINDOWS 167db96d56Sopenharmony_ci# define WIN32_LEAN_AND_MEAN 177db96d56Sopenharmony_ci# include "windows.h" 187db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ciPyThreadState* _PyOS_ReadlineTState = NULL; 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_cistatic PyThread_type_lock _PyOS_ReadlineLock = NULL; 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ciint (*PyOS_InputHook)(void) = NULL; 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci/* This function restarts a fgets() after an EINTR error occurred 287db96d56Sopenharmony_ci except if _PyOS_InterruptOccurred() returns true. */ 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_cistatic int 317db96d56Sopenharmony_cimy_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp) 327db96d56Sopenharmony_ci{ 337db96d56Sopenharmony_ci#ifdef MS_WINDOWS 347db96d56Sopenharmony_ci HANDLE handle; 357db96d56Sopenharmony_ci _Py_BEGIN_SUPPRESS_IPH 367db96d56Sopenharmony_ci handle = (HANDLE)_get_osfhandle(fileno(fp)); 377db96d56Sopenharmony_ci _Py_END_SUPPRESS_IPH 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci /* bpo-40826: fgets(fp) does crash if fileno(fp) is closed */ 407db96d56Sopenharmony_ci if (handle == INVALID_HANDLE_VALUE) { 417db96d56Sopenharmony_ci return -1; /* EOF */ 427db96d56Sopenharmony_ci } 437db96d56Sopenharmony_ci#endif 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_ci while (1) { 467db96d56Sopenharmony_ci if (PyOS_InputHook != NULL) { 477db96d56Sopenharmony_ci (void)(PyOS_InputHook)(); 487db96d56Sopenharmony_ci } 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ci errno = 0; 517db96d56Sopenharmony_ci clearerr(fp); 527db96d56Sopenharmony_ci char *p = fgets(buf, len, fp); 537db96d56Sopenharmony_ci if (p != NULL) { 547db96d56Sopenharmony_ci return 0; /* No error */ 557db96d56Sopenharmony_ci } 567db96d56Sopenharmony_ci int err = errno; 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci#ifdef MS_WINDOWS 597db96d56Sopenharmony_ci /* Ctrl-C anywhere on the line or Ctrl-Z if the only character 607db96d56Sopenharmony_ci on a line will set ERROR_OPERATION_ABORTED. Under normal 617db96d56Sopenharmony_ci circumstances Ctrl-C will also have caused the SIGINT handler 627db96d56Sopenharmony_ci to fire which will have set the event object returned by 637db96d56Sopenharmony_ci _PyOS_SigintEvent. This signal fires in another thread and 647db96d56Sopenharmony_ci is not guaranteed to have occurred before this point in the 657db96d56Sopenharmony_ci code. 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci Therefore: check whether the event is set with a small timeout. 687db96d56Sopenharmony_ci If it is, assume this is a Ctrl-C and reset the event. If it 697db96d56Sopenharmony_ci isn't set assume that this is a Ctrl-Z on its own and drop 707db96d56Sopenharmony_ci through to check for EOF. 717db96d56Sopenharmony_ci */ 727db96d56Sopenharmony_ci if (GetLastError()==ERROR_OPERATION_ABORTED) { 737db96d56Sopenharmony_ci HANDLE hInterruptEvent = _PyOS_SigintEvent(); 747db96d56Sopenharmony_ci switch (WaitForSingleObjectEx(hInterruptEvent, 10, FALSE)) { 757db96d56Sopenharmony_ci case WAIT_OBJECT_0: 767db96d56Sopenharmony_ci ResetEvent(hInterruptEvent); 777db96d56Sopenharmony_ci return 1; /* Interrupt */ 787db96d56Sopenharmony_ci case WAIT_FAILED: 797db96d56Sopenharmony_ci return -2; /* Error */ 807db96d56Sopenharmony_ci } 817db96d56Sopenharmony_ci } 827db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci if (feof(fp)) { 857db96d56Sopenharmony_ci clearerr(fp); 867db96d56Sopenharmony_ci return -1; /* EOF */ 877db96d56Sopenharmony_ci } 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci#ifdef EINTR 907db96d56Sopenharmony_ci if (err == EINTR) { 917db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 927db96d56Sopenharmony_ci int s = PyErr_CheckSignals(); 937db96d56Sopenharmony_ci PyEval_SaveThread(); 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ci if (s < 0) { 967db96d56Sopenharmony_ci return 1; 977db96d56Sopenharmony_ci } 987db96d56Sopenharmony_ci /* try again */ 997db96d56Sopenharmony_ci continue; 1007db96d56Sopenharmony_ci } 1017db96d56Sopenharmony_ci#endif 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci if (_PyOS_InterruptOccurred(tstate)) { 1047db96d56Sopenharmony_ci return 1; /* Interrupt */ 1057db96d56Sopenharmony_ci } 1067db96d56Sopenharmony_ci return -2; /* Error */ 1077db96d56Sopenharmony_ci } 1087db96d56Sopenharmony_ci /* NOTREACHED */ 1097db96d56Sopenharmony_ci} 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci#ifdef MS_WINDOWS 1127db96d56Sopenharmony_ci/* Readline implementation using ReadConsoleW */ 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ciextern char _get_console_type(HANDLE handle); 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_cichar * 1177db96d56Sopenharmony_ci_PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn) 1187db96d56Sopenharmony_ci{ 1197db96d56Sopenharmony_ci static wchar_t wbuf_local[1024 * 16]; 1207db96d56Sopenharmony_ci const DWORD chunk_size = 1024; 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci DWORD n_read, total_read, wbuflen, u8len; 1237db96d56Sopenharmony_ci wchar_t *wbuf; 1247db96d56Sopenharmony_ci char *buf = NULL; 1257db96d56Sopenharmony_ci int err = 0; 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci n_read = (DWORD)-1; 1287db96d56Sopenharmony_ci total_read = 0; 1297db96d56Sopenharmony_ci wbuf = wbuf_local; 1307db96d56Sopenharmony_ci wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1; 1317db96d56Sopenharmony_ci while (1) { 1327db96d56Sopenharmony_ci if (PyOS_InputHook != NULL) { 1337db96d56Sopenharmony_ci (void)(PyOS_InputHook)(); 1347db96d56Sopenharmony_ci } 1357db96d56Sopenharmony_ci if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) { 1367db96d56Sopenharmony_ci err = GetLastError(); 1377db96d56Sopenharmony_ci goto exit; 1387db96d56Sopenharmony_ci } 1397db96d56Sopenharmony_ci if (n_read == (DWORD)-1 && (err = GetLastError()) == ERROR_OPERATION_ABORTED) { 1407db96d56Sopenharmony_ci break; 1417db96d56Sopenharmony_ci } 1427db96d56Sopenharmony_ci if (n_read == 0) { 1437db96d56Sopenharmony_ci int s; 1447db96d56Sopenharmony_ci err = GetLastError(); 1457db96d56Sopenharmony_ci if (err != ERROR_OPERATION_ABORTED) 1467db96d56Sopenharmony_ci goto exit; 1477db96d56Sopenharmony_ci err = 0; 1487db96d56Sopenharmony_ci HANDLE hInterruptEvent = _PyOS_SigintEvent(); 1497db96d56Sopenharmony_ci if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE) 1507db96d56Sopenharmony_ci == WAIT_OBJECT_0) { 1517db96d56Sopenharmony_ci ResetEvent(hInterruptEvent); 1527db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 1537db96d56Sopenharmony_ci s = PyErr_CheckSignals(); 1547db96d56Sopenharmony_ci PyEval_SaveThread(); 1557db96d56Sopenharmony_ci if (s < 0) { 1567db96d56Sopenharmony_ci goto exit; 1577db96d56Sopenharmony_ci } 1587db96d56Sopenharmony_ci } 1597db96d56Sopenharmony_ci break; 1607db96d56Sopenharmony_ci } 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci total_read += n_read; 1637db96d56Sopenharmony_ci if (total_read == 0 || wbuf[total_read - 1] == L'\n') { 1647db96d56Sopenharmony_ci break; 1657db96d56Sopenharmony_ci } 1667db96d56Sopenharmony_ci wbuflen += chunk_size; 1677db96d56Sopenharmony_ci if (wbuf == wbuf_local) { 1687db96d56Sopenharmony_ci wbuf[total_read] = '\0'; 1697db96d56Sopenharmony_ci wbuf = (wchar_t*)PyMem_RawMalloc(wbuflen * sizeof(wchar_t)); 1707db96d56Sopenharmony_ci if (wbuf) { 1717db96d56Sopenharmony_ci wcscpy_s(wbuf, wbuflen, wbuf_local); 1727db96d56Sopenharmony_ci } 1737db96d56Sopenharmony_ci else { 1747db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 1757db96d56Sopenharmony_ci PyErr_NoMemory(); 1767db96d56Sopenharmony_ci PyEval_SaveThread(); 1777db96d56Sopenharmony_ci goto exit; 1787db96d56Sopenharmony_ci } 1797db96d56Sopenharmony_ci } 1807db96d56Sopenharmony_ci else { 1817db96d56Sopenharmony_ci wchar_t *tmp = PyMem_RawRealloc(wbuf, wbuflen * sizeof(wchar_t)); 1827db96d56Sopenharmony_ci if (tmp == NULL) { 1837db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 1847db96d56Sopenharmony_ci PyErr_NoMemory(); 1857db96d56Sopenharmony_ci PyEval_SaveThread(); 1867db96d56Sopenharmony_ci goto exit; 1877db96d56Sopenharmony_ci } 1887db96d56Sopenharmony_ci wbuf = tmp; 1897db96d56Sopenharmony_ci } 1907db96d56Sopenharmony_ci } 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci if (wbuf[0] == '\x1a') { 1937db96d56Sopenharmony_ci buf = PyMem_RawMalloc(1); 1947db96d56Sopenharmony_ci if (buf) { 1957db96d56Sopenharmony_ci buf[0] = '\0'; 1967db96d56Sopenharmony_ci } 1977db96d56Sopenharmony_ci else { 1987db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 1997db96d56Sopenharmony_ci PyErr_NoMemory(); 2007db96d56Sopenharmony_ci PyEval_SaveThread(); 2017db96d56Sopenharmony_ci } 2027db96d56Sopenharmony_ci goto exit; 2037db96d56Sopenharmony_ci } 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci u8len = WideCharToMultiByte(CP_UTF8, 0, 2067db96d56Sopenharmony_ci wbuf, total_read, 2077db96d56Sopenharmony_ci NULL, 0, 2087db96d56Sopenharmony_ci NULL, NULL); 2097db96d56Sopenharmony_ci buf = PyMem_RawMalloc(u8len + 1); 2107db96d56Sopenharmony_ci if (buf == NULL) { 2117db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 2127db96d56Sopenharmony_ci PyErr_NoMemory(); 2137db96d56Sopenharmony_ci PyEval_SaveThread(); 2147db96d56Sopenharmony_ci goto exit; 2157db96d56Sopenharmony_ci } 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci u8len = WideCharToMultiByte(CP_UTF8, 0, 2187db96d56Sopenharmony_ci wbuf, total_read, 2197db96d56Sopenharmony_ci buf, u8len, 2207db96d56Sopenharmony_ci NULL, NULL); 2217db96d56Sopenharmony_ci buf[u8len] = '\0'; 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ciexit: 2247db96d56Sopenharmony_ci if (wbuf != wbuf_local) { 2257db96d56Sopenharmony_ci PyMem_RawFree(wbuf); 2267db96d56Sopenharmony_ci } 2277db96d56Sopenharmony_ci 2287db96d56Sopenharmony_ci if (err) { 2297db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 2307db96d56Sopenharmony_ci PyErr_SetFromWindowsErr(err); 2317db96d56Sopenharmony_ci PyEval_SaveThread(); 2327db96d56Sopenharmony_ci } 2337db96d56Sopenharmony_ci return buf; 2347db96d56Sopenharmony_ci} 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci#endif 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci/* Readline implementation using fgets() */ 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_cichar * 2427db96d56Sopenharmony_ciPyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) 2437db96d56Sopenharmony_ci{ 2447db96d56Sopenharmony_ci size_t n; 2457db96d56Sopenharmony_ci char *p, *pr; 2467db96d56Sopenharmony_ci PyThreadState *tstate = _PyOS_ReadlineTState; 2477db96d56Sopenharmony_ci assert(tstate != NULL); 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci#ifdef MS_WINDOWS 2507db96d56Sopenharmony_ci if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin) { 2517db96d56Sopenharmony_ci HANDLE hStdIn, hStdErr; 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ci hStdIn = _Py_get_osfhandle_noraise(fileno(sys_stdin)); 2547db96d56Sopenharmony_ci hStdErr = _Py_get_osfhandle_noraise(fileno(stderr)); 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci if (_get_console_type(hStdIn) == 'r') { 2577db96d56Sopenharmony_ci fflush(sys_stdout); 2587db96d56Sopenharmony_ci if (prompt) { 2597db96d56Sopenharmony_ci if (_get_console_type(hStdErr) == 'w') { 2607db96d56Sopenharmony_ci wchar_t *wbuf; 2617db96d56Sopenharmony_ci int wlen; 2627db96d56Sopenharmony_ci wlen = MultiByteToWideChar(CP_UTF8, 0, prompt, -1, 2637db96d56Sopenharmony_ci NULL, 0); 2647db96d56Sopenharmony_ci if (wlen) { 2657db96d56Sopenharmony_ci wbuf = PyMem_RawMalloc(wlen * sizeof(wchar_t)); 2667db96d56Sopenharmony_ci if (wbuf == NULL) { 2677db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 2687db96d56Sopenharmony_ci PyErr_NoMemory(); 2697db96d56Sopenharmony_ci PyEval_SaveThread(); 2707db96d56Sopenharmony_ci return NULL; 2717db96d56Sopenharmony_ci } 2727db96d56Sopenharmony_ci wlen = MultiByteToWideChar(CP_UTF8, 0, prompt, -1, 2737db96d56Sopenharmony_ci wbuf, wlen); 2747db96d56Sopenharmony_ci if (wlen) { 2757db96d56Sopenharmony_ci DWORD n; 2767db96d56Sopenharmony_ci fflush(stderr); 2777db96d56Sopenharmony_ci /* wlen includes null terminator, so subtract 1 */ 2787db96d56Sopenharmony_ci WriteConsoleW(hStdErr, wbuf, wlen - 1, &n, NULL); 2797db96d56Sopenharmony_ci } 2807db96d56Sopenharmony_ci PyMem_RawFree(wbuf); 2817db96d56Sopenharmony_ci } 2827db96d56Sopenharmony_ci } else { 2837db96d56Sopenharmony_ci fprintf(stderr, "%s", prompt); 2847db96d56Sopenharmony_ci fflush(stderr); 2857db96d56Sopenharmony_ci } 2867db96d56Sopenharmony_ci } 2877db96d56Sopenharmony_ci clearerr(sys_stdin); 2887db96d56Sopenharmony_ci return _PyOS_WindowsConsoleReadline(tstate, hStdIn); 2897db96d56Sopenharmony_ci } 2907db96d56Sopenharmony_ci } 2917db96d56Sopenharmony_ci#endif 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci fflush(sys_stdout); 2947db96d56Sopenharmony_ci if (prompt) { 2957db96d56Sopenharmony_ci fprintf(stderr, "%s", prompt); 2967db96d56Sopenharmony_ci } 2977db96d56Sopenharmony_ci fflush(stderr); 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci n = 0; 3007db96d56Sopenharmony_ci p = NULL; 3017db96d56Sopenharmony_ci do { 3027db96d56Sopenharmony_ci size_t incr = (n > 0) ? n + 2 : 100; 3037db96d56Sopenharmony_ci if (incr > INT_MAX) { 3047db96d56Sopenharmony_ci PyMem_RawFree(p); 3057db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 3067db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "input line too long"); 3077db96d56Sopenharmony_ci PyEval_SaveThread(); 3087db96d56Sopenharmony_ci return NULL; 3097db96d56Sopenharmony_ci } 3107db96d56Sopenharmony_ci pr = (char *)PyMem_RawRealloc(p, n + incr); 3117db96d56Sopenharmony_ci if (pr == NULL) { 3127db96d56Sopenharmony_ci PyMem_RawFree(p); 3137db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 3147db96d56Sopenharmony_ci PyErr_NoMemory(); 3157db96d56Sopenharmony_ci PyEval_SaveThread(); 3167db96d56Sopenharmony_ci return NULL; 3177db96d56Sopenharmony_ci } 3187db96d56Sopenharmony_ci p = pr; 3197db96d56Sopenharmony_ci int err = my_fgets(tstate, p + n, (int)incr, sys_stdin); 3207db96d56Sopenharmony_ci if (err == 1) { 3217db96d56Sopenharmony_ci // Interrupt 3227db96d56Sopenharmony_ci PyMem_RawFree(p); 3237db96d56Sopenharmony_ci return NULL; 3247db96d56Sopenharmony_ci } else if (err != 0) { 3257db96d56Sopenharmony_ci // EOF or error 3267db96d56Sopenharmony_ci p[n] = '\0'; 3277db96d56Sopenharmony_ci break; 3287db96d56Sopenharmony_ci } 3297db96d56Sopenharmony_ci n += strlen(p + n); 3307db96d56Sopenharmony_ci } while (p[n-1] != '\n'); 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci pr = (char *)PyMem_RawRealloc(p, n+1); 3337db96d56Sopenharmony_ci if (pr == NULL) { 3347db96d56Sopenharmony_ci PyMem_RawFree(p); 3357db96d56Sopenharmony_ci PyEval_RestoreThread(tstate); 3367db96d56Sopenharmony_ci PyErr_NoMemory(); 3377db96d56Sopenharmony_ci PyEval_SaveThread(); 3387db96d56Sopenharmony_ci return NULL; 3397db96d56Sopenharmony_ci } 3407db96d56Sopenharmony_ci return pr; 3417db96d56Sopenharmony_ci} 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci/* By initializing this function pointer, systems embedding Python can 3457db96d56Sopenharmony_ci override the readline function. 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci Note: Python expects in return a buffer allocated with PyMem_Malloc. */ 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_cichar *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) = NULL; 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ci/* Interface used by tokenizer.c and bltinmodule.c */ 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_cichar * 3557db96d56Sopenharmony_ciPyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) 3567db96d56Sopenharmony_ci{ 3577db96d56Sopenharmony_ci char *rv, *res; 3587db96d56Sopenharmony_ci size_t len; 3597db96d56Sopenharmony_ci 3607db96d56Sopenharmony_ci PyThreadState *tstate = _PyThreadState_GET(); 3617db96d56Sopenharmony_ci if (_PyOS_ReadlineTState == tstate) { 3627db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 3637db96d56Sopenharmony_ci "can't re-enter readline"); 3647db96d56Sopenharmony_ci return NULL; 3657db96d56Sopenharmony_ci } 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci if (PyOS_ReadlineFunctionPointer == NULL) { 3697db96d56Sopenharmony_ci PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; 3707db96d56Sopenharmony_ci } 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci if (_PyOS_ReadlineLock == NULL) { 3737db96d56Sopenharmony_ci _PyOS_ReadlineLock = PyThread_allocate_lock(); 3747db96d56Sopenharmony_ci if (_PyOS_ReadlineLock == NULL) { 3757db96d56Sopenharmony_ci PyErr_SetString(PyExc_MemoryError, "can't allocate lock"); 3767db96d56Sopenharmony_ci return NULL; 3777db96d56Sopenharmony_ci } 3787db96d56Sopenharmony_ci } 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci _PyOS_ReadlineTState = tstate; 3817db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 3827db96d56Sopenharmony_ci PyThread_acquire_lock(_PyOS_ReadlineLock, 1); 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci /* This is needed to handle the unlikely case that the 3857db96d56Sopenharmony_ci * interpreter is in interactive mode *and* stdin/out are not 3867db96d56Sopenharmony_ci * a tty. This can happen, for example if python is run like 3877db96d56Sopenharmony_ci * this: python -i < test1.py 3887db96d56Sopenharmony_ci */ 3897db96d56Sopenharmony_ci if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) 3907db96d56Sopenharmony_ci rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); 3917db96d56Sopenharmony_ci else 3927db96d56Sopenharmony_ci rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, 3937db96d56Sopenharmony_ci prompt); 3947db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci PyThread_release_lock(_PyOS_ReadlineLock); 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci _PyOS_ReadlineTState = NULL; 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci if (rv == NULL) 4017db96d56Sopenharmony_ci return NULL; 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci len = strlen(rv) + 1; 4047db96d56Sopenharmony_ci res = PyMem_Malloc(len); 4057db96d56Sopenharmony_ci if (res != NULL) { 4067db96d56Sopenharmony_ci memcpy(res, rv, len); 4077db96d56Sopenharmony_ci } 4087db96d56Sopenharmony_ci else { 4097db96d56Sopenharmony_ci PyErr_NoMemory(); 4107db96d56Sopenharmony_ci } 4117db96d56Sopenharmony_ci PyMem_RawFree(rv); 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ci return res; 4147db96d56Sopenharmony_ci} 415