YAP 7.1.0
pipes.c
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: pipes.c *
12* Last rev: 5/2/88 *
13* mods: *
14* comments: Input/Output C implemented predicates *
15* *
16*************************************************************************/
17#ifdef SCCS
18static char SccsId[] = "%W% %G%";
19#endif
20
29#include "Yap.h"
30#include "Yatom.h"
31#include "YapHeap.h"
32#include "yapio.h"
33#include <stdlib.h>
34#if HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37#if HAVE_STDARG_H
38#include <stdarg.h>
39#endif
40#ifdef _WIN32
41#if HAVE_IO_H
42/* Windows */
43#include <io.h>
44#endif
45#if HAVE_SOCKET
46#include <winsock2.h>
47#endif
48#include <windows.h>
49#ifndef S_ISDIR
50#define S_ISDIR(x) (((x)&_S_IFDIR)==_S_IFDIR)
51#endif
52#endif
53#if HAVE_ERRNO_H
54#include <errno.h>
55#endif
56#if HAVE_FCNTL_H
57#include <fcntl.h>
58#endif
59#include "iopreds.h"
60
61static int PipePutc( int, int);
62static int ConsolePipePutc( int, int);
63static int PipeGetc( int);
64static int ConsolePipeGetc( int);
65
66/* static */
67static int
68ConsolePipePutc (int sno, int ch)
69{
70 StreamDesc *s = &GLOBAL_Stream[sno];
71 char c = ch;
72#if MAC || _MSC_VER
73 if (ch == 10)
74 {
75 ch = '\n';
76 }
77#endif
78 {
79 int out = 0;
80 while (!out) {
81 out = write(s->u.pipe.fd, &c, sizeof(c));
82 if (out <0) {
83#if HAVE_STRERROR
84 Yap_Error(PERMISSION_ERROR_INPUT_STREAM, TermNil, "error writing stream pipe: %s", strerror(errno));
85#else
86 Yap_Error(PERMISSION_ERROR_INPUT_STREAM, TermNil, "error writing stream pipe");
87#endif
88 }
89 }
90 }
91 count_output_char(ch,s);
92 return ((int) ch);
93}
94
95static int
96PipePutc (int sno, int ch)
97{
98 StreamDesc *s = &GLOBAL_Stream[sno];
99 char c = ch;
100#if MAC || _MSC_VER
101 if (ch == 10)
102 {
103 ch = '\n';
104 }
105#endif
106 {
107 int out = 0;
108 while (!out) {
109 out = write(s->u.pipe.fd, &c, sizeof(c));
110 if (out <0) {
111#if HAVE_STRERROR
112 Yap_Error(PERMISSION_ERROR_INPUT_STREAM, TermNil, "error writing stream pipe: %s", strerror(errno));
113#else
114 Yap_Error(PERMISSION_ERROR_INPUT_STREAM, TermNil, "error writing stream pipe");
115#endif
116 }
117 }
118 }
119 console_count_output_char(ch,s);
120 return ((int) ch);
121}
122
123
124/*
125 Basically, the same as console but also sends a prompt and takes care of
126 finding out whether we are at the start of a LOCAL_newline.
127*/
128static int
129ConsolePipeGetc(int sno)
130{
131 CACHE_REGS
132 StreamDesc *s = &GLOBAL_Stream[sno];
133 int ch;
134 char c;
135#if _MSC_VER || defined(__MINGW32__)
136 DWORD count;
137#else
138 int count;
139#endif
140
141 /* send the prompt away */
142 if (LOCAL_newline) {
143 char *cptr = LOCAL_Prompt, ch;
144 /* use the default routine */
145 while ((ch = *cptr++) != '\0') {
146 GLOBAL_Stream[StdErrStream].stream_putc(StdErrStream, ch);
147 }
148 strncpy(LOCAL_Prompt, RepAtom (LOCAL_AtPrompt)->StrOfAE, MAX_PROMPT);
149 LOCAL_newline = false;
150 }
151 /* should be able to use a buffer */
152 LOCAL_PrologMode |= ConsoleGetcMode;
153 count = read(s->u.pipe.fd, &c, sizeof(char));
154 LOCAL_PrologMode &= ~ConsoleGetcMode;
155 if (count == 0) {
156 return console_post_process_eof(s);
157 } else if (count > 0) {
158 ch = c;
159 } else {
160 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "read");
161 return console_post_process_eof(s);
162 }
163 return console_post_process_read_char(ch, s);
164}
165
166
167static int
168PipeGetc(int sno)
169{
170 StreamDesc *s = &GLOBAL_Stream[sno];
171 Int ch;
172 char c;
173
174 /* should be able to use a buffer */
175 int count;
176 count = read(s->u.pipe.fd, &c, sizeof(char));
177 if (count == 0) {
178 return EOF;
179 } else if (count > 0) {
180 ch = c;
181 } else {
182#if HAVE_STRERROR
183 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "at pipe getc: %s", strerror(errno));
184#else
185 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "at pipe getc");
186#endif
187 return EOF;
188 }
189 return ch;
190}
191
192void
193Yap_PipeOps( StreamDesc *st )
194{
195 st->stream_putc = PipePutc;
196 st->stream_getc = PipeGetc;
197}
198
199void
200Yap_ConsolePipeOps( StreamDesc *st )
201{
202 st->stream_putc = ConsolePipePutc;
203 st->stream_getc = ConsolePipeGetc;
204}
205
206static Int
207open_pipe_stream (USES_REGS1)
208{
209 Term t1, t2;
210 StreamDesc *st;
211 int sno;
212 int filedes[2];
213
214 if (
215#if _MSC_VER || defined(__MINGW32__)
216 // assume for now only text streams...
217 _pipe(filedes, 1024, O_TEXT)
218#else
219 pipe(filedes)
220#endif
221 != 0)
222 {
223 return (PlIOError (SYSTEM_ERROR_INTERNAL,TermNil, "error %s", strerror(errno)) );
224 }
225 sno = GetFreeStreamD();
226 if (sno < 0)
227 return (PlIOError (RESOURCE_ERROR_MAX_STREAMS,TermNil, "new stream not available for open_pipe_stream/2"));
228 t1 = Yap_MkStream (sno);
229 st = &GLOBAL_Stream[sno];
230 st->status = Input_Stream_f | Pipe_Stream_f;
231 st->linestart = 0;
232 st->charcount = 0;
233 st->linecount = 1;
234 st->stream_putc = PipePutc;
235 st->stream_getc = PipeGetc;
236 st->vfs = NULL;
237 Yap_DefaultStreamOps( st );
238 st->u.pipe.fd = filedes[0];
239 st->file = fdopen( filedes[0], "r");
240 UNLOCK(st->streamlock);
241 sno = GetFreeStreamD();
242 if (sno < 0)
243 return (PlIOError (RESOURCE_ERROR_MAX_STREAMS,TermNil, "new stream not available for open_pipe_stream/2"));
244 st = &GLOBAL_Stream[sno];
245 st->status = Output_Stream_f | Pipe_Stream_f;
246 st->linestart = 0;
247 st->charcount = 0;
248 st->linecount = 1;
249 st->vfs = NULL;
250 st->stream_putc = PipePutc;
251 st->stream_getc = PipeGetc;
252 Yap_DefaultStreamOps( st );
253 st->u.pipe.fd = filedes[1];
254 st->file = fdopen( filedes[1], "w");
255 UNLOCK(st->streamlock);
256 t2 = Yap_MkStream (sno);
257 return
258 Yap_unify (ARG1, t1) &&
259 Yap_unify (ARG2, t2);
260}
261
262void
263Yap_InitPipes( void )
264{
265 Yap_InitCPred ("open_pipe_stream", 2, open_pipe_stream, SafePredFlag);
266}
Main definitions.
int(* stream_getc)(int)
function the stream uses for writing a character
Definition: YapStreams.h:256
struct vfs * vfs
function the stream uses for reading a character
Definition: YapStreams.h:259