#include "Python.h"
#include "pycore_fileutils.h"
#include "pycore_pystate.h"
#ifdef MS_WINDOWS
# ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
# endif
# include "windows.h"
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState;
PyThreadState *_PyOS_ReadlineTState = …;
static PyMutex _PyOS_ReadlineLock;
int (*PyOS_InputHook)(void) = …;
static int
my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp)
{ … }
#ifdef HAVE_WINDOWS_CONSOLE_IO
extern char _get_console_type(HANDLE handle);
char *
_PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn)
{
static wchar_t wbuf_local[1024 * 16];
const DWORD chunk_size = 1024;
DWORD n_read, total_read, wbuflen, u8len;
wchar_t *wbuf;
char *buf = NULL;
int err = 0;
n_read = (DWORD)-1;
total_read = 0;
wbuf = wbuf_local;
wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1;
while (1) {
if (PyOS_InputHook != NULL &&
_Py_IsMainInterpreter(tstate->interp))
{
(void)(PyOS_InputHook)();
}
if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) {
err = GetLastError();
goto exit;
}
if (n_read == (DWORD)-1 && (err = GetLastError()) == ERROR_OPERATION_ABORTED) {
break;
}
if (n_read == 0) {
int s;
err = GetLastError();
if (err != ERROR_OPERATION_ABORTED)
goto exit;
err = 0;
HANDLE hInterruptEvent = _PyOS_SigintEvent();
if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE)
== WAIT_OBJECT_0) {
ResetEvent(hInterruptEvent);
PyEval_RestoreThread(tstate);
s = PyErr_CheckSignals();
PyEval_SaveThread();
if (s < 0) {
goto exit;
}
}
break;
}
total_read += n_read;
if (total_read == 0 || wbuf[total_read - 1] == L'\n') {
break;
}
wbuflen += chunk_size;
if (wbuf == wbuf_local) {
wbuf[total_read] = '\0';
wbuf = (wchar_t*)PyMem_RawMalloc(wbuflen * sizeof(wchar_t));
if (wbuf) {
wcscpy_s(wbuf, wbuflen, wbuf_local);
}
else {
PyEval_RestoreThread(tstate);
PyErr_NoMemory();
PyEval_SaveThread();
goto exit;
}
}
else {
wchar_t *tmp = PyMem_RawRealloc(wbuf, wbuflen * sizeof(wchar_t));
if (tmp == NULL) {
PyEval_RestoreThread(tstate);
PyErr_NoMemory();
PyEval_SaveThread();
goto exit;
}
wbuf = tmp;
}
}
if (wbuf[0] == '\x1a') {
buf = PyMem_RawMalloc(1);
if (buf) {
buf[0] = '\0';
}
else {
PyEval_RestoreThread(tstate);
PyErr_NoMemory();
PyEval_SaveThread();
}
goto exit;
}
u8len = WideCharToMultiByte(CP_UTF8, 0,
wbuf, total_read,
NULL, 0,
NULL, NULL);
buf = PyMem_RawMalloc(u8len + 1);
if (buf == NULL) {
PyEval_RestoreThread(tstate);
PyErr_NoMemory();
PyEval_SaveThread();
goto exit;
}
u8len = WideCharToMultiByte(CP_UTF8, 0,
wbuf, total_read,
buf, u8len,
NULL, NULL);
buf[u8len] = '\0';
exit:
if (wbuf != wbuf_local) {
PyMem_RawFree(wbuf);
}
if (err) {
PyEval_RestoreThread(tstate);
PyErr_SetFromWindowsErr(err);
PyEval_SaveThread();
}
return buf;
}
#endif
char *
PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
{ … }
char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) = …;
char *
PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
{ … }