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/os/mem.c

396 lines
10 KiB
C
Raw Normal View History

/*************************************************************************
2015-06-18 01:32:33 +01:00
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
2016-04-05 02:53:39 +01:00
* File: sockets.c *
2015-06-18 01:32:33 +01:00
* Last rev: 5/2/88 *
* mods: *
* comments: Input/Output C implemented predicates *
* *
*************************************************************************/
#ifdef SCCS
static char SccsId[] = "%W% %G%";
#endif
/*
* This file includes the definition of a socket related IO.
*
*/
#include "sysbits.h"
2015-06-18 01:32:33 +01:00
#if !MAY_READ
2016-04-05 02:53:39 +01:00
static int MemGetc(int);
2015-06-18 01:32:33 +01:00
/* read from memory */
2016-04-05 02:53:39 +01:00
static int MemGetc(int sno) {
register StreamDesc *s = &GLOBAL_Stream[sno];
Int ch;
int spos;
spos = s->u.mem_string.pos;
if (spos == s->u.mem_string.max_size) {
return -1;
} else {
ch = s->u.mem_string.buf[spos];
s->u.mem_string.pos = ++spos;
}
return ch;
2015-06-18 01:32:33 +01:00
}
#endif
#if !MAY_WRITE
2016-04-05 02:53:39 +01:00
static int MemPutc(int, int);
2015-06-18 01:32:33 +01:00
/* static */
2016-04-05 02:53:39 +01:00
static int MemPutc(int sno, int ch) {
2015-06-18 01:32:33 +01:00
StreamDesc *s = &GLOBAL_Stream[sno];
#if MAC || _MSC_VER
2016-04-05 02:53:39 +01:00
if (ch == 10) {
ch = '\n';
}
2015-06-18 01:32:33 +01:00
#endif
s->u.mem_string.buf[s->u.mem_string.pos++] = ch;
2016-04-05 02:53:39 +01:00
if (s->u.mem_string.pos >= s->u.mem_string.max_size - 8) {
2015-06-18 01:32:33 +01:00
int old_src = s->u.mem_string.src, new_src;
/* oops, we have reached an overflow */
Int new_max_size = s->u.mem_string.max_size + Yap_page_size;
char *newbuf;
if (old_src == MEM_BUF_CODE &&
2016-04-05 02:53:39 +01:00
(newbuf = Yap_AllocAtomSpace(new_max_size * sizeof(char))) != NULL) {
2015-06-18 01:32:33 +01:00
new_src = MEM_BUF_CODE;
#if HAVE_MEMMOVE
2016-04-05 02:53:39 +01:00
memmove((void *)newbuf, (void *)s->u.mem_string.buf,
(size_t)((s->u.mem_string.pos) * sizeof(char)));
2015-06-18 01:32:33 +01:00
#else
2016-04-05 02:53:39 +01:00
{
Int n = s->u.mem_string.pos;
char *to = newbuf;
char *from = s->u.mem_string.buf;
while (n-- >= 0) {
*to++ = *from++;
}
2015-06-18 01:32:33 +01:00
}
#endif
Yap_FreeAtomSpace(s->u.mem_string.buf);
#if !HAVE_SYSTEM_MALLOC
2016-04-05 02:53:39 +01:00
} else if ((newbuf = (ADDR)realloc(s->u.mem_string.buf,
new_max_size * sizeof(char))) != NULL) {
2015-06-18 01:32:33 +01:00
new_src = MEM_BUF_MALLOC;
#endif
} else {
if (GLOBAL_Stream[sno].u.mem_string.error_handler) {
2016-04-05 02:53:39 +01:00
CACHE_REGS
LOCAL_Error_Size = new_max_size * sizeof(char);
save_machine_regs();
longjmp(*(jmp_buf *)GLOBAL_Stream[sno].u.mem_string.error_handler, 1);
2015-06-18 01:32:33 +01:00
} else {
2016-04-05 02:53:39 +01:00
Yap_Error(RESOURCE_ERROR_HEAP, TermNil,
"YAP could not grow heap for writing to string");
2015-06-18 01:32:33 +01:00
}
return -1;
}
2016-04-05 02:53:39 +01:00
if (old_src == MEM_BUF_CODE) {
2015-06-18 01:32:33 +01:00
}
s->u.mem_string.buf = newbuf;
s->u.mem_string.max_size = new_max_size;
s->u.mem_string.src = new_src;
}
2016-04-05 02:53:39 +01:00
count_output_char(ch, s);
return ((int)ch);
2015-06-18 01:32:33 +01:00
}
#endif
2016-04-05 02:53:39 +01:00
int Yap_open_buf_read_stream(const char *nbuf, size_t nchars, encoding_t *encp,
memBufSource src) {
CACHE_REGS
2015-06-18 01:32:33 +01:00
int sno;
StreamDesc *st;
FILE *f;
encoding_t encoding;
stream_flags_t flags;
2016-04-05 02:53:39 +01:00
2015-06-18 01:32:33 +01:00
sno = GetFreeStreamD();
if (sno < 0)
2016-04-05 02:53:39 +01:00
return (PlIOError(RESOURCE_ERROR_MAX_STREAMS, TermNil,
"new stream not available for open_mem_read_stream/1"));
st = GLOBAL_Stream + sno;
if (encp)
encoding = *encp;
else
encoding = LOCAL_encoding;
2015-06-18 01:32:33 +01:00
#if MAY_READ
// like any file stream.
2016-04-14 12:00:09 +01:00
st->file = f = fmemopen((void *)nbuf, nchars, "r");
flags = Input_Stream_f | InMemory_Stream_f | Seekable_Stream_f;
2015-06-18 01:32:33 +01:00
#else
2016-04-14 12:00:09 +01:00
sT->file = f = NULL;
flags = Input_Stream_f | InMemory_Stream_f;
#endif
2016-04-05 02:53:39 +01:00
Yap_initStream(sno, f, NULL, TermNil, encoding, flags, AtomRead);
// like any file stream.
#if !MAY_READ
2015-06-18 01:32:33 +01:00
/* currently these streams are not seekable */
st->status = Input_Stream_f | InMemory_Stream_f;
st->u.mem_string.pos = 0;
st->u.mem_string.buf = (char *)nbuf;
st->u.mem_string.max_size = nchars;
st->u.mem_string.error_handler = NULL;
st->u.mem_string.src = src;
#endif
Yap_DefaultStreamOps(st);
2015-06-18 01:32:33 +01:00
UNLOCK(st->streamlock);
return sno;
}
static Int
2016-04-05 02:53:39 +01:00
open_mem_read_stream(USES_REGS1) /* $open_mem_read_stream(+List,-Stream) */
2015-06-18 01:32:33 +01:00
{
Term t, ti;
int sno;
Int sl = 0, nchars = 0;
char *nbuf;
ti = Deref(ARG1);
while (ti != TermNil) {
if (IsVarTerm(ti)) {
Yap_Error(INSTANTIATION_ERROR, ti, "open_mem_read_stream");
return (FALSE);
} else if (!IsPairTerm(ti)) {
Yap_Error(TYPE_ERROR_LIST, ti, "open_mem_read_stream");
return (FALSE);
} else {
sl++;
ti = TailOfTerm(ti);
}
}
2016-04-05 02:53:39 +01:00
while ((nbuf = (char *)Yap_AllocAtomSpace((sl + 1) * sizeof(char))) == NULL) {
if (!Yap_growheap(FALSE, (sl + 1) * sizeof(char), NULL)) {
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
return (FALSE);
2015-06-18 01:32:33 +01:00
}
}
ti = Deref(ARG1);
while (ti != TermNil) {
Term ts = HeadOfTerm(ti);
if (IsVarTerm(ts)) {
Yap_Error(INSTANTIATION_ERROR, ARG1, "open_mem_read_stream");
return (FALSE);
} else if (!IsIntTerm(ts)) {
Yap_Error(TYPE_ERROR_INTEGER, ARG1, "open_mem_read_stream");
return (FALSE);
}
nbuf[nchars++] = IntOfTerm(ts);
ti = TailOfTerm(ti);
}
nbuf[nchars] = '\0';
sno = Yap_open_buf_read_stream(nbuf, nchars, &LOCAL_encoding, MEM_BUF_CODE);
2016-04-05 02:53:39 +01:00
t = Yap_MkStream(sno);
return (Yap_unify(ARG2, t));
2015-06-18 01:32:33 +01:00
}
2016-04-05 02:53:39 +01:00
int Yap_open_buf_write_stream(char *buf, size_t nchars, encoding_t *encp,
memBufSource sr) {
CACHE_REGS
2016-04-05 02:53:39 +01:00
int sno;
StreamDesc *st;
2015-08-07 22:57:53 +01:00
2016-04-05 02:53:39 +01:00
sno = GetFreeStreamD();
if (sno < 0)
return -1;
st = GLOBAL_Stream + sno;
st->status = Output_Stream_f | InMemory_Stream_f;
if (!buf) {
if (!nchars) {
nchars = Yap_page_size;
2015-06-18 01:32:33 +01:00
}
2016-04-05 02:53:39 +01:00
buf = malloc(nchars);
st->status |= FreeOnClose_Stream_f;
}
st->nsize = nchars;
st->linepos = 0;
st->charcount = 0;
st->linecount = 1;
if (encp)
st->encoding = *encp;
else
st->encoding = LOCAL_encoding;
Yap_DefaultStreamOps(st);
2015-06-18 01:32:33 +01:00
#if MAY_WRITE
2016-04-12 16:04:33 +01:00
#if HAVE_FMEMOPEN
st->file = fmemopen((void *)buf, nchars, "w");
2015-06-18 01:32:33 +01:00
#else
2016-04-12 16:04:33 +01:00
st->file = open_memstream(buf, &st->nsize);
st->status |= Seekable_Stream_f;
#endif
st->nsize = nchars;
st->nbuf = buf;
if (!st->nbuf) {
return -1;
}
2016-04-05 02:53:39 +01:00
st->u.mem_string.pos = 0;
st->u.mem_string.buf = st->nbuf;
st->u.mem_string.max_size = nchars;
#endif
UNLOCK(st->streamlock);
return sno;
2015-06-18 01:32:33 +01:00
}
2016-04-05 02:53:39 +01:00
int Yap_OpenBufWriteStream(USES_REGS1) {
2015-06-18 01:32:33 +01:00
char *nbuf;
2016-04-05 02:53:39 +01:00
size_t sz = Yap_page_size;
2015-06-18 01:32:33 +01:00
2016-04-05 02:53:39 +01:00
while ((nbuf = (char *)Yap_AllocAtomSpace(Yap_page_size * sizeof(char))) ==
NULL) {
if (!Yap_growheap(FALSE, Yap_page_size * sizeof(char), NULL)) {
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
2015-06-18 01:32:33 +01:00
return -1;
}
}
2016-04-05 02:53:39 +01:00
return Yap_open_buf_write_stream(
nbuf, sz, &GLOBAL_Stream[LOCAL_c_output_stream].encoding, 0);
2015-06-18 01:32:33 +01:00
}
static Int
2016-04-05 02:53:39 +01:00
open_mem_write_stream(USES_REGS1) /* $open_mem_write_stream(-Stream) */
2015-06-18 01:32:33 +01:00
{
Term t;
int sno;
2016-04-05 02:53:39 +01:00
sno = Yap_OpenBufWriteStream(PASS_REGS1);
2015-06-18 01:32:33 +01:00
if (sno == -1)
2016-04-05 02:53:39 +01:00
return (PlIOError(SYSTEM_ERROR_INTERNAL, TermNil,
"new stream not available for open_mem_read_stream/1"));
t = Yap_MkStream(sno);
return (Yap_unify(ARG1, t));
2015-06-18 01:32:33 +01:00
}
2016-04-05 02:53:39 +01:00
/**
2015-06-18 01:32:33 +01:00
* Yap_PeekMemwriteStream() shows the current buffer for a memory stream.
2016-04-05 02:53:39 +01:00
*
2015-06-18 01:32:33 +01:00
* @param sno, the in-memory stream
2016-04-05 02:53:39 +01:00
*
2015-06-18 01:32:33 +01:00
* @return temporary buffer, discarded by close and may be moved away
* by other writes..
*/
2016-04-05 02:53:39 +01:00
char *Yap_MemExportStreamPtr(int sno) {
2015-07-23 01:33:30 +01:00
#if MAY_WRITE
char *s;
2016-04-05 02:53:39 +01:00
if (fflush(GLOBAL_Stream[sno].file) == 0) {
s = GLOBAL_Stream[sno].nbuf;
2015-08-07 22:57:53 +01:00
return s;
}
2015-07-23 01:33:30 +01:00
return NULL;
#else
return GLOBAL_Stream[sno].u.mem_string.buf;
2015-07-23 01:33:30 +01:00
#endif
2015-06-18 01:32:33 +01:00
}
2016-04-05 02:53:39 +01:00
static Int peek_mem_write_stream(
USES_REGS1) { /* '$peek_mem_write_stream'(+GLOBAL_Stream,?S0,?S) */
Int sno =
Yap_CheckStream(ARG1, (Output_Stream_f | InMemory_Stream_f), "close/2");
2015-07-23 01:33:30 +01:00
Int i;
2015-06-18 01:32:33 +01:00
Term tf = ARG2;
CELL *HI;
2015-07-23 01:33:30 +01:00
const char *ptr;
2015-06-18 01:32:33 +01:00
if (sno < 0)
return (FALSE);
2016-04-05 02:53:39 +01:00
restart:
2015-06-18 01:32:33 +01:00
HI = HR;
2015-07-23 01:33:30 +01:00
#if MAY_WRITE
if (fflush(GLOBAL_Stream[sno].file) == 0) {
2016-04-05 02:53:39 +01:00
ptr = GLOBAL_Stream[sno].nbuf;
i = GLOBAL_Stream[sno].nsize;
}
2015-07-23 01:33:30 +01:00
#else
2016-04-05 02:53:39 +01:00
ptr = GLOBAL_Stream[sno].u.mem_string.buf;
i = GLOBAL_Stream[sno].u.mem_string.pos;
2015-07-23 01:33:30 +01:00
#endif
2015-06-18 01:32:33 +01:00
while (i > 0) {
--i;
2016-04-05 02:53:39 +01:00
tf = MkPairTerm(MkIntTerm(ptr[i]), tf);
2015-06-18 01:32:33 +01:00
if (HR + 1024 >= ASP) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
HR = HI;
2016-04-05 02:53:39 +01:00
if (!Yap_gcl((ASP - HI) * sizeof(CELL), 3, ENV, Yap_gcP())) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
return (FALSE);
2015-06-18 01:32:33 +01:00
}
i = GLOBAL_Stream[sno].u.mem_string.pos;
tf = ARG2;
LOCK(GLOBAL_Stream[sno].streamlock);
goto restart;
}
}
UNLOCK(GLOBAL_Stream[sno].streamlock);
2016-04-05 02:53:39 +01:00
return (Yap_unify(ARG3, tf));
2015-06-18 01:32:33 +01:00
}
2016-04-05 02:53:39 +01:00
void Yap_MemOps(StreamDesc *st) {
2015-06-18 01:32:33 +01:00
#if MAY_WRITE
st->stream_putc = FilePutc;
#else
2016-04-05 02:53:39 +01:00
st->stream_putc = MemPutc;
2015-06-18 01:32:33 +01:00
#endif
#if MAY_READ
st->stream_getc = PlGetc;
#else
st->stream_getc = MemGetc;
#endif
}
2016-04-05 02:53:39 +01:00
bool Yap_CloseMemoryStream(int sno) {
if (!(GLOBAL_Stream[sno].status & Output_Stream_f)) {
#if MAY_WRITE
2016-04-05 02:53:39 +01:00
fclose(GLOBAL_Stream[sno].file);
if (GLOBAL_Stream[sno].status & FreeOnClose_Stream_f)
free(GLOBAL_Stream[sno].nbuf);
#else
if (GLOBAL_Stream[sno].u.mem_string.src == MEM_BUF_CODE)
Yap_FreeAtomSpace(GLOBAL_Stream[sno].u.mem_string.buf);
else if (GLOBAL_Stream[sno].u.mem_string.src == MEM_BUF_MALLOC) {
free(GLOBAL_Stream[sno].u.mem_string.buf);
}
2016-04-05 02:53:39 +01:00
#endif
} else {
#if MAY_READ
2016-04-05 02:53:39 +01:00
fclose(GLOBAL_Stream[sno].file);
2016-04-14 12:00:09 +01:00
if (GLOBAL_Stream[sno].status & FreeOnClose_Stream_f)
free(GLOBAL_Stream[sno].nbuf);
#else
2016-04-05 02:53:39 +01:00
if (GLOBAL_Stream[sno].u.mem_string.src == MEM_BUF_CODE)
Yap_FreeAtomSpace(GLOBAL_Stream[sno].u.mem_string.buf);
else if (GLOBAL_Stream[sno].u.mem_string.src == MEM_BUF_MALLOC) {
free(GLOBAL_Stream[sno].u.mem_string.buf);
}
2016-04-05 02:53:39 +01:00
#endif
}
return true;
}
2016-04-05 02:53:39 +01:00
void Yap_InitMems(void) {
CACHE_REGS
2015-06-18 01:32:33 +01:00
Term cm = CurrentModule;
CurrentModule = CHARSIO_MODULE;
2016-04-05 02:53:39 +01:00
Yap_InitCPred("open_mem_read_stream", 2, open_mem_read_stream, SyncPredFlag);
Yap_InitCPred("open_mem_write_stream", 1, open_mem_write_stream,
SyncPredFlag);
Yap_InitCPred("peek_mem_write_stream", 3, peek_mem_write_stream,
SyncPredFlag);
2015-06-18 01:32:33 +01:00
CurrentModule = cm;
}