1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
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
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "libguile/_scm.h"
30 #include "libguile/chars.h"
31 #include "libguile/modules.h"
32 #include "libguile/ports.h"
33 #include "libguile/rdelim.h"
34 #include "libguile/root.h"
35 #include "libguile/strings.h"
36 #include "libguile/strports.h"
37 #include "libguile/validate.h"
39 SCM_DEFINE (scm_read_delimited_x
, "%read-delimited!", 3, 3, 0,
40 (SCM delims
, SCM str
, SCM gobble
, SCM port
, SCM start
, SCM end
),
41 "Read characters from @var{port} into @var{str} until one of the\n"
42 "characters in the @var{delims} string is encountered. If\n"
43 "@var{gobble} is true, discard the delimiter character;\n"
44 "otherwise, leave it in the input stream for the next read. If\n"
45 "@var{port} is not specified, use the value of\n"
46 "@code{(current-input-port)}. If @var{start} or @var{end} are\n"
47 "specified, store data only into the substring of @var{str}\n"
48 "bounded by @var{start} and @var{end} (which default to the\n"
49 "beginning and end of the string, respectively).\n"
51 " Return a pair consisting of the delimiter that terminated the\n"
52 "string and the number of characters read. If reading stopped\n"
53 "at the end of file, the delimiter returned is the\n"
54 "@var{eof-object}; if the string was filled without encountering\n"
55 "a delimiter, this value is @code{#f}.")
56 #define FUNC_NAME s_scm_read_delimited_x
66 SCM_VALIDATE_STRING (1, delims
);
67 cdelims
= SCM_I_STRING_CHARS (delims
);
68 num_delims
= SCM_I_STRING_LENGTH (delims
);
70 SCM_VALIDATE_STRING (2, str
);
71 buf
= SCM_I_STRING_CHARS (str
);
72 scm_i_get_substring_spec (SCM_I_STRING_LENGTH (str
),
73 start
, &cstart
, end
, &cend
);
75 if (SCM_UNBNDP (port
))
78 SCM_VALIDATE_OPINPORT (4, port
);
80 for (j
= cstart
; j
< cend
; j
++)
85 for (k
= 0; k
< num_delims
; k
++)
89 if (scm_is_false (gobble
))
92 return scm_cons (SCM_MAKE_CHAR (c
),
93 scm_from_size_t (j
- cstart
));
97 return scm_cons (SCM_EOF_VAL
,
98 scm_from_size_t (j
- cstart
));
102 return scm_cons (SCM_BOOL_F
, scm_from_size_t (j
- cstart
));
106 static unsigned char *
107 scm_do_read_line (SCM port
, size_t *len_p
)
109 scm_t_port
*pt
= SCM_PTAB_ENTRY (port
);
112 /* I thought reading lines was simple. Mercy me. */
114 /* The common case: the buffer contains a complete line.
115 This needs to be fast. */
116 if ((end
= memchr (pt
->read_pos
, '\n', (pt
->read_end
- pt
->read_pos
)))
119 size_t buf_len
= (end
+ 1) - pt
->read_pos
;
120 /* Allocate a buffer of the perfect size. */
121 unsigned char *buf
= scm_malloc (buf_len
+ 1);
123 memcpy (buf
, pt
->read_pos
, buf_len
);
124 pt
->read_pos
+= buf_len
;
132 /* The buffer contains no newlines. */
134 /* When live, len is always the number of characters in the
135 current buffer that are part of the current line. */
136 size_t len
= (pt
->read_end
- pt
->read_pos
);
137 size_t buf_size
= (len
< 50) ? 60 : len
* 2;
138 /* Invariant: buf always has buf_size + 1 characters allocated;
139 the `+ 1' is for the final '\0'. */
140 unsigned char *buf
= scm_malloc (buf_size
+ 1);
145 if (buf_len
+ len
> buf_size
)
147 size_t new_size
= (buf_len
+ len
) * 2;
148 buf
= scm_realloc (buf
, new_size
+ 1);
152 /* Copy what we've got out of the port, into our buffer. */
153 memcpy (buf
+ buf_len
, pt
->read_pos
, len
);
157 /* If we had seen a newline, we're done now. */
161 /* Get more characters. */
162 if (scm_fill_input (port
) == EOF
)
164 /* If we're missing a final newline in the file, return
165 what we did get, sans newline. */
173 /* Search the buffer for newlines. */
174 if ((end
= memchr (pt
->read_pos
, '\n',
175 (len
= (pt
->read_end
- pt
->read_pos
))))
177 len
= (end
- pt
->read_pos
) + 1;
180 /* I wonder how expensive this realloc is. */
181 buf
= scm_realloc (buf
, buf_len
+ 1);
191 * truncates any terminating newline from its input, and returns
192 * a cons of the string read and its terminating character. Doing
193 * so makes it easy to implement the hairy `read-line' options
194 * efficiently in Scheme.
197 SCM_DEFINE (scm_read_line
, "%read-line", 0, 1, 0,
199 "Read a newline-terminated line from @var{port}, allocating storage as\n"
200 "necessary. The newline terminator (if any) is removed from the string,\n"
201 "and a pair consisting of the line and its delimiter is returned. The\n"
202 "delimiter may be either a newline or the @var{eof-object}; if\n"
203 "@code{%read-line} is called at the end of file, it returns the pair\n"
204 "@code{(#<eof> . #<eof>)}.")
205 #define FUNC_NAME s_scm_read_line
212 if (SCM_UNBNDP (port
))
214 SCM_VALIDATE_OPINPORT (1,port
);
216 pt
= SCM_PTAB_ENTRY (port
);
217 if (pt
->rw_active
== SCM_PORT_WRITE
)
218 scm_ptobs
[SCM_PTOBNUM (port
)].flush (port
);
220 s
= (char *) scm_do_read_line (port
, &slen
);
223 term
= line
= SCM_EOF_VAL
;
226 if (s
[slen
-1] == '\n')
228 term
= SCM_MAKE_CHAR ('\n');
230 line
= scm_take_str (s
, slen
-1);
235 /* Fix: we should check for eof on the port before assuming this. */
237 line
= scm_take_str (s
, slen
);
238 SCM_COL (port
) += slen
;
243 pt
->rw_active
= SCM_PORT_READ
;
245 return scm_cons (line
, term
);
249 SCM_DEFINE (scm_write_line
, "write-line", 1, 1, 0,
251 "Display @var{obj} and a newline character to @var{port}. If\n"
252 "@var{port} is not specified, @code{(current-output-port)} is\n"
253 "used. This function is equivalent to:\n"
255 "(display obj [port])\n"
258 #define FUNC_NAME s_scm_write_line
260 scm_display (obj
, port
);
261 return scm_newline (port
);
266 scm_init_rdelim_builtins (void)
268 #include "libguile/rdelim.x"
270 return SCM_UNSPECIFIED
;
274 scm_init_rdelim (void)
276 scm_c_define_gsubr ("%init-rdelim-builtins", 0, 0, 0,
277 scm_init_rdelim_builtins
);