write-char should handle UCS-4 characters
[bpt/guile.git] / libguile / strports.c
CommitLineData
f1ce9199 1/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002, 2003, 2005, 2006, 2009 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
0f2d19dd 292SCM
889975e5 293scm_i_mkstrport (SCM pos, const char *locale_str, size_t str_len, long modes, const char *caller)
0f2d19dd 294{
889975e5 295 SCM z, str;
92c2555f 296 scm_t_port *pt;
889975e5
MG
297 size_t c_pos;
298 char *buf;
299
300 /* Because ports are inherently 8-bit, strings need to be converted
301 to a locale representation for storage. But, since string ports
302 rely on string functionality for their memory management, we need
303 to create a new string that has the 8-bit locale representation
fac32b51
MG
304 of the underlying string.
305
306 locale_str is already in the locale of the port. */
889975e5
MG
307 str = scm_i_make_string (str_len, &buf);
308 memcpy (buf, locale_str, str_len);
cc95e00a 309
e11e83f3
MV
310 c_pos = scm_to_unsigned_integer (pos, 0, str_len);
311
754c9491
JB
312 if (!((modes & SCM_WRTNG) || (modes & SCM_RDNG)))
313 scm_misc_error ("scm_mkstrport", "port must read or write", SCM_EOL);
5f16b897 314
9de87eea 315 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
da220f27
HWN
316 z = scm_new_port_table_entry (scm_tc16_strport);
317 pt = SCM_PTAB_ENTRY(z);
74a16888 318 SCM_SETSTREAM (z, SCM_UNPACK (str));
da220f27 319 SCM_SET_CELL_TYPE(z, scm_tc16_strport|modes);
5a6d139b 320 pt->write_buf = pt->read_buf = (unsigned char *) scm_i_string_chars (str);
e11e83f3 321 pt->read_pos = pt->write_pos = pt->read_buf + c_pos;
754c9491
JB
322 pt->write_buf_size = pt->read_buf_size = str_len;
323 pt->write_end = pt->read_end = pt->read_buf + pt->read_buf_size;
3fe6190f 324
0de97b83 325 pt->rw_random = 1;
3fe6190f 326
9de87eea 327 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
3fe6190f
GH
328
329 /* ensure write_pos is writable. */
754c9491
JB
330 if ((modes & SCM_WRTNG) && pt->write_pos == pt->write_end)
331 st_flush (z);
0f2d19dd
JB
332 return z;
333}
334
889975e5
MG
335SCM
336scm_mkstrport (SCM pos, SCM str, long modes, const char *caller)
337{
338 SCM z;
339 size_t str_len;
340 char *buf;
341
342 SCM_ASSERT (scm_is_string (str), str, SCM_ARG1, caller);
343
344 /* Because ports are inherently 8-bit, strings need to be converted
345 to a locale representation for storage. But, since string ports
346 rely on string functionality for their memory management, we need
347 to create a new string that has the 8-bit locale representation
348 of the underlying string. This violates the guideline that the
349 internal encoding of characters in strings is in unicode
350 codepoints. */
fac32b51
MG
351
352 /* Ports are initialized with the thread-default values for encoding and
353 invalid sequence handling. */
889975e5
MG
354 buf = scm_to_locale_stringn (str, &str_len);
355 z = scm_i_mkstrport (pos, buf, str_len, modes, caller);
356 free (buf);
357 return z;
358}
359
fac32b51
MG
360/* Create a new string from a string port's buffer, converting from
361 the port's 8-bit locale-specific representation to the standard
362 string representation. */
3fe6190f
GH
363SCM scm_strport_to_string (SCM port)
364{
92c2555f 365 scm_t_port *pt = SCM_PTAB_ENTRY (port);
36284627 366 SCM str;
cc95e00a 367
3fe6190f
GH
368 if (pt->rw_active == SCM_PORT_WRITE)
369 st_flush (port);
36284627 370
fac32b51
MG
371 if (pt->read_buf_size == 0)
372 return scm_nullstr;
373
374 if (pt->encoding == NULL)
375 {
376 char *buf;
377 str = scm_i_make_string (pt->read_buf_size, &buf);
378 memcpy (buf, pt->read_buf, pt->read_buf_size);
379 }
380 else
381 str = scm_i_from_stringn ((char *)pt->read_buf, pt->read_buf_size,
382 pt->encoding, pt->ilseq_handler);
36284627
DH
383 scm_remember_upto_here_1 (port);
384 return str;
3fe6190f
GH
385}
386
889975e5
MG
387/* Create a vector containing the locale representation of the string in the
388 port's buffer. */
389SCM scm_strport_to_locale_u8vector (SCM port)
390{
391 scm_t_port *pt = SCM_PTAB_ENTRY (port);
392 SCM vec;
393 char *buf;
394
395 if (pt->rw_active == SCM_PORT_WRITE)
396 st_flush (port);
397
398 buf = scm_malloc (pt->read_buf_size);
399 memcpy (buf, pt->read_buf, pt->read_buf_size);
400 vec = scm_take_u8vector ((unsigned char *) buf, pt->read_buf_size);
401 scm_remember_upto_here_1 (port);
402 return vec;
403}
404
fe78b6c0
KN
405SCM_DEFINE (scm_object_to_string, "object->string", 1, 1, 0,
406 (SCM obj, SCM printer),
407 "Return a Scheme string obtained by printing @var{obj}.\n"
408 "Printing function can be specified by the optional second\n"
409 "argument @var{printer} (default: @code{write}).")
1f3908c4
KN
410#define FUNC_NAME s_scm_object_to_string
411{
fe78b6c0
KN
412 SCM str, port;
413
414 if (!SCM_UNBNDP (printer))
415 SCM_VALIDATE_PROC (2, printer);
1f3908c4 416
cc95e00a 417 str = scm_c_make_string (0, SCM_UNDEFINED);
1a92274c 418 port = scm_mkstrport (SCM_INUM0, str, SCM_OPN | SCM_WRTNG, FUNC_NAME);
fe78b6c0
KN
419
420 if (SCM_UNBNDP (printer))
421 scm_write (obj, port);
422 else
fdc28395 423 scm_call_2 (printer, obj, port);
fe78b6c0 424
1f3908c4
KN
425 return scm_strport_to_string (port);
426}
427#undef FUNC_NAME
428
889975e5
MG
429SCM_DEFINE (scm_call_with_output_locale_u8vector, "call-with-output-locale-u8vector", 1, 0, 0,
430 (SCM proc),
431 "Calls the one-argument procedure @var{proc} with a newly created output\n"
432 "port. When the function returns, a vector containing the bytes of a\n"
433 "locale representation of the characters written into the port is returned\n")
434#define FUNC_NAME s_scm_call_with_output_locale_u8vector
435{
436 SCM p;
437
438 p = scm_mkstrport (SCM_INUM0,
439 scm_make_string (SCM_INUM0, SCM_UNDEFINED),
440 SCM_OPN | SCM_WRTNG,
441 FUNC_NAME);
442 scm_call_1 (proc, p);
443
444 return scm_get_output_locale_u8vector (p);
445}
446#undef FUNC_NAME
447
3b3b36dd 448SCM_DEFINE (scm_call_with_output_string, "call-with-output-string", 1, 0, 0,
1bbd0b84 449 (SCM proc),
b380b885
MD
450 "Calls the one-argument procedure @var{proc} with a newly created output\n"
451 "port. When the function returns, the string composed of the characters\n"
452 "written into the port is returned.")
1bbd0b84 453#define FUNC_NAME s_scm_call_with_output_string
0f2d19dd
JB
454{
455 SCM p;
754c9491
JB
456
457 p = scm_mkstrport (SCM_INUM0,
458 scm_make_string (SCM_INUM0, SCM_UNDEFINED),
459 SCM_OPN | SCM_WRTNG,
1bbd0b84 460 FUNC_NAME);
fdc28395 461 scm_call_1 (proc, p);
3fe6190f 462
184b85a3 463 return scm_get_output_string (p);
0f2d19dd 464}
1bbd0b84 465#undef FUNC_NAME
0f2d19dd 466
3b3b36dd 467SCM_DEFINE (scm_call_with_input_string, "call-with-input-string", 2, 0, 0,
1e6808ea
MG
468 (SCM string, SCM proc),
469 "Calls the one-argument procedure @var{proc} with a newly\n"
470 "created input port from which @var{string}'s contents may be\n"
471 "read. The value yielded by the @var{proc} is returned.")
1bbd0b84 472#define FUNC_NAME s_scm_call_with_input_string
0f2d19dd 473{
1e6808ea 474 SCM p = scm_mkstrport(SCM_INUM0, string, SCM_OPN | SCM_RDNG, FUNC_NAME);
fdc28395 475 return scm_call_1 (proc, p);
0f2d19dd 476}
1bbd0b84 477#undef FUNC_NAME
0f2d19dd 478
e87a03fc
MG
479SCM_DEFINE (scm_open_input_string, "open-input-string", 1, 0, 0,
480 (SCM str),
1e6808ea
MG
481 "Take a string and return an input port that delivers characters\n"
482 "from the string. The port can be closed by\n"
e87a03fc
MG
483 "@code{close-input-port}, though its storage will be reclaimed\n"
484 "by the garbage collector if it becomes inaccessible.")
485#define FUNC_NAME s_scm_open_input_string
486{
487 SCM p = scm_mkstrport(SCM_INUM0, str, SCM_OPN | SCM_RDNG, FUNC_NAME);
488 return p;
489}
490#undef FUNC_NAME
491
889975e5
MG
492SCM_DEFINE (scm_open_input_locale_u8vector, "open-input-locale-u8vector", 1, 0, 0,
493 (SCM vec),
494 "Take a u8vector containing the bytes of a string encoded in the\n"
495 "current locale and return an input port that delivers characters\n"
496 "from the string. The port can be closed by\n"
497 "@code{close-input-port}, though its storage will be reclaimed\n"
498 "by the garbage collector if it becomes inaccessible.")
499#define FUNC_NAME s_scm_open_input_locale_u8vector
500{
501 scm_t_array_handle hnd;
502 ssize_t inc;
503 size_t len;
504 const scm_t_uint8 *buf;
505
506 buf = scm_u8vector_elements (vec, &hnd, &len, &inc);
507 SCM p = scm_i_mkstrport(SCM_INUM0, (const char *) buf, len, SCM_OPN | SCM_RDNG, FUNC_NAME);
508 scm_array_handle_release (&hnd);
509 return p;
510}
511#undef FUNC_NAME
512
e87a03fc
MG
513SCM_DEFINE (scm_open_output_string, "open-output-string", 0, 0, 0,
514 (void),
1e6808ea 515 "Return an output port that will accumulate characters for\n"
e87a03fc
MG
516 "retrieval by @code{get-output-string}. The port can be closed\n"
517 "by the procedure @code{close-output-port}, though its storage\n"
518 "will be reclaimed by the garbage collector if it becomes\n"
519 "inaccessible.")
520#define FUNC_NAME s_scm_open_output_string
521{
522 SCM p;
523
524 p = scm_mkstrport (SCM_INUM0,
525 scm_make_string (SCM_INUM0, SCM_UNDEFINED),
526 SCM_OPN | SCM_WRTNG,
527 FUNC_NAME);
528 return p;
529}
530#undef FUNC_NAME
531
532SCM_DEFINE (scm_get_output_string, "get-output-string", 1, 0, 0,
533 (SCM port),
534 "Given an output port created by @code{open-output-string},\n"
1e6808ea 535 "return a string consisting of the characters that have been\n"
e87a03fc
MG
536 "output to the port so far.")
537#define FUNC_NAME s_scm_get_output_string
538{
539 SCM_VALIDATE_OPOUTSTRPORT (1, port);
540 return scm_strport_to_string (port);
541}
542#undef FUNC_NAME
1cc91f1b 543
cd07a097 544
889975e5
MG
545SCM_DEFINE (scm_get_output_locale_u8vector, "get-output-locale-u8vector", 1, 0, 0,
546 (SCM port),
547 "Given an output port created by @code{open-output-string},\n"
548 "return a u8 vector containing the characters of the string\n"
549 "encoded in the current locale.")
550#define FUNC_NAME s_scm_get_output_locale_u8vector
551{
552 SCM_VALIDATE_OPOUTSTRPORT (1, port);
553 return scm_strport_to_locale_u8vector (port);
554}
555#undef FUNC_NAME
556
557
a8aa30d8
MD
558/* Given a null-terminated string EXPR containing a Scheme expression
559 read it, and return it as an SCM value. */
560SCM
ca13a04a 561scm_c_read_string (const char *expr)
a8aa30d8 562{
889975e5
MG
563 /* FIXME: the c string gets packed into a string, only to get
564 immediately unpacked in scm_mkstrport. */
3fe6190f 565 SCM port = scm_mkstrport (SCM_INUM0,
cc95e00a 566 scm_from_locale_string (expr),
a8aa30d8 567 SCM_OPN | SCM_RDNG,
ca13a04a 568 "scm_c_read_string");
a8aa30d8
MD
569 SCM form;
570
571 /* Read expressions from that port; ignore the values. */
deca31e1 572 form = scm_read (port);
a8aa30d8
MD
573
574 scm_close_port (port);
575 return form;
576}
577
cd07a097 578/* Given a null-terminated string EXPR containing Scheme program text,
a8aa30d8
MD
579 evaluate it, and return the result of the last expression evaluated. */
580SCM
ca13a04a 581scm_c_eval_string (const char *expr)
cd07a097 582{
cc95e00a 583 return scm_eval_string (scm_from_locale_string (expr));
b377f53e
JB
584}
585
209b52fe
MV
586SCM
587scm_c_eval_string_in_module (const char *expr, SCM module)
588{
cc95e00a 589 return scm_eval_string_in_module (scm_from_locale_string (expr), module);
209b52fe
MV
590}
591
592
96e83482
MV
593static SCM
594inner_eval_string (void *data)
b377f53e 595{
96e83482 596 SCM port = (SCM)data;
cd07a097 597 SCM form;
b377f53e 598 SCM ans = SCM_UNSPECIFIED;
cd07a097
JB
599
600 /* Read expressions from that port; ignore the values. */
0c32d76c 601 while (!SCM_EOF_OBJECT_P (form = scm_read (port)))
96e83482 602 ans = scm_primitive_eval_x (form);
cd07a097 603
0d7368d7
JB
604 /* Don't close the port here; if we re-enter this function via a
605 continuation, then the next time we enter it, we'll get an error.
606 It's a string port anyway, so there's no advantage to closing it
607 early. */
608
a8aa30d8 609 return ans;
cd07a097 610}
96e83482 611
209b52fe
MV
612SCM_DEFINE (scm_eval_string_in_module, "eval-string", 1, 1, 0,
613 (SCM string, SCM module),
96e83482
MV
614 "Evaluate @var{string} as the text representation of a Scheme\n"
615 "form or forms, and return whatever value they produce.\n"
209b52fe
MV
616 "Evaluation takes place in the given module, or the current\n"
617 "module when no module is given.\n"
618 "While the code is evaluated, the given module is made the\n"
619 "current one. The current module is restored when this\n"
620 "procedure returns.")
621#define FUNC_NAME s_scm_eval_string_in_module
96e83482
MV
622{
623 SCM port = scm_mkstrport (SCM_INUM0, string, SCM_OPN | SCM_RDNG,
209b52fe
MV
624 FUNC_NAME);
625 if (SCM_UNBNDP (module))
626 module = scm_current_module ();
aeec5be1
MV
627 else
628 SCM_VALIDATE_MODULE (2, module);
209b52fe 629 return scm_c_call_with_current_module (module,
96e83482
MV
630 inner_eval_string, (void *)port);
631}
1bbd0b84 632#undef FUNC_NAME
cd07a097 633
209b52fe
MV
634SCM
635scm_eval_string (SCM string)
636{
637 return scm_eval_string_in_module (string, SCM_UNDEFINED);
638}
639
92c2555f 640static scm_t_bits
0b6881fa 641scm_make_stptob ()
0f2d19dd 642{
92c2555f 643 scm_t_bits tc = scm_make_port_type ("string", stfill_buffer, st_write);
a98bddfd 644
6c747373 645 scm_set_port_mark (tc, scm_markstream);
affc96b5
GH
646 scm_set_port_end_input (tc, st_end_input);
647 scm_set_port_flush (tc, st_flush);
6c747373 648 scm_set_port_seek (tc, st_seek);
affc96b5 649 scm_set_port_truncate (tc, st_truncate);
a98bddfd
DH
650
651 return tc;
0f2d19dd
JB
652}
653
0f2d19dd
JB
654void
655scm_init_strports ()
0f2d19dd 656{
a98bddfd
DH
657 scm_tc16_strport = scm_make_stptob ();
658
a0599745 659#include "libguile/strports.x"
0f2d19dd
JB
660}
661
89e00824
ML
662
663/*
664 Local Variables:
665 c-file-style: "gnu"
666 End:
667*/