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