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/iopreds.c

2114 lines
58 KiB
C
Raw Normal View History

2015-06-18 01:39:03 +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 *
* *
**************************************************************************
* *
* File: iopreds.c *
* Last rev: 5/2/88 *
* mods: *
* comments: Input/Output C implemented predicates *
* *
*************************************************************************/
2015-06-18 01:39:03 +01:00
#ifdef SCCS
static char SccsId[] = "%W% %G%";
#endif
/**
* @file iopreds.c
* @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
* @date Wed Jan 20 00:45:56 2016
2016-02-18 12:10:58 +00:00
*
* @brief main open and close predicates over generic streams.
2016-02-18 12:10:58 +00:00
*
*/
2015-06-18 01:39:03 +01:00
/*
2016-02-18 12:10:58 +00:00
* This file includes the definition of a miscellania of standard predicates *
2018-05-21 14:45:24 +01:00
*for yap refering to: Files and GLOBAL_1588
*ams, Simple Input/Output,
2015-06-18 01:39:03 +01:00
*
*/
#include "Yap.h"
#include "YapEval.h"
2015-06-18 01:39:03 +01:00
#include "YapHeap.h"
#include "YapText.h"
2016-04-05 02:53:39 +01:00
#include "Yatom.h"
#include "yapio.h"
2015-06-18 01:39:03 +01:00
#include <stdlib.h>
2017-11-29 13:47:57 +00:00
2016-04-05 02:53:39 +01:00
#if HAVE_UNISTD_H
2017-11-29 13:47:57 +00:00
2016-04-05 02:53:39 +01:00
#include <unistd.h>
2017-11-29 13:47:57 +00:00
2016-04-05 02:53:39 +01:00
#endif
2015-06-18 01:39:03 +01:00
#if HAVE_STDARG_H
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <stdarg.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#if HAVE_CTYPE_H
#endif
#if HAVE_WCTYPE_H
#endif
#if HAVE_SYS_TIME_H
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <sys/time.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#if HAVE_SYS_TYPES_H
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <sys/types.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#ifdef HAVE_SYS_STAT_H
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <sys/stat.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
2015-10-05 10:33:52 +01:00
#if HAVE_SYS_SELECT_H && !_MSC_VER && !defined(__MINGW32__)
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <sys/select.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#ifdef HAVE_UNISTD_H
#endif
#if HAVE_STRING_H
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <string.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#if HAVE_SIGNAL_H
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#include <signal.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#if HAVE_FCNTL_H
/* for O_BINARY and O_TEXT in WIN32 */
#include <fcntl.h>
2017-11-29 13:47:57 +00:00
2015-06-18 01:39:03 +01:00
#endif
#ifdef _WIN32
#if HAVE_IO_H
/* Windows */
#include <io.h>
#endif
#endif
#if !HAVE_STRNCAT
2015-12-15 09:14:15 +00:00
#define strncat(X, Y, Z) strcat(X, Y)
2015-06-18 01:39:03 +01:00
#endif
#if !HAVE_STRNCPY
2015-12-15 09:14:15 +00:00
#define strncpy(X, Y, Z) strcpy(X, Y)
2015-06-18 01:39:03 +01:00
#endif
2015-10-05 10:33:52 +01:00
#if _MSC_VER || defined(__MINGW32__)
2015-06-18 01:39:03 +01:00
#if HAVE_SOCKET
#include <winsock2.h>
#endif
#include <windows.h>
#ifndef S_ISDIR
2015-12-15 09:14:15 +00:00
#define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
2015-06-18 01:39:03 +01:00
#endif
#endif
2015-06-18 01:39:03 +01:00
#include "iopreds.h"
#include "getw.h"
2015-12-15 09:14:15 +00:00
static int get_wchar_from_file(int);
2015-06-18 01:39:03 +01:00
FILE *Yap_stdin;
FILE *Yap_stdout;
FILE *Yap_stderr;
2016-02-11 14:17:30 +00:00
static Term gethdir(Term t) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
Atom aref = AtomOfTerm(t);
2018-01-05 16:57:38 +00:00
char *s = RepAtom(aref)->StrOfAE;
size_t nsz;
2016-02-11 14:17:30 +00:00
2018-01-05 16:57:38 +00:00
s = strncpy(LOCAL_FileNameBuf, RepAtom(aref)->StrOfAE, MAXPATHLEN - 1);
if (!s) {
return false;
}
if (TermDot == t) {
return TermEmptyAtom;
}
nsz = strlen(s);
if (!Yap_dir_separator(s[nsz - 1])) {
2016-02-11 14:17:30 +00:00
#if _WIN32
2018-01-05 16:57:38 +00:00
s[nsz] = '\\';
2016-02-11 14:17:30 +00:00
#else
2018-01-05 16:57:38 +00:00
s[nsz] = '/';
2016-02-11 14:17:30 +00:00
#endif
2018-01-05 16:57:38 +00:00
s[nsz + 1] = '\0';
}
return MkAtomTerm(Yap_LookupAtom(s));
2016-02-11 14:17:30 +00:00
}
2016-05-12 11:44:00 +01:00
static Term issolutions(Term t) {
2018-01-05 16:57:38 +00:00
if (t == TermFirst || t == TermAll)
return t;
2015-12-15 09:14:15 +00:00
2018-01-05 16:57:38 +00:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "solutions in {first, all}.");
2016-05-12 11:44:00 +01:00
return TermZERO;
2018-01-05 16:57:38 +00:00
}
if (IsAtomTerm(t)) {
Yap_Error(DOMAIN_ERROR_SOLUTIONS, t, "solutions in {first, all}");
return TermZERO;
}
Yap_Error(TYPE_ERROR_ATOM, t, "solutions in {first, all}}");
return TermZERO;
2015-09-21 23:05:36 +01:00
}
2016-05-12 11:44:00 +01:00
static Term is_file_type(Term t) {
2018-01-05 16:57:38 +00:00
if (t == TermTxt || t == TermProlog || t == TermSource ||
t == TermExecutable || t == TermQly || t == TermDirectory)
return t;
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t,
"file_type in {txt,prolog,exe,directory...}");
2016-05-12 11:44:00 +01:00
return TermZERO;
2018-01-05 16:57:38 +00:00
}
if (IsAtomTerm(t)) {
Yap_Error(DOMAIN_ERROR_FILE_TYPE, t,
"file_type in {txt,prolog,exe,directory...}");
return TermZERO;
}
Yap_Error(TYPE_ERROR_ATOM, t, "file_type in {txt,prolog,exe,directory...}");
return TermZERO;
2015-09-21 23:05:36 +01:00
}
2016-05-12 11:44:00 +01:00
static Term is_file_errors(Term t) {
2018-01-05 16:57:38 +00:00
if (t == TermFail || t == TermError)
return t;
2015-12-15 09:14:15 +00:00
2018-01-05 16:57:38 +00:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "file_error in {fail,error}.");
2016-05-12 11:44:00 +01:00
return TermZERO;
2018-01-05 16:57:38 +00:00
}
if (IsAtomTerm(t)) {
Yap_Error(DOMAIN_ERROR_FILE_ERRORS, t, "file_error in {fail,error}.");
return TermZERO;
}
Yap_Error(TYPE_ERROR_ATOM, t, "file_error in {fail,error}.");
return TermZERO;
2015-09-21 23:05:36 +01:00
}
2015-06-18 01:39:03 +01:00
2018-01-18 14:47:27 +00:00
int ResetEOF(StreamDesc *s) {
2018-01-27 10:17:27 +00:00
if (s->status & Eof_Error_Stream_f) {
Atom name = s->name;
// Yap_CloseStream(s - GLOBAL_Stream);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, MkAtomTerm(name),
"GetC");
return FALSE;
} else if (s->status & Reset_Eof_Stream_f) {
s->status &= ~Push_Eof_Stream_f;
/* reset the eof indicator on file */
if (feof(s->file))
clearerr(s->file);
/* reset our function for reading input */
Yap_DefaultStreamOps(s);
/* next, reset our own error indicator */
s->status &= ~Eof_Stream_f;
/* try reading again */
return TRUE;
} else {
s->status |= Past_Eof_Stream_f;
return FALSE;
}
2018-01-18 14:47:27 +00:00
}
/* handle reading from a stream after having found an EOF */
static int EOFWGetc(int sno) {
2018-01-27 10:17:27 +00:00
register StreamDesc *s = &GLOBAL_Stream[sno];
2018-01-18 14:47:27 +00:00
2018-01-27 10:17:27 +00:00
if (s->status & Push_Eof_Stream_f) {
/* ok, we have pushed an EOF, send it away */
s->status &= ~Push_Eof_Stream_f;
2018-01-18 14:47:27 +00:00
return EOF;
2018-01-27 10:17:27 +00:00
}
if (ResetEOF(s)) {
Yap_DefaultStreamOps(s);
return (s->stream_wgetc(sno));
}
return EOF;
2018-01-18 14:47:27 +00:00
}
static int EOFGetc(int sno) {
2018-01-27 10:17:27 +00:00
register StreamDesc *s = &GLOBAL_Stream[sno];
2018-01-18 14:47:27 +00:00
2018-01-27 10:17:27 +00:00
if (s->status & Push_Eof_Stream_f) {
/* ok, we have pushed an EOF, send it away */
s->status &= ~Push_Eof_Stream_f;
ResetEOF(s);
2018-01-18 14:47:27 +00:00
return EOF;
2018-01-27 10:17:27 +00:00
}
if (ResetEOF(s)) {
Yap_DefaultStreamOps(s);
return s->stream_getc(sno);
}
return EOF;
2018-01-18 14:47:27 +00:00
}
2015-12-15 09:14:15 +00:00
static void unix_upd_stream_info(StreamDesc *s) {
2018-01-05 16:57:38 +00:00
if (s->status & InMemory_Stream_f) {
s->status |= Seekable_Stream_f;
return;
}
Yap_socketStream(s);
2017-11-29 13:47:57 +00:00
#if _MSC_VER || defined(__MINGW32__)
2018-01-05 16:57:38 +00:00
{
if (_isatty(_fileno(s->file))) {
s->status |= Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f;
/* make all console descriptors unbuffered */
setvbuf(s->file, NULL, _IONBF, 0);
2017-11-29 13:47:57 +00:00
return;
}
2018-01-05 16:57:38 +00:00
#if _MSC_VER
/* standard error stream should never be buffered */
else if (StdErrStream == s - GLOBAL_Stream) {
setvbuf(s->file, NULL, _IONBF, 0);
}
#endif
s->status |= Seekable_Stream_f;
return;
}
2015-06-18 01:39:03 +01:00
#else
#if HAVE_ISATTY
#if __simplescalar__
2018-01-05 16:57:38 +00:00
/* isatty does not seem to work with simplescar. I'll assume the first
2018-04-24 17:51:00 +01:00
three streams will probably be ttys (pipes are not thatg different) */
2018-01-05 16:57:38 +00:00
if (s - Stream < 3) {
s->name = AtomTty;
s->status |= Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f;
}
2017-11-29 13:47:57 +00:00
#else
2018-01-05 16:57:38 +00:00
{
int filedes; /* visualc */
if (!s->file) {
s->name = AtomNil;
return;
}
filedes = fileno(s->file);
if (isatty(filedes)) {
2015-10-05 10:33:52 +01:00
#if HAVE_TTYNAME
2018-01-05 16:57:38 +00:00
int rc = ttyname_r(filedes, LOCAL_FileNameBuf, YAP_FILENAME_MAX - 1);
if (rc == 0)
s->name = Yap_LookupAtom(LOCAL_FileNameBuf);
else
s->name = AtomTtys;
2015-06-18 01:39:03 +01:00
#else
2018-01-05 16:57:38 +00:00
s->name = AtomTty;
2015-06-18 01:39:03 +01:00
#endif
2018-01-05 16:57:38 +00:00
s->status |= Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f;
return;
2015-06-18 01:39:03 +01:00
}
2018-01-05 16:57:38 +00:00
}
2015-06-18 01:39:03 +01:00
#endif
#endif /* HAVE_ISATTY */
#endif /* _MSC_VER */
2018-01-05 16:57:38 +00:00
s->status |= Seekable_Stream_f;
2015-06-18 01:39:03 +01:00
}
2018-03-02 21:18:24 +00:00
static void default_peek(StreamDesc *st) {
{
st->stream_peek = Yap_peekChar;
st->stream_wpeek = Yap_peekWide;
}
if (st->status & Eof_Stream_f) {
st->stream_peek = EOFPeek;
st->stream_wpeek = EOFPeek;
st->stream_getc = EOFGetc;
st->stream_wgetc = EOFWGetc;
}
if (GLOBAL_CharConversionTable != NULL)
st->stream_wgetc_for_read = ISOWGetc;
else
st->stream_wgetc_for_read = st->stream_wgetc;
}
void Yap_DefaultStreamOps(StreamDesc *st) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-03-02 21:18:24 +00:00
2018-04-27 13:01:08 +01:00
st->stream_wputc = put_wchar;
2018-03-02 21:18:24 +00:00
st->stream_wgetc = get_wchar;
2018-03-26 15:01:21 +01:00
if (st->vfs && !st->file) {
2018-01-05 16:57:38 +00:00
st->stream_putc = st->vfs->put_char;
2018-09-26 01:14:14 +01:00
st->stream_wputc = st->vfs->put_wchar;
2018-03-02 21:18:24 +00:00
st->stream_getc = st->vfs->get_char;
2018-10-16 14:31:16 +01:00
st->stream_wgetc = st->vfs->get_wchar;
2018-03-02 21:18:24 +00:00
default_peek(st);
return;
2018-01-05 16:57:38 +00:00
} else {
2018-03-02 21:18:24 +00:00
if (st->encoding == ENC_ISO_UTF8)
st->stream_wgetc = get_wchar_UTF8;
2018-01-05 16:57:38 +00:00
st->stream_putc = FilePutc;
st->stream_getc = PlGetc;
2018-03-02 21:18:24 +00:00
if (st->status & Pipe_Stream_f) {
Yap_PipeOps(st);
} else if (st->status & InMemory_Stream_f) {
Yap_MemOps(st);
} else if (st->status & Tty_Stream_f) {
Yap_ConsoleOps(st);
} else {
unix_upd_stream_info(st);
}
if (st->status & (Promptable_Stream_f)) {
Yap_ConsoleOps(st);
}
2016-04-12 16:04:33 +01:00
#ifndef _WIN32
2018-03-02 21:18:24 +00:00
else if (st->file != NULL && 0 && !(st->status & InMemory_Stream_f)) {
st->stream_wgetc = get_wchar_from_file;
}
2016-04-10 14:21:17 +01:00
#endif
2018-03-02 21:18:24 +00:00
if (st->buf.on) {
st->stream_getc = Yap_popChar;
st->stream_wgetc = Yap_popChar;
}
2018-01-18 14:47:27 +00:00
}
2018-02-10 14:12:29 +00:00
#if USE_READLINE
2018-02-01 01:44:34 +00:00
if (st->status & Readline_Stream_f) {
2018-03-02 21:18:24 +00:00
st->stream_peek = Yap_ReadlinePeekChar;
st->stream_wpeek = Yap_ReadlinePeekChar;
}
2018-02-01 01:44:34 +00:00
/* else {
2018-04-24 17:51:00 +01:00
st->stream_peek = Yap_peekWithGetc;
st->stream_wpeek = Yap_peekWideWithGetwc;
}
} else if (st->status & Seekable_Stream_f) {
st->stream_peek = Yap_peekWithSeek;
st->stream_wpeek = Yap_peekWideWithSeek;
} */
2018-02-10 14:12:29 +00:00
else
#endif
2018-03-02 21:18:24 +00:00
default_peek(st);
}
static void InitFileIO(StreamDesc *s) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
Yap_DefaultStreamOps(s);
2015-06-18 01:39:03 +01:00
}
2017-07-25 01:10:44 +01:00
static void InitStdStream(int sno, SMALLUNSGN flags, FILE *file, VFS_t *vfsp) {
2018-01-05 16:57:38 +00:00
StreamDesc *s = &GLOBAL_Stream[sno];
s->file = file;
s->status = flags;
s->linepos = 0;
s->linecount = 1;
s->charcount = 0;
s->vfs = vfsp;
2018-01-18 14:47:27 +00:00
s->buf.on = false;
2018-01-05 16:57:38 +00:00
s->encoding = ENC_ISO_UTF8;
INIT_LOCK(s->streamlock);
2018-03-17 10:38:56 +00:00
if (vfsp == NULL) {
2018-04-24 17:51:00 +01:00
unix_upd_stream_info(s);
2018-01-05 16:57:38 +00:00
}
/* Getting streams to prompt is a mess because we need for cooperation
between readers and writers to the stream :-(
*/
InitFileIO(s);
switch (sno) {
case 0:
s->name = AtomUserIn;
break;
case 1:
s->name = AtomUserOut;
break;
default:
s->name = AtomUserErr;
break;
}
s->user_name = MkAtomTerm(s->name);
2015-06-18 01:39:03 +01:00
#if LIGHT
2018-01-05 16:57:38 +00:00
s->status |= Tty_Stream_f | Promptable_Stream_f;
2015-06-18 01:39:03 +01:00
#endif
2018-01-18 14:47:27 +00:00
s->buf.on = false;
2018-01-05 16:57:38 +00:00
Yap_DefaultStreamOps(s);
2015-06-18 01:39:03 +01:00
#if HAVE_SETBUF
2018-01-05 16:57:38 +00:00
if (s->status & Tty_Stream_f && sno == 0) {
/* make sure input is unbuffered if it comes from stdin, this
makes life simpler for interrupt handling */
setbuf(stdin, NULL);
// fprintf(stderr,"here I am\n");
}
2015-06-18 01:39:03 +01:00
#endif /* HAVE_SETBUF */
}
2017-09-06 01:17:43 +01:00
void Yap_InitStdStream(int sno, unsigned int flags, FILE *file, VFS_t *vfsp) {
2018-01-05 16:57:38 +00:00
InitStdStream(sno, flags, file, vfsp);
2017-07-25 01:10:44 +01:00
}
2015-12-15 09:14:15 +00:00
Term Yap_StreamUserName(int sno) {
2018-01-05 16:57:38 +00:00
Term atname;
StreamDesc *s = &GLOBAL_Stream[sno];
if (s->user_name != 0L) {
return (s->user_name);
}
if ((atname = StreamName(sno)))
return atname;
return TermNil;
2015-07-06 12:03:16 +01:00
}
2015-06-18 01:39:03 +01:00
2015-12-15 09:14:15 +00:00
static void InitStdStreams(void) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
if (LOCAL_sockets_io) {
InitStdStream(StdInStream, Input_Stream_f, NULL, NULL);
InitStdStream(StdOutStream, Output_Stream_f, NULL, NULL);
InitStdStream(StdErrStream, Output_Stream_f, NULL, NULL);
} else {
InitStdStream(StdInStream, Input_Stream_f, stdin, NULL);
InitStdStream(StdOutStream, Output_Stream_f, stdout, NULL);
InitStdStream(StdErrStream, Output_Stream_f, stderr, NULL);
}
2018-01-05 16:57:38 +00:00
GLOBAL_Stream[StdInStream].name = Yap_LookupAtom("user_input");
GLOBAL_Stream[StdOutStream].name = Yap_LookupAtom("user_output");
GLOBAL_Stream[StdErrStream].name = Yap_LookupAtom("user_error");
2016-07-31 16:28:05 +01:00
#if USE_READLINE
2018-01-05 16:57:38 +00:00
if (GLOBAL_Stream[StdInStream].status & Tty_Stream_f &&
GLOBAL_Stream[StdOutStream].status & Tty_Stream_f &&
2018-06-28 12:48:29 +01:00
GLOBAL_Stream[StdErrStream].status & Tty_Stream_f && !Yap_Embedded) {
2018-01-05 16:57:38 +00:00
Yap_InitReadline(TermTrue);
}
2016-07-31 16:28:05 +01:00
#endif
2018-01-05 16:57:38 +00:00
LOCAL_c_input_stream = StdInStream;
LOCAL_c_output_stream = StdOutStream;
LOCAL_c_error_stream = StdErrStream;
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
void Yap_InitStdStreams(void) { InitStdStreams(); }
2015-09-29 23:44:11 +01:00
2015-12-15 09:14:15 +00:00
Int PlIOError__(const char *file, const char *function, int lineno,
yap_error_number type, Term culprit, ...) {
2018-01-05 16:57:38 +00:00
if (trueLocalPrologFlag(FILEERRORS_FLAG) ||
type == RESOURCE_ERROR_MAX_STREAMS /* do not catch resource errors */) {
va_list args;
const char *format;
char who[1024];
va_start(args, culprit);
format = va_arg(args, char *);
if (format) {
vsnprintf(who, 1023, format, args);
2015-10-18 11:49:18 +01:00
} else {
2018-01-05 16:57:38 +00:00
who[0] = '\0';
2015-10-18 11:49:18 +01:00
}
2018-01-05 16:57:38 +00:00
va_end(args);
2018-03-29 22:33:53 +01:00
Yap_Error__(false, file, function, lineno, type, culprit, who);
2018-01-05 16:57:38 +00:00
/* and fail */
return false;
} else {
pop_text_stack(0);
memset(LOCAL_ActiveError, 0, sizeof(*LOCAL_ActiveError));
return false;
}
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
static int eolflg = 1;
2015-06-18 01:39:03 +01:00
2015-12-15 09:14:15 +00:00
static char my_line[200] = {0};
static char *lp = my_line;
2015-06-18 01:39:03 +01:00
2015-12-15 09:14:15 +00:00
FILE *curfile, *Yap_logfile;
2015-06-18 01:39:03 +01:00
bool Yap_Option[256];
#ifdef MACC
2015-12-15 09:14:15 +00:00
static void InTTYLine(char *line) {
char *p = line;
char ch;
2015-06-18 01:39:03 +01:00
while ((ch = InKey()) != '\n' && ch != '\r')
if (ch == 8) {
if (line < p)
2015-10-05 10:33:52 +01:00
BackupTTY(*--p);
2015-06-18 01:39:03 +01:00
} else
TTYChar(*p++ = ch);
TTYChar('\n');
*p = 0;
}
#endif
2015-12-15 09:14:15 +00:00
void Yap_DebugSetIFile(char *fname) {
2018-01-05 16:57:38 +00:00
if (curfile)
fclose(curfile);
curfile = fopen(fname, "r");
if (curfile == NULL) {
curfile = stdin;
Yap_Warning("%% YAP open %s for input\n", fname);
}
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
void Yap_DebugEndline() { *lp = 0; }
2015-11-05 17:16:10 +00:00
2015-12-15 09:14:15 +00:00
int Yap_DebugGetc() {
2018-01-05 16:57:38 +00:00
int ch;
if (eolflg) {
if (curfile != NULL) {
if (fgets(my_line, 200, curfile) == 0)
curfile = NULL;
}
if (curfile == NULL)
if (fgets(my_line, 200, stdin) == NULL) {
return EOF;
}
eolflg = 0;
lp = my_line;
}
if ((ch = *lp++) == 0)
ch = '\n', eolflg = 1;
if (Yap_Option['l' - 96])
putc(ch, Yap_logfile);
return (ch);
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
int Yap_DebugPutc(FILE *s, wchar_t ch) {
2018-01-05 16:57:38 +00:00
if (Yap_Option['l' - 96])
(void)putc(ch, Yap_logfile);
2018-05-24 21:45:38 +01:00
return (putc(ch, stderr));
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
int Yap_DebugPuts(FILE *s, const char *sch) {
2018-01-05 16:57:38 +00:00
if (Yap_Option['l' - 96])
(void)fputs(sch, Yap_logfile);
2018-05-24 21:45:38 +01:00
return fputs(sch, stderr);
}
2015-12-15 09:14:15 +00:00
void Yap_DebugErrorPuts(const char *s) { Yap_DebugPuts(stderr, s); }
2015-12-15 09:14:15 +00:00
void Yap_DebugPlWrite(Term t) {
2018-01-05 16:57:38 +00:00
if (t == 0)
fprintf(stderr, "NULL");
Yap_plwrite(t, GLOBAL_Stream + 2, 0, 0, GLOBAL_MaxPriority);
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
void Yap_DebugPlWriteln(Term t) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
if (t == 0)
fprintf(stderr, "NULL");
2018-01-05 16:57:38 +00:00
Yap_plwrite(t, NULL, 15, 0, GLOBAL_MaxPriority);
Yap_DebugPutc(GLOBAL_Stream[LOCAL_c_error_stream].file, '.');
Yap_DebugPutc(GLOBAL_Stream[LOCAL_c_error_stream].file, 10);
2015-11-05 17:16:10 +00:00
}
2015-12-15 09:14:15 +00:00
void Yap_DebugErrorPutc(int c) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
Yap_DebugPutc(GLOBAL_Stream[LOCAL_c_error_stream].file, c);
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
void Yap_DebugWriteIndicator(PredEntry *ap) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
Term tmod = ap->ModuleOfPred;
2018-01-05 16:57:38 +00:00
if (!tmod)
tmod = TermProlog;
2015-09-25 10:57:26 +01:00
#if THREADS
2018-01-05 16:57:38 +00:00
Yap_DebugPlWrite(MkIntegerTerm(worker_id));
Yap_DebugPutc(stderr, ' ');
2015-09-25 10:57:26 +01:00
#endif
2018-01-05 16:57:38 +00:00
Yap_DebugPutc(stderr, '>');
Yap_DebugPutc(stderr, '\t');
Yap_DebugPlWrite(tmod);
Yap_DebugPutc(stderr, ':');
if (ap->ModuleOfPred == IDB_MODULE) {
Term t = Deref(ARG1);
if (IsAtomTerm(t)) {
Yap_DebugPlWrite(t);
} else if (IsIntegerTerm(t)) {
Yap_DebugPlWrite(t);
2015-10-05 10:33:52 +01:00
} else {
2018-01-05 16:57:38 +00:00
Functor f = FunctorOfTerm(t);
Atom At = NameOfFunctor(f);
Yap_DebugPlWrite(MkAtomTerm(At));
Yap_DebugPutc(stderr, '/');
Yap_DebugPlWrite(MkIntegerTerm(ArityOfFunctor(f)));
}
} else {
if (ap->ArityOfPE == 0) {
Atom At = (Atom)ap->FunctorOfPred;
Yap_DebugPlWrite(MkAtomTerm(At));
} else {
Functor f = ap->FunctorOfPred;
Atom At = NameOfFunctor(f);
Yap_DebugPlWrite(MkAtomTerm(At));
Yap_DebugPutc(stderr, '/');
Yap_DebugPlWrite(MkIntegerTerm(ArityOfFunctor(f)));
2015-10-05 10:33:52 +01:00
}
2018-01-05 16:57:38 +00:00
}
2015-09-25 10:57:26 +01:00
2018-01-05 16:57:38 +00:00
Yap_DebugPutc(stderr, '\n');
2015-12-15 09:14:15 +00:00
}
2015-09-25 10:57:26 +01:00
2015-06-18 01:39:03 +01:00
/* static */
2015-12-15 09:14:15 +00:00
int FilePutc(int sno, int ch) {
2018-01-05 16:57:38 +00:00
StreamDesc *s = &GLOBAL_Stream[sno];
2015-06-18 01:39:03 +01:00
#if MAC || _MSC_VER
2018-01-05 16:57:38 +00:00
if (ch == 10) {
ch = '\n';
}
2015-06-18 01:39:03 +01:00
#endif
2018-01-05 16:57:38 +00:00
putc(ch, s->file);
2015-06-18 01:39:03 +01:00
#if MAC || _MSC_VER
2018-01-05 16:57:38 +00:00
if (ch == 10) {
fflush(s->file);
}
2015-06-18 01:39:03 +01:00
#endif
2018-01-05 16:57:38 +00:00
count_output_char(ch, s);
return ((int)ch);
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
static int NullPutc(int sno, int ch) {
2018-01-05 16:57:38 +00:00
StreamDesc *s = &GLOBAL_Stream[sno];
2015-06-18 01:39:03 +01:00
#if MAC || _MSC_VER
2018-01-05 16:57:38 +00:00
if (ch == 10) {
ch = '\n';
}
2015-06-18 01:39:03 +01:00
#endif
2018-01-05 16:57:38 +00:00
count_output_char(ch, s);
return ((int)ch);
2015-06-18 01:39:03 +01:00
}
/* check if we read a LOCAL_newline or an EOF */
2015-12-15 09:14:15 +00:00
int console_post_process_eof(StreamDesc *s) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
if (!ResetEOF(s)) {
s->status |= Eof_Stream_f;
s->stream_getc = EOFGetc;
s->stream_wgetc = EOFWGetc;
s->stream_wgetc_for_read = EOFWGetc;
LOCAL_newline = true;
}
2018-01-05 16:57:38 +00:00
return EOFCHAR;
2015-06-18 01:39:03 +01:00
}
/* check if we read a newline or an EOF */
int post_process_read_wchar(int ch, size_t n, StreamDesc *s) {
2018-01-05 16:57:38 +00:00
if (ch == EOF) {
return post_process_weof(s);
}
2016-10-20 04:44:59 +01:00
#if DEBUG
2018-01-05 16:57:38 +00:00
if (GLOBAL_Option[1]) {
static int v;
fprintf(stderr, "%d %C\n", v, ch);
v++;
}
2016-08-15 20:52:15 +01:00
#endif
2018-01-05 16:57:38 +00:00
s->charcount += n;
s->linepos += n;
if (ch == '\n') {
++s->linecount;
s->linepos = 0;
/* don't convert if the stream is binary */
if (!(s->status & Binary_Stream_f))
ch = 10;
}
return ch;
2015-06-18 01:39:03 +01:00
}
2015-12-15 09:14:15 +00:00
int post_process_weof(StreamDesc *s) {
2018-01-05 16:57:38 +00:00
if (!ResetEOF(s)) {
s->status |= Eof_Stream_f;
s->stream_wgetc = EOFWGetc;
s->stream_getc = EOFGetc;
s->stream_wgetc_for_read = EOFWGetc;
}
return EOFCHAR;
}
2018-01-05 16:57:38 +00:00
void *Yap_RepStreamFromId(int sno) { return GLOBAL_Stream + (sno); }
2017-12-05 15:14:57 +00:00
2016-01-03 02:06:09 +00:00
/**
2016-07-31 16:28:05 +01:00
* caled after EOF found a peek, it just calls console_post_process to
*conclude
2016-01-03 02:06:09 +00:00
*the job.
*
* @param sno
*
2015-12-15 09:14:15 +00:00
* @return EOF
*/
int EOFPeek(int sno) { return EOFCHAR; }
2015-12-15 09:14:15 +00:00
int EOFWPeek(int sno) { return EOFCHAR; }
2015-06-18 01:39:03 +01:00
/* standard routine, it should read from anything pointed by a FILE *.
2018-04-24 17:51:00 +01:00
It could be made more efficient by doing our own buffering and avoiding
post_process_read_char, something to think about */
2015-12-15 09:14:15 +00:00
int PlGetc(int sno) {
2018-01-05 16:57:38 +00:00
StreamDesc *s = &GLOBAL_Stream[sno];
return fgetc(s->file);
2015-06-18 01:39:03 +01:00
}
2016-04-05 02:53:39 +01:00
// layered version
static inline int get_wchar_from_file(int sno) {
2018-01-05 16:57:38 +00:00
return post_process_read_wchar(fgetwc(GLOBAL_Stream[sno].file), 1,
GLOBAL_Stream + sno);
2016-04-05 02:53:39 +01:00
}
2015-06-18 01:39:03 +01:00
#ifndef MB_LEN_MAX
#define MB_LEN_MAX 6
#endif
2016-04-05 02:53:39 +01:00
static int handle_write_encoding_error(int sno, wchar_t ch) {
2018-01-05 16:57:38 +00:00
if (GLOBAL_Stream[sno].status & RepError_Xml_f) {
/* use HTML/XML encoding in ASCII */
int i = ch, digits = 1;
GLOBAL_Stream[sno].stream_putc(sno, '&');
GLOBAL_Stream[sno].stream_putc(sno, '#');
while (digits < i)
digits *= 10;
if (digits > i)
digits /= 10;
while (i) {
GLOBAL_Stream[sno].stream_putc(sno, i / digits);
i %= 10;
digits /= 10;
}
GLOBAL_Stream[sno].stream_putc(sno, ';');
return ch;
} else if (GLOBAL_Stream[sno].status & RepError_Prolog_f) {
/* write quoted */
GLOBAL_Stream[sno].stream_putc(sno, '\\');
GLOBAL_Stream[sno].stream_putc(sno, 'u');
GLOBAL_Stream[sno].stream_putc(sno, ch >> 24);
GLOBAL_Stream[sno].stream_putc(sno, 256 & (ch >> 16));
GLOBAL_Stream[sno].stream_putc(sno, 256 & (ch >> 8));
GLOBAL_Stream[sno].stream_putc(sno, 256 & ch);
return ch;
} else {
CACHE_REGS
2018-04-27 13:01:08 +01:00
Yap_Error(REPRESENTATION_ERROR_CHARACTER, MkIntegerTerm(ch),
"charater %ld cannot be encoded in stream %d",
(unsigned long int)ch, sno);
2018-01-05 16:57:38 +00:00
return -1;
}
2017-11-29 13:47:57 +00:00
}
2016-02-26 17:45:45 +00:00
2017-11-29 13:47:57 +00:00
int put_wchar(int sno, wchar_t ch) {
2018-01-05 16:57:38 +00:00
/* pass the bucck if we can */
switch (GLOBAL_Stream[sno].encoding) {
case ENC_OCTET:
return GLOBAL_Stream[sno].stream_putc(sno, ch);
case ENC_ISO_LATIN1:
if (ch >= 0xff) {
return handle_write_encoding_error(sno, ch);
}
return GLOBAL_Stream[sno].stream_putc(sno, ch);
case ENC_ISO_ASCII:
if (ch >= 0x80) {
return handle_write_encoding_error(sno, ch);
}
return GLOBAL_Stream[sno].stream_putc(sno, ch);
case ENC_ISO_ANSI: {
char buf[MB_LEN_MAX];
mbstate_t mbstate;
int n;
memset((void *)&mbstate, 0, sizeof(mbstate_t));
if ((n = wcrtomb(buf, ch, &mbstate)) < 0) {
/* error */
GLOBAL_Stream[sno].stream_putc(sno, ch);
return -1;
} else {
int i;
for (i = 0; i < n; i++) {
GLOBAL_Stream[sno].stream_putc(sno, buf[i]);
}
return ch;
}
2018-04-27 13:01:08 +01:00
case ENC_ISO_UTF8:
if (ch < 0x80) {
GLOBAL_Stream[sno].stream_putc(sno, ch);
} else if (ch < 0x800) {
GLOBAL_Stream[sno].stream_putc(sno, 0xC0 | ch >> 6);
GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch & 0x3F));
} else if (ch < 0x10000) {
GLOBAL_Stream[sno].stream_putc(sno, 0xE0 | ch >> 12);
GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch >> 6 & 0x3F));
GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch & 0x3F));
} else if (ch < 0x200000) {
GLOBAL_Stream[sno].stream_putc(sno, 0xF0 | ch >> 18);
GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch >> 12 & 0x3F));
GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch >> 6 & 0x3F));
GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch & 0x3F));
} else {
/* should never happen */
return -1;
}
return ch;
break;
case ENC_UTF16_LE: {
if (ch < 0x10000) {
GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
} else {
// computations
uint16_t ich = ch;
uint16_t lead = LEAD_OFFSET + (ich >> 10);
uint16_t trail = 0xDC00 + (ich & 0x3FF);
GLOBAL_Stream[sno].stream_putc(sno, (trail & 0xff));
GLOBAL_Stream[sno].stream_putc(sno, (trail >> 8));
GLOBAL_Stream[sno].stream_putc(sno, (lead & 0xff));
GLOBAL_Stream[sno].stream_putc(sno, (lead >> 8));
}
return ch;
}
case ENC_UTF16_BE: {
// computations
if (ch < 0x10000) {
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
} else {
uint16_t lead = (uint16_t)LEAD_OFFSET + ((uint16_t)ch >> 10);
uint16_t trail = 0xDC00 + ((uint16_t)ch & 0x3FF);
GLOBAL_Stream[sno].stream_putc(sno, (lead >> 8));
GLOBAL_Stream[sno].stream_putc(sno, (lead & 0xff));
GLOBAL_Stream[sno].stream_putc(sno, (trail >> 8));
GLOBAL_Stream[sno].stream_putc(sno, (trail & 0xff));
}
return ch;
}
case ENC_UCS2_LE: {
if (ch >= 0x10000) {
return 0;
}
GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
return ch;
}
case ENC_UCS2_BE: {
// computations
if (ch < 0x10000) {
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
2018-01-05 16:57:38 +00:00
return ch;
2018-04-27 13:01:08 +01:00
} else {
return 0;
}
}
case ENC_ISO_UTF32_BE:
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 24) & 0xff);
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 16) & 0xff);
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8) & 0xff);
GLOBAL_Stream[sno].stream_putc(sno, ch & 0xff);
return ch;
case ENC_ISO_UTF32_LE:
GLOBAL_Stream[sno].stream_putc(sno, ch & 0xff);
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8) & 0xff);
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 16) & 0xff);
GLOBAL_Stream[sno].stream_putc(sno, (ch >> 24) & 0xff);
return ch;
2018-01-05 16:57:38 +00:00
}
}
return -1;
2016-04-05 02:53:39 +01:00
}
/* used by user-code to read characters from the current input stream */
int Yap_PlGetchar(void) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
return (
GLOBAL_Stream[LOCAL_c_input_stream].stream_getc(LOCAL_c_input_stream));
2016-04-05 02:53:39 +01:00
}
int Yap_PlGetWchar(void) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
return get_wchar(LOCAL_c_input_stream);
2016-04-05 02:53:39 +01:00
}
/* avoid using a variable to call a function */
int Yap_PlFGetchar(void) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
return (PlGetc(LOCAL_c_input_stream));
2016-04-05 02:53:39 +01:00
}
Term Yap_MkStream(int n) {
2018-01-05 16:57:38 +00:00
Term t[1];
t[0] = MkIntTerm(n);
return (Yap_MkApplTerm(FunctorStream, 1, t));
2016-04-05 02:53:39 +01:00
}
2016-02-26 17:45:45 +00:00
2016-04-05 02:53:39 +01:00
/* given a stream index, get the corresponding fd */
Int GetStreamFd(int sno) {
2015-06-18 01:39:03 +01:00
#if HAVE_SOCKET
2018-01-05 16:57:38 +00:00
if (GLOBAL_Stream[sno].status & Socket_Stream_f) {
return (GLOBAL_Stream[sno].u.socket.fd);
} else
2015-06-18 01:39:03 +01:00
#endif
2018-04-27 13:01:08 +01:00
if (GLOBAL_Stream[sno].status & Pipe_Stream_f) {
return (GLOBAL_Stream[sno].u.pipe.fd);
} else if (GLOBAL_Stream[sno].status & InMemory_Stream_f) {
return (-1);
}
2018-01-05 16:57:38 +00:00
return (fileno(GLOBAL_Stream[sno].file));
2016-04-05 02:53:39 +01:00
}
2015-06-18 01:39:03 +01:00
2016-04-05 02:53:39 +01:00
Int Yap_GetStreamFd(int sno) { return GetStreamFd(sno); }
2015-06-18 01:39:03 +01:00
2016-04-05 02:53:39 +01:00
static int binary_file(const char *file_name) {
2015-06-18 01:39:03 +01:00
#if HAVE_STAT
2015-10-05 10:33:52 +01:00
#if _MSC_VER || defined(__MINGW32__)
2018-01-05 16:57:38 +00:00
struct _stat ss;
if (_stat(file_name, &ss) != 0)
2015-06-18 01:39:03 +01:00
#else
2018-04-27 13:01:08 +01:00
struct stat ss;
2018-01-05 16:57:38 +00:00
if (stat(file_name, &ss) != 0)
2015-06-18 01:39:03 +01:00
#endif
2018-04-27 13:01:08 +01:00
{
/* ignore errors while checking a file */
return false;
}
2018-01-05 16:57:38 +00:00
return (S_ISDIR(ss.st_mode));
2015-10-05 10:33:52 +01:00
#else
2018-01-05 16:57:38 +00:00
return (FALSE);
2015-10-05 10:33:52 +01:00
#endif
2016-04-05 02:53:39 +01:00
}
2015-06-18 01:39:03 +01:00
2016-04-05 02:53:39 +01:00
static int write_bom(int sno, StreamDesc *st) {
2018-01-05 16:57:38 +00:00
/* dump encoding */
switch (st->encoding) {
case ENC_ISO_UTF8:
if (st->stream_putc(sno, 0xEF) < 0)
return false;
if (st->stream_putc(sno, 0xBB) < 0)
return false;
if (st->stream_putc(sno, 0xBF) < 0)
return false;
st->status |= HAS_BOM_f;
return true;
case ENC_UTF16_BE:
case ENC_UCS2_BE:
if (st->stream_putc(sno, 0xFE) < 0)
return false;
if (st->stream_putc(sno, 0xFF) < 0)
return false;
st->status |= HAS_BOM_f;
return true;
case ENC_UTF16_LE:
case ENC_UCS2_LE:
if (st->stream_putc(sno, 0xFF) < 0)
return false;
if (st->stream_putc(sno, 0xFE) < 0)
return false;
st->status |= HAS_BOM_f;
return true;
case ENC_ISO_UTF32_BE:
if (st->stream_putc(sno, 0x00) < 0)
return false;
if (st->stream_putc(sno, 0x00) < 0)
return false;
if (st->stream_putc(sno, 0xFE) < 0)
return false;
if (st->stream_putc(sno, 0xFF) < 0)
return false;
st->status |= HAS_BOM_f;
return true;
case ENC_ISO_UTF32_LE:
if (st->stream_putc(sno, 0xFF) < 0)
return false;
if (st->stream_putc(sno, 0xFE) < 0)
return false;
if (st->stream_putc(sno, 0x00) < 0)
return false;
if (st->stream_putc(sno, 0x00) < 0)
return false;
st->status |= HAS_BOM_f;
return true;
default:
return true;
}
2016-04-05 02:53:39 +01:00
}
2015-12-15 09:14:15 +00:00
2016-04-05 02:53:39 +01:00
static void check_bom(int sno, StreamDesc *st) {
2018-01-05 16:57:38 +00:00
int ch1, ch2, ch3, ch4;
if (st->file == NULL) {
PlIOError(SYSTEM_ERROR_INTERNAL, Yap_MkStream(sno),
"YAP does not support BOM n %x type of files", st->status);
return;
}
ch1 = st->stream_getc(sno);
switch (ch1) {
case 0x00: {
ch2 = st->stream_getc(sno);
if (ch2 != 0x00) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
return;
} else {
ch3 = st->stream_getc(sno);
if (ch3 == EOFCHAR || ch3 != 0xFE) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
ungetc(ch3, st->file);
return;
} else {
ch4 = st->stream_getc(sno);
if (ch4 == EOFCHAR || ch3 != 0xFF) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
ungetc(ch3, st->file);
ungetc(ch4, st->file);
return;
} else {
st->status |= HAS_BOM_f;
st->encoding = ENC_ISO_UTF32_BE;
return;
2016-02-18 12:10:58 +00:00
}
2018-01-05 16:57:38 +00:00
}
}
}
case 0xFE: {
ch2 = fgetc(st->file);
if (ch2 != 0xFF) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
return;
} else {
st->status |= HAS_BOM_f;
st->encoding = ENC_UTF16_BE;
return;
}
}
case 0xFF: {
ch2 = fgetc(st->file);
if (ch2 != 0xFE) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
return;
} else {
ch3 = fgetc(st->file);
if (ch3 != 0x00) {
ungetc(ch3, st->file);
} else {
ch4 = fgetc(st->file);
if (ch4 == 0x00) {
st->status |= HAS_BOM_f;
st->encoding = ENC_ISO_UTF32_LE;
return;
} else {
ungetc(ch4, st->file);
ungetc(0x00, st->file);
2017-11-29 13:47:57 +00:00
}
2018-01-05 16:57:38 +00:00
}
}
st->status |= HAS_BOM_f;
st->encoding = ENC_UTF16_LE;
return;
}
case 0xEF:
ch2 = fgetc(st->file);
if (ch2 != 0xBB) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
return;
} else {
ch3 = fgetc(st->file);
if (ch3 != 0xBF) {
ungetc(ch1, st->file);
ungetc(ch2, st->file);
ungetc(ch3, st->file);
return;
} else {
st->status |= HAS_BOM_f;
st->encoding = ENC_ISO_UTF8;
return;
}
2015-12-15 09:14:15 +00:00
}
2018-01-05 16:57:38 +00:00
default:
ungetc(ch1, st->file);
}
2016-04-05 02:53:39 +01:00
}
2015-06-18 01:39:03 +01:00
bool Yap_initStream(int sno, FILE *fd, Atom name, const char *io_mode,
2018-04-27 13:01:08 +01:00
Term file_name, encoding_t encoding, stream_flags_t flags,
void *vfs) {
2018-07-09 00:50:00 +01:00
// fprintf(stderr,"+ %s --> %d\n", name, sno);
2018-01-05 16:57:38 +00:00
StreamDesc *st = &GLOBAL_Stream[sno];
2018-07-09 00:50:00 +01:00
__android_log_print(
ANDROID_LOG_INFO, "YAPDroid", "init %s %s:%s stream <%d>", io_mode,
CurrentModule == 0 ? "prolog"
: RepAtom(AtomOfTerm(CurrentModule))->StrOfAE,
name, sno);
if (io_mode == NULL)
2018-04-27 13:01:08 +01:00
Yap_Error(PERMISSION_ERROR_NEW_ALIAS_FOR_STREAM, MkIntegerTerm(sno),
"File opened with NULL Permissions");
2018-04-24 17:51:00 +01:00
if (strchr(io_mode, 'a')) {
2018-04-27 13:01:08 +01:00
st->status = Append_Stream_f | Output_Stream_f | flags;
} else if (strchr(io_mode, 'w')) {
st->status = Output_Stream_f | flags;
}
2018-04-24 17:51:00 +01:00
if (strchr(io_mode, 'r')) {
2018-04-27 13:01:08 +01:00
st->status = Input_Stream_f | flags;
2018-04-24 17:51:00 +01:00
}
if (strchr(io_mode, 'b')) {
2018-04-27 13:01:08 +01:00
st->status = Binary_Stream_f | flags;
2018-04-24 17:51:00 +01:00
}
2018-01-05 16:57:38 +00:00
2018-04-27 13:01:08 +01:00
// st->vfs = vfs;
2018-01-18 14:47:27 +00:00
st->buf.on = false;
2018-01-05 16:57:38 +00:00
st->charcount = 0;
st->linecount = 1;
if (flags & Binary_Stream_f) {
st->encoding = ENC_OCTET;
} else {
st->encoding = encoding;
}
2018-10-08 13:51:17 +01:00
st->name = Yap_guessFileName(fd, sno, YAP_FILENAME_MAX);
if (!st->name)
2018-04-27 13:01:08 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, file_name,
"Yap_guessFileName failed: opening a file without a name");
2018-01-05 16:57:38 +00:00
st->user_name = file_name;
st->file = fd;
st->linepos = 0;
2018-06-26 11:07:07 +01:00
Yap_DefaultStreamOps(st);
return true;
2016-04-05 02:53:39 +01:00
}
2015-06-18 01:39:03 +01:00
2016-04-05 02:53:39 +01:00
static bool open_header(int sno, Atom open_mode) {
2018-01-05 16:57:38 +00:00
if (open_mode == AtomWrite) {
const char *ptr;
const char s[] = "#!";
int ch;
ptr = s;
while ((ch = *ptr++))
GLOBAL_Stream[sno].stream_wputc(sno, ch);
const char *b = Yap_FindExecutable();
ptr = b;
while ((ch = *ptr++))
GLOBAL_Stream[sno].stream_wputc(sno, ch);
const char *l = " -L --\n\n YAP script\n#\n# .\n";
ptr = l;
while ((ch = *ptr++))
GLOBAL_Stream[sno].stream_wputc(sno, ch);
} else if (open_mode == AtomRead) {
// skip header
int ch;
while ((ch = Yap_peek(sno)) == '#') {
while ((ch = GLOBAL_Stream[sno].stream_wgetc(sno)) != 10 && ch != -1)
;
}
2018-01-05 16:57:38 +00:00
}
return true;
2016-04-05 02:53:39 +01:00
}
2018-04-27 13:01:08 +01:00
#define OPEN_DEFS() \
PAR("alias", isatom, OPEN_ALIAS) \
, PAR("bom", booleanFlag, OPEN_BOM), PAR("buffer", isatom, OPEN_BUFFER), \
PAR("close_on_abort", booleanFlag, OPEN_CLOSE_ON_ABORT), \
PAR("create", isatom, OPEN_CREATE), \
PAR("encoding", isatom, OPEN_ENCODING), \
PAR("eof_action", isatom, OPEN_EOF_ACTION), \
PAR("expand_filename", booleanFlag, OPEN_EXPAND_FILENAME), \
PAR("file_name", isatom, OPEN_FILE_NAME), PAR("input", ok, OPEN_INPUT), \
PAR("locale", isatom, OPEN_LOCALE), PAR("lock", isatom, OPEN_LOCK), \
PAR("mode", isatom, OPEN_MODE), PAR("output", ok, OPEN_OUTPUT), \
PAR("representation_errors", booleanFlag, OPEN_REPRESENTATION_ERRORS), \
PAR("reposition", booleanFlag, OPEN_REPOSITION), \
PAR("script", booleanFlag, OPEN_SCRIPT), PAR("type", isatom, OPEN_TYPE), \
PAR("wait", booleanFlag, OPEN_WAIT), PAR(NULL, ok, OPEN_END)
2015-12-15 09:14:15 +00:00
#define PAR(x, y, z) z
2018-01-05 16:57:38 +00:00
typedef enum open_enum_choices { OPEN_DEFS() } open_choices_t;
2015-06-18 01:39:03 +01:00
#undef PAR
2018-04-27 13:01:08 +01:00
#define PAR(x, y, z) \
2015-12-15 09:14:15 +00:00
{ x, y, z }
2015-10-05 10:33:52 +01:00
2016-04-05 02:53:39 +01:00
static const param_t open_defs[] = {OPEN_DEFS()};
2015-06-18 01:39:03 +01:00
#undef PAR
2018-10-16 14:31:16 +01:00
static bool fill_stream(int sno, StreamDesc *st, Term tin, const char *io_mode,
Term user_name, encoding_t enc) {
2018-06-14 11:27:43 +01:00
struct vfs *vfsp = NULL;
const char *fname;
if (IsAtomTerm(tin))
fname = RepAtom(AtomOfTerm(tin))->StrOfAE;
else if (IsStringTerm(tin))
fname = StringOfTerm(tin);
else
fname = NULL;
st->file = NULL;
if (fname) {
if ((vfsp = vfs_owner(fname)) != NULL &&
vfsp->open(vfsp, fname, io_mode, sno)) {
// read, write, append
user_name = st->user_name;
st->vfs = vfsp;
UNLOCK(st->streamlock);
} else {
st->file = fopen(fname, io_mode);
if (st->file == NULL) {
UNLOCK(st->streamlock);
if (errno == ENOENT && !strchr(io_mode, 'r')) {
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, tin, "%s: %s", fname,
strerror(errno));
} else {
PlIOError(PERMISSION_ERROR_OPEN_SOURCE_SINK, tin, "%s: %s", fname,
strerror(errno));
}
}
st->vfs = NULL;
}
if (!st->file && !st->vfs) {
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, tin, "%s", fname);
/* extract BACK info passed through the stream descriptor */
return false;
}
} else if (IsApplTerm(tin)) {
Functor f = FunctorOfTerm(tin);
if (f == FunctorAtom || f == FunctorString || f == FunctorCodes1 ||
f == FunctorCodes || f == FunctorChars1 || f == FunctorChars) {
if (strchr(io_mode, 'r')) {
return Yap_OpenBufWriteStream(PASS_REGS1);
} else {
2018-10-16 14:31:16 +01:00
int j = push_text_stack();
2018-06-14 11:27:43 +01:00
const char *buf;
buf = Yap_TextTermToText(tin PASS_REGS);
if (!buf) {
2018-10-07 16:57:44 +01:00
pop_text_stack(j);
2018-06-14 11:27:43 +01:00
return false;
}
2018-10-07 16:57:44 +01:00
buf = pop_output_text_stack(j, buf);
2018-07-09 00:50:00 +01:00
Atom nat = Yap_LookupAtom(Yap_StrPrefix(buf, 32));
2018-06-14 11:27:43 +01:00
sno = Yap_open_buf_read_stream(buf, strlen(buf) + 1, &LOCAL_encoding,
2018-07-09 00:50:00 +01:00
MEM_BUF_MALLOC, nat,
MkAtomTerm(NameOfFunctor(f)));
2018-10-16 14:31:16 +01:00
pop_text_stack(j);
2018-06-14 11:27:43 +01:00
return Yap_OpenBufWriteStream(PASS_REGS1);
}
} else if (!strcmp(RepAtom(NameOfFunctor(f))->StrOfAE, "popen")) {
const char *buf;
int i = push_text_stack();
buf = Yap_TextTermToText(ArgOfTerm(1, tin) PASS_REGS);
if (buf == NULL) {
return false;
}
#if _WIN32
st->file = _popen(buf, io_mode);
#else
st->file = popen(buf, io_mode);
#endif
fname = "popen";
user_name = tin;
st->status |= Popen_Stream_f;
pop_text_stack(i);
} else {
2018-10-07 16:57:44 +01:00
Yap_ThrowError(DOMAIN_ERROR_SOURCE_SINK, tin, "open");
2018-06-14 11:27:43 +01:00
}
}
if (!strchr(io_mode, 'b') && binary_file(fname)) {
st->status |= Binary_Stream_f;
}
2018-10-16 14:31:16 +01:00
Yap_initStream(sno, st->file, Yap_LookupAtom(fname), io_mode, user_name,
LOCAL_encoding, st->status, vfsp);
2018-06-14 11:27:43 +01:00
return true;
}
2018-04-27 13:01:08 +01:00
static Int do_open(Term file_name, Term t2, Term tlist USES_REGS) {
2018-01-05 16:57:38 +00:00
Atom open_mode;
bool avoid_bom = false, needs_bom = false;
Term tenc;
char io_mode[8];
2018-06-14 11:27:43 +01:00
int sno = GetFreeStreamD();
if (sno < 0)
return (PlIOError(RESOURCE_ERROR_MAX_STREAMS, file_name,
"new stream not available for opening"));
StreamDesc *st = GLOBAL_Stream + sno;
memset(st, 0, sizeof(*st));
// user requested encoding?
// BOM mess
st->encoding = LOCAL_encoding;
if (st->encoding == ENC_UTF16_BE || st->encoding == ENC_UTF16_LE ||
st->encoding == ENC_UCS2_BE || st->encoding == ENC_UCS2_LE ||
st->encoding == ENC_ISO_UTF32_BE || st->encoding == ENC_ISO_UTF32_LE) {
st->status |= HAS_BOM_f;
}
st->user_name = Deref(file_name);
2018-06-05 11:20:39 +01:00
if (IsVarTerm(file_name)) {
Yap_ThrowError(INSTANTIATION_ERROR, file_name,
"while opening a list of options");
}
2018-01-05 16:57:38 +00:00
// open mode
if (IsVarTerm(t2)) {
Yap_Error(INSTANTIATION_ERROR, t2, "open/3");
2018-06-14 11:27:43 +01:00
return false;
2018-01-05 16:57:38 +00:00
}
if (!IsAtomTerm(t2)) {
if (IsStringTerm(t2)) {
open_mode = Yap_LookupAtom(StringOfTerm(t2));
2017-11-29 13:47:57 +00:00
} else {
2018-01-05 16:57:38 +00:00
Yap_Error(TYPE_ERROR_ATOM, t2, "open/3");
2018-06-14 11:27:43 +01:00
return false;
2018-01-05 16:57:38 +00:00
}
} else {
open_mode = AtomOfTerm(t2);
}
2018-07-09 00:50:00 +01:00
/* get options */
xarg *args =
Yap_ArgListToVector(tlist, open_defs, OPEN_END, DOMAIN_ERROR_OPEN_OPTION);
2018-01-05 16:57:38 +00:00
if (args == NULL) {
if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
Yap_Error(LOCAL_Error_TYPE, tlist, "option handling in open/3");
2017-11-29 13:47:57 +00:00
}
2018-01-05 16:57:38 +00:00
return false;
}
/* done */
2018-06-14 11:27:43 +01:00
st->status = 0;
2018-07-09 00:50:00 +01:00
const char *s_encoding;
2018-01-05 16:57:38 +00:00
if (args[OPEN_ENCODING].used) {
tenc = args[OPEN_ENCODING].tvalue;
s_encoding = RepAtom(AtomOfTerm(tenc))->StrOfAE;
} else {
s_encoding = "default";
}
// default encoding, no bom yet
2018-06-14 11:27:43 +01:00
st->encoding = enc_id(s_encoding, ENC_OCTET);
2018-01-05 16:57:38 +00:00
// only set encoding after getting BOM
2018-04-27 13:01:08 +01:00
char const *fname0;
2018-01-05 16:57:38 +00:00
bool ok = (args[OPEN_EXPAND_FILENAME].used
2018-04-27 13:01:08 +01:00
? args[OPEN_EXPAND_FILENAME].tvalue == TermTrue
: false) ||
trueGlobalPrologFlag(OPEN_EXPANDS_FILENAME_FLAG);
if (ok) {
if (((IsAtomTerm(file_name) &&
(fname0 = RepAtom(AtomOfTerm(file_name))->StrOfAE))) ||
(IsStringTerm(file_name) && (fname0 = StringOfTerm(file_name)))) {
int lvl = push_text_stack();
const char *fname = Yap_AbsoluteFile(fname0, ok);
file_name = MkAtomTerm(Yap_LookupAtom(fname));
if (!fname) {
pop_text_stack(lvl);
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, ARG1, NULL);
}
}
2018-01-05 16:57:38 +00:00
}
// Skip scripts that start with !#/.. or similar
2018-03-17 10:38:56 +00:00
if (open_mode == AtomRead) {
strncpy(io_mode, "r", 8);
} else if (open_mode == AtomWrite) {
strncpy(io_mode, "w", 8);
} else if (open_mode == AtomAppend) {
strncpy(io_mode, "a", 8);
} else {
return false;
}
2018-04-24 17:51:00 +01:00
// binary type
2018-01-05 16:57:38 +00:00
if (args[OPEN_TYPE].used) {
Term t = args[OPEN_TYPE].tvalue;
bool bin = (t == TermBinary);
if (bin) {
2015-10-05 10:33:52 +01:00
#ifdef _WIN32
2018-01-05 16:57:38 +00:00
strncat(io_mode, "b", 8);
2015-06-18 01:39:03 +01:00
#endif
2018-06-14 11:27:43 +01:00
st->status |= Binary_Stream_f;
st->encoding = ENC_OCTET;
2018-01-05 16:57:38 +00:00
avoid_bom = true;
needs_bom = false;
} else if (t == TermText) {
2015-10-05 10:33:52 +01:00
#ifdef _WIN32
2018-01-05 16:57:38 +00:00
strncat(io_mode, "t", 8);
2015-06-18 01:39:03 +01:00
#endif
2018-01-05 16:57:38 +00:00
/* note that this matters for UNICODE style conversions */
2016-05-14 02:25:51 +01:00
} else {
2018-05-27 00:47:03 +01:00
Yap_Error(DOMAIN_ERROR_STREAM_OPTION, t,
2018-01-05 16:57:38 +00:00
"type is ~a, must be one of binary or text", t);
}
}
2018-07-09 00:50:00 +01:00
2018-06-14 11:27:43 +01:00
st = &GLOBAL_Stream[sno];
2018-07-09 00:50:00 +01:00
if (!fill_stream(sno, st, file_name, io_mode, st->user_name, st->encoding)) {
2018-04-27 13:01:08 +01:00
return false;
}
2018-03-17 10:38:56 +00:00
2018-07-09 00:50:00 +01:00
if (args[OPEN_BOM].used) {
2018-04-27 13:01:08 +01:00
if (args[OPEN_BOM].tvalue == TermTrue) {
avoid_bom = false;
2018-01-05 16:57:38 +00:00
needs_bom = true;
2018-04-27 13:01:08 +01:00
} else if (args[OPEN_BOM].tvalue == TermFalse) {
avoid_bom = true;
needs_bom = false;
2018-03-17 10:38:56 +00:00
}
2018-04-27 13:01:08 +01:00
}
2018-03-17 10:38:56 +00:00
bool script =
2018-04-27 13:01:08 +01:00
(args[OPEN_SCRIPT].used ? args[OPEN_SCRIPT].tvalue == TermTrue : false);
2018-03-02 21:18:24 +00:00
2018-01-05 16:57:38 +00:00
if (args[OPEN_ALIAS].used) {
Atom al = AtomOfTerm(args[OPEN_ALIAS].tvalue);
if (!Yap_AddAlias(al, sno)) {
free(args);
return false;
}
}
if (st - GLOBAL_Stream < 3) {
2018-06-14 11:27:43 +01:00
st->status |= RepError_Prolog_f;
2018-01-05 16:57:38 +00:00
}
2015-06-18 01:39:03 +01:00
#if MAC
2018-01-05 16:57:38 +00:00
if (open_mode == AtomWrite) {
Yap_SetTextFile(RepAtom(AtomOfTerm(file_name))->StrOfAE);
}
2015-06-18 01:39:03 +01:00
#endif
2018-06-14 11:27:43 +01:00
// interactive streams do not have a start, so they probably don't have
// a BOM
avoid_bom = avoid_bom || (st->status & Tty_Stream_f);
2018-01-05 16:57:38 +00:00
if (needs_bom && !write_bom(sno, st)) {
return false;
} else if (open_mode == AtomRead && !avoid_bom) {
check_bom(sno, st); // can change encoding
2018-06-14 11:27:43 +01:00
// follow declaration unless there is v
if (st->status & HAS_BOM_f) {
st->encoding = enc_id(s_encoding, st->encoding);
}
2018-01-05 16:57:38 +00:00
}
Yap_DefaultStreamOps(st);
2018-02-14 00:13:13 +00:00
if (script) {
2018-03-02 21:18:24 +00:00
open_header(sno, open_mode);
2018-02-14 00:13:13 +00:00
}
2018-01-05 16:57:38 +00:00
2018-03-02 21:18:24 +00:00
free(args);
2018-01-05 16:57:38 +00:00
UNLOCK(st->streamlock);
{
Term t = Yap_MkStream(sno);
return (Yap_unify(ARG3, t));
}
2016-04-05 02:53:39 +01:00
}
2016-04-05 02:53:39 +01:00
/** @pred open(+ _F_,+ _M_,- _S_) is iso
2018-04-24 17:51:00 +01:00
Opens the file with name _F_ in mode _M_ (`read`, `write` or
`append`), returning _S_ unified with the stream name.
2018-04-24 17:51:00 +01:00
Yap allows 64 streams opened at the same time. If you need more,
redefine the MaxStreams constant. Each stream is either an input or
an output stream but not both. There are always 3 open streams:
user_input for reading, user_output for writing and user_error for
writing. If there is no ambiguity, the atoms user_input and
user_output may be referred to as `user`.
2018-04-24 17:51:00 +01:00
The `file_errors` flag controls whether errors are reported when in
mode `read` or `append` the file _F_ does not exist or is not
readable, and whether in mode `write` or `append` the file is not
writable.
2016-04-05 02:53:39 +01:00
*/
2015-07-06 12:03:16 +01:00
2018-02-02 11:50:07 +00:00
static Int open3(USES_REGS1) {
2018-01-05 16:57:38 +00:00
/* '$open'(+File,+Mode,?Stream,-ReturnCode) */
return do_open(Deref(ARG1), Deref(ARG2), TermNil PASS_REGS);
2016-04-05 02:53:39 +01:00
}
2016-04-05 02:53:39 +01:00
/** @pred open(+ _F_,+ _M_,- _S_,+ _Opts_) is iso
2018-04-27 13:01:08 +01:00
Opens the file with name _F_ in mode _M_ (`read`, `write` or
`append`), returning _S_ unified with the stream name, and following
these options:
2018-04-27 13:01:08 +01:00
+ `type(+ _T_)` is iso
2018-04-27 13:01:08 +01:00
Specify whether the stream is a `text` stream (default), or a
`binary` stream.
2018-04-27 13:01:08 +01:00
+ `reposition(+ _Bool_)` is iso
Specify whether it is possible to reposition the stream (`true`), or
not (`false`). By default, YAP enables repositioning for all
files, except terminal files and sockets.
2018-04-27 13:01:08 +01:00
+ `eof(+ _Action_)` is iso
2018-04-27 13:01:08 +01:00
Specify the action to take if attempting to input characters from a
stream where we have previously found an `end_of_file`. The possible
actions are `error`, that raises an error, `reset`, that tries to
reset the stream and is used for `tty` type files, and `eof_code`,
which generates a new `end_of_file` (default for non-tty files).
2018-04-27 13:01:08 +01:00
+ `alias(+ _Name_)` is iso
2018-04-27 13:01:08 +01:00
Specify an alias to the stream. The alias <tt>Name</tt> must be an atom.
The
alias can be used instead of the stream descriptor for every operation
concerning the stream.
2018-04-27 13:01:08 +01:00
The operation will fail and give an error if the alias name is already
in use. YAP allows several aliases for the same file, but only
one is returned by stream_property/2
2018-04-27 13:01:08 +01:00
+ `bom(+ _Bool_)`
2018-04-27 13:01:08 +01:00
If present and `true`, a BOM (<em>Byte Order Mark</em>) was
detected while opening the file for reading or a BOM was written while
opening the stream. See BOM for details.
2018-04-27 13:01:08 +01:00
+ `encoding(+ _Encoding_)`
2018-04-27 13:01:08 +01:00
Set the encoding used for text. See Encoding for an overview of
wide character and encoding issues.
2018-04-27 13:01:08 +01:00
+ `representation_errors(+ _Mode_)`
2018-04-27 13:01:08 +01:00
Change the behaviour when writing characters to the stream that cannot
be represented by the encoding. The behaviour is one of `error`
(throw and Input/Output error exception), `prolog` (write `\u...\`
escape code or `xml` (write `\&#...;` XML character entity).
The initial mode is `prolog` for the user streams and
`error` for all other streams. See also Encoding.
2018-04-27 13:01:08 +01:00
+ `expand_filename(+ _Mode_)`
2018-04-27 13:01:08 +01:00
If _Mode_ is `true` then do filename expansion, then ask Prolog
to do file name expansion before actually trying to opening the file:
this includes processing `~` characters and processing `$`
environment variables at the beginning of the file. Otherwise, just try
to open the file using the given name.
2018-04-27 13:01:08 +01:00
The default behavior is given by the Prolog flag
open_expands_filename.
2018-04-27 13:01:08 +01:00
+ `script( + _Boolean_ )` YAP extension.
2018-04-27 13:01:08 +01:00
The file may be a Prolog script. In `read` mode just check for
initial lines if they start with the hash symbol, and skip them. In
`write` mode output an header that can be used to launch the file by
calling `yap -l file -- $*`. Note that YAP will not set file
permissions as executable. In `append` mode ignore the flag.
2015-06-18 01:39:03 +01:00
2016-04-05 02:53:39 +01:00
*/
static Int open4(USES_REGS1) { /* '$open'(+File,+Mode,?Stream,-ReturnCode) */
2018-01-05 16:57:38 +00:00
return do_open(Deref(ARG1), Deref(ARG2), Deref(ARG4) PASS_REGS);
2016-04-05 02:53:39 +01:00
}
2016-02-26 17:45:45 +00:00
2016-04-05 02:53:39 +01:00
static Int p_file_expansion(USES_REGS1) { /* '$file_expansion'(+File,-Name) */
2018-01-05 16:57:38 +00:00
Term file_name = Deref(ARG1);
2016-04-05 02:53:39 +01:00
2018-01-05 16:57:38 +00:00
/* we know file_name is bound */
if (IsVarTerm(file_name)) {
PlIOError(INSTANTIATION_ERROR, file_name, "absolute_file_name/3");
return (FALSE);
}
2018-03-02 21:18:24 +00:00
int lvl = push_text_stack();
const char *tmp;
if ((tmp = Yap_AbsoluteFile(RepAtom(AtomOfTerm(file_name))->StrOfAE,
false)) == NULL) {
pop_text_stack(lvl);
return (PlIOError(EXISTENCE_ERROR_SOURCE_SINK, file_name,
"absolute_file_name/3"));
2018-02-14 00:13:13 +00:00
}
bool rc = (Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(tmp))));
2018-03-02 21:18:24 +00:00
pop_text_stack(lvl);
return rc;
2016-04-05 02:53:39 +01:00
}
2015-06-18 01:39:03 +01:00
2016-04-05 02:53:39 +01:00
static Int p_open_null_stream(USES_REGS1) {
2018-01-05 16:57:38 +00:00
Term t;
StreamDesc *st;
int sno = GetFreeStreamD();
if (sno < 0)
return (PlIOError(SYSTEM_ERROR_INTERNAL, TermNil,
"new stream not available for open_null_stream/1"));
st = &GLOBAL_Stream[sno];
st->status = Append_Stream_f | Output_Stream_f | Null_Stream_f;
2015-06-18 01:39:03 +01:00
#if _WIN32
2018-01-05 16:57:38 +00:00
st->file = fopen("NUL", "w");
2015-06-18 01:39:03 +01:00
#else
2018-01-05 16:57:38 +00:00
st->file = fopen("/dev/null", "w");
2015-10-05 10:33:52 +01:00
#endif
2018-01-05 16:57:38 +00:00
if (st->file == NULL) {
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
"Could not open NULL stream (/dev/null,NUL)");
return false;
}
st->linepos = 0;
st->charcount = 0;
st->linecount = 1;
st->stream_putc = NullPutc;
st->stream_wputc = put_wchar;
st->stream_getc = PlGetc;
st->stream_wgetc = get_wchar;
st->stream_wgetc_for_read = get_wchar;
st->user_name = MkAtomTerm(st->name = AtomDevNull);
UNLOCK(st->streamlock);
t = Yap_MkStream(sno);
return (Yap_unify(ARG1, t));
2017-11-29 13:47:57 +00:00
}
2018-04-27 13:01:08 +01:00
int Yap_OpenStream(Term tin, const char *io_mode, Term user_name,
encoding_t enc) {
2018-01-05 16:57:38 +00:00
CACHE_REGS
2018-04-27 13:01:08 +01:00
int sno;
2018-01-05 16:57:38 +00:00
StreamDesc *st;
sno = GetFreeStreamD();
if (sno < 0) {
2018-04-27 13:01:08 +01:00
PlIOError(RESOURCE_ERROR_MAX_STREAMS, tin,
"new stream not available for opening");
2018-01-05 16:57:38 +00:00
return -1;
}
st = GLOBAL_Stream + sno;
2018-04-24 17:51:00 +01:00
// fname = Yap_VF(fname);
2018-04-27 13:01:08 +01:00
2018-07-09 00:50:00 +01:00
if (fill_stream(sno, st, tin, io_mode, user_name, enc))
return sno;
2018-06-14 11:27:43 +01:00
return -1;
2018-04-27 13:01:08 +01:00
}
2018-04-24 17:51:00 +01:00
2018-10-16 14:31:16 +01:00
int Yap_FileStream(FILE *fd, Atom name, Term file_name, int flags,
2018-04-27 13:01:08 +01:00
VFS_t *vfsp) {
CACHE_REGS
int sno;
const char *mode;
sno = GetFreeStreamD();
if (sno < 0)
return (PlIOError(RESOURCE_ERROR_MAX_STREAMS, file_name,
"new stream not available for opening"));
if (flags & Output_Stream_f) {
if (flags & Append_Stream_f)
mode = "a";
else
mode = "w";
} else {
mode = "r";
2018-04-24 17:51:00 +01:00
}
2018-04-27 13:01:08 +01:00
Yap_initStream(sno, fd, name, mode, file_name, LOCAL_encoding, flags, vfsp);
return sno;
}
2017-11-29 13:47:57 +00:00
2018-04-27 13:01:08 +01:00
#define CheckStream(arg, kind, msg) \
2015-12-15 09:14:15 +00:00
CheckStream__(__FILE__, __FUNCTION__, __LINE__, arg, kind, msg)
2015-10-18 11:49:18 +01:00
2018-04-27 13:01:08 +01:00
static int CheckStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
int sno = -1;
arg = Deref(arg);
if (IsVarTerm(arg)) {
Yap_Error(INSTANTIATION_ERROR, arg, msg);
return -1;
} else if (IsAtomTerm(arg)) {
Atom sname = AtomOfTerm(arg);
if (sname == AtomUser) {
if (kind & Input_Stream_f) {
if (kind & (Output_Stream_f | Append_Stream_f)) {
PlIOError__(file, f, line, PERMISSION_ERROR_OUTPUT_STREAM, arg,
"ambiguous use of 'user' as a stream");
return (-1);
}
sname = AtomUserIn;
2018-01-05 16:57:38 +00:00
} else {
2018-04-27 13:01:08 +01:00
sname = AtomUserOut;
2018-04-24 17:51:00 +01:00
}
2017-11-29 13:47:57 +00:00
}
2018-04-27 13:01:08 +01:00
if ((sno = Yap_CheckAlias(sname)) < 0) {
2018-04-24 17:51:00 +01:00
UNLOCK(GLOBAL_Stream[sno].streamlock);
2018-04-27 13:01:08 +01:00
PlIOError__(file, f, line, EXISTENCE_ERROR_STREAM, arg, msg);
2018-04-24 17:51:00 +01:00
return -1;
2018-04-27 13:01:08 +01:00
} else {
LOCK(GLOBAL_Stream[sno].streamlock);
2017-11-29 13:47:57 +00:00
}
2018-04-27 13:01:08 +01:00
} else if (IsApplTerm(arg) && FunctorOfTerm(arg) == FunctorStream) {
arg = ArgOfTerm(1, arg);
if (!IsVarTerm(arg) && IsIntegerTerm(arg)) {
sno = IntegerOfTerm(arg);
2018-04-24 17:51:00 +01:00
}
2018-01-05 16:57:38 +00:00
}
2018-04-27 13:01:08 +01:00
if (sno < 0) {
Yap_Error(DOMAIN_ERROR_STREAM_OR_ALIAS, arg, msg);
return -1;
2018-04-24 17:51:00 +01:00
}
2018-04-27 13:01:08 +01:00
if (GLOBAL_Stream[sno].status & Free_Stream_f) {
PlIOError__(file, f, line, EXISTENCE_ERROR_STREAM, arg, msg);
return -1;
}
LOCK(GLOBAL_Stream[sno].streamlock);
if ((GLOBAL_Stream[sno].status & Input_Stream_f) &&
!(kind & Input_Stream_f)) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
PlIOError__(file, f, line, PERMISSION_ERROR_OUTPUT_STREAM, arg, msg);
return -1;
}
if ((GLOBAL_Stream[sno].status & (Append_Stream_f | Output_Stream_f)) &&
!(kind & Output_Stream_f)) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
PlIOError__(file, f, line, PERMISSION_ERROR_INPUT_STREAM, arg, msg);
return -1;
}
return sno;
}
2016-02-26 17:45:45 +00:00
2018-04-27 13:01:08 +01:00
int Yap_CheckStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
return CheckStream__(file, f, line, arg, kind, msg);
}
int Yap_CheckTextStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
int sno;
if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
return -1;
if ((GLOBAL_Stream[sno].status & Binary_Stream_f)) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
if (kind == Input_Stream_f)
PlIOError__(file, f, line, PERMISSION_ERROR_INPUT_BINARY_STREAM, arg,
msg);
else
PlIOError__(file, f, line, PERMISSION_ERROR_OUTPUT_BINARY_STREAM, arg,
msg);
return -1;
2018-01-05 16:57:38 +00:00
}
2018-04-27 13:01:08 +01:00
return sno;
}
2018-06-05 11:20:39 +01:00
int Yap_CheckTextWriteStream__(const char *file, const char *f, int line,
Term arg, const char *msg) {
2018-06-02 23:04:51 +01:00
int sno, kind = Output_Stream_f;
if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
return -1;
if ((GLOBAL_Stream[sno].status & Binary_Stream_f)) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
if (kind & Output_Stream_f)
PlIOError__(file, f, line, PERMISSION_ERROR_INPUT_BINARY_STREAM, arg,
msg);
else
PlIOError__(file, f, line, PERMISSION_ERROR_OUTPUT_BINARY_STREAM, arg,
msg);
return -1;
}
return sno;
}
2018-06-05 11:20:39 +01:00
int Yap_CheckTextReadStream__(const char *file, const char *f, int line,
Term arg, const char *msg) {
2018-06-02 23:04:51 +01:00
int sno, kind = Input_Stream_f;
if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
return -1;
if ((GLOBAL_Stream[sno].status & Binary_Stream_f)) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
if (kind & Input_Stream_f)
PlIOError__(file, f, line, PERMISSION_ERROR_INPUT_BINARY_STREAM, arg,
msg);
else
PlIOError__(file, f, line, PERMISSION_ERROR_OUTPUT_BINARY_STREAM, arg,
msg);
return -1;
}
return sno;
}
2018-04-27 13:01:08 +01:00
int Yap_CheckBinaryStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
int sno;
if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
return -1;
if (!(GLOBAL_Stream[sno].status & Binary_Stream_f)) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
if (kind == Input_Stream_f)
PlIOError__(file, f, line, PERMISSION_ERROR_INPUT_TEXT_STREAM, arg, msg);
else
PlIOError__(file, f, line, PERMISSION_ERROR_OUTPUT_TEXT_STREAM, arg, msg);
return -1;
2018-01-05 16:57:38 +00:00
}
2018-04-27 13:01:08 +01:00
return sno;
}
2016-04-19 23:30:02 +01:00
2018-04-27 13:01:08 +01:00
/* used from C-interface */
int Yap_GetFreeStreamDForReading(void) {
int sno = GetFreeStreamD();
StreamDesc *s;
2018-01-05 16:57:38 +00:00
2018-04-27 13:01:08 +01:00
if (sno < 0)
2016-04-05 02:53:39 +01:00
return sno;
2018-04-27 13:01:08 +01:00
s = GLOBAL_Stream + sno;
s->status |= User_Stream_f | Input_Stream_f;
s->charcount = 0;
s->linecount = 1;
s->linepos = 0;
Yap_DefaultStreamOps(s);
UNLOCK(s->streamlock);
return sno;
}
2015-06-18 01:39:03 +01:00
2018-04-27 13:01:08 +01:00
/**
* @pred always_prompt_user
*
* Ensure that the stream always prompts before asking the standard input
stream for data.
2018-04-27 13:01:08 +01:00
*/
static Int always_prompt_user(USES_REGS1) {
StreamDesc *s = GLOBAL_Stream + StdInStream;
2015-12-15 09:14:15 +00:00
2018-04-27 13:01:08 +01:00
s->status |= Promptable_Stream_f;
Yap_DefaultStreamOps(s);
return (TRUE);
}
2015-06-18 01:39:03 +01:00
2018-07-09 00:50:00 +01:00
/** @pred close(+ _S_) is iso
2018-04-24 17:51:00 +01:00
Closes the stream _S_. If _S_ does not stand for a stream
currently opened an error is reported. The streams user_input,
user_output, and user_error can never be closed.
2018-06-25 13:44:09 +01:00
*/
2018-07-09 00:50:00 +01:00
static Int close1(USES_REGS1) { /* '$close'(+GLOBAL_Stream) */
2018-04-27 13:01:08 +01:00
int sno = CheckStream(
ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f), "close/2");
if (sno < 0)
return false;
if (sno <= StdErrStream) {
2016-04-05 02:53:39 +01:00
UNLOCK(GLOBAL_Stream[sno].streamlock);
2018-04-27 13:01:08 +01:00
return true;
2018-01-05 16:57:38 +00:00
}
2018-04-27 13:01:08 +01:00
Yap_CloseStream(sno);
UNLOCK(GLOBAL_Stream[sno].streamlock);
return (TRUE);
}
2015-06-18 01:39:03 +01:00
2018-04-27 13:01:08 +01:00
#define CLOSE_DEFS() \
2016-01-31 10:37:41 +00:00
PAR("force", booleanFlag, CLOSE_FORCE), PAR(NULL, ok, CLOSE_END)
2015-06-18 01:39:03 +01:00
2015-12-15 09:14:15 +00:00
#define PAR(x, y, z) z
2015-10-05 10:33:52 +01:00
2018-04-27 13:01:08 +01:00
typedef enum close_enum_choices { CLOSE_DEFS() } close_choices_t;
2015-06-18 01:39:03 +01:00
#undef PAR
2018-04-27 13:01:08 +01:00
#define PAR(x, y, z) \
2015-12-15 09:14:15 +00:00
{ x, y, z }
2015-10-05 10:33:52 +01:00
2018-04-27 13:01:08 +01:00
static const param_t close_defs[] = {CLOSE_DEFS()};
2015-06-18 01:39:03 +01:00
#undef PAR
2018-04-27 13:01:08 +01:00
/** @pred close(+ _S_,+ _O_) is iso
2018-04-27 13:01:08 +01:00
Closes the stream _S_, following options _O_.
2018-04-27 13:01:08 +01:00
The only valid options are `force(true)` and `force(false)`.
YAP currently ignores these options.
2018-04-27 13:01:08 +01:00
*/
static Int close2(USES_REGS1) { /* '$close'(+GLOBAL_Stream) */
Int sno = CheckStream(
ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f), "close/2");
Term tlist;
if (sno < 0)
return (FALSE);
if (sno <= StdErrStream) {
UNLOCK(GLOBAL_Stream[sno].streamlock);
return TRUE;
}
2018-06-14 11:27:43 +01:00
xarg *args = Yap_ArgListToVector((tlist = Deref(ARG2)), close_defs, CLOSE_END,
DOMAIN_ERROR_CLOSE_OPTION);
2018-04-27 13:01:08 +01:00
if (args == NULL) {
if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
Yap_Error(LOCAL_Error_TYPE, tlist, NULL);
2018-01-05 16:57:38 +00:00
}
2018-04-27 13:01:08 +01:00
return false;
2018-01-05 16:57:38 +00:00
}
2018-04-27 13:01:08 +01:00
// if (args[CLOSE_FORCE].used) {
// }
Yap_CloseStream(sno);
UNLOCK(GLOBAL_Stream[sno].streamlock);
return (TRUE);
}
2015-06-18 01:39:03 +01:00
2018-04-27 13:01:08 +01:00
Term read_line(int sno) {
CACHE_REGS
Term tail;
Int ch;
2015-06-18 01:39:03 +01:00
2018-04-27 13:01:08 +01:00
if ((ch = GLOBAL_Stream[sno].stream_wgetc(sno)) == 10) {
return (TermNil);
}
tail = read_line(sno);
return (MkPairTerm(MkIntTerm(ch), tail));
}
#define ABSOLUTE_FILE_NAME_DEFS() \
PAR("access", isatom, ABSOLUTE_FILE_NAME_ACCESS) \
, PAR("expand", booleanFlag, ABSOLUTE_FILE_NAME_EXPAND), \
PAR("extensions", ok, ABSOLUTE_FILE_NAME_EXTENSIONS), \
PAR("file_errors", is_file_errors, ABSOLUTE_FILE_NAME_FILE_ERRORS), \
PAR("file_type", is_file_type, ABSOLUTE_FILE_NAME_FILE_TYPE), \
PAR("glob", ok, ABSOLUTE_FILE_NAME_GLOB), \
PAR("relative_to", isatom, ABSOLUTE_FILE_NAME_RELATIVE_TO), \
PAR("solutions", issolutions, ABSOLUTE_FILE_NAME_SOLUTIONS), \
PAR("verbose_file_search", booleanFlag, \
ABSOLUTE_FILE_NAME_VERBOSE_FILE_SEARCH), \
PAR(NULL, ok, ABSOLUTE_FILE_NAME_END)
2015-06-18 01:39:03 +01:00
2015-12-15 09:14:15 +00:00
#define PAR(x, y, z) z
2015-06-18 01:39:03 +01:00
2018-04-27 13:01:08 +01:00
typedef enum ABSOLUTE_FILE_NAME_enum_ {
ABSOLUTE_FILE_NAME_DEFS()
} absolute_file_name_choices_t;
2015-09-21 23:05:36 +01:00
#undef PAR
2018-04-27 13:01:08 +01:00
#define PAR(x, y, z) \
2015-12-15 09:14:15 +00:00
{ x, y, z }
2015-10-05 10:33:52 +01:00
2018-04-27 13:01:08 +01:00
static const param_t absolute_file_name_search_defs[] = {
2018-01-05 16:57:38 +00:00
ABSOLUTE_FILE_NAME_DEFS()};
2015-09-21 23:05:36 +01:00
#undef PAR
2018-04-27 13:01:08 +01:00
static Int abs_file_parameters(USES_REGS1) {
Term t[ABSOLUTE_FILE_NAME_END];
Term tlist = Deref(ARG1), tf;
/* get options */
xarg *args = Yap_ArgListToVector(tlist, absolute_file_name_search_defs,
2018-06-14 11:27:43 +01:00
ABSOLUTE_FILE_NAME_END,
DOMAIN_ERROR_ABSOLUTE_FILE_NAME_OPTION);
2018-04-27 13:01:08 +01:00
if (args == NULL) {
if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
Yap_Error(LOCAL_Error_TYPE, tlist, NULL);
2018-04-24 17:51:00 +01:00
}
2018-01-05 16:57:38 +00:00
return false;
}
2018-04-27 13:01:08 +01:00
/* done */
if (args[ABSOLUTE_FILE_NAME_EXTENSIONS].used) {
t[ABSOLUTE_FILE_NAME_EXTENSIONS] =
args[ABSOLUTE_FILE_NAME_EXTENSIONS].tvalue;
} else {
t[ABSOLUTE_FILE_NAME_EXTENSIONS] = TermNil;
}
if (args[ABSOLUTE_FILE_NAME_RELATIVE_TO].used) {
t[ABSOLUTE_FILE_NAME_RELATIVE_TO] =
gethdir(args[ABSOLUTE_FILE_NAME_RELATIVE_TO].tvalue);
} else {
t[ABSOLUTE_FILE_NAME_RELATIVE_TO] = gethdir(TermDot);
}
if (args[ABSOLUTE_FILE_NAME_FILE_TYPE].used)
t[ABSOLUTE_FILE_NAME_FILE_TYPE] = args[ABSOLUTE_FILE_NAME_FILE_TYPE].tvalue;
else
t[ABSOLUTE_FILE_NAME_FILE_TYPE] = TermTxt;
if (args[ABSOLUTE_FILE_NAME_ACCESS].used)
t[ABSOLUTE_FILE_NAME_ACCESS] = args[ABSOLUTE_FILE_NAME_ACCESS].tvalue;
else
t[ABSOLUTE_FILE_NAME_ACCESS] = TermNone;
if (args[ABSOLUTE_FILE_NAME_FILE_ERRORS].used)
t[ABSOLUTE_FILE_NAME_FILE_ERRORS] =
args[ABSOLUTE_FILE_NAME_FILE_ERRORS].tvalue;
else
t[ABSOLUTE_FILE_NAME_FILE_ERRORS] = TermError;
if (args[ABSOLUTE_FILE_NAME_SOLUTIONS].used)
t[ABSOLUTE_FILE_NAME_SOLUTIONS] = args[ABSOLUTE_FILE_NAME_SOLUTIONS].tvalue;
else
t[ABSOLUTE_FILE_NAME_SOLUTIONS] = TermFirst;
if (args[ABSOLUTE_FILE_NAME_EXPAND].used)
t[ABSOLUTE_FILE_NAME_EXPAND] = args[ABSOLUTE_FILE_NAME_EXPAND].tvalue;
else
t[ABSOLUTE_FILE_NAME_EXPAND] = TermFalse;
if (args[ABSOLUTE_FILE_NAME_GLOB].used) {
t[ABSOLUTE_FILE_NAME_GLOB] = args[ABSOLUTE_FILE_NAME_GLOB].tvalue;
t[ABSOLUTE_FILE_NAME_EXPAND] = TermTrue;
} else
t[ABSOLUTE_FILE_NAME_GLOB] = TermEmptyAtom;
if (args[ABSOLUTE_FILE_NAME_VERBOSE_FILE_SEARCH].used)
t[ABSOLUTE_FILE_NAME_VERBOSE_FILE_SEARCH] =
args[ABSOLUTE_FILE_NAME_VERBOSE_FILE_SEARCH].tvalue;
else
t[ABSOLUTE_FILE_NAME_VERBOSE_FILE_SEARCH] =
(trueGlobalPrologFlag(VERBOSE_FILE_SEARCH_FLAG) ? TermTrue : TermFalse);
tf = Yap_MkApplTerm(Yap_MkFunctor(AtomOpt, ABSOLUTE_FILE_NAME_END),
ABSOLUTE_FILE_NAME_END, t);
return (Yap_unify(ARG2, tf));
}
2015-09-21 23:05:36 +01:00
2018-04-27 13:01:08 +01:00
static Int get_abs_file_parameter(USES_REGS1) {
Term t = Deref(ARG1), topts = Deref(ARG2);
/* get options */
/* done */
int i = Yap_ArgKey(AtomOfTerm(t), absolute_file_name_search_defs,
ABSOLUTE_FILE_NAME_END);
if (i >= 0)
return Yap_unify(ARG3, ArgOfTerm(i + 1, topts));
Yap_Error(DOMAIN_ERROR_ABSOLUTE_FILE_NAME_OPTION, ARG1, NULL);
return false;
}
void Yap_InitPlIO(struct yap_boot_params *argi) {
Int i;
if (argi->inp > 0)
Yap_stdin = fdopen(argi->inp - 1, "r");
2018-06-26 10:13:11 +01:00
else if (argi->inp < 0)
2018-04-27 13:01:08 +01:00
Yap_stdin = NULL;
else
Yap_stdin = stdin;
if (argi->out > 0)
Yap_stdout = fdopen(argi->out - 1, "a");
2018-06-26 10:13:11 +01:00
else if (argi->out < 0)
2018-04-27 13:01:08 +01:00
Yap_stdout = NULL;
else
Yap_stdout = stdout;
if (argi->err > 0)
Yap_stderr = fdopen(argi->err - 1, "a");
else if (argi->out)
Yap_stdout = NULL;
else
Yap_stderr = stderr;
GLOBAL_Stream =
2018-01-05 16:57:38 +00:00
(StreamDesc *)Yap_AllocCodeSpace(sizeof(StreamDesc) * MaxStreams);
2018-04-27 13:01:08 +01:00
for (i = 0; i < MaxStreams; ++i) {
INIT_LOCK(GLOBAL_Stream[i].streamlock);
GLOBAL_Stream[i].status = Free_Stream_f;
}
InitStdStreams();
}
void Yap_InitIOPreds(void) {
/* here the Input/Output predicates */
Yap_InitCPred("always_prompt_user", 0, always_prompt_user,
SafePredFlag | SyncPredFlag);
Yap_InitCPred("close", 1, close1, SafePredFlag | SyncPredFlag);
Yap_InitCPred("close", 2, close2, SafePredFlag | SyncPredFlag);
Yap_InitCPred("open", 4, open4, SyncPredFlag);
Yap_InitCPred("open", 3, open3, SyncPredFlag);
Yap_InitCPred("abs_file_parameters", 2, abs_file_parameters,
SyncPredFlag | HiddenPredFlag);
Yap_InitCPred("get_abs_file_parameter", 3, get_abs_file_parameter,
SafePredFlag | SyncPredFlag | HiddenPredFlag);
Yap_InitCPred("$file_expansion", 2, p_file_expansion,
SafePredFlag | SyncPredFlag | HiddenPredFlag);
Yap_InitCPred("$open_null_stream", 1, p_open_null_stream,
SafePredFlag | SyncPredFlag | HiddenPredFlag);
Yap_InitIOStreams();
Yap_InitAliases();
Yap_InitCharsio();
Yap_InitChtypes();
Yap_InitConsole();
Yap_InitReadUtil();
Yap_InitMems();
Yap_InitPipes();
Yap_InitFiles();
Yap_InitWriteTPreds();
Yap_InitReadTPreds();
Yap_InitFormat();
Yap_InitRandomPreds();
#if USE_READLINE
2018-04-27 13:01:08 +01:00
Yap_InitReadlinePreds();
2016-01-31 10:37:41 +00:00
#endif
2018-04-27 13:01:08 +01:00
Yap_InitSockets();
Yap_InitSignalPreds();
Yap_InitSysPreds();
Yap_InitTimePreds();
}