Commit 191d7d5b authored by Kevin Modzelewski's avatar Kevin Modzelewski

raw_input()

parent 9dfad04e
......@@ -374,7 +374,10 @@ STDPYTHON_SRCS := \
marshal.c \
$(EXTRA_STDPYTHON_SRCS)
FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS))
STDPARSER_SRCS := \
myreadline.c
FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS)) $(addprefix from_cpython/Parser/,$(STDPARSER_SRCS))
# The stdlib objects have slightly longer dependency chains,
# so put them first in the list:
......
......@@ -97,5 +97,10 @@ file(GLOB_RECURSE STDPYTHON_SRCS Python
marshal.c
)
# compile specified files in from_cpython/Python
file(GLOB_RECURSE STDPARSER_SRCS Parser
myreadline.c
)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-tautological-compare -Wno-type-limits -Wno-unused-result -Wno-strict-aliasing")
add_library(FROM_CPYTHON OBJECT ${STDMODULE_SRCS} ${STDOBJECT_SRCS} ${STDPYTHON_SRCS})
add_library(FROM_CPYTHON OBJECT ${STDMODULE_SRCS} ${STDOBJECT_SRCS} ${STDPYTHON_SRCS} ${STDPARSER_SRCS})
......@@ -148,9 +148,9 @@ PyAPI_FUNC(void) PyOS_FiniInterrupts(void) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyByteArray_Fini(void) PYSTON_NOEXCEPT;
/* Stuff with no proper home (yet) */
PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *) PYSTON_NOEXCEPT;
PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, const char *) PYSTON_NOEXCEPT;
PyAPI_DATA(int) (*PyOS_InputHook)(void);
PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *);
PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *);
PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState;
/* Stack size, in "pointers" (so we get extra safety margins
......
// This file is originally from CPython 2.7, with modifications for Pyston
/* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
By default, or when stdin is not a tty device, we have a super
simple my_readline function using fgets.
Optionally, we can use the GNU readline library.
my_readline() has a different return value from GNU readline():
- NULL if an interrupt occurred or if an error occurred
- a malloc'ed empty string if EOF was read
- a malloc'ed string ending in \n normally
*/
#include "Python.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;
#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
int i;
#endif
while (1) {
if (PyOS_InputHook != NULL)
(void)(PyOS_InputHook)();
errno = 0;
clearerr(fp);
p = fgets(buf, len, fp);
if (p != NULL)
return 0; /* No error */
#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. 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) {
for (i = 0; i < 10; i++) {
if (PyOS_InterruptOccurred())
return 1;
Sleep(1);
}
}
#endif /* MS_WINDOWS */
if (feof(fp)) {
clearerr(fp);
return -1; /* EOF */
}
#ifdef EINTR
if (errno == EINTR) {
int s;
#ifdef WITH_THREAD
// Pyston change: changed to our internal API
//PyEval_RestoreThread(_PyOS_ReadlineTState);
endAllowThreads();
#endif
s = PyErr_CheckSignals();
#ifdef WITH_THREAD
// Pyston change: changed to our internal API
//PyEval_SaveThread();
beginAllowThreads();
#endif
if (s < 0)
return 1;
/* try again */
continue;
}
#endif
if (PyOS_InterruptOccurred()) {
return 1; /* Interrupt */
}
return -2; /* Error */
}
/* NOTREACHED */
}
/* Readline implementation using fgets() */
char *
PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
{
size_t n;
char *p;
n = 100;
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_FREE(p);
return NULL;
case -1: /* EOF */
case -2: /* Error */
default: /* Shouldn't happen */
*p = '\0';
break;
}
n = strlen(p);
while (n > 0 && p[n-1] != '\n') {
size_t incr = n+2;
p = (char *)PyMem_REALLOC(p, n + incr);
if (p == NULL)
return NULL;
if (incr > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, "input line too long");
}
if (my_fgets(p+n, (int)incr, sys_stdin) != 0)
break;
n += strlen(p+n);
}
return (char *)PyMem_REALLOC(p, n+1);
}
/* By initializing this function pointer, systems embedding Python can
override the readline function.
Note: Python expects in return a buffer allocated with PyMem_Malloc. */
char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *);
/* Interface used by tokenizer.c and bltinmodule.c */
char *
PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
{
char *rv;
if (_PyOS_ReadlineTState == PyThreadState_GET()) {
PyErr_SetString(PyExc_RuntimeError,
"can't re-enter readline");
return NULL;
}
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();
}
#endif
_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
* a tty. This can happen, for example if python is run like
* this: python -i < test1.py
*/
if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt);
else
rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
prompt);
Py_END_ALLOW_THREADS
#ifdef WITH_THREAD
PyThread_release_lock(_PyOS_ReadlineLock);
#endif
_PyOS_ReadlineTState = NULL;
return rv;
}
......@@ -990,8 +990,75 @@ Box* builtinIter(Box* obj, Box* sentinel) {
return r;
}
// Copied from builtin_raw_input, but without the argument handling
// 'v' is the prompt, and can be NULL corresponding to the arg not getting passed.
static PyObject* raw_input(PyObject* v) noexcept {
PyObject* fin = PySys_GetObject("stdin");
PyObject* fout = PySys_GetObject("stdout");
if (fin == NULL) {
PyErr_SetString(PyExc_RuntimeError, "[raw_]input: lost sys.stdin");
return NULL;
}
if (fout == NULL) {
PyErr_SetString(PyExc_RuntimeError, "[raw_]input: lost sys.stdout");
return NULL;
}
if (PyFile_SoftSpace(fout, 0)) {
if (PyFile_WriteString(" ", fout) != 0)
return NULL;
}
if (PyFile_AsFile(fin) && PyFile_AsFile(fout) && isatty(fileno(PyFile_AsFile(fin)))
&& isatty(fileno(PyFile_AsFile(fout)))) {
PyObject* po;
const char* prompt;
char* s;
PyObject* result;
if (v != NULL) {
po = PyObject_Str(v);
if (po == NULL)
return NULL;
prompt = PyString_AsString(po);
if (prompt == NULL)
return NULL;
} else {
po = NULL;
prompt = "";
}
s = PyOS_Readline(PyFile_AsFile(fin), PyFile_AsFile(fout), prompt);
Py_XDECREF(po);
if (s == NULL) {
if (!PyErr_Occurred())
PyErr_SetNone(PyExc_KeyboardInterrupt);
return NULL;
}
if (*s == '\0') {
PyErr_SetNone(PyExc_EOFError);
result = NULL;
} else { /* strip trailing '\n' */
size_t len = strlen(s);
if (len > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError, "[raw_]input: input too long");
result = NULL;
} else {
result = PyString_FromStringAndSize(s, len - 1);
}
}
PyMem_FREE(s);
return result;
}
if (v != NULL) {
if (PyFile_WriteObject(v, fout, Py_PRINT_RAW) != 0)
return NULL;
}
return PyFile_GetLine(fin, -1);
}
Box* rawInput(Box* prompt) {
Py_FatalError("unimplemented");
Box* r = raw_input(prompt);
if (!r)
throwCAPIException();
return r;
}
Box* input(Box* prompt) {
......
......@@ -1152,6 +1152,90 @@ extern "C" int PyFile_SoftSpace(PyObject* f, int newflag) noexcept {
}
}
extern "C" PyObject* PyFile_GetLine(PyObject* f, int n) noexcept {
PyObject* result;
if (f == NULL) {
PyErr_BadInternalCall();
return NULL;
}
if (PyFile_Check(f)) {
BoxedFile* fo = (BoxedFile*)f;
if (fo->f_fp == NULL)
return err_closed();
if (!fo->readable)
return err_mode("reading");
/* refuse to mix with f.next() */
if (fo->f_buf != NULL && (fo->f_bufend - fo->f_bufptr) > 0 && fo->f_buf[0] != '\0')
return err_iterbuffered();
result = get_line(fo, n);
} else {
PyObject* reader;
PyObject* args;
reader = PyObject_GetAttrString(f, "readline");
if (reader == NULL)
return NULL;
if (n <= 0)
args = PyTuple_New(0);
else
args = Py_BuildValue("(i)", n);
if (args == NULL) {
Py_DECREF(reader);
return NULL;
}
result = PyEval_CallObject(reader, args);
Py_DECREF(reader);
Py_DECREF(args);
if (result != NULL && !PyString_Check(result) && !PyUnicode_Check(result)) {
Py_DECREF(result);
result = NULL;
PyErr_SetString(PyExc_TypeError, "object.readline() returned non-string");
}
}
if (n < 0 && result != NULL && PyString_Check(result)) {
char* s = PyString_AS_STRING(result);
Py_ssize_t len = PyString_GET_SIZE(result);
if (len == 0) {
Py_DECREF(result);
result = NULL;
PyErr_SetString(PyExc_EOFError, "EOF when reading a line");
} else if (s[len - 1] == '\n') {
if (/*result->ob_refcnt*/ 2 == 1) {
if (_PyString_Resize(&result, len - 1))
return NULL;
} else {
PyObject* v;
v = PyString_FromStringAndSize(s, len - 1);
Py_DECREF(result);
result = v;
}
}
}
#ifdef Py_USING_UNICODE
if (n < 0 && result != NULL && PyUnicode_Check(result)) {
Py_UNICODE* s = PyUnicode_AS_UNICODE(result);
Py_ssize_t len = PyUnicode_GET_SIZE(result);
if (len == 0) {
Py_DECREF(result);
result = NULL;
PyErr_SetString(PyExc_EOFError, "EOF when reading a line");
} else if (s[len - 1] == '\n') {
if (/*result->ob_refcnt*/ 2 == 1)
PyUnicode_Resize(&result, len - 1);
else {
PyObject* v;
v = PyUnicode_FromUnicode(s, len - 1);
Py_DECREF(result);
result = v;
}
}
}
#endif
return result;
}
/*
** Py_UniversalNewlineFread is an fread variation that understands
** all of \r, \n and \r\n conventions.
......
import StringIO
import sys
orig_stdin = sys.stdin
sio = StringIO.StringIO("hello world\nfoo")
sys.stdin = sio
print repr(raw_input())
print repr(raw_input("hi"))
sys.stdin = orig_stdin
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment