YAP 7.1.0
fmem.c
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: mem.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
21/*
22 * This file includes the definition of a socket related IO.
23 *
24 */
25
26#define _GNU_SOURCE
27
28
29#include "format.h"
30#include "sysbits.h"
31#include "YapText.h"
32
33 char *Yap_StrPrefix( const char *buf, size_t n) {
34 char *b = Malloc(n);
35 strncpy(b, buf, n - 1);
36 if (strlen(buf) > n - 1)
37 b[15] = '\0';
38 return b;
39}
40
41
42#if HAVE_FMEMOPEN
43
44bool fill_pads(int sno, int sno0, int total, format_info *fg USES_REGS)
45// uses directly the buffer in the memory stream.
46{
47 int nfillers, fill_space, lfill_space, nchars;
48 int (*f_putc)(int, int);
49 const char *buf;
50 int phys_end;
51
52 f_putc = GLOBAL_Stream[sno0].stream_putc;
53 if (fflush(GLOBAL_Stream[sno].file) == 0) {
54 buf = GLOBAL_Stream[sno].nbuf;
55 phys_end = ftell(GLOBAL_Stream[sno].file);
56} else
57 return false;
58 if (fg->gapi == 0) {
59 fg->gap[0].phys = phys_end;
60 fg->gap[0].filler = ' ';
61
62 fg->gapi = 1;
63 }
64 nchars =total-( GLOBAL_Stream[sno].charcount - GLOBAL_Stream[sno].linestart) ;
65 if (nchars < 0)
66 nchars = 0; /* ignore */
67 nfillers = fg->gapi;
68 fill_space = nchars / nfillers;
69 lfill_space = nchars % nfillers;
70
71 int i = fg->phys_start;
72 gap_t *padi = fg->gap;
73 while (i < phys_end) {
74 if (i == padi->phys) {
75 int j;
76 for (j = 0; j < fill_space; j++)
77 f_putc(sno0, padi->filler);
78 padi++;
79 /* last gap??*/
80 if (padi - fg->gap == fg->gapi) {
81 for (j = 0; j < fill_space; j++)
82 f_putc(sno0, (padi - 1)->filler);
83 }
84 }
85 f_putc(sno0, buf[i++]);
86 }
87 // final gap
88 if (i == padi->phys) {
89 int j;
90 for (j = 0; j < fill_space + lfill_space; j++)
91 f_putc(sno0, padi->filler);
92 };
93
94 rewind(GLOBAL_Stream[sno].file);
95 Yap_flush(sno0);
96 fg->lstart = GLOBAL_Stream[sno].charcount-GLOBAL_Stream[sno].linestart ;
97GLOBAL_Stream[sno].linecount = 1;
98 GLOBAL_Stream[sno].charcount=0;
99 GLOBAL_Stream[sno].linestart = 0;
100 GLOBAL_Stream[sno].buf.on = false;
101 fg->phys_start = 0;
102 fg->gapi = 0;
103 return true;
104}
105
106bool Yap_set_stream_to_buf(StreamDesc *st, const char *buf,
107 size_t nchars USES_REGS) {
108 FILE *f;
109
110 // like any file stream.
111 st->file = f = fmemopen((char *)buf, nchars, "r");
112 st->status = Input_Stream_f | Seekable_Stream_f | InMemory_Stream_f;
113 st->vfs = NULL;
114 st->buf.on = false;
115 st->encoding = LOCAL_encoding;
116 Yap_DefaultStreamOps(st);
117 st-> linecount = 1;
118 st->linestart = st->charcount = 0;
119 return true;
120}
121
122
123int Yap_open_buf_read_stream(void *spt, const char *buf, size_t nchars,
124 encoding_t *encp, memBufSource src, Atom fname,
125 Term uname) {
126 CACHE_REGS
127 FILE *f;
128 StreamDesc *st = spt;
129 encoding_t encoding;
130 stream_flags_t flags;
131 int sno;
132 if (!buf) {
133 return -1;
134 }
135 if (st == NULL) {
136 sno = GetFreeStreamD();
137 if (sno < 0)
138 return (PlIOError(RESOURCE_ERROR_MAX_STREAMS, TermNil,
139 "new stream not available for open_mem_read_stream/1"));
140 st = GLOBAL_Stream + sno;
141 } else {
142 sno = st-GLOBAL_Stream;
143 }
144 if (encp)
145 encoding = *encp;
146 else
147 encoding = LOCAL_encoding;
148 // like any file stream.
149 char nbuf[32];
150 if (fname == NULL) {
151 nbuf[0] = '@';
152 nbuf[1] = '@';
153 nbuf[2] = '\0';
154 strncpy(nbuf+2,buf,30);
155 if (nbuf[28])
156 nbuf[28]=nbuf[29]=nbuf[30]=',';
157 Atom name = Yap_LookupAtom(nbuf);
158 if (fname == NULL) {
159 fname=name;
160 }
161 }
162 if (uname==0) {
163 uname = MkAtomTerm(fname);
164 }
165 f = st->file = fmemopen((void*)buf, nchars, "r");
166 st->vfs = NULL;
167 flags = Input_Stream_f | InMemory_Stream_f | Seekable_Stream_f;
168 Yap_initStream(sno, f, fname, "r", uname, encoding, flags, NULL);
169 // like any file stream.
170 Yap_DefaultStreamOps(st);
171 UNLOCK(st->streamlock);
172 return sno;
173}
174
175static Int
176open_mem_read_stream(USES_REGS1) /* $open_mem_read_stream(+List,-Stream) */
177{
178 Term t, ti;
179 int sno;
180 const char *buf;
181
182 ti = Deref(ARG1);
183 int l = push_text_stack();
184 buf = Yap_TextTermToText(ti);
185 if (!buf) {
186 pop_text_stack(l);
187 return false;
188 }
189 buf = pop_output_text_stack(l, buf);
190 sno = Yap_open_buf_read_stream(NULL,buf, strlen(buf) + 1, &LOCAL_encoding,
191 MEM_BUF_MALLOC, Yap_LookupAtom(Yap_StrPrefix((char *)buf,16)), TermNone);
192 t = Yap_MkStream(sno);
193 return Yap_unify(ARG2, t);
194}
195
196// open a buffer for writing, currently just ignores buf and nchars.
197
198int Yap_open_buf_write_stream(encoding_t enc, memBufSource src) {
199 CACHE_REGS
200 int sno;
201 StreamDesc *st;
202
203 sno = GetFreeStreamD();
204 if (sno < 0)
205 return -1;
206
207 st = GLOBAL_Stream + sno;
208 st->status = Output_Stream_f | InMemory_Stream_f;
209 st->linestart = 0;
210 st->charcount = 0;
211 st->linecount = 1;
212 st->encoding = enc;
213 st->vfs = NULL;
214 st->buf.on = true;
215 st->nbuf = NULL;
216 st->status |= (Seekable_Stream_f|CloseOnException_Stream_f);
217 #if HAVE_OPEN_MEMSTREAM
218 st->file = open_memstream(&st->nbuf, &st->nsize);
219 #else
220 if (st->nbuf == NULL)
221 st->nbuf = malloc(32*K);
222 st->file = fmemopen((void *)st->nbuf, st->nsize, "w+");
223 #endif
224 Yap_DefaultStreamOps(st);
225 UNLOCK(st->streamlock);
226 return sno;
227}
228
229int Yap_OpenBufWriteStream(USES_REGS1) {
230
231 return Yap_open_buf_write_stream(
232 GLOBAL_Stream[LOCAL_c_output_stream].encoding, 0);
233}
234
235static Int
236open_mem_write_stream(USES_REGS1) /* $open_mem_write_stream(-Stream) */
237{
238 Term t;
239 int sno;
240
241 sno = Yap_OpenBufWriteStream(PASS_REGS1);
242 if (sno == -1)
243 return (PlIOError(SYSTEM_ERROR_INTERNAL, TermNil,
244 "new stream not available for open_mem_read_stream/1"));
245 t = Yap_MkStream(sno);
246 GLOBAL_Stream[sno].status |= InMemory_Stream_f;
247 return (Yap_unify(ARG1, t));
248}
249
258char *Yap_MemExportStreamPtr(int sno) {
259FILE *f = GLOBAL_Stream[sno].file;
260 if (fflush(f) < 0) {
261 return NULL;
262 }
263
264 size_t sz = GLOBAL_Stream[sno].nsize+2;
265 GLOBAL_Stream[sno].nsize='\0';
266 sz = sz < 32? 32:sz;
267#if HAVE_OPEN_MEMSTREAM
268 char *buf = Malloc( sz );
269 strcpy(buf, GLOBAL_Stream[sno].nbuf );
270
271
272#else
273 size_t len;
274 len = fseek(GLOBAL_Stream[sno].file, 0, SEEK_END);
275 buf = malloc(len+1);
276 fread(buf, len, 1, GLOBAL_Stream[sno].file);
277 buf[len] = '\0';
278#endif
279
280 return buf;
281}
282
283static Int peek_mem_write_stream(
284 USES_REGS1) { /* '$peek_mem_write_stream'(+GLOBAL_Stream,?S0,?S) */
285 Int sno =
286 Yap_CheckStream(ARG1, (Output_Stream_f | InMemory_Stream_f), "close/2");
287 Term tf = ARG2;
288 CELL *HI;
289 char *ptr;
290 int ch;
291
292 if (sno < 0)
293 return (FALSE);
294 char *p = ptr = Yap_MemExportStreamPtr(sno);
295 restart:
296 HI = HR;
297 while ((ch = *p++)) {
298 HR[0] = MkIntTerm(ch);
299 HR[1] = AbsPair(HR+2);
300 HR += 2;
301 if (HR + 1024 >= ASP) {
302 UNLOCK(GLOBAL_Stream[sno].streamlock);
303 HR = HI;
304 if (!Yap_dogc()) {
305 UNLOCK(GLOBAL_Stream[sno].streamlock);
306 Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
307 return (FALSE);
308 }
309 LOCK(GLOBAL_Stream[sno].streamlock);
310 goto restart;
311 }
312 }
313 HR[-1] = tf;
314 UNLOCK(GLOBAL_Stream[sno].streamlock);
315
316 fclose(GLOBAL_Stream[sno].file);
317 free(GLOBAL_Stream[sno].nbuf);
318 #if HAVE_OPEN_MEMSTREAM
319 GLOBAL_Stream[sno].file = open_memstream(&GLOBAL_Stream[sno].nbuf, &GLOBAL_Stream[sno].nsize);
320 #else
321 if (GLOBAL_Stream[sno].nbuf == NULL)
322 GLOBAL_Stream[sno].nbuf = malloc(32*K);
323 GLOBAL_Stream[sno].file = fmemopen((void *)GLOBAL_Stream[sno].nbuf, GLOBAL_Stream[sno]. nsize, "w+");
324 #endif
325
326 return (Yap_unify(ARG3, AbsPair(HI)));
327}
328
329void Yap_MemOps(StreamDesc *st) {
330 st->stream_putc = FilePutc;
331
332 st->stream_getc = PlGetc;
333}
334
335int format_synch(int sno, int sno0, format_info *fg) {
336 char *s;
337 if (sno==sno0)
338 return sno;
339 s = Yap_MemExportStreamPtr(sno);
340 if (GLOBAL_Stream[sno0].vfs) {
341 int ch;
342 int (*f)() = GLOBAL_Stream[sno0].vfs->put_char;
343 while ((ch = *s++)) {
344 f(sno0, ch);
345 }
346 } else {
347 int ch;
348 int (*f)() = GLOBAL_Stream[sno0].stream_putc;
349 while ((ch = *s++)) {
350 f(sno0, ch);
351 }
352 }
353 fclose(GLOBAL_Stream[sno].file);
354 free(GLOBAL_Stream[sno].nbuf);
355 #if HAVE_OPEN_MEMSTREAM
356 GLOBAL_Stream[sno].file = open_memstream(&GLOBAL_Stream[sno].nbuf, &GLOBAL_Stream[sno].nsize);
357 #else
358 if (GLOBAL_Stream[sno].nbuf == NULL)
359 GLOBAL_Stream[sno].nbuf = malloc(32*K);
360 GLOBAL_Stream[sno].file = fmemopen((void *)GLOBAL_Stream[sno].nbuf, GLOBAL_Stream[sno]. nsize, "w+");
361 #endif
362 fg->lstart = 0;
363 fg->phys_start = 0;
364 fg->gapi = 0;
365
366 Yap_flush(sno0);
367 return sno;
368}
369
370
371bool Yap_CloseMemoryStream(int sno) {
372
373 if ((GLOBAL_Stream[sno].status & Output_Stream_f) &&
374 GLOBAL_Stream[sno].file) {
375 fflush(GLOBAL_Stream[sno].file);
376 fclose(GLOBAL_Stream[sno].file);
377 if (GLOBAL_Stream[sno].status & FreeOnClose_Stream_f)
378 free(GLOBAL_Stream[sno].nbuf);
379 } else {
380 if (GLOBAL_Stream[sno].file)
381 fclose(GLOBAL_Stream[sno].file);
382 if (GLOBAL_Stream[sno].status & FreeOnClose_Stream_f)
383 free(GLOBAL_Stream[sno].nbuf);
384 }
385 Yap_ReleaseStream(sno);
386 return true;
387}
388
389void Yap_InitMems(void) {
390 CACHE_REGS
391 Yap_InitCPred("open_mem_read_stream", 2, open_mem_read_stream, SyncPredFlag);
392 Yap_InitCPred("open_mem_write_stream", 1, open_mem_write_stream,
393 SyncPredFlag);
394 Yap_InitCPred("peek_mem_write_stream", 3, peek_mem_write_stream,
395 SyncPredFlag);
396}
397
398#endif
void * Malloc(size_t sz USES_REGS)
allocate a temporary text block
Definition: alloc.c:1759
@ encoding
support for coding systens, YAP relies on UTF-8 internally
Definition: YapLFlagInfo.h:83
Definition: format.h:6
int(* stream_getc)(int)
function the stream uses for writing a character
Definition: YapStreams.h:256
encoding_t encoding
check if the next wide character is available
Definition: YapStreams.h:265
struct vfs * vfs
function the stream uses for reading a character
Definition: YapStreams.h:259
Definition: VFS.h:74
int(* put_char)(int sno, int ch)
unget an octet from the stream
Definition: VFS.h:91