This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/python/pyio.c

333 lines
8.7 KiB
C
Raw Normal View History

2018-03-02 21:18:24 +00:00
#include "py4yap.h"
#include <VFS.h>
#include "YapStreams.h"
2018-06-01 13:22:13 +01:00
#include "YapUTF8.h"
2018-03-02 21:18:24 +00:00
2018-03-12 15:11:59 +00:00
YAP_Term TermErrStream, TermOutStream;
2018-03-02 21:18:24 +00:00
2018-06-05 11:20:39 +01:00
static void pyflush(StreamDesc *st) {
#if 0
2018-06-01 13:22:13 +01:00
st->u.w_irl.ptr[0] = '\0';
2018-12-12 00:39:17 +00:00
// fprintf(stderr,"%s\n", st->u.w_irl.buf);
2018-06-01 13:22:13 +01:00
term_t tg = python_acquire_GIL();
if (st->user_name == TermOutStream){
PySys_WriteStdout("%s", st->u.w_irl.buf);
} else {
PySys_WriteStderr("%s", st->u.w_irl.buf);
2018-06-05 11:20:39 +01:00
2018-06-01 13:22:13 +01:00
}
python_release_GIL(tg);
st->u.w_irl.ptr = st->u.w_irl.buf;
2018-06-05 11:20:39 +01:00
#endif
2018-06-01 13:22:13 +01:00
}
2018-05-24 21:45:38 +01:00
static int py_putc(int sno, int ch) {
2018-03-02 21:18:24 +00:00
// PyObject *pyw; // buffer
// int pyw_kind;
// PyObject *pyw_data;
StreamDesc *st = YAP_GetStreamFromId(sno);
2018-06-01 13:22:13 +01:00
#if 0
if (false && (st->user_name == TermOutStream || st->user_name == TermErrStream)) {
size_t sz = put_utf8(st->u.w_irl.ptr, ch);
if (sz > 0) {
st->u.w_irl.ptr += sz;
if (ch == '\n' || st->u.w_irl.ptr - st->u.w_irl.buf > 256)
{pyflush(st); }
}
return ch;
2018-03-12 15:11:59 +00:00
}
2018-06-05 11:20:39 +01:00
#endif
2018-10-16 14:33:16 +01:00
unsigned char s[2];
2018-03-12 15:11:59 +00:00
PyObject *err;
2018-03-02 21:18:24 +00:00
s[0] = ch;
s[1] = '\0';
2018-03-19 11:43:14 +00:00
term_t g0 = python_acquire_GIL();
2018-03-02 21:18:24 +00:00
PyObject_CallMethodObjArgs(st->u.private_data, PyUnicode_FromString("write"),
2018-10-16 14:33:16 +01:00
PyUnicode_FromString((char *)s), NULL);
python_release_GIL(g0);
if ((err = PyErr_Occurred())) {
PyErr_SetString(
err,
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
}
return ch;
}
static int py_wputc(int sno, int ch) {
// PyObject *pyw; // buffer
// int pyw_kind;
// PyObject *pyw_data;
StreamDesc *st = YAP_GetStreamFromId(sno);
#if 0
if (false && (st->user_name == TermOutStream || st->user_name == TermErrStream)) {
size_t sz = put_utf8(st->u.w_irl.ptr, ch);
if (sz > 0) {
st->u.w_irl.ptr += sz;
if (ch == '\n' || st->u.w_irl.ptr - st->u.w_irl.buf > 256)
{pyflush(st); }
}
return ch;
}
#endif
unsigned char s[8];
PyObject *err;
size_t n = put_utf8(s, ch);
s[n] = '\0';
term_t g0 = python_acquire_GIL();
PyObject_CallMethodObjArgs(st->u.private_data, PyUnicode_FromString("write"),
PyUnicode_FromString((char *)s), NULL);
2018-03-12 15:11:59 +00:00
python_release_GIL(g0);
2018-05-21 14:45:24 +01:00
if ((err = PyErr_Occurred())) {
2018-03-02 21:18:24 +00:00
PyErr_SetString(
err,
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
}
return ch;
}
2018-03-12 15:11:59 +00:00
VFS_t pystream;
2018-05-21 14:45:24 +01:00
static void *py_open(VFS_t *me, const char *name, const char *io_mode,
int sno) {
2018-03-12 15:11:59 +00:00
#if HAVE_STRCASESTR
if (strcasestr(name, "/python/") == name)
name += strlen("/python/");
#else
if (strstr(name, "/python/") == name)
name += strlen("/python/");
#endif
2018-03-18 00:44:08 +00:00
term_t ctk = python_acquire_GIL();
2018-05-21 14:45:24 +01:00
PyObject *pystream = string_to_python(name, true, NULL);
if (pystream == NULL || pystream == Py_None) {
python_release_GIL(ctk);
return NULL;
2018-12-12 00:39:17 +00:00
}
2018-03-12 15:11:59 +00:00
StreamDesc *st = YAP_RepStreamFromId(sno);
2018-03-17 10:38:56 +00:00
st->name = YAP_LookupAtom(name);
2018-07-21 12:08:09 +01:00
if (strcmp(name, "sys.stdout") == 0 || strcmp(name, "sys.stderr") == 0 ||
2018-06-14 11:27:43 +01:00
strcmp(name, "input") == 0) {
st->status |= Tty_Stream_f;
}
/*
2018-06-01 13:22:13 +01:00
if (!outbuf)
outbuf = ( unsigned char *)malloc(1024);
st->u.w_irl.ptr = st->u.w_irl.buf = outbuf;
2018-06-02 10:36:04 +01:00
]\]
2018-03-12 15:11:59 +00:00
st->user_name = TermOutStream;
2018-05-21 14:45:24 +01:00
} else if (strcmp(name, "sys.stderr") == 0) {
2018-03-12 15:11:59 +00:00
st->user_name = TermErrStream;
2018-06-01 13:22:13 +01:00
if (!errbuf)
errbuf = ( unsigned char *)malloc(1024);
st->u.w_irl.ptr = st->u.w_irl.buf = errbuf;
2018-06-01 08:37:25 +01:00
// } else if (strcmp(name, "input") == 0) {
//pystream = PyObject_Call(pystream, PyTuple_New(0), NULL);
2018-06-01 13:22:13 +01:00
} else */
2018-06-05 11:20:39 +01:00
{ st->user_name = YAP_MkAtomTerm(st->name); }
st->u.private_data = pystream;
2018-03-17 10:38:56 +00:00
st->vfs = me;
2018-05-26 00:22:27 +01:00
st->file = NULL;
2018-05-21 14:45:24 +01:00
python_release_GIL(ctk);
2018-03-12 15:11:59 +00:00
return st;
}
2018-06-01 13:22:13 +01:00
static void py_flush(int sno) {
StreamDesc *s = YAP_GetStreamFromId(sno);
term_t tg = python_acquire_GIL();
PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush");
2018-06-05 11:20:39 +01:00
pyflush(s);
2018-06-01 13:22:13 +01:00
PyObject_CallFunction(flush, NULL);
python_release_GIL(tg);
}
2018-03-12 15:11:59 +00:00
static bool py_close(int sno) {
2018-03-17 10:38:56 +00:00
StreamDesc *st = YAP_RepStreamFromId(sno);
2018-06-05 11:20:39 +01:00
if (st->status & (Output_Stream_f | Append_Stream_f))
py_flush(sno);
2018-05-21 14:45:24 +01:00
if (strcmp(st->name, "sys.stdout") && strcmp(st->name, "sys.stderr")) {
Py_XDECREF(st->u.private_data);
2018-06-01 13:22:13 +01:00
st->u.w_irl.buf = st->u.w_irl.ptr = NULL;
2018-03-18 00:44:08 +00:00
}
2018-05-21 14:45:24 +01:00
st->u.private_data = NULL;
2018-03-18 00:44:08 +00:00
st->vfs = NULL;
2018-03-12 15:11:59 +00:00
return true;
}
2018-07-27 11:11:04 +01:00
static bool pygetLine(StreamDesc *rl_iostream, int sno) {
2018-07-21 12:08:09 +01:00
// term_t ctk = python_acquire_GIL();
2018-07-27 11:11:04 +01:00
const char *myrl_line;
2018-10-16 14:33:16 +01:00
PyObject *user_line, *readl = NULL;
PyObject *err;
2018-07-27 11:11:04 +01:00
StreamDesc *s = YAP_GetStreamFromId(sno);
2018-10-16 14:33:16 +01:00
// term_t tg = python_acquire_GIL();
PyObject_Print(s->u.private_data,stderr,0);
if (PyFunction_Check( s->u.private_data )) {
readl = s->u.private_data;
}
if (!strcmp(RepAtom(s->name)->StrOfAE, "user_input")) {
2018-07-31 15:18:56 +01:00
// note that input may change
2018-10-16 14:33:16 +01:00
readl = PythonLookupSpecial("input");
2018-07-31 15:18:56 +01:00
}
2018-10-16 14:33:16 +01:00
if (readl == NULL) {
readl = PythonLookup("readline", s->u.private_data);
2018-07-31 15:18:56 +01:00
}
2018-10-16 14:33:16 +01:00
if (readl == NULL) {
readl = PythonLookup("read", s->u.private_data);
}
if (readl == NULL) {
if ((err = PyErr_Occurred())) {
PyErr_Print();
Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), NULL);
}
}
user_line = PyObject_CallFunctionObjArgs(readl,
NULL);
if ((err = PyErr_Occurred())) {
PyErr_Print();
Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), err);
}
2018-07-31 15:18:56 +01:00
myrl_line = PyUnicode_AsUTF8(user_line);
2018-07-27 11:11:04 +01:00
if (myrl_line == NULL)
return NULL;
2018-07-21 12:08:09 +01:00
if ((err = PyErr_Occurred())) {
2018-07-27 11:11:04 +01:00
if (PyErr_GivenExceptionMatches(err, PyExc_EOFError))
return NULL;
2018-10-16 14:33:16 +01:00
PyErr_Print();
2018-06-14 11:27:43 +01:00
Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), err);
2018-10-16 14:33:16 +01:00
2018-06-14 11:27:43 +01:00
}
2018-08-08 20:46:47 +01:00
rl_iostream->u.irl.ptr = rl_iostream->u.irl.buf = (unsigned char *)myrl_line;
2018-03-12 15:11:59 +00:00
return true;
2018-03-02 21:18:24 +00:00
}
2018-03-12 15:11:59 +00:00
static int py_getc(int sno) {
StreamDesc *s = YAP_RepStreamFromId(sno);
int ch;
bool fetch = (s->u.irl.buf == NULL);
2018-03-02 21:18:24 +00:00
2018-06-14 11:27:43 +01:00
if (fetch) {
2018-07-27 11:11:04 +01:00
if (!pygetLine(s, sno)) {
2018-06-14 11:27:43 +01:00
return EOF;
2018-03-12 15:11:59 +00:00
}
2018-06-14 11:27:43 +01:00
}
2018-07-27 11:11:04 +01:00
const unsigned char *ttyptr = s->u.irl.ptr++;
2018-06-14 11:27:43 +01:00
ch = *ttyptr;
if (ch == '\0') {
2018-07-27 11:11:04 +01:00
ch = 10;
2018-03-12 15:11:59 +00:00
}
2018-05-21 14:45:24 +01:00
return ch;
2018-03-12 15:11:59 +00:00
}
2018-10-16 14:33:16 +01:00
static int py_wgetc(int sno) {
StreamDesc *s = YAP_RepStreamFromId(sno);
int ch;
bool fetch = (s->u.irl.ptr == NULL);
if (fetch) {
if (!pygetLine(s, sno)) {
return EOF;
}
}
if (s->u.irl.ptr == NULL)
return 10; // ????
const unsigned char *ttyptr = s->u.irl.ptr;
if (*ttyptr == '\0') {
ch = 10;
s->u.irl.ptr = NULL;
} else {
size_t n = get_utf8(ttyptr, strlen((char *)ttyptr), &ch);
s->u.irl.ptr += n;
}
return ch;
}
2018-03-12 15:11:59 +00:00
/**
@brief Yap_ReadlinePeekChar peeks the next char from the
readline buffer, but does not actually grab it.
The idea is to take advantage of the buffering. Special care must be taken
with EOF, though.
*/
2018-03-02 21:18:24 +00:00
static int py_peek(int sno) {
2018-03-12 15:11:59 +00:00
StreamDesc *s = YAP_RepStreamFromId(sno);
int ch;
if (s->u.irl.buf) {
const unsigned char *ttyptr = s->u.irl.ptr;
ch = *ttyptr;
if (ch == '\0') {
ch = '\n';
}
return ch;
}
2018-07-27 11:11:04 +01:00
if (pygetLine(s, sno)) {
2018-03-12 15:11:59 +00:00
ch = s->u.irl.ptr[0];
if (ch == '\0') {
ch = '\n';
}
} else {
return EOF;
}
return ch;
2018-03-02 21:18:24 +00:00
}
static int64_t py_seek(int sno, int64_t where, int how) {
2018-03-12 15:11:59 +00:00
StreamDesc *g0 = YAP_RepStreamFromId(sno);
2018-05-21 14:45:24 +01:00
term_t s0 = python_acquire_GIL();
2018-03-12 15:11:59 +00:00
PyObject *fseek = PyObject_GetAttrString(g0->u.private_data, "seek");
2018-03-02 21:18:24 +00:00
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where),
PyLong_FromLong(how), NULL);
2018-05-21 14:45:24 +01:00
python_release_GIL(s0);
return PyLong_AsLong(pyr);
2018-03-02 21:18:24 +00:00
}
#if 0
static void python_output(void) {
PyObject *stream = string_to_python("sys.stdout", true, NULL);
StreamDesc *st = YAP_GetStreamFromId(1);
st->u.private_data = stream;
st->vfs = &pystream;
stream = string_to_python("sys.stderr", true, NULL);
st = YAP_GetStreamFromIds(2);
st->u.private_data = stream;
st->vfs = &pystream;
}
#endif
static bool initialized = false;
bool init_python_vfs(void) {
// pyw = PyUnicode_FromString("x");
// pyw_kind = PyUnicode_KIND(pyw);
// pyw_data = PyUnicode_DATA(pyw);
if (initialized)
return false;
initialized = true;
pystream.name = "python stream";
pystream.vflags =
VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_READ | VFS_HAS_PREFIX;
pystream.prefix = "/python/";
pystream.suffix = NULL;
pystream.open = py_open;
pystream.close = py_close;
2018-03-12 15:11:59 +00:00
pystream.get_char = py_getc;
2018-10-16 14:33:16 +01:00
pystream.get_wchar = py_wgetc;
2018-03-02 21:18:24 +00:00
pystream.peek_char = py_peek;
2018-05-24 21:45:38 +01:00
pystream.put_char = py_putc;
2018-10-16 14:33:16 +01:00
pystream.put_wchar = py_wputc;
2018-03-02 21:18:24 +00:00
pystream.flush = py_flush;
pystream.seek = py_seek;
pystream.next = GLOBAL_VFS;
GLOBAL_VFS = &pystream;
2018-03-12 15:11:59 +00:00
TermOutStream = YAP_MkAtomTerm(YAP_LookupAtom("std.output"));
TermErrStream = YAP_MkAtomTerm(YAP_LookupAtom("std.error"));
2018-03-02 21:18:24 +00:00
// NULL;
return true;
}