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

319 lines
8.2 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-12-21 20:57:53 +00:00
static void py_flush(int sno) {
StreamDesc *st = YAP_GetStreamFromId(sno);
PyObject *fl =
PyObject_GetAttrString(st->u.private_data, "flush");
if (fl) {
PyObject_CallFunctionObjArgs(fl,
NULL);
}
2018-06-05 11:20:39 +01:00
#if 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)) {
2018-12-21 20:57:53 +00:00
size_t sz = put_utf8(st->u.w_irl.ptr, ch);
if (sz > 0) {
st->u.w_irl.ptr += sz;
if ( st->u.w_irl.ptr - st->u.w_irl.buf > 256)
{py_flush(sno); }
}
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(
2018-12-21 20:57:53 +00:00
err,
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
2018-10-16 14:33:16 +01:00
}
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)) {
2018-12-21 20:57:53 +00:00
size_t sz = put_utf8(st->u.w_irl.ptr, ch);
if (sz > 0) {
st->u.w_irl.ptr += sz;
if ( st->u.w_irl.ptr - st->u.w_irl.buf > 256)
{py_flush(sno); }
}
return ch;
2018-10-16 14:33:16 +01:00
}
#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(
2018-12-21 20:57:53 +00:00
err,
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
2018-03-02 21:18:24 +00:00
}
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)
2018-12-21 20:57:53 +00:00
outbuf = ( unsigned char *)malloc(1024);
2018-06-01 13:22:13 +01:00
st->u.w_irl.ptr = st->u.w_irl.buf = outbuf;
2018-06-02 10:36:04 +01:00
2018-12-21 20:57:53 +00:00
]\]
2018-03-12 15:11:59 +00:00
st->user_name = TermOutStream;
2018-12-21 20:57:53 +00: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)
2018-12-21 20:57:53 +00:00
errbuf = ( unsigned char *)malloc(1024);
2018-06-01 13:22:13 +01:00
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-12-21 20:57:53 +00:00
if (st->status & (Output_Stream_f | Append_Stream_f))
py_flush(sno);
2018-03-12 15:11:59 +00:00
return st;
}
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) {
const char *myrl_line;
2018-12-21 20:57:53 +00:00
PyObject *user_line;
2018-10-16 14:33:16 +01:00
PyObject *err;
2018-07-27 11:11:04 +01:00
StreamDesc *s = YAP_GetStreamFromId(sno);
2018-12-21 20:57:53 +00:00
term_t tg = python_acquire_GIL();
// PyObject_Print(s->u.private_data,stderr,0);
2018-10-16 14:33:16 +01:00
if (PyFunction_Check( s->u.private_data )) {
2018-12-21 20:57:53 +00:00
user_line = PyObject_CallFunctionObjArgs( s->u.private_data ,
NULL);
} else if ( s->u.private_data == NULL) {
PyObject *readl =
PyObject_GetAttrString(s->u.private_data, "readline");
if (!readl) {
readl =
2019-03-26 23:53:47 +00:00
PyObject_GetAttrString(s->u.private_data, "input");
2018-10-16 14:33:16 +01:00
}
2018-12-21 20:57:53 +00:00
if (readl)
user_line = PyObject_CallFunctionObjArgs(readl,
NULL);
2018-07-31 15:18:56 +01:00
}
2018-12-21 20:57:53 +00:00
python_release_GIL(tg);
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-12-21 20:57:53 +00:00
PyErr_Print();
Yap_ThrowError(SYSTEM_ERROR_GET_FAILED, YAP_MkIntTerm(sno), NULL);
2018-06-14 11:27:43 +01:00
}
2018-12-21 20:57:53 +00:00
myrl_line = PyUnicode_AsUTF8(user_line);
if (myrl_line == NULL)
return NULL;
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
/**
2018-12-21 20:57:53 +00:00
@brief Yap_ReadlinePeekChar peeks the next char from the
readline buffer, but does not actually grab it.
2018-03-12 15:11:59 +00:00
2018-12-21 20:57:53 +00:00
The idea is to take advantage of the buffering. Special care must be taken
with EOF, though.
2018-03-12 15:11:59 +00:00
*/
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-12-21 20:57:53 +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 =
2018-12-21 20:57:53 +00:00
VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_READ | VFS_HAS_PREFIX;
2018-03-02 21:18:24 +00:00
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;
}