summaryrefslogtreecommitdiffstats
path: root/Parser/myreadline.c
diff options
context:
space:
mode:
Diffstat (limited to 'Parser/myreadline.c')
-rw-r--r--Parser/myreadline.c280
1 files changed, 65 insertions, 215 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index 43e5583..5376214 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -10,31 +10,40 @@
*/
#include "Python.h"
-#include "pycore_pystate.h"
#ifdef MS_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif /* MS_WINDOWS */
+#ifdef __VMS
+extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt);
+#endif
+
-PyThreadState* _PyOS_ReadlineTState = NULL;
+PyThreadState* _PyOS_ReadlineTState;
+#ifdef WITH_THREAD
#include "pythread.h"
static PyThread_type_lock _PyOS_ReadlineLock = NULL;
+#endif
int (*PyOS_InputHook)(void) = NULL;
+#ifdef RISCOS
+int Py_RISCOSWimpFlag;
+#endif
+
/* This function restarts a fgets() after an EINTR error occurred
except if PyOS_InterruptOccurred() returns true. */
static int
my_fgets(char *buf, int len, FILE *fp)
{
+ char *p;
#ifdef MS_WINDOWS
- HANDLE hInterruptEvent;
+ int i;
#endif
- char *p;
- int err;
+
while (1) {
if (PyOS_InputHook != NULL)
(void)(PyOS_InputHook)();
@@ -43,29 +52,24 @@ my_fgets(char *buf, int len, FILE *fp)
p = fgets(buf, len, fp);
if (p != NULL)
return 0; /* No error */
- err = errno;
#ifdef MS_WINDOWS
/* Ctrl-C anywhere on the line or Ctrl-Z if the only character
on a line will set ERROR_OPERATION_ABORTED. Under normal
circumstances Ctrl-C will also have caused the SIGINT handler
- to fire which will have set the event object returned by
- _PyOS_SigintEvent. This signal fires in another thread and
- is not guaranteed to have occurred before this point in the
- code.
-
- Therefore: check whether the event is set with a small timeout.
- If it is, assume this is a Ctrl-C and reset the event. If it
- isn't set assume that this is a Ctrl-Z on its own and drop
- through to check for EOF.
+ to fire. This signal fires in another thread and is not
+ guaranteed to have occurred before this point in the code.
+
+ Therefore: check in a small loop to see if the trigger has
+ fired, in which case assume this is a Ctrl-C event. If it
+ hasn't fired within 10ms assume that this is a Ctrl-Z on its
+ own or that the signal isn't going to fire for some other
+ reason and drop through to check for EOF.
*/
if (GetLastError()==ERROR_OPERATION_ABORTED) {
- hInterruptEvent = _PyOS_SigintEvent();
- switch (WaitForSingleObjectEx(hInterruptEvent, 10, FALSE)) {
- case WAIT_OBJECT_0:
- ResetEvent(hInterruptEvent);
- return 1; /* Interrupt */
- case WAIT_FAILED:
- return -2; /* Error */
+ for (i = 0; i < 10; i++) {
+ if (PyOS_InterruptOccurred())
+ return 1;
+ Sleep(1);
}
}
#endif /* MS_WINDOWS */
@@ -74,14 +78,18 @@ my_fgets(char *buf, int len, FILE *fp)
return -1; /* EOF */
}
#ifdef EINTR
- if (err == EINTR) {
+ if (errno == EINTR) {
int s;
+#ifdef WITH_THREAD
PyEval_RestoreThread(_PyOS_ReadlineTState);
+#endif
s = PyErr_CheckSignals();
+#ifdef WITH_THREAD
PyEval_SaveThread();
+#endif
if (s < 0)
return 1;
- /* try again */
+ /* try again */
continue;
}
#endif
@@ -93,185 +101,35 @@ my_fgets(char *buf, int len, FILE *fp)
/* NOTREACHED */
}
-#ifdef MS_WINDOWS
-/* Readline implementation using ReadConsoleW */
-
-extern char _get_console_type(HANDLE handle);
-
-char *
-_PyOS_WindowsConsoleReadline(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) {
- (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(_PyOS_ReadlineTState);
- 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 {
- PyErr_NoMemory();
- goto exit;
- }
- }
- else {
- wchar_t *tmp = PyMem_RawRealloc(wbuf, wbuflen * sizeof(wchar_t));
- if (tmp == NULL) {
- PyErr_NoMemory();
- goto exit;
- }
- wbuf = tmp;
- }
- }
-
- if (wbuf[0] == '\x1a') {
- buf = PyMem_RawMalloc(1);
- if (buf)
- buf[0] = '\0';
- else {
- PyErr_NoMemory();
- }
- goto exit;
- }
-
- u8len = WideCharToMultiByte(CP_UTF8, 0, wbuf, total_read, NULL, 0, NULL, NULL);
- buf = PyMem_RawMalloc(u8len + 1);
- if (buf == NULL) {
- PyErr_NoMemory();
- 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(_PyOS_ReadlineTState);
- PyErr_SetFromWindowsErr(err);
- PyEval_SaveThread();
- }
-
- return buf;
-}
-
-#endif
-
/* Readline implementation using fgets() */
char *
-PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
+PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
{
size_t n;
char *p, *pr;
-
-#ifdef MS_WINDOWS
- if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin) {
- HANDLE hStdIn, hStdErr;
-
- _Py_BEGIN_SUPPRESS_IPH
- hStdIn = (HANDLE)_get_osfhandle(fileno(sys_stdin));
- hStdErr = (HANDLE)_get_osfhandle(fileno(stderr));
- _Py_END_SUPPRESS_IPH
-
- if (_get_console_type(hStdIn) == 'r') {
- fflush(sys_stdout);
- if (prompt) {
- if (_get_console_type(hStdErr) == 'w') {
- wchar_t *wbuf;
- int wlen;
- wlen = MultiByteToWideChar(CP_UTF8, 0, prompt, -1,
- NULL, 0);
- if (wlen) {
- wbuf = PyMem_RawMalloc(wlen * sizeof(wchar_t));
- if (wbuf == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- wlen = MultiByteToWideChar(CP_UTF8, 0, prompt, -1,
- wbuf, wlen);
- if (wlen) {
- DWORD n;
- fflush(stderr);
- /* wlen includes null terminator, so subtract 1 */
- WriteConsoleW(hStdErr, wbuf, wlen - 1, &n, NULL);
- }
- PyMem_RawFree(wbuf);
- }
- } else {
- fprintf(stderr, "%s", prompt);
- fflush(stderr);
- }
- }
- clearerr(sys_stdin);
- return _PyOS_WindowsConsoleReadline(hStdIn);
- }
- }
-#endif
-
n = 100;
- p = (char *)PyMem_RawMalloc(n);
- if (p == NULL) {
- PyErr_NoMemory();
+ if ((p = (char *)PyMem_MALLOC(n)) == NULL)
return NULL;
- }
-
fflush(sys_stdout);
+#ifndef RISCOS
if (prompt)
fprintf(stderr, "%s", prompt);
+#else
+ if (prompt) {
+ if(Py_RISCOSWimpFlag)
+ fprintf(stderr, "\x0cr%s\x0c", prompt);
+ else
+ fprintf(stderr, "%s", prompt);
+ }
+#endif
fflush(stderr);
-
switch (my_fgets(p, (int)n, sys_stdin)) {
case 0: /* Normal case */
break;
case 1: /* Interrupt */
- PyMem_RawFree(p);
+ PyMem_FREE(p);
return NULL;
case -1: /* EOF */
case -2: /* Error */
@@ -283,13 +141,13 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
while (n > 0 && p[n-1] != '\n') {
size_t incr = n+2;
if (incr > INT_MAX) {
- PyMem_RawFree(p);
+ PyMem_FREE(p);
PyErr_SetString(PyExc_OverflowError, "input line too long");
return NULL;
}
- pr = (char *)PyMem_RawRealloc(p, n + incr);
+ pr = (char *)PyMem_REALLOC(p, n + incr);
if (pr == NULL) {
- PyMem_RawFree(p);
+ PyMem_FREE(p);
PyErr_NoMemory();
return NULL;
}
@@ -298,9 +156,9 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
break;
n += strlen(p+n);
}
- pr = (char *)PyMem_RawRealloc(p, n+1);
+ pr = (char *)PyMem_REALLOC(p, n+1);
if (pr == NULL) {
- PyMem_RawFree(p);
+ PyMem_FREE(p);
PyErr_NoMemory();
return NULL;
}
@@ -313,18 +171,17 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
Note: Python expects in return a buffer allocated with PyMem_Malloc. */
-char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) = NULL;
+char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *);
/* Interface used by tokenizer.c and bltinmodule.c */
char *
-PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
+PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
{
- char *rv, *res;
- size_t len;
+ char *rv;
- if (_PyOS_ReadlineTState == _PyThreadState_GET()) {
+ if (_PyOS_ReadlineTState == PyThreadState_GET()) {
PyErr_SetString(PyExc_RuntimeError,
"can't re-enter readline");
return NULL;
@@ -332,20 +189,24 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
if (PyOS_ReadlineFunctionPointer == NULL) {
+#ifdef __VMS
+ PyOS_ReadlineFunctionPointer = vms__StdioReadline;
+#else
PyOS_ReadlineFunctionPointer = PyOS_StdioReadline;
+#endif
}
+#ifdef WITH_THREAD
if (_PyOS_ReadlineLock == NULL) {
_PyOS_ReadlineLock = PyThread_allocate_lock();
- if (_PyOS_ReadlineLock == NULL) {
- PyErr_SetString(PyExc_MemoryError, "can't allocate lock");
- return NULL;
- }
}
+#endif
- _PyOS_ReadlineTState = _PyThreadState_GET();
+ _PyOS_ReadlineTState = PyThreadState_GET();
Py_BEGIN_ALLOW_THREADS
+#ifdef WITH_THREAD
PyThread_acquire_lock(_PyOS_ReadlineLock, 1);
+#endif
/* This is needed to handle the unlikely case that the
* interpreter is in interactive mode *and* stdin/out are not
@@ -359,22 +220,11 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
prompt);
Py_END_ALLOW_THREADS
+#ifdef WITH_THREAD
PyThread_release_lock(_PyOS_ReadlineLock);
+#endif
_PyOS_ReadlineTState = NULL;
- if (rv == NULL)
- return NULL;
-
- len = strlen(rv) + 1;
- res = PyMem_Malloc(len);
- if (res != NULL) {
- memcpy(res, rv, len);
- }
- else {
- PyErr_NoMemory();
- }
- PyMem_RawFree(rv);
-
- return res;
+ return rv;
}