YAP 7.1.0
mem.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#include "sysbits.h"
27
28#if !HAVE_FMEMOPEN || !defined(HAVE_FMEMOPEN)
29
30#include "YapStreams.h"
31
32#include "format.h"
33
34int format_synch(int sno, int sno0, format_info *fg) {
35 int (*f_putc)(int, int);
36 const char *s;
37 int n;
38 if (sno == sno0) {
39 return sno;
40 }
41 f_putc = GLOBAL_Stream[sno0].stream_putc;
42 s = GLOBAL_Stream[sno].u.mem_string.buf;
43 n = GLOBAL_Stream[sno].u.mem_string.pos;
44 while (n--) {
45 f_putc(sno0, *s++);
46 }
47 GLOBAL_Stream[sno].u.mem_string.pos = 0;
48 GLOBAL_Stream[sno].linecount = 1;
49 GLOBAL_Stream[sno].linepos = 0;
50 GLOBAL_Stream[sno].charcount = 0;
51 GLOBAL_Stream[sno].vfs = NULL;
52 fg->lstart = 0;
53 fg->phys_start = 0;
54 fg->gapi = 0;
55 return sno;
56}
57
58// uses directly the buffer in the memory stream.
59bool fill_pads(int sno, int sno0, int total, format_info *fg USES_REGS) {
60 int nfillers, fill_space, lfill_space, nchars;
61 int (*f_putc)(int, int);
62 const char *buf;
63 int phys_end;
64
65 f_putc = GLOBAL_Stream[sno0].stream_putc;
66 buf = GLOBAL_Stream[sno].u.mem_string.buf;
67 phys_end = GLOBAL_Stream[sno].u.mem_string.pos;
68 if (fg->gapi == 0) {
69 fg->gap[0].phys = phys_end;
70 fg->gap[0].filler = ' ';
71 fg->gapi = 1;
72 }
73 nchars = total - GLOBAL_Stream[sno].linepos;
74 if (nchars < 0)
75 nchars = 0; /* ignore */
76 nfillers = fg->gapi;
77 fill_space = nchars / nfillers;
78 lfill_space = nchars % nfillers;
79
80 int i = fg->phys_start;
81 gap_t *padi = fg->gap;
82 while (i < phys_end) {
83 if (i == padi->phys) {
84 int j;
85 for (j = 0; j < fill_space; j++)
86 f_putc(sno0, padi->filler);
87 padi++;
88 /* last gap??*/
89 if (padi - fg->gap == fg->gapi) {
90 for (j = 0; j < fill_space; j++)
91 f_putc(sno0, (padi - 1)->filler);
92 }
93 }
94 f_putc(sno0, buf[i++]);
95 }
96 // final gap
97 if (i == padi->phys) {
98 int j;
99 for (j = 0; j < fill_space + lfill_space; j++)
100 f_putc(sno0, padi->filler);
101 };
102
103 GLOBAL_Stream[sno].u.mem_string.pos = 0;
104 GLOBAL_Stream[sno].linecount = 1;
105 GLOBAL_Stream[sno].linepos += 0;
106 GLOBAL_Stream[sno].charcount = nchars;
107 GLOBAL_Stream[sno].vfs = NULL;
108 GLOBAL_Stream[sno].file = NULL;
109 fg->phys_start = 0;
110 fg->lstart = GLOBAL_Stream[sno].linepos;
111 fg->gapi = 0;
112 return true;
113}
114
115/* read from memory */
116static int MemGetc(int sno) {
117 register StreamDesc *s = &GLOBAL_Stream[sno];
118 Int ch;
119 int spos;
120
121 spos = s->u.mem_string.pos;
122 if (spos == s->u.mem_string.max_size) {
123 return -1;
124 } else {
125 ch = s->u.mem_string.buf[spos];
126 s->u.mem_string.pos = ++spos;
127 }
128 return ch;
129}
130
131/* peek from memory */
132int Yap_MemPeekc(int sno) {
133 StreamDesc *s = &GLOBAL_Stream[sno];
134 Int ch;
135 int spos;
136
137 spos = s->u.mem_string.pos;
138 if (spos == s->u.mem_string.max_size) {
139 return -1;
140 } else {
141 ch = s->u.mem_string.buf[spos];
142 }
143 return ch;
144}
145
146static int MemPutc(int, int);
147
148/* static */
149static int MemPutc(int sno, int ch) {
150 StreamDesc *s = &GLOBAL_Stream[sno];
151#if MAC || _MSC_VER
152 if (ch == 10) {
153 ch = '\n';
154 }
155#endif
156 s->u.mem_string.buf[s->u.mem_string.pos++] = ch;
157 if (s->u.mem_string.pos >= s->u.mem_string.max_size - 8) {
158 int new_src;
159
160 /* oops, we have reached an overflow */
161 Int new_max_size = s->u.mem_string.max_size + Yap_page_size;
162 char *newbuf;
163 if ((newbuf = (ADDR)realloc(s->u.mem_string.buf,
164 new_max_size * sizeof(char))) != NULL) {
165 new_src = MEM_BUF_MALLOC;
166 } else {
167 if (GLOBAL_Stream[sno].u.mem_string.error_handler) {
168 CACHE_REGS
169 LOCAL_Error_Size = new_max_size * sizeof(char);
170 save_machine_regs();
171 longjmp(*(jmp_buf *)GLOBAL_Stream[sno].u.mem_string.error_handler, 1);
172 } else {
173 Yap_Error(RESOURCE_ERROR_HEAP, TermNil,
174 "YAP could not grow heap for writing to string");
175 }
176 return -1;
177 }
178 s->u.mem_string.buf = newbuf;
179 s->u.mem_string.max_size = new_max_size;
180 s->u.mem_string.src = new_src;
181 }
182 count_output_char(ch, s);
183 return ((int)ch);
184}
185
186bool Yap_set_stream_to_buf(StreamDesc *st, const char *buf,
187 size_t nchars USES_REGS) {
188 FILE *f;
189 stream_flags_t flags;
190
191 st->file = f = NULL;
192 flags = Input_Stream_f | InMemory_Stream_f;
193 st->vfs = NULL;
194 Yap_initStream(st - GLOBAL_Stream, f, Yap_LookupAtom("buffer"), "r", TermNil, LOCAL_encoding, flags, NULL);
195 // like any file stream.
196 /* currently these streams are not seekable */
197 st->status = Input_Stream_f | InMemory_Stream_f;
198 st->u.mem_string.pos = 0;
199 st->u.mem_string.buf = (char *)buf;
200 st->u.mem_string.max_size = nchars;
201 st->u.mem_string.error_handler = NULL;
202 // st->u.mem_string.src = src; check new assets coode
203 Yap_DefaultStreamOps(st);
204 return true;
205}
206
207int Yap_open_buf_read_stream(const char *buf, size_t nchars, encoding_t *encp, memBufSource src , Atom name, Term uname) {
208 CACHE_REGS
209 int sno;
210 StreamDesc *st;
211 FILE *f;
212 encoding_t encoding;
213 stream_flags_t flags;
214
215 sno = GetFreeStreamD();
216 if (sno < 0)
217 return (PlIOError(RESOURCE_ERROR_MAX_STREAMS, TermNil,
218 "new stream not available for open_mem_read_stream/1"));
219 st = GLOBAL_Stream + sno;
220 if (encp)
221 encoding = *encp;
222 else
223 encoding = LOCAL_encoding;
224 st->file = f = NULL;
225 flags = Input_Stream_f | InMemory_Stream_f;
226 st->vfs = NULL;
227 st->name = name;
228 Yap_initStream(sno, f, Yap_LookupAtom("Memory Stream"),"wa", TermNil, encoding, flags, NULL);
229 // like any file stream.
230 /* currently these streams are not seekable */
231 st->status = Input_Stream_f | InMemory_Stream_f;
232 st->u.mem_string.pos = 0;
233 st->u.mem_string.buf = (char *)buf;
234 st->u.mem_string.max_size = nchars;
235 st->u.mem_string.error_handler = NULL;
236 st->u.mem_string.src = src;
237 Yap_DefaultStreamOps(st);
238 UNLOCK(st->streamlock);
239 return sno;
240}
241
242static Int
243open_mem_read_stream(USES_REGS1) /* $open_mem_read_stream(+List,-Stream) */
244{
245 Term t, ti;
246 int sno;
247 int i = push_text_stack();
248 const char *buf;
249
250 ti = Deref(ARG1);
251 buf = Yap_TextTermToText(ti PASS_REGS);
252 if (!buf) {
253 return false;
254 }
255 buf = pop_output_text_stack(i, buf);
256 sno = Yap_open_buf_read_stream(buf, strlen(buf) + 1, &LOCAL_encoding,
257 MEM_BUF_MALLOC, AtomNil, TermNil);
258 t = Yap_MkStream(sno);
259 return Yap_unify(ARG2, t);
260}
261
262// open a buffer for writing, currently just ignores buf and nchars.
263
264int Yap_open_buf_write_stream(encoding_t enc, memBufSource src) {
265 CACHE_REGS
266 int sno;
267 StreamDesc *st;
268
269 sno = GetFreeStreamD();
270 if (sno < 0)
271 return -1;
272 st = GLOBAL_Stream + sno;
273 st->status = Output_Stream_f | InMemory_Stream_f | FreeOnClose_Stream_f;
274 st->linepos = 0;
275 st->charcount = 0;
276 st->linecount = 1;
277 st->encoding = enc;
278 st->vfs = NULL;
279 st->file = NULL;
280 Yap_DefaultStreamOps(st);
281 st->nbuf = st->u.mem_string.buf = malloc(PLGETC_BUF_SIZE);
282 st->u.mem_string.src = MEM_BUF_MALLOC;
283 st->u.mem_string.max_size = PLGETC_BUF_SIZE - 1;
284 st->u.mem_string.pos = 0;
285 UNLOCK(st->streamlock);
286 return sno;
287}
288
289int Yap_OpenBufWriteStream(USES_REGS1) {
290
291 return Yap_open_buf_write_stream(
292 GLOBAL_Stream[LOCAL_c_output_stream].encoding, 0);
293}
294
295static Int
296open_mem_write_stream(USES_REGS1) /* $open_mem_write_stream(-Stream) */
297{
298 Term t;
299 int sno;
300
301 sno = Yap_OpenBufWriteStream(PASS_REGS1);
302 if (sno == -1)
303 return (PlIOError(SYSTEM_ERROR_INTERNAL, TermNil,
304 "new stream not available for open_mem_read_stream/1"));
305 t = Yap_MkStream(sno);
306 GLOBAL_Stream[sno].status |= InMemory_Stream_f;
307 return (Yap_unify(ARG1, t));
308}
309
318char *Yap_MemExportStreamPtr(int sno) {
319
320 GLOBAL_Stream[sno].u.mem_string.buf[GLOBAL_Stream[sno].u.mem_string.pos] =
321 '\0';
322 return GLOBAL_Stream[sno].u.mem_string.buf;
323}
324
325static Int peek_mem_write_stream(
326 USES_REGS1) { /* '$peek_mem_write_stream'(+GLOBAL_Stream,?S0,?S) */
327 Int sno =
328 Yap_CheckStream(ARG1, (Output_Stream_f | InMemory_Stream_f), "close/2");
329 Int i;
330 Term tf = ARG2;
331 CELL *HI;
332 const char *ptr;
333
334 if (sno < 0)
335 return (FALSE);
336restart:
337 HI = HR;
338 ptr = GLOBAL_Stream[sno].u.mem_string.buf;
339 i = GLOBAL_Stream[sno].u.mem_string.pos;
340 while (i > 0) {
341 --i;
342 tf = MkPairTerm(MkIntTerm(ptr[i]), tf);
343 if (HR + 1024 >= ASP) {
344 UNLOCK(GLOBAL_Stream[sno].streamlock);
345 HR = HI;
346 if (!Yap_gcl((ASP - HI) * sizeof(CELL), 3, ENV, Yap_gcP())) {
347 UNLOCK(GLOBAL_Stream[sno].streamlock);
348 Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
349 return (FALSE);
350 }
351 i = GLOBAL_Stream[sno].u.mem_string.pos;
352 tf = ARG2;
353 LOCK(GLOBAL_Stream[sno].streamlock);
354 goto restart;
355 }
356 }
357 UNLOCK(GLOBAL_Stream[sno].streamlock);
358 return (Yap_unify(ARG3, tf));
359}
360
361void Yap_MemOps(StreamDesc *st) {
362 st->stream_putc = MemPutc;
363
364 st->stream_getc = MemGetc;
365}
366
367bool Yap_CloseMemoryStream(int sno) {
368 if ((GLOBAL_Stream[sno].status & Output_Stream_f)) {
369 if (GLOBAL_Stream[sno].u.mem_string.src == MEM_BUF_MALLOC) {
370 free(GLOBAL_Stream[sno].u.mem_string.buf);
371 }
372 } else {
373 if (GLOBAL_Stream[sno].u.mem_string.src == MEM_BUF_MALLOC) {
374 free(GLOBAL_Stream[sno].u.mem_string.buf);
375 }
376 }
377 return true;
378}
379
380void Yap_InitMems(void) {
381 CACHE_REGS
382 Yap_InitCPred("open_mem_read_stream", 2, open_mem_read_stream, SyncPredFlag);
383 Yap_InitCPred("open_mem_write_stream", 1, open_mem_write_stream,
384 SyncPredFlag);
385 Yap_InitCPred("peek_mem_write_stream", 3, peek_mem_write_stream,
386 SyncPredFlag);
387}
388
389#endif
@ 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