add ice-9 eval-string
[bpt/guile.git] / libguile / strports.c
CommitLineData
574b7be0 1/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002, 2003, 2005, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
0f2d19dd
JB
20\f
21
dbb605f5 22#ifdef HAVE_CONFIG_H
c986274f
RB
23# include <config.h>
24#endif
25
a0599745 26#include "libguile/_scm.h"
681b9005
MD
27
28#include <stdio.h>
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32
2fa901a5 33#include "libguile/arrays.h"
a0599745
MD
34#include "libguile/eval.h"
35#include "libguile/ports.h"
36#include "libguile/read.h"
37#include "libguile/root.h"
38#include "libguile/strings.h"
07bcf91d 39#include "libguile/modules.h"
fe78b6c0 40#include "libguile/validate.h"
ca13a04a 41#include "libguile/deprecation.h"
889975e5 42#include "libguile/srfi-4.h"
20e6290e 43
a0599745 44#include "libguile/strports.h"
0f2d19dd 45
95b88819
GH
46#ifdef HAVE_STRING_H
47#include <string.h>
48#endif
49
0f2d19dd
JB
50\f
51
52/* {Ports - string ports}
53 *
54 */
55
3fe6190f 56/* NOTES:
cc95e00a
MV
57
58 We break the rules set forth by strings.h about accessing the
59 internals of strings here. We can do this since we can guarantee
60 that the string used as pt->stream is not in use by anyone else.
61 Thus, it's representation will not change asynchronously.
62
63 (Ports aren't thread-safe yet anyway...)
64
3fe6190f
GH
65 write_buf/write_end point to the ends of the allocated string.
66 read_buf/read_end in principle point to the part of the string which
67 has been written to, but this is only updated after a flush.
68 read_pos and write_pos in principle should be equal, but this is only true
61e452ba 69 when rw_active is SCM_PORT_NEITHER.
bf5ad0da
KR
70
71 ENHANCE-ME - output blocks:
72
73 The current code keeps an output string as a single block. That means
74 when the size is increased the entire old contents must be copied. It'd
75 be more efficient to begin a new block when the old one is full, so
76 there's no re-copying of previous data.
77
78 To make seeking efficient, keeping the pieces in a vector might be best,
79 though appending is probably the most common operation. The size of each
80 block could be progressively increased, so the bigger the string the
81 bigger the blocks.
82
83 When `get-output-string' is called the blocks have to be coalesced into a
84 string, the result could be kept as a single big block. If blocks were
85 strings then `get-output-string' could notice when there's just one and
86 return that with a copy-on-write (though repeated calls to
87 `get-output-string' are probably unlikely).
88
89 Another possibility would be to extend the port mechanism to let SCM
90 strings come through directly from `display' and friends. That way if a
91 big string is written it can be kept as a copy-on-write, saving time
92 copying and maybe saving some space. */
93
1cc91f1b 94
92c2555f 95scm_t_bits scm_tc16_strport;
a98bddfd
DH
96
97
ee149d03
JB
98static int
99stfill_buffer (SCM port)
0f2d19dd 100{
92c2555f 101 scm_t_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 102
ee149d03
JB
103 if (pt->read_pos >= pt->read_end)
104 return EOF;
105 else
41b0806d 106 return scm_return_first_int (*pt->read_pos, port);
0f2d19dd
JB
107}
108
3fe6190f
GH
109/* change the size of a port's string to new_size. this doesn't
110 change read_buf_size. */
754c9491 111static void
f1ce9199 112st_resize_port (scm_t_port *pt, scm_t_off new_size)
754c9491 113{
94115ae3 114 SCM old_stream = SCM_PACK (pt->stream);
cc95e00a
MV
115 const char *src = scm_i_string_chars (old_stream);
116 char *dst;
117 SCM new_stream = scm_i_make_string (new_size, &dst);
118 unsigned long int old_size = scm_i_string_length (old_stream);
c014a02e
ML
119 unsigned long int min_size = min (old_size, new_size);
120 unsigned long int i;
74a16888 121
f1ce9199 122 scm_t_off index = pt->write_pos - pt->write_buf;
3fe6190f
GH
123
124 pt->write_buf_size = new_size;
125
94115ae3 126 for (i = 0; i != min_size; ++i)
cc95e00a 127 dst[i] = src[i];
8824ac88
MV
128
129 scm_remember_upto_here_1 (old_stream);
754c9491 130
94115ae3 131 /* reset buffer. */
754c9491 132 {
729dbac3 133 pt->stream = SCM_UNPACK (new_stream);
5a6d139b 134 pt->read_buf = pt->write_buf = (unsigned char *)dst;
3fe6190f
GH
135 pt->read_pos = pt->write_pos = pt->write_buf + index;
136 pt->write_end = pt->write_buf + pt->write_buf_size;
137 pt->read_end = pt->read_buf + pt->read_buf_size;
754c9491
JB
138 }
139}
140
3fe6190f
GH
141/* amount by which write_buf is expanded. */
142#define SCM_WRITE_BLOCK 80
143
144/* ensure that write_pos < write_end by enlarging the buffer when
bf5ad0da
KR
145 necessary. update read_buf to account for written chars.
146
147 The buffer is enlarged by 1.5 times, plus SCM_WRITE_BLOCK. Adding just a
148 fixed amount is no good, because there's a block copy for each increment,
149 and that copying would take quadratic time. In the past it was found to
150 be very slow just adding 80 bytes each time (eg. about 10 seconds for
151 writing a 100kbyte string). */
152
ee149d03
JB
153static void
154st_flush (SCM port)
0f2d19dd 155{
92c2555f 156 scm_t_port *pt = SCM_PTAB_ENTRY (port);
ee149d03
JB
157
158 if (pt->write_pos == pt->write_end)
159 {
bf5ad0da 160 st_resize_port (pt, pt->write_buf_size * 3 / 2 + SCM_WRITE_BLOCK);
754c9491
JB
161 }
162 pt->read_pos = pt->write_pos;
3fe6190f
GH
163 if (pt->read_pos > pt->read_end)
164 {
165 pt->read_end = (unsigned char *) pt->read_pos;
166 pt->read_buf_size = pt->read_end - pt->read_buf;
167 }
61e452ba 168 pt->rw_active = SCM_PORT_NEITHER;
754c9491
JB
169}
170
31703ab8 171static void
8aa011a1 172st_write (SCM port, const void *data, size_t size)
31703ab8 173{
92c2555f 174 scm_t_port *pt = SCM_PTAB_ENTRY (port);
31703ab8
GH
175 const char *input = (char *) data;
176
177 while (size > 0)
178 {
179 int space = pt->write_end - pt->write_pos;
180 int write_len = (size > space) ? space : size;
181
4b8ec619 182 memcpy ((char *) pt->write_pos, input, write_len);
31703ab8
GH
183 pt->write_pos += write_len;
184 size -= write_len;
185 input += write_len;
186 if (write_len == space)
187 st_flush (port);
188 }
189}
190
754c9491 191static void
affc96b5 192st_end_input (SCM port, int offset)
754c9491 193{
92c2555f 194 scm_t_port *pt = SCM_PTAB_ENTRY (port);
7dcb364d 195
cd19d608
GH
196 if (pt->read_pos - pt->read_buf < offset)
197 scm_misc_error ("st_end_input", "negative position", SCM_EOL);
198
a3c8b9fc 199 pt->write_pos = (unsigned char *) (pt->read_pos = pt->read_pos - offset);
61e452ba 200 pt->rw_active = SCM_PORT_NEITHER;
754c9491
JB
201}
202
f1ce9199
LC
203static scm_t_off
204st_seek (SCM port, scm_t_off offset, int whence)
754c9491 205{
92c2555f 206 scm_t_port *pt = SCM_PTAB_ENTRY (port);
f1ce9199 207 scm_t_off target;
754c9491 208
7dcb364d
GH
209 if (pt->rw_active == SCM_PORT_READ && offset == 0 && whence == SEEK_CUR)
210 /* special case to avoid disturbing the unread-char buffer. */
754c9491 211 {
7dcb364d
GH
212 if (pt->read_buf == pt->putback_buf)
213 {
214 target = pt->saved_read_pos - pt->saved_read_buf
215 - (pt->read_end - pt->read_pos);
216 }
217 else
218 {
219 target = pt->read_pos - pt->read_buf;
220 }
754c9491 221 }
7dcb364d
GH
222 else
223 /* all other cases. */
754c9491 224 {
7dcb364d
GH
225 if (pt->rw_active == SCM_PORT_WRITE)
226 st_flush (port);
227
228 if (pt->rw_active == SCM_PORT_READ)
229 scm_end_input (port);
230
231 switch (whence)
232 {
233 case SEEK_CUR:
234 target = pt->read_pos - pt->read_buf + offset;
235 break;
236 case SEEK_END:
237 target = pt->read_end - pt->read_buf + offset;
238 break;
239 default: /* SEEK_SET */
240 target = offset;
241 break;
242 }
243
244 if (target < 0)
245 scm_misc_error ("st_seek", "negative offset", SCM_EOL);
246
247 if (target >= pt->write_buf_size)
3fe6190f 248 {
206d3de3 249 if (!(SCM_CELL_WORD_0 (port) & SCM_WRTNG))
3fe6190f 250 {
7dcb364d
GH
251 if (target > pt->write_buf_size)
252 {
253 scm_misc_error ("st_seek",
254 "seek past end of read-only strport",
255 SCM_EOL);
256 }
257 }
258 else
259 {
260 st_resize_port (pt, target + (target == pt->write_buf_size
261 ? SCM_WRITE_BLOCK
262 : 0));
3fe6190f
GH
263 }
264 }
7dcb364d
GH
265 pt->read_pos = pt->write_pos = pt->read_buf + target;
266 if (pt->read_pos > pt->read_end)
3fe6190f 267 {
7dcb364d
GH
268 pt->read_end = (unsigned char *) pt->read_pos;
269 pt->read_buf_size = pt->read_end - pt->read_buf;
3fe6190f 270 }
ee149d03 271 }
754c9491
JB
272 return target;
273}
274
275static void
f1ce9199 276st_truncate (SCM port, scm_t_off length)
754c9491 277{
92c2555f 278 scm_t_port *pt = SCM_PTAB_ENTRY (port);
3fe6190f
GH
279
280 if (length > pt->write_buf_size)
281 st_resize_port (pt, length);
282
283 pt->read_buf_size = length;
284 pt->read_end = pt->read_buf + length;
285 if (pt->read_pos > pt->read_end)
286 pt->read_pos = pt->read_end;
754c9491 287
3fe6190f
GH
288 if (pt->write_pos > pt->read_end)
289 pt->write_pos = pt->read_end;
0f2d19dd
JB
290}
291
7b041912
LC
292SCM
293scm_mkstrport (SCM pos, SCM str, long modes, const char *caller)
0f2d19dd 294{
7b041912 295 SCM z;
92c2555f 296 scm_t_port *pt;
7b041912
LC
297 size_t str_len, c_pos;
298 char *buf, *c_str;
fac32b51 299
7b041912
LC
300 SCM_ASSERT (scm_is_string (str), str, SCM_ARG1, caller);
301 c_pos = scm_to_unsigned_integer (pos, 0, scm_i_string_length (str));
e11e83f3 302
754c9491
JB
303 if (!((modes & SCM_WRTNG) || (modes & SCM_RDNG)))
304 scm_misc_error ("scm_mkstrport", "port must read or write", SCM_EOL);
5f16b897 305
7b041912
LC
306 scm_dynwind_begin (0);
307 scm_i_dynwind_pthread_mutex_lock (&scm_i_port_table_mutex);
308
da220f27
HWN
309 z = scm_new_port_table_entry (scm_tc16_strport);
310 pt = SCM_PTAB_ENTRY(z);
74a16888 311 SCM_SETSTREAM (z, SCM_UNPACK (str));
7b041912
LC
312 SCM_SET_CELL_TYPE (z, scm_tc16_strport | modes);
313
314 /* Create a copy of STR in the encoding of Z. */
315 buf = scm_to_stringn (str, &str_len, pt->encoding,
316 SCM_FAILED_CONVERSION_ERROR);
574b7be0 317 c_str = scm_gc_malloc_pointerless (str_len, "strport");
7b041912
LC
318 memcpy (c_str, buf, str_len);
319 free (buf);
320
321 pt->write_buf = pt->read_buf = (unsigned char *) c_str;
e11e83f3 322 pt->read_pos = pt->write_pos = pt->read_buf + c_pos;
754c9491
JB
323 pt->write_buf_size = pt->read_buf_size = str_len;
324 pt->write_end = pt->read_end = pt->read_buf + pt->read_buf_size;
3fe6190f 325
0de97b83 326 pt->rw_random = 1;
3fe6190f 327
7b041912
LC
328 scm_dynwind_end ();
329
330 /* Ensure WRITE_POS is writable. */
754c9491
JB
331 if ((modes & SCM_WRTNG) && pt->write_pos == pt->write_end)
332 st_flush (z);
25ebc034 333
25ebc034 334 scm_i_set_conversion_strategy_x (z, SCM_FAILED_CONVERSION_ERROR);
0f2d19dd
JB
335 return z;
336}
337
7b041912
LC
338/* Create a new string from the buffer of PORT, a string port, converting from
339 PORT's encoding to the standard string representation. */
340SCM
341scm_strport_to_string (SCM port)
3fe6190f 342{
36284627 343 SCM str;
7b041912
LC
344 scm_t_port *pt = SCM_PTAB_ENTRY (port);
345
3fe6190f
GH
346 if (pt->rw_active == SCM_PORT_WRITE)
347 st_flush (port);
36284627 348
fac32b51
MG
349 if (pt->read_buf_size == 0)
350 return scm_nullstr;
351
352 if (pt->encoding == NULL)
353 {
354 char *buf;
355 str = scm_i_make_string (pt->read_buf_size, &buf);
356 memcpy (buf, pt->read_buf, pt->read_buf_size);
357 }
358 else
f7f4d047
MG
359 str = scm_from_stringn ((char *)pt->read_buf, pt->read_buf_size,
360 pt->encoding, pt->ilseq_handler);
36284627
DH
361 scm_remember_upto_here_1 (port);
362 return str;
3fe6190f
GH
363}
364
fe78b6c0
KN
365SCM_DEFINE (scm_object_to_string, "object->string", 1, 1, 0,
366 (SCM obj, SCM printer),
367 "Return a Scheme string obtained by printing @var{obj}.\n"
368 "Printing function can be specified by the optional second\n"
369 "argument @var{printer} (default: @code{write}).")
1f3908c4
KN
370#define FUNC_NAME s_scm_object_to_string
371{
fe78b6c0
KN
372 SCM str, port;
373
374 if (!SCM_UNBNDP (printer))
375 SCM_VALIDATE_PROC (2, printer);
1f3908c4 376
cc95e00a 377 str = scm_c_make_string (0, SCM_UNDEFINED);
1a92274c 378 port = scm_mkstrport (SCM_INUM0, str, SCM_OPN | SCM_WRTNG, FUNC_NAME);
fe78b6c0
KN
379
380 if (SCM_UNBNDP (printer))
381 scm_write (obj, port);
382 else
fdc28395 383 scm_call_2 (printer, obj, port);
fe78b6c0 384
1f3908c4
KN
385 return scm_strport_to_string (port);
386}
387#undef FUNC_NAME
388
3b3b36dd 389SCM_DEFINE (scm_call_with_output_string, "call-with-output-string", 1, 0, 0,
1bbd0b84 390 (SCM proc),
b380b885
MD
391 "Calls the one-argument procedure @var{proc} with a newly created output\n"
392 "port. When the function returns, the string composed of the characters\n"
393 "written into the port is returned.")
1bbd0b84 394#define FUNC_NAME s_scm_call_with_output_string
0f2d19dd
JB
395{
396 SCM p;
754c9491
JB
397
398 p = scm_mkstrport (SCM_INUM0,
399 scm_make_string (SCM_INUM0, SCM_UNDEFINED),
400 SCM_OPN | SCM_WRTNG,
1bbd0b84 401 FUNC_NAME);
fdc28395 402 scm_call_1 (proc, p);
3fe6190f 403
184b85a3 404 return scm_get_output_string (p);
0f2d19dd 405}
1bbd0b84 406#undef FUNC_NAME
0f2d19dd 407
3b3b36dd 408SCM_DEFINE (scm_call_with_input_string, "call-with-input-string", 2, 0, 0,
1e6808ea
MG
409 (SCM string, SCM proc),
410 "Calls the one-argument procedure @var{proc} with a newly\n"
411 "created input port from which @var{string}'s contents may be\n"
412 "read. The value yielded by the @var{proc} is returned.")
1bbd0b84 413#define FUNC_NAME s_scm_call_with_input_string
0f2d19dd 414{
1e6808ea 415 SCM p = scm_mkstrport(SCM_INUM0, string, SCM_OPN | SCM_RDNG, FUNC_NAME);
fdc28395 416 return scm_call_1 (proc, p);
0f2d19dd 417}
1bbd0b84 418#undef FUNC_NAME
0f2d19dd 419
e87a03fc
MG
420SCM_DEFINE (scm_open_input_string, "open-input-string", 1, 0, 0,
421 (SCM str),
1e6808ea
MG
422 "Take a string and return an input port that delivers characters\n"
423 "from the string. The port can be closed by\n"
e87a03fc
MG
424 "@code{close-input-port}, though its storage will be reclaimed\n"
425 "by the garbage collector if it becomes inaccessible.")
426#define FUNC_NAME s_scm_open_input_string
427{
428 SCM p = scm_mkstrport(SCM_INUM0, str, SCM_OPN | SCM_RDNG, FUNC_NAME);
429 return p;
430}
431#undef FUNC_NAME
432
433SCM_DEFINE (scm_open_output_string, "open-output-string", 0, 0, 0,
434 (void),
1e6808ea 435 "Return an output port that will accumulate characters for\n"
e87a03fc
MG
436 "retrieval by @code{get-output-string}. The port can be closed\n"
437 "by the procedure @code{close-output-port}, though its storage\n"
438 "will be reclaimed by the garbage collector if it becomes\n"
439 "inaccessible.")
440#define FUNC_NAME s_scm_open_output_string
441{
442 SCM p;
443
444 p = scm_mkstrport (SCM_INUM0,
445 scm_make_string (SCM_INUM0, SCM_UNDEFINED),
446 SCM_OPN | SCM_WRTNG,
447 FUNC_NAME);
448 return p;
449}
450#undef FUNC_NAME
451
452SCM_DEFINE (scm_get_output_string, "get-output-string", 1, 0, 0,
453 (SCM port),
454 "Given an output port created by @code{open-output-string},\n"
1e6808ea 455 "return a string consisting of the characters that have been\n"
e87a03fc
MG
456 "output to the port so far.")
457#define FUNC_NAME s_scm_get_output_string
458{
459 SCM_VALIDATE_OPOUTSTRPORT (1, port);
460 return scm_strport_to_string (port);
461}
462#undef FUNC_NAME
1cc91f1b 463
cd07a097 464
a8aa30d8
MD
465/* Given a null-terminated string EXPR containing a Scheme expression
466 read it, and return it as an SCM value. */
467SCM
ca13a04a 468scm_c_read_string (const char *expr)
a8aa30d8 469{
889975e5
MG
470 /* FIXME: the c string gets packed into a string, only to get
471 immediately unpacked in scm_mkstrport. */
3fe6190f 472 SCM port = scm_mkstrport (SCM_INUM0,
cc95e00a 473 scm_from_locale_string (expr),
a8aa30d8 474 SCM_OPN | SCM_RDNG,
ca13a04a 475 "scm_c_read_string");
a8aa30d8
MD
476 SCM form;
477
deca31e1 478 form = scm_read (port);
a8aa30d8
MD
479
480 scm_close_port (port);
481 return form;
482}
483
cd07a097 484/* Given a null-terminated string EXPR containing Scheme program text,
a8aa30d8
MD
485 evaluate it, and return the result of the last expression evaluated. */
486SCM
ca13a04a 487scm_c_eval_string (const char *expr)
cd07a097 488{
cc95e00a 489 return scm_eval_string (scm_from_locale_string (expr));
b377f53e
JB
490}
491
209b52fe
MV
492SCM
493scm_c_eval_string_in_module (const char *expr, SCM module)
494{
cc95e00a 495 return scm_eval_string_in_module (scm_from_locale_string (expr), module);
209b52fe
MV
496}
497
498
96e83482
MV
499static SCM
500inner_eval_string (void *data)
b377f53e 501{
96e83482 502 SCM port = (SCM)data;
cd07a097 503 SCM form;
b377f53e 504 SCM ans = SCM_UNSPECIFIED;
cd07a097
JB
505
506 /* Read expressions from that port; ignore the values. */
0c32d76c 507 while (!SCM_EOF_OBJECT_P (form = scm_read (port)))
96e83482 508 ans = scm_primitive_eval_x (form);
cd07a097 509
0d7368d7
JB
510 /* Don't close the port here; if we re-enter this function via a
511 continuation, then the next time we enter it, we'll get an error.
512 It's a string port anyway, so there's no advantage to closing it
513 early. */
514
a8aa30d8 515 return ans;
cd07a097 516}
96e83482 517
209b52fe
MV
518SCM_DEFINE (scm_eval_string_in_module, "eval-string", 1, 1, 0,
519 (SCM string, SCM module),
96e83482
MV
520 "Evaluate @var{string} as the text representation of a Scheme\n"
521 "form or forms, and return whatever value they produce.\n"
209b52fe
MV
522 "Evaluation takes place in the given module, or the current\n"
523 "module when no module is given.\n"
524 "While the code is evaluated, the given module is made the\n"
525 "current one. The current module is restored when this\n"
526 "procedure returns.")
527#define FUNC_NAME s_scm_eval_string_in_module
96e83482
MV
528{
529 SCM port = scm_mkstrport (SCM_INUM0, string, SCM_OPN | SCM_RDNG,
209b52fe
MV
530 FUNC_NAME);
531 if (SCM_UNBNDP (module))
532 module = scm_current_module ();
aeec5be1
MV
533 else
534 SCM_VALIDATE_MODULE (2, module);
209b52fe 535 return scm_c_call_with_current_module (module,
96e83482
MV
536 inner_eval_string, (void *)port);
537}
1bbd0b84 538#undef FUNC_NAME
cd07a097 539
209b52fe
MV
540SCM
541scm_eval_string (SCM string)
542{
543 return scm_eval_string_in_module (string, SCM_UNDEFINED);
544}
545
92c2555f 546static scm_t_bits
0b6881fa 547scm_make_stptob ()
0f2d19dd 548{
92c2555f 549 scm_t_bits tc = scm_make_port_type ("string", stfill_buffer, st_write);
a98bddfd 550
affc96b5
GH
551 scm_set_port_end_input (tc, st_end_input);
552 scm_set_port_flush (tc, st_flush);
6c747373 553 scm_set_port_seek (tc, st_seek);
affc96b5 554 scm_set_port_truncate (tc, st_truncate);
a98bddfd
DH
555
556 return tc;
0f2d19dd
JB
557}
558
0f2d19dd
JB
559void
560scm_init_strports ()
0f2d19dd 561{
a98bddfd
DH
562 scm_tc16_strport = scm_make_stptob ();
563
a0599745 564#include "libguile/strports.x"
0f2d19dd
JB
565}
566
89e00824
ML
567
568/*
569 Local Variables:
570 c-file-style: "gnu"
571 End:
572*/