* Makefile.am (version.texi): Override automake's rule for
[bpt/guile.git] / libguile / strings.c
CommitLineData
7dc6e754 1/* Copyright (C) 1995,1996,1998 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd
JB
45\f
46
47#include <stdio.h>
48#include "_scm.h"
20e6290e 49#include "chars.h"
0f2d19dd 50
20e6290e 51#include "strings.h"
1bbd0b84 52#include "scm_validate.h"
0f2d19dd
JB
53\f
54
55/* {Strings}
56 */
57
3b3b36dd 58SCM_DEFINE (scm_string_p, "string?", 1, 0, 0,
6fa73e72
GB
59 (SCM obj),
60 "Returns #t iff OBJ is a string, else returns #f.")
1bbd0b84 61#define FUNC_NAME s_scm_string_p
0f2d19dd 62{
6fa73e72 63 if (SCM_IMP (obj))
0f2d19dd 64 return SCM_BOOL_F;
6fa73e72 65 return SCM_BOOL(SCM_STRINGP (obj));
0f2d19dd 66}
1bbd0b84 67#undef FUNC_NAME
0f2d19dd 68
3b3b36dd 69SCM_DEFINE (scm_read_only_string_p, "read-only-string?", 1, 0, 0,
1bbd0b84 70 (SCM x),
b380b885
MD
71 "Return true of OBJ can be read as a string,\n\n"
72 "This illustrates the difference between @code{string?} and\n"
73 "@code{read-only-string?}:\n\n"
74 "@example\n"
75 "(string? \"a string\") @result{} #t\n"
76 "(string? 'a-symbol) @result{} #f\n\n"
77 "(read-only-string? \"a string\") @result{} #t\n"
78 "(read-only-string? 'a-symbol) @result{} #t\n"
79 "@end example")
1bbd0b84 80#define FUNC_NAME s_scm_read_only_string_p
0f2d19dd
JB
81{
82 if (SCM_IMP (x))
83 return SCM_BOOL_F;
1bbd0b84 84 return SCM_BOOL(SCM_ROSTRINGP (x));
0f2d19dd 85}
1bbd0b84 86#undef FUNC_NAME
0f2d19dd 87
1bbd0b84 88SCM_REGISTER_PROC(s_list_to_string, "list->string", 1, 0, 0, scm_string);
1cc91f1b 89
1bbd0b84 90
3b3b36dd 91SCM_DEFINE (scm_string, "string", 0, 0, 1,
6fa73e72
GB
92 (SCM chrs),
93 "Returns a newly allocated string composed of the arguments, CHRS.")
1bbd0b84 94#define FUNC_NAME s_scm_string
0f2d19dd
JB
95{
96 SCM res;
a65b9c80 97 register unsigned char *data;
0f2d19dd
JB
98 long i;
99 long len;
100 SCM_DEFER_INTS;
101 i = scm_ilength (chrs);
102 if (i < 0)
103 {
104 SCM_ALLOW_INTS;
1bbd0b84 105 SCM_ASSERT (0, chrs, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
106 }
107 len = 0;
108 {
109 SCM s;
110
111 for (len = 0, s = chrs; s != SCM_EOL; s = SCM_CDR (s))
112 if (SCM_ICHRP (SCM_CAR (s)))
113 len += 1;
0c95b57d 114 else if (SCM_ROSTRINGP (SCM_CAR (s)))
0f2d19dd
JB
115 len += SCM_ROLENGTH (SCM_CAR (s));
116 else
117 {
118 SCM_ALLOW_INTS;
1bbd0b84 119 SCM_ASSERT (0, s, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
120 }
121 }
122 res = scm_makstr (len, 0);
a65b9c80 123 data = SCM_UCHARS (res);
0f2d19dd
JB
124 for (;SCM_NNULLP (chrs);chrs = SCM_CDR (chrs))
125 {
126 if (SCM_ICHRP (SCM_CAR (chrs)))
127 *data++ = SCM_ICHR (SCM_CAR (chrs));
128 else
129 {
130 int l;
131 char * c;
132 l = SCM_ROLENGTH (SCM_CAR (chrs));
cdbadcac 133 c = SCM_ROCHARS (SCM_CAR (chrs));
0f2d19dd
JB
134 while (l)
135 {
136 --l;
137 *data++ = *c++;
138 }
139 }
140 }
141 SCM_ALLOW_INTS;
142 return res;
143}
1bbd0b84 144#undef FUNC_NAME
0f2d19dd 145
1cc91f1b 146
0f2d19dd 147SCM
1bbd0b84 148scm_makstr (long len, int slots)
0f2d19dd
JB
149{
150 SCM s;
151 SCM * mem;
152 SCM_NEWCELL (s);
153 --slots;
154 SCM_REDEFER_INTS;
155 mem = (SCM *)scm_must_malloc (sizeof (SCM) * (slots + 1) + len + 1,
1bbd0b84 156 "scm_makstr");
0f2d19dd
JB
157 if (slots >= 0)
158 {
159 int x;
160 mem[slots] = (SCM)mem;
161 for (x = 0; x < slots; ++x)
162 mem[x] = SCM_BOOL_F;
163 }
164 SCM_SETCHARS (s, (char *) (mem + slots + 1));
165 SCM_SETLENGTH (s, len, scm_tc7_string);
166 SCM_REALLOW_INTS;
167 SCM_CHARS (s)[len] = 0;
168 return s;
169}
170
171/* converts C scm_array of strings to SCM scm_list of strings. */
172/* If argc < 0, a null terminated scm_array is assumed. */
1cc91f1b 173
0f2d19dd 174SCM
1bbd0b84 175scm_makfromstrs (int argc, char **argv)
0f2d19dd
JB
176{
177 int i = argc;
178 SCM lst = SCM_EOL;
179 if (0 > i)
180 for (i = 0; argv[i]; i++);
181 while (i--)
182 lst = scm_cons (scm_makfromstr (argv[i], (scm_sizet) strlen (argv[i]), 0), lst);
183 return lst;
184}
185
186
ee149d03
JB
187/* This function must only be applied to memory obtained via malloc,
188 since the GC is going to apply `free' to it when the string is
189 dropped.
190
191 Also, s[len] must be `\0', since we promise that strings are
192 null-terminated. Perhaps we could handle non-null-terminated
193 strings by claiming they're shared substrings of a string we just
194 made up. */
0f2d19dd 195SCM
ee149d03 196scm_take_str (char *s, int len)
0f2d19dd
JB
197{
198 SCM answer;
199 SCM_NEWCELL (answer);
200 SCM_DEFER_INTS;
ee149d03
JB
201 SCM_SETLENGTH (answer, len, scm_tc7_string);
202 scm_done_malloc (len + 1);
203 SCM_SETCHARS (answer, s);
0f2d19dd
JB
204 SCM_ALLOW_INTS;
205 return answer;
206}
207
ee149d03
JB
208/* `s' must be a malloc'd string. See scm_take_str. */
209SCM
210scm_take0str (char *s)
211{
212 return scm_take_str (s, strlen (s));
213}
214
1cc91f1b 215
0f2d19dd 216SCM
1bbd0b84 217scm_makfromstr (const char *src, scm_sizet len, int slots)
0f2d19dd
JB
218{
219 SCM s;
220 register char *dst;
221 s = scm_makstr ((long) len, slots);
222 dst = SCM_CHARS (s);
223 while (len--)
224 *dst++ = *src++;
225 return s;
226}
227
228
1cc91f1b 229
0f2d19dd 230SCM
1bbd0b84 231scm_makfrom0str (const char *src)
0f2d19dd
JB
232{
233 if (!src) return SCM_BOOL_F;
234 return scm_makfromstr (src, (scm_sizet) strlen (src), 0);
235}
236
1cc91f1b 237
0f2d19dd 238SCM
1bbd0b84 239scm_makfrom0str_opt (const char *src)
0f2d19dd
JB
240{
241 return scm_makfrom0str (src);
242}
243
244
245
246
3b3b36dd 247SCM_DEFINE (scm_make_string, "make-string", 1, 1, 0,
6fa73e72
GB
248 (SCM k, SCM chr),
249 "Returns a newly allocated string of\n"
250 "length K. If CHR is given, then all elements of the string\n"
251 "are initialized to CHR, otherwise the contents of the\n"
252 "STRING are unspecified.\n"
253 "")
1bbd0b84 254#define FUNC_NAME s_scm_make_string
0f2d19dd
JB
255{
256 SCM res;
0f2d19dd 257 register long i;
3b3b36dd 258 SCM_VALIDATE_INUM_MIN_COPY (1,k,0,i);
0f2d19dd 259 res = scm_makstr (i, 0);
6c951427 260 if (!SCM_UNBNDP (chr))
0f2d19dd 261 {
9a8351bc 262 SCM_VALIDATE_ICHR (2,chr);
6c951427
GH
263 {
264 unsigned char *dst = SCM_UCHARS (res);
265 char c = SCM_ICHR (chr);
266
267 memset (dst, c, i);
268 }
0f2d19dd
JB
269 }
270 return res;
271}
1bbd0b84 272#undef FUNC_NAME
0f2d19dd 273
3b3b36dd 274SCM_DEFINE (scm_string_length, "string-length", 1, 0, 0,
6fa73e72
GB
275 (SCM string),
276 "Returns the number of characters in STRING")
1bbd0b84 277#define FUNC_NAME s_scm_string_length
0f2d19dd 278{
6fa73e72
GB
279 SCM_VALIDATE_ROSTRING (1,string);
280 return SCM_MAKINUM (SCM_ROLENGTH (string));
0f2d19dd 281}
1bbd0b84 282#undef FUNC_NAME
0f2d19dd 283
3b3b36dd 284SCM_DEFINE (scm_string_ref, "string-ref", 1, 1, 0,
6fa73e72
GB
285 (SCM str, SCM k),
286 "Returns character K of STR using zero-origin indexing.\n"
287 "K must be a valid index of STR.")
1bbd0b84 288#define FUNC_NAME s_scm_string_ref
0f2d19dd 289{
3b3b36dd
GB
290 SCM_VALIDATE_ROSTRING (1,str);
291 SCM_VALIDATE_INUM_DEF (2,k,0);
5bff3127 292 SCM_ASSERT_RANGE (2,k,SCM_INUM (k) < SCM_ROLENGTH (str) && SCM_INUM (k) >= 0);
a65b9c80 293 return SCM_MAKICHR (SCM_ROUCHARS (str)[SCM_INUM (k)]);
0f2d19dd 294}
1bbd0b84 295#undef FUNC_NAME
0f2d19dd 296
3b3b36dd 297SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
6fa73e72
GB
298 (SCM str, SCM k, SCM chr),
299 "Stores CHR in element K of STRING and returns an unspecified value.\n"
300 "K must be a valid index of STR.")
1bbd0b84 301#define FUNC_NAME s_scm_string_set_x
0f2d19dd 302{
3b3b36dd
GB
303 SCM_VALIDATE_RWSTRING (1,str);
304 SCM_VALIDATE_INUM_RANGE (2,k,0,SCM_LENGTH(str));
9a8351bc 305 SCM_VALIDATE_ICHR (3,chr);
a65b9c80 306 SCM_UCHARS (str)[SCM_INUM (k)] = SCM_ICHR (chr);
0f2d19dd
JB
307 return SCM_UNSPECIFIED;
308}
1bbd0b84 309#undef FUNC_NAME
0f2d19dd
JB
310
311
312
3b3b36dd 313SCM_DEFINE (scm_substring, "substring", 2, 1, 0,
1bbd0b84 314 (SCM str, SCM start, SCM end),
6fa73e72
GB
315 "Returns a newly allocated string formed from the characters\n"
316 "of STR beginning with index START (inclusive) and ending with\n"
317 "index END (exclusive).\n"
318 "STR must be a string, START and END must be exact integers satisfying:\n\n"
319 "0 <= START <= END <= (string-length STR).")
1bbd0b84 320#define FUNC_NAME s_scm_substring
0f2d19dd
JB
321{
322 long l;
3b3b36dd
GB
323 SCM_VALIDATE_ROSTRING (1,str);
324 SCM_VALIDATE_INUM (2,start);
325 SCM_VALIDATE_INUM_DEF (3,end,SCM_ROLENGTH(str));
5bff3127
GB
326 SCM_ASSERT_RANGE (2,start,SCM_INUM (start) <= SCM_ROLENGTH (str));
327 SCM_ASSERT_RANGE (2,end,SCM_INUM (end) <= SCM_ROLENGTH (str));
0f2d19dd 328 l = SCM_INUM (end)-SCM_INUM (start);
1bbd0b84 329 SCM_ASSERT (l >= 0, SCM_MAKINUM (l), SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
330 return scm_makfromstr (&SCM_ROCHARS (str)[SCM_INUM (start)], (scm_sizet)l, 0);
331}
1bbd0b84 332#undef FUNC_NAME
0f2d19dd 333
3b3b36dd 334SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1,
6fa73e72
GB
335 (SCM args),
336 "Returns a newly allocated string whose characters form the\n"
337 "concatenation of the given strings, ARGS.")
1bbd0b84 338#define FUNC_NAME s_scm_string_append
0f2d19dd
JB
339{
340 SCM res;
341 register long i = 0;
342 register SCM l, s;
a65b9c80 343 register unsigned char *data;
368cf54d 344 for (l = args;SCM_CONSP (l);) {
0f2d19dd 345 s = SCM_CAR (l);
3b3b36dd 346 SCM_VALIDATE_ROSTRING (SCM_ARGn,s);
0f2d19dd
JB
347 i += SCM_ROLENGTH (s);
348 l = SCM_CDR (l);
349 }
1bbd0b84 350 SCM_ASSERT (SCM_NULLP (l), args, SCM_ARGn, FUNC_NAME);
0f2d19dd 351 res = scm_makstr (i, 0);
a65b9c80 352 data = SCM_UCHARS (res);
0f2d19dd
JB
353 for (l = args;SCM_NIMP (l);l = SCM_CDR (l)) {
354 s = SCM_CAR (l);
a65b9c80 355 for (i = 0;i<SCM_ROLENGTH (s);i++) *data++ = SCM_ROUCHARS (s)[i];
0f2d19dd
JB
356 }
357 return res;
358}
1bbd0b84 359#undef FUNC_NAME
0f2d19dd 360
3b3b36dd 361SCM_DEFINE (scm_make_shared_substring, "make-shared-substring", 1, 2, 0,
1bbd0b84 362 (SCM str, SCM frm, SCM to),
b380b885
MD
363 "Return a shared substring of @var{str}. The semantics are the same as\n"
364 "for the @code{substring} function: the shared substring returned\n"
365 "includes all of the text from @var{str} between indexes @var{start}\n"
366 "(inclusive) and @var{end} (exclusive). If @var{end} is omitted, it\n"
367 "defaults to the end of @var{str}. The shared substring returned by\n"
368 "@code{make-shared-substring} occupies the same storage space as\n"
369 "@var{str}.")
1bbd0b84 370#define FUNC_NAME s_scm_make_shared_substring
0f2d19dd
JB
371{
372 long f;
373 long t;
374 SCM answer;
375 SCM len_str;
376
3b3b36dd
GB
377 SCM_VALIDATE_ROSTRING (1,str);
378 SCM_VALIDATE_INUM_DEF_COPY (2,frm,0,f);
379 SCM_VALIDATE_INUM_DEF_COPY (3,to,SCM_ROLENGTH(str),t);
0f2d19dd 380
5bff3127
GB
381 SCM_ASSERT_RANGE (2,frm,(f >= 0));
382 SCM_ASSERT_RANGE (3,to, (f <= t) && (t <= SCM_ROLENGTH (str)));
0f2d19dd
JB
383
384 SCM_NEWCELL (answer);
385 SCM_NEWCELL (len_str);
386
387 SCM_DEFER_INTS;
388 if (SCM_SUBSTRP (str))
389 {
390 long offset;
391 offset = SCM_INUM (SCM_SUBSTR_OFFSET (str));
392 f += offset;
393 t += offset;
394 SCM_SETCAR (len_str, SCM_MAKINUM (f));
395 SCM_SETCDR (len_str, SCM_SUBSTR_STR (str));
396 SCM_SETCDR (answer, len_str);
397 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
398 }
399 else
400 {
401 SCM_SETCAR (len_str, SCM_MAKINUM (f));
402 SCM_SETCDR (len_str, str);
403 SCM_SETCDR (answer, len_str);
404 SCM_SETLENGTH (answer, t - f, scm_tc7_substring);
405 }
406 SCM_ALLOW_INTS;
407 return answer;
408}
1bbd0b84 409#undef FUNC_NAME
1cc91f1b 410
0f2d19dd
JB
411void
412scm_init_strings ()
0f2d19dd
JB
413{
414#include "strings.x"
415}
416