Changed all uses of SCM_VALIDATE_INUM, SCM_VALIDATE_INUM_COPY,
[bpt/guile.git] / srfi / srfi-13.c
CommitLineData
ca003b26
MG
1/* srfi-13.c --- SRFI-13 procedures for Guile
2 *
597e2cbd 3 * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
0f216433 4 *
73be1d9e
MV
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
0f216433 9 *
73be1d9e
MV
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ca003b26 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
73be1d9e 13 * Lesser General Public License for more details.
0f216433 14 *
73be1d9e
MV
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
ca003b26
MG
19
20
21#include <string.h>
22#include <ctype.h>
23
24#include <libguile.h>
25
653c7291 26#include "srfi-13.h"
ca003b26
MG
27#include "srfi-14.h"
28
0f216433 29SCM_DEFINE (scm_string_any, "string-any", 2, 2, 0,
ca003b26
MG
30 (SCM pred, SCM s, SCM start, SCM end),
31 "Check if the predicate @var{pred} is true for any character in\n"
32 "the string @var{s}, proceeding from left (index @var{start}) to\n"
33 "right (index @var{end}). If @code{string-any} returns true,\n"
fafb71de
MG
34 "the returned true value is the one produced by the first\n"
35 "successful application of @var{pred}.")
ca003b26
MG
36#define FUNC_NAME s_scm_string_any
37{
38 char * cstr;
39 int cstart, cend;
40 SCM res;
41
42 SCM_VALIDATE_PROC (1, pred);
43 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
44 3, start, cstart,
45 4, end, cend);
46 cstr += cstart;
47 while (cstart < cend)
48 {
2c4df451 49 res = scm_call_1 (pred, SCM_MAKE_CHAR (*cstr));
00874d5f 50 if (scm_is_true (res))
ca003b26
MG
51 return res;
52 cstr++;
53 cstart++;
54 }
55 return SCM_BOOL_F;
56}
57#undef FUNC_NAME
58
59
0f216433 60SCM_DEFINE (scm_string_every, "string-every", 2, 2, 0,
ca003b26
MG
61 (SCM pred, SCM s, SCM start, SCM end),
62 "Check if the predicate @var{pred} is true for every character\n"
63 "in the string @var{s}, proceeding from left (index @var{start})\n"
64 "to right (index @var{end}). If @code{string-every} returns\n"
65 "true, the returned true value is the one produced by the final\n"
66 "application of @var{pred} to the last character of @var{s}.")
67#define FUNC_NAME s_scm_string_every
68{
69 char * cstr;
70 int cstart, cend;
71 SCM res;
72
73 SCM_VALIDATE_PROC (1, pred);
74 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
75 3, start, cstart,
76 4, end, cend);
77 res = SCM_BOOL_F;
78 cstr += cstart;
79 while (cstart < cend)
80 {
2c4df451 81 res = scm_call_1 (pred, SCM_MAKE_CHAR (*cstr));
00874d5f 82 if (scm_is_false (res))
ca003b26
MG
83 return res;
84 cstr++;
85 cstart++;
86 }
87 return res;
88}
89#undef FUNC_NAME
90
91
0f216433 92SCM_DEFINE (scm_string_tabulate, "string-tabulate", 2, 0, 0,
ca003b26
MG
93 (SCM proc, SCM len),
94 "@var{proc} is an integer->char procedure. Construct a string\n"
95 "of size @var{len} by applying @var{proc} to each index to\n"
96 "produce the corresponding string element. The order in which\n"
97 "@var{proc} is applied to the indices is not specified.")
98#define FUNC_NAME s_scm_string_tabulate
99{
1a161b8e 100 size_t clen, i;
ca003b26
MG
101 SCM res;
102 SCM ch;
103 char * p;
104
105 SCM_VALIDATE_PROC (1, proc);
1a161b8e 106 clen = scm_to_size_t (len);
ca003b26
MG
107 SCM_ASSERT_RANGE (2, len, clen >= 0);
108
109 res = scm_allocate_string (clen);
110 p = SCM_STRING_CHARS (res);
111 i = 0;
112 while (i < clen)
113 {
1a161b8e 114 ch = scm_call_1 (proc, scm_from_int (i));
ca003b26 115 if (!SCM_CHARP (ch))
2c4df451 116 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
ca003b26
MG
117 *p++ = SCM_CHAR (ch);
118 i++;
119 }
120 return res;
121}
122#undef FUNC_NAME
123
124
125SCM_DEFINE (scm_string_to_listS, "string->list", 1, 2, 0,
126 (SCM str, SCM start, SCM end),
127 "Convert the string @var{str} into a list of characters.")
128#define FUNC_NAME s_scm_string_to_listS
129{
130 char * cstr;
131 int cstart, cend;
132 SCM result = SCM_EOL;
133
134 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
135 2, start, cstart,
136 3, end, cend);
137 while (cstart < cend)
138 {
139 cend--;
140 result = scm_cons (SCM_MAKE_CHAR (cstr[cend]), result);
141 }
142 return result;
143}
144#undef FUNC_NAME
145
0f216433 146SCM_DEFINE (scm_reverse_list_to_string, "reverse-list->string", 1, 0, 0,
ca003b26
MG
147 (SCM chrs),
148 "An efficient implementation of @code{(compose string->list\n"
149 "reverse)}:\n"
150 "\n"
151 "@smalllisp\n"
152 "(reverse-list->string '(#\a #\B #\c)) @result{} \"cBa\"\n"
153 "@end smalllisp")
154#define FUNC_NAME s_scm_reverse_list_to_string
155{
156 SCM result;
157 long i = scm_ilength (chrs);
0f216433 158
ca003b26
MG
159 if (i < 0)
160 SCM_WRONG_TYPE_ARG (1, chrs);
161 result = scm_allocate_string (i);
162
163 {
164 unsigned char *data = SCM_STRING_UCHARS (result) + i;
165
36284627 166 while (!SCM_NULLP (chrs))
ca003b26
MG
167 {
168 SCM elt = SCM_CAR (chrs);
169
170 SCM_VALIDATE_CHAR (SCM_ARGn, elt);
171 data--;
172 *data = SCM_CHAR (elt);
173 chrs = SCM_CDR (chrs);
174 }
175 }
176 return result;
177}
178#undef FUNC_NAME
179
180
181SCM_SYMBOL (scm_sym_infix, "infix");
182SCM_SYMBOL (scm_sym_strict_infix, "strict-infix");
183SCM_SYMBOL (scm_sym_suffix, "suffix");
184SCM_SYMBOL (scm_sym_prefix, "prefix");
185
0f216433 186SCM_DEFINE (scm_string_join, "string-join", 1, 2, 0,
ca003b26
MG
187 (SCM ls, SCM delimiter, SCM grammar),
188 "Append the string in the string list @var{ls}, using the string\n"
189 "@var{delim} as a delimiter between the elements of @var{ls}.\n"
190 "@var{grammar} is a symbol which specifies how the delimiter is\n"
191 "placed between the strings, and defaults to the symbol\n"
192 "@code{infix}.\n"
193 "\n"
194 "@table @code\n"
195 "@item infix\n"
196 "Insert the separator between list elements. An empty string\n"
197 "will produce an empty list.\n"
198 "@item string-infix\n"
199 "Like @code{infix}, but will raise an error if given the empty\n"
200 "list.\n"
201 "@item suffix\n"
202 "Insert the separator after every list element.\n"
203 "@item prefix\n"
204 "Insert the separator before each list element.\n"
205 "@end table")
206#define FUNC_NAME s_scm_string_join
207{
208#define GRAM_INFIX 0
209#define GRAM_STRICT_INFIX 1
210#define GRAM_SUFFIX 2
211#define GRAM_PREFIX 3
212 SCM tmp;
213 SCM result;
214 int gram = GRAM_INFIX;
215 int del_len = 0, extra_len = 0;
216 int len = 0;
217 char * p;
218 long strings = scm_ilength (ls);
219
220 /* Validate the string list. */
221 if (strings < 0)
222 SCM_WRONG_TYPE_ARG (1, ls);
223
224 /* Validate the delimiter and record its length. */
225 if (SCM_UNBNDP (delimiter))
226 {
227 delimiter = scm_makfrom0str (" ");
228 del_len = 1;
229 }
230 else
231 {
232 SCM_VALIDATE_STRING (2, delimiter);
233 del_len = SCM_STRING_LENGTH (delimiter);
234 }
235
236 /* Validate the grammar symbol and remember the grammar. */
237 if (SCM_UNBNDP (grammar))
238 gram = GRAM_INFIX;
239 else if (SCM_EQ_P (grammar, scm_sym_infix))
240 gram = GRAM_INFIX;
241 else if (SCM_EQ_P (grammar, scm_sym_strict_infix))
242 gram = GRAM_STRICT_INFIX;
243 else if (SCM_EQ_P (grammar, scm_sym_suffix))
244 gram = GRAM_SUFFIX;
245 else if (SCM_EQ_P (grammar, scm_sym_prefix))
246 gram = GRAM_PREFIX;
247 else
248 SCM_WRONG_TYPE_ARG (3, grammar);
249
250 /* Check grammar constraints and calculate the space required for
251 the delimiter(s). */
252 switch (gram)
253 {
254 case GRAM_INFIX:
255 if (!SCM_NULLP (ls))
256 extra_len = (strings > 0) ? ((strings - 1) * del_len) : 0;
257 break;
258 case GRAM_STRICT_INFIX:
259 if (strings == 0)
260 SCM_MISC_ERROR ("strict-infix grammar requires non-empty list",
261 SCM_EOL);
262 extra_len = (strings - 1) * del_len;
263 break;
264 default:
265 extra_len = strings * del_len;
266 break;
267 }
268
269 tmp = ls;
270 while (SCM_CONSP (tmp))
271 {
272 SCM elt = SCM_CAR (tmp);
273 SCM_VALIDATE_STRING (1, elt);
274 len += SCM_STRING_LENGTH (elt);
275 tmp = SCM_CDR (tmp);
276 }
277
278 result = scm_allocate_string (len + extra_len);
279 p = SCM_STRING_CHARS (result);
280
281 tmp = ls;
282 switch (gram)
283 {
284 case GRAM_INFIX:
285 case GRAM_STRICT_INFIX:
286 while (!SCM_NULLP (tmp))
287 {
288 SCM elt = SCM_CAR (tmp);
289 memmove (p, SCM_STRING_CHARS (elt),
290 SCM_STRING_LENGTH (elt) * sizeof (char));
291 p += SCM_STRING_LENGTH (elt);
292 if (!SCM_NULLP (SCM_CDR (tmp)) && del_len > 0)
293 {
294 memmove (p, SCM_STRING_CHARS (delimiter),
295 SCM_STRING_LENGTH (delimiter) * sizeof (char));
296 p += del_len;
297 }
298 tmp = SCM_CDR (tmp);
299 }
300 break;
301 case GRAM_SUFFIX:
302 while (!SCM_NULLP (tmp))
303 {
304 SCM elt = SCM_CAR (tmp);
305 memmove (p, SCM_STRING_CHARS (elt),
306 SCM_STRING_LENGTH (elt) * sizeof (char));
307 p += SCM_STRING_LENGTH (elt);
308 if (del_len > 0)
309 {
310 memmove (p, SCM_STRING_CHARS (delimiter),
311 SCM_STRING_LENGTH (delimiter) * sizeof (char));
312 p += del_len;
313 }
314 tmp = SCM_CDR (tmp);
315 }
316 break;
317 case GRAM_PREFIX:
318 while (!SCM_NULLP (tmp))
319 {
320 SCM elt = SCM_CAR (tmp);
321 if (del_len > 0)
322 {
323 memmove (p, SCM_STRING_CHARS (delimiter),
324 SCM_STRING_LENGTH (delimiter) * sizeof (char));
325 p += del_len;
326 }
327 memmove (p, SCM_STRING_CHARS (elt),
328 SCM_STRING_LENGTH (elt) * sizeof (char));
329 p += SCM_STRING_LENGTH (elt);
330 tmp = SCM_CDR (tmp);
331 }
332 break;
333 }
334 return result;
0f216433
TTN
335#undef GRAM_INFIX
336#undef GRAM_STRICT_INFIX
337#undef GRAM_SUFFIX
338#undef GRAM_PREFIX
ca003b26
MG
339}
340#undef FUNC_NAME
341
342
343SCM_DEFINE (scm_string_copyS, "string-copy", 1, 2, 0,
344 (SCM str, SCM start, SCM end),
345 "Return a freshly allocated copy of the string @var{str}. If\n"
346 "given, @var{start} and @var{end} delimit the portion of\n"
347 "@var{str} which is copied.")
348#define FUNC_NAME s_scm_string_copyS
349{
350 char * cstr;
351 int cstart, cend;
352
353 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
354 2, start, cstart,
355 3, end, cend);
36284627 356 return scm_mem2string (cstr + cstart, cend - cstart);
0f216433 357
ca003b26
MG
358}
359#undef FUNC_NAME
360
361
0f216433 362SCM_DEFINE (scm_substring_shared, "substring/shared", 2, 1, 0,
ca003b26
MG
363 (SCM str, SCM start, SCM end),
364 "Like @code{substring}, but the result may share memory with the\n"
365 "argument @var{str}.")
366#define FUNC_NAME s_scm_substring_shared
367{
1a161b8e 368 size_t s, e;
ca003b26 369 SCM_VALIDATE_STRING (1, str);
1a161b8e 370 s = scm_to_size_t (start);
ca003b26 371 if (SCM_UNBNDP (end))
1a161b8e 372 e = SCM_STRING_LENGTH (str);
ca003b26 373 else
1a161b8e
MV
374 e = scm_to_size_t (end);
375 if (s == 0 && e == SCM_STRING_LENGTH (str))
ca003b26 376 return str;
1a161b8e
MV
377 else
378 return scm_substring (str, start, end);
ca003b26
MG
379}
380#undef FUNC_NAME
381
382
0f216433 383SCM_DEFINE (scm_string_copy_x, "string-copy!", 3, 2, 0,
ca003b26
MG
384 (SCM target, SCM tstart, SCM s, SCM start, SCM end),
385 "Copy the sequence of characters from index range [@var{start},\n"
386 "@var{end}) in string @var{s} to string @var{target}, beginning\n"
387 "at index @var{tstart}. The characters are copied left-to-right\n"
388 "or right-to-left as needed -- the copy is guaranteed to work,\n"
389 "even if @var{target} and @var{s} are the same string. It is an\n"
390 "error if the copy operation runs off the end of the target\n"
391 "string.")
392#define FUNC_NAME s_scm_string_copy_x
393{
394 char * cstr, * ctarget;
395 int cstart, cend, ctstart, dummy;
396 int len;
397 SCM sdummy = SCM_UNDEFINED;
398
399 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, target, ctarget,
400 2, tstart, ctstart,
401 2, sdummy, dummy);
402 SCM_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cstr,
403 4, start, cstart,
404 5, end, cend);
405 len = cend - cstart;
406 SCM_ASSERT_RANGE (3, s, len <= SCM_STRING_LENGTH (target) - ctstart);
407
408 memmove (SCM_STRING_CHARS (target) + ctstart,
409 SCM_STRING_CHARS (s) + cstart,
410 len * sizeof (char));
411 return SCM_UNSPECIFIED;
412}
413#undef FUNC_NAME
414
415
0f216433 416SCM_DEFINE (scm_string_take, "string-take", 2, 0, 0,
ca003b26
MG
417 (SCM s, SCM n),
418 "Return the @var{n} first characters of @var{s}.")
419#define FUNC_NAME s_scm_string_take
420{
421 char * cstr;
1a161b8e 422 size_t cn;
ca003b26
MG
423
424 SCM_VALIDATE_STRING_COPY (1, s, cstr);
1a161b8e 425 cn = scm_to_unsigned_integer (n, 0, SCM_STRING_LENGTH (s));
0f216433 426
36284627 427 return scm_mem2string (cstr, cn);
ca003b26
MG
428}
429#undef FUNC_NAME
430
431
0f216433 432SCM_DEFINE (scm_string_drop, "string-drop", 2, 0, 0,
ca003b26
MG
433 (SCM s, SCM n),
434 "Return all but the first @var{n} characters of @var{s}.")
435#define FUNC_NAME s_scm_string_drop
436{
437 char * cstr;
1a161b8e 438 size_t cn;
ca003b26
MG
439
440 SCM_VALIDATE_STRING_COPY (1, s, cstr);
1a161b8e 441 cn = scm_to_unsigned_integer (n, 0, SCM_STRING_LENGTH (s));
0f216433 442
36284627 443 return scm_mem2string (cstr + cn, SCM_STRING_LENGTH (s) - cn);
ca003b26
MG
444}
445#undef FUNC_NAME
446
447
0f216433 448SCM_DEFINE (scm_string_take_right, "string-take-right", 2, 0, 0,
ca003b26
MG
449 (SCM s, SCM n),
450 "Return the @var{n} last characters of @var{s}.")
451#define FUNC_NAME s_scm_string_take_right
452{
453 char * cstr;
1a161b8e 454 size_t cn;
ca003b26
MG
455
456 SCM_VALIDATE_STRING_COPY (1, s, cstr);
1a161b8e 457 cn = scm_to_unsigned_integer (n, 0, SCM_STRING_LENGTH (s));
0f216433 458
36284627 459 return scm_mem2string (cstr + SCM_STRING_LENGTH (s) - cn, cn);
ca003b26
MG
460}
461#undef FUNC_NAME
462
463
0f216433 464SCM_DEFINE (scm_string_drop_right, "string-drop-right", 2, 0, 0,
ca003b26
MG
465 (SCM s, SCM n),
466 "Return all but the last @var{n} characters of @var{s}.")
467#define FUNC_NAME s_scm_string_drop_right
468{
469 char * cstr;
1a161b8e 470 size_t cn;
ca003b26
MG
471
472 SCM_VALIDATE_STRING_COPY (1, s, cstr);
1a161b8e 473 cn = scm_to_unsigned_integer (n, 0, SCM_STRING_LENGTH (s));
0f216433 474
36284627 475 return scm_mem2string (cstr, SCM_STRING_LENGTH (s) - cn);
ca003b26
MG
476}
477#undef FUNC_NAME
478
479
480SCM_DEFINE (scm_string_pad, "string-pad", 2, 3, 0,
481 (SCM s, SCM len, SCM chr, SCM start, SCM end),
482 "Take that characters from @var{start} to @var{end} from the\n"
483 "string @var{s} and return a new string, right-padded by the\n"
484 "character @var{chr} to length @var{len}. If the resulting\n"
485 "string is longer than @var{len}, it is truncated on the right.")
486#define FUNC_NAME s_scm_string_pad
487{
488 char cchr;
489 char * cstr;
1a161b8e 490 size_t cstart, cend, clen;
ca003b26
MG
491 SCM result;
492
493 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
494 4, start, cstart,
495 5, end, cend);
1a161b8e
MV
496 clen = scm_to_size_t (len);
497
ca003b26
MG
498 if (SCM_UNBNDP (chr))
499 cchr = ' ';
500 else
501 {
502 SCM_VALIDATE_CHAR (3, chr);
503 cchr = SCM_CHAR (chr);
504 }
505 result = scm_allocate_string (clen);
506 if (clen < (cend - cstart))
507 memmove (SCM_STRING_CHARS (result),
508 cstr + cend - clen,
509 clen * sizeof (char));
510 else
511 {
512 memset (SCM_STRING_CHARS (result), cchr,
513 (clen - (cend - cstart)) * sizeof (char));
514 memmove (SCM_STRING_CHARS (result) + (clen - (cend - cstart)),
515 cstr + cstart,
516 (cend - cstart) * sizeof (char));
517 }
518 return result;
519}
520#undef FUNC_NAME
521
522
523SCM_DEFINE (scm_string_pad_right, "string-pad-right", 2, 3, 0,
524 (SCM s, SCM len, SCM chr, SCM start, SCM end),
525 "Take that characters from @var{start} to @var{end} from the\n"
526 "string @var{s} and return a new string, left-padded by the\n"
527 "character @var{chr} to length @var{len}. If the resulting\n"
528 "string is longer than @var{len}, it is truncated on the left.")
529#define FUNC_NAME s_scm_string_pad_right
530{
531 char cchr;
532 char * cstr;
1a161b8e 533 size_t cstart, cend, clen;
ca003b26
MG
534 SCM result;
535
536 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
537 4, start, cstart,
538 5, end, cend);
1a161b8e
MV
539 clen = scm_to_size_t (len);
540
ca003b26
MG
541 if (SCM_UNBNDP (chr))
542 cchr = ' ';
543 else
544 {
545 SCM_VALIDATE_CHAR (3, chr);
546 cchr = SCM_CHAR (chr);
547 }
548 result = scm_allocate_string (clen);
549 if (clen < (cend - cstart))
550 memmove (SCM_STRING_CHARS (result), cstr + cstart, clen * sizeof (char));
551 else
552 {
553 memset (SCM_STRING_CHARS (result) + (cend - cstart),
554 cchr, (clen - (cend - cstart)) * sizeof (char));
555 memmove (SCM_STRING_CHARS (result), cstr + cstart,
556 (cend - cstart) * sizeof (char));
557 }
558 return result;
559}
560#undef FUNC_NAME
561
562
563SCM_DEFINE (scm_string_trim, "string-trim", 1, 3, 0,
564 (SCM s, SCM char_pred, SCM start, SCM end),
565 "Trim @var{s} by skipping over all characters on the left\n"
566 "that satisfy the parameter @var{char_pred}:\n"
567 "\n"
568 "@itemize @bullet\n"
569 "@item\n"
570 "if it is the character @var{ch}, characters equal to\n"
571 "@var{ch} are trimmed,\n"
572 "\n"
573 "@item\n"
574 "if it is a procedure @var{pred} characters that\n"
575 "satisfy @var{pred} are trimmed,\n"
576 "\n"
577 "@item\n"
578 "if it is a character set, characters in that set are trimmed.\n"
579 "@end itemize\n"
580 "\n"
581 "If called without a @var{char_pred} argument, all whitespace is\n"
582 "trimmed.")
583#define FUNC_NAME s_scm_string_trim
584{
585 char * cstr;
1a161b8e 586 size_t cstart, cend;
ca003b26
MG
587
588 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
589 3, start, cstart,
590 4, end, cend);
591 if (SCM_UNBNDP (char_pred))
592 {
593 while (cstart < cend)
594 {
597e2cbd 595 if (!isspace((int) (unsigned char) cstr[cstart]))
ca003b26
MG
596 break;
597 cstart++;
598 }
599 }
600 else if (SCM_CHARP (char_pred))
601 {
602 char chr = SCM_CHAR (char_pred);
603 while (cstart < cend)
604 {
605 if (chr != cstr[cstart])
606 break;
607 cstart++;
608 }
609 }
610 else if (SCM_CHARSETP (char_pred))
611 {
612 while (cstart < cend)
613 {
614 if (!SCM_CHARSET_GET (char_pred, cstr[cstart]))
615 break;
616 cstart++;
617 }
618 }
619 else
620 {
621 SCM_VALIDATE_PROC (2, char_pred);
622 while (cstart < cend)
623 {
624 SCM res;
625
2c4df451 626 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
00874d5f 627 if (scm_is_false (res))
ca003b26
MG
628 break;
629 cstart++;
630 }
631 }
36284627 632 return scm_mem2string (cstr + cstart, cend - cstart);
ca003b26
MG
633}
634#undef FUNC_NAME
635
636
637SCM_DEFINE (scm_string_trim_right, "string-trim-right", 1, 3, 0,
638 (SCM s, SCM char_pred, SCM start, SCM end),
639 "Trim @var{s} by skipping over all characters on the rightt\n"
640 "that satisfy the parameter @var{char_pred}:\n"
641 "\n"
642 "@itemize @bullet\n"
643 "@item\n"
644 "if it is the character @var{ch}, characters equal to @var{ch}\n"
645 "are trimmed,\n"
646 "\n"
647 "@item\n"
648 "if it is a procedure @var{pred} characters that satisfy\n"
649 "@var{pred} are trimmed,\n"
650 "\n"
651 "@item\n"
652 "if it is a character sets, all characters in that set are\n"
653 "trimmed.\n"
654 "@end itemize\n"
655 "\n"
656 "If called without a @var{char_pred} argument, all whitespace is\n"
657 "trimmed.")
658#define FUNC_NAME s_scm_string_trim_right
659{
660 char * cstr;
661 int cstart, cend;
662
663 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
664 3, start, cstart,
665 4, end, cend);
666 if (SCM_UNBNDP (char_pred))
667 {
668 while (cstart < cend)
669 {
597e2cbd 670 if (!isspace((int) (unsigned char) cstr[cend - 1]))
ca003b26
MG
671 break;
672 cend--;
673 }
674 }
675 else if (SCM_CHARP (char_pred))
676 {
677 char chr = SCM_CHAR (char_pred);
678 while (cstart < cend)
679 {
680 if (chr != cstr[cend - 1])
681 break;
682 cend--;
683 }
684 }
685 else if (SCM_CHARSETP (char_pred))
686 {
687 while (cstart < cend)
688 {
689 if (!SCM_CHARSET_GET (char_pred, cstr[cend - 1]))
690 break;
691 cend--;
692 }
693 }
694 else
695 {
696 SCM_VALIDATE_PROC (2, char_pred);
697 while (cstart < cend)
698 {
699 SCM res;
700
2c4df451 701 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cend - 1]));
00874d5f 702 if (scm_is_false (res))
ca003b26
MG
703 break;
704 cend--;
705 }
706 }
36284627 707 return scm_mem2string (cstr + cstart, cend - cstart);
ca003b26
MG
708}
709#undef FUNC_NAME
710
711
712SCM_DEFINE (scm_string_trim_both, "string-trim-both", 1, 3, 0,
713 (SCM s, SCM char_pred, SCM start, SCM end),
714 "Trim @var{s} by skipping over all characters on both sides of\n"
715 "the string that satisfy the parameter @var{char_pred}:\n"
716 "\n"
2d953700 717 "@itemize @bullet\n"
ca003b26
MG
718 "@item\n"
719 "if it is the character @var{ch}, characters equal to @var{ch}\n"
720 "are trimmed,\n"
721 "\n"
722 "@item\n"
723 "if it is a procedure @var{pred} characters that satisfy\n"
724 "@var{pred} are trimmed,\n"
725 "\n"
726 "@item\n"
727 "if it is a character set, the characters in the set are\n"
728 "trimmed.\n"
729 "@end itemize\n"
730 "\n"
731 "If called without a @var{char_pred} argument, all whitespace is\n"
732 "trimmed.")
733#define FUNC_NAME s_scm_string_trim_both
734{
735 char * cstr;
736 int cstart, cend;
737
738 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
739 3, start, cstart,
740 4, end, cend);
741 if (SCM_UNBNDP (char_pred))
742 {
743 while (cstart < cend)
744 {
597e2cbd 745 if (!isspace((int) (unsigned char) cstr[cstart]))
ca003b26
MG
746 break;
747 cstart++;
748 }
749 while (cstart < cend)
750 {
597e2cbd 751 if (!isspace((int) (unsigned char) cstr[cend - 1]))
ca003b26
MG
752 break;
753 cend--;
754 }
755 }
756 else if (SCM_CHARP (char_pred))
757 {
758 char chr = SCM_CHAR (char_pred);
759 while (cstart < cend)
760 {
761 if (chr != cstr[cstart])
762 break;
763 cstart++;
764 }
765 while (cstart < cend)
766 {
767 if (chr != cstr[cend - 1])
768 break;
769 cend--;
770 }
771 }
772 else if (SCM_CHARSETP (char_pred))
773 {
774 while (cstart < cend)
775 {
776 if (!SCM_CHARSET_GET (char_pred, cstr[cstart]))
777 break;
778 cstart++;
779 }
780 while (cstart < cend)
781 {
782 if (!SCM_CHARSET_GET (char_pred, cstr[cend - 1]))
783 break;
784 cend--;
785 }
786 }
787 else
788 {
789 SCM_VALIDATE_PROC (2, char_pred);
790 while (cstart < cend)
791 {
792 SCM res;
793
2c4df451 794 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
00874d5f 795 if (scm_is_false (res))
ca003b26
MG
796 break;
797 cstart++;
798 }
799 while (cstart < cend)
800 {
801 SCM res;
802
2c4df451 803 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cend - 1]));
00874d5f 804 if (scm_is_false (res))
ca003b26
MG
805 break;
806 cend--;
807 }
808 }
36284627 809 return scm_mem2string (cstr + cstart, cend - cstart);
ca003b26
MG
810}
811#undef FUNC_NAME
812
813
814SCM_DEFINE (scm_string_fill_xS, "string-fill!", 2, 2, 0,
815 (SCM str, SCM chr, SCM start, SCM end),
816 "Stores @var{chr} in every element of the given @var{str} and\n"
817 "returns an unspecified value.")
818#define FUNC_NAME s_scm_string_fill_xS
819{
820 char * cstr;
821 int cstart, cend;
822 int c;
823 long k;
824
825 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
826 3, start, cstart,
827 4, end, cend);
828 SCM_VALIDATE_CHAR_COPY (2, chr, c);
829 for (k = cstart; k < cend; k++)
830 cstr[k] = c;
831 return SCM_UNSPECIFIED;
832}
833#undef FUNC_NAME
834
835
836SCM_DEFINE (scm_string_compare, "string-compare", 5, 4, 0,
837 (SCM s1, SCM s2, SCM proc_lt, SCM proc_eq, SCM proc_gt, SCM start1, SCM end1, SCM start2, SCM end2),
838 "Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the\n"
839 "mismatch index, depending upon whether @var{s1} is less than,\n"
840 "equal to, or greater than @var{s2}. The mismatch index is the\n"
841 "largest index @var{i} such that for every 0 <= @var{j} <\n"
842 "@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is,\n"
843 "@var{i} is the first position that does not match.")
844#define FUNC_NAME s_scm_string_compare
845{
846 char * cstr1, * cstr2;
847 int cstart1, cend1, cstart2, cend2;
848
849 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
850 6, start1, cstart1,
851 7, end1, cend1);
852 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
853 8, start2, cstart2,
854 9, end2, cend2);
855 SCM_VALIDATE_PROC (3, proc_lt);
856 SCM_VALIDATE_PROC (4, proc_eq);
857 SCM_VALIDATE_PROC (5, proc_gt);
0f216433 858
ca003b26
MG
859 while (cstart1 < cend1 && cstart2 < cend2)
860 {
861 if (cstr1[cstart1] < cstr2[cstart2])
93ccaef0 862 return scm_call_1 (proc_lt, SCM_I_MAKINUM (cstart1));
ca003b26 863 else if (cstr1[cstart1] > cstr2[cstart2])
93ccaef0 864 return scm_call_1 (proc_gt, SCM_I_MAKINUM (cstart1));
ca003b26
MG
865 cstart1++;
866 cstart2++;
867 }
868 if (cstart1 < cend1)
93ccaef0 869 return scm_call_1 (proc_gt, SCM_I_MAKINUM (cstart1));
ca003b26 870 else if (cstart2 < cend2)
93ccaef0 871 return scm_call_1 (proc_lt, SCM_I_MAKINUM (cstart1));
ca003b26 872 else
93ccaef0 873 return scm_call_1 (proc_eq, SCM_I_MAKINUM (cstart1));
ca003b26
MG
874}
875#undef FUNC_NAME
876
877
878SCM_DEFINE (scm_string_compare_ci, "string-compare-ci", 5, 4, 0,
879 (SCM s1, SCM s2, SCM proc_lt, SCM proc_eq, SCM proc_gt, SCM start1, SCM end1, SCM start2, SCM end2),
880 "Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the\n"
881 "mismatch index, depending upon whether @var{s1} is less than,\n"
882 "equal to, or greater than @var{s2}. The mismatch index is the\n"
883 "largest index @var{i} such that for every 0 <= @var{j} <\n"
884 "@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is,\n"
885 "@var{i} is the first position that does not match. The\n"
886 "character comparison is done case-insensitively.")
887#define FUNC_NAME s_scm_string_compare_ci
888{
889 char * cstr1, * cstr2;
890 int cstart1, cend1, cstart2, cend2;
891
892 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
893 6, start1, cstart1,
894 7, end1, cend1);
895 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
896 8, start2, cstart2,
897 9, end2, cend2);
898 SCM_VALIDATE_PROC (3, proc_lt);
899 SCM_VALIDATE_PROC (4, proc_eq);
900 SCM_VALIDATE_PROC (5, proc_gt);
0f216433 901
ca003b26
MG
902 while (cstart1 < cend1 && cstart2 < cend2)
903 {
84fad130 904 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
93ccaef0 905 return scm_call_1 (proc_lt, SCM_I_MAKINUM (cstart1));
84fad130 906 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
93ccaef0 907 return scm_call_1 (proc_gt, SCM_I_MAKINUM (cstart1));
ca003b26
MG
908 cstart1++;
909 cstart2++;
910 }
911 if (cstart1 < cend1)
93ccaef0 912 return scm_call_1 (proc_gt, SCM_I_MAKINUM (cstart1));
ca003b26 913 else if (cstart2 < cend2)
93ccaef0 914 return scm_call_1 (proc_lt, SCM_I_MAKINUM (cstart1));
ca003b26 915 else
93ccaef0 916 return scm_call_1 (proc_eq, SCM_I_MAKINUM (cstart1));
ca003b26
MG
917}
918#undef FUNC_NAME
919
920
921SCM_DEFINE (scm_string_eq, "string=", 2, 4, 0,
922 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
923 "Return @code{#f} if @var{s1} and @var{s2} are not equal, a true\n"
924 "value otherwise.")
925#define FUNC_NAME s_scm_string_eq
926{
927 char * cstr1, * cstr2;
928 int cstart1, cend1, cstart2, cend2;
929
930 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
931 3, start1, cstart1,
932 4, end1, cend1);
933 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
934 5, start2, cstart2,
935 6, end2, cend2);
0f216433 936
ca003b26
MG
937 while (cstart1 < cend1 && cstart2 < cend2)
938 {
939 if (cstr1[cstart1] < cstr2[cstart2])
940 return SCM_BOOL_F;
941 else if (cstr1[cstart1] > cstr2[cstart2])
942 return SCM_BOOL_F;
943 cstart1++;
944 cstart2++;
945 }
946 if (cstart1 < cend1)
947 return SCM_BOOL_F;
948 else if (cstart2 < cend2)
949 return SCM_BOOL_F;
950 else
93ccaef0 951 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
952}
953#undef FUNC_NAME
954
955
956SCM_DEFINE (scm_string_neq, "string<>", 2, 4, 0,
957 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
958 "Return @code{#f} if @var{s1} and @var{s2} are equal, a true\n"
959 "value otherwise.")
960#define FUNC_NAME s_scm_string_neq
961{
962 char * cstr1, * cstr2;
963 int cstart1, cend1, cstart2, cend2;
964
965 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
966 3, start1, cstart1,
967 4, end1, cend1);
968 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
969 5, start2, cstart2,
970 6, end2, cend2);
0f216433 971
ca003b26
MG
972 while (cstart1 < cend1 && cstart2 < cend2)
973 {
974 if (cstr1[cstart1] < cstr2[cstart2])
93ccaef0 975 return SCM_I_MAKINUM (cstart1);
ca003b26 976 else if (cstr1[cstart1] > cstr2[cstart2])
93ccaef0 977 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
978 cstart1++;
979 cstart2++;
980 }
981 if (cstart1 < cend1)
93ccaef0 982 return SCM_I_MAKINUM (cstart1);
ca003b26 983 else if (cstart2 < cend2)
93ccaef0 984 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
985 else
986 return SCM_BOOL_F;
987}
988#undef FUNC_NAME
989
990
991SCM_DEFINE (scm_string_lt, "string<", 2, 4, 0,
992 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
993 "Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a\n"
994 "true value otherwise.")
995#define FUNC_NAME s_scm_string_lt
996{
997 char * cstr1, * cstr2;
998 int cstart1, cend1, cstart2, cend2;
999
1000 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1001 3, start1, cstart1,
1002 4, end1, cend1);
1003 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1004 5, start2, cstart2,
1005 6, end2, cend2);
0f216433 1006
ca003b26
MG
1007 while (cstart1 < cend1 && cstart2 < cend2)
1008 {
1009 if (cstr1[cstart1] < cstr2[cstart2])
93ccaef0 1010 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1011 else if (cstr1[cstart1] > cstr2[cstart2])
1012 return SCM_BOOL_F;
1013 cstart1++;
1014 cstart2++;
1015 }
1016 if (cstart1 < cend1)
1017 return SCM_BOOL_F;
1018 else if (cstart2 < cend2)
93ccaef0 1019 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1020 else
1021 return SCM_BOOL_F;
1022}
1023#undef FUNC_NAME
1024
1025
1026SCM_DEFINE (scm_string_gt, "string>", 2, 4, 0,
1027 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1028 "Return @code{#f} if @var{s1} is less or equal to @var{s2}, a\n"
1029 "true value otherwise.")
1030#define FUNC_NAME s_scm_string_gt
1031{
1032 char * cstr1, * cstr2;
1033 int cstart1, cend1, cstart2, cend2;
1034
1035 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1036 3, start1, cstart1,
1037 4, end1, cend1);
1038 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1039 5, start2, cstart2,
1040 6, end2, cend2);
0f216433 1041
ca003b26
MG
1042 while (cstart1 < cend1 && cstart2 < cend2)
1043 {
1044 if (cstr1[cstart1] < cstr2[cstart2])
1045 return SCM_BOOL_F;
1046 else if (cstr1[cstart1] > cstr2[cstart2])
93ccaef0 1047 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1048 cstart1++;
1049 cstart2++;
1050 }
1051 if (cstart1 < cend1)
93ccaef0 1052 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1053 else if (cstart2 < cend2)
1054 return SCM_BOOL_F;
1055 else
1056 return SCM_BOOL_F;
1057}
1058#undef FUNC_NAME
1059
1060
1061SCM_DEFINE (scm_string_le, "string<=", 2, 4, 0,
1062 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1063 "Return @code{#f} if @var{s1} is greater to @var{s2}, a true\n"
1064 "value otherwise.")
1065#define FUNC_NAME s_scm_string_le
1066{
1067 char * cstr1, * cstr2;
1068 int cstart1, cend1, cstart2, cend2;
1069
1070 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1071 3, start1, cstart1,
1072 4, end1, cend1);
1073 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1074 5, start2, cstart2,
1075 6, end2, cend2);
0f216433 1076
ca003b26
MG
1077 while (cstart1 < cend1 && cstart2 < cend2)
1078 {
1079 if (cstr1[cstart1] < cstr2[cstart2])
93ccaef0 1080 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1081 else if (cstr1[cstart1] > cstr2[cstart2])
1082 return SCM_BOOL_F;
1083 cstart1++;
1084 cstart2++;
1085 }
1086 if (cstart1 < cend1)
1087 return SCM_BOOL_F;
1088 else if (cstart2 < cend2)
93ccaef0 1089 return SCM_I_MAKINUM (cstart1);
ca003b26 1090 else
93ccaef0 1091 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1092}
1093#undef FUNC_NAME
1094
1095
1096SCM_DEFINE (scm_string_ge, "string>=", 2, 4, 0,
1097 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1098 "Return @code{#f} if @var{s1} is less to @var{s2}, a true value\n"
1099 "otherwise.")
1100#define FUNC_NAME s_scm_string_ge
1101{
1102 char * cstr1, * cstr2;
1103 int cstart1, cend1, cstart2, cend2;
1104
1105 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1106 3, start1, cstart1,
1107 4, end1, cend1);
1108 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1109 5, start2, cstart2,
1110 6, end2, cend2);
0f216433 1111
ca003b26
MG
1112 while (cstart1 < cend1 && cstart2 < cend2)
1113 {
1114 if (cstr1[cstart1] < cstr2[cstart2])
1115 return SCM_BOOL_F;
1116 else if (cstr1[cstart1] > cstr2[cstart2])
93ccaef0 1117 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1118 cstart1++;
1119 cstart2++;
1120 }
1121 if (cstart1 < cend1)
93ccaef0 1122 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1123 else if (cstart2 < cend2)
1124 return SCM_BOOL_F;
1125 else
93ccaef0 1126 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1127}
1128#undef FUNC_NAME
1129
1130
1131SCM_DEFINE (scm_string_ci_eq, "string-ci=", 2, 4, 0,
1132 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1133 "Return @code{#f} if @var{s1} and @var{s2} are not equal, a true\n"
1134 "value otherwise. The character comparison is done\n"
1135 "case-insensitively.")
1136#define FUNC_NAME s_scm_string_ci_eq
1137{
1138 char * cstr1, * cstr2;
1139 int cstart1, cend1, cstart2, cend2;
1140
1141 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1142 3, start1, cstart1,
1143 4, end1, cend1);
1144 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1145 5, start2, cstart2,
1146 6, end2, cend2);
0f216433 1147
ca003b26
MG
1148 while (cstart1 < cend1 && cstart2 < cend2)
1149 {
84fad130 1150 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
ca003b26 1151 return SCM_BOOL_F;
84fad130 1152 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
ca003b26
MG
1153 return SCM_BOOL_F;
1154 cstart1++;
1155 cstart2++;
1156 }
1157 if (cstart1 < cend1)
1158 return SCM_BOOL_F;
1159 else if (cstart2 < cend2)
1160 return SCM_BOOL_F;
1161 else
93ccaef0 1162 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1163}
1164#undef FUNC_NAME
1165
1166
1167SCM_DEFINE (scm_string_ci_neq, "string-ci<>", 2, 4, 0,
1168 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1169 "Return @code{#f} if @var{s1} and @var{s2} are equal, a true\n"
1170 "value otherwise. The character comparison is done\n"
1171 "case-insensitively.")
1172#define FUNC_NAME s_scm_string_ci_neq
1173{
1174 char * cstr1, * cstr2;
1175 int cstart1, cend1, cstart2, cend2;
1176
1177 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1178 3, start1, cstart1,
1179 4, end1, cend1);
1180 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1181 5, start2, cstart2,
1182 6, end2, cend2);
0f216433 1183
ca003b26
MG
1184 while (cstart1 < cend1 && cstart2 < cend2)
1185 {
84fad130 1186 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
93ccaef0 1187 return SCM_I_MAKINUM (cstart1);
84fad130 1188 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
93ccaef0 1189 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1190 cstart1++;
1191 cstart2++;
1192 }
1193 if (cstart1 < cend1)
93ccaef0 1194 return SCM_I_MAKINUM (cstart1);
ca003b26 1195 else if (cstart2 < cend2)
93ccaef0 1196 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1197 else
1198 return SCM_BOOL_F;
1199}
1200#undef FUNC_NAME
1201
1202
1203SCM_DEFINE (scm_string_ci_lt, "string-ci<", 2, 4, 0,
1204 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1205 "Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a\n"
1206 "true value otherwise. The character comparison is done\n"
1207 "case-insensitively.")
1208#define FUNC_NAME s_scm_string_ci_lt
1209{
1210 char * cstr1, * cstr2;
1211 int cstart1, cend1, cstart2, cend2;
1212
1213 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1214 3, start1, cstart1,
1215 4, end1, cend1);
1216 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1217 5, start2, cstart2,
1218 6, end2, cend2);
0f216433 1219
ca003b26
MG
1220 while (cstart1 < cend1 && cstart2 < cend2)
1221 {
84fad130 1222 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
93ccaef0 1223 return SCM_I_MAKINUM (cstart1);
84fad130 1224 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
ca003b26
MG
1225 return SCM_BOOL_F;
1226 cstart1++;
1227 cstart2++;
1228 }
1229 if (cstart1 < cend1)
1230 return SCM_BOOL_F;
1231 else if (cstart2 < cend2)
93ccaef0 1232 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1233 else
1234 return SCM_BOOL_F;
1235}
1236#undef FUNC_NAME
1237
1238
1239SCM_DEFINE (scm_string_ci_gt, "string-ci>", 2, 4, 0,
1240 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1241 "Return @code{#f} if @var{s1} is less or equal to @var{s2}, a\n"
1242 "true value otherwise. The character comparison is done\n"
1243 "case-insensitively.")
1244#define FUNC_NAME s_scm_string_ci_gt
1245{
1246 char * cstr1, * cstr2;
1247 int cstart1, cend1, cstart2, cend2;
1248
1249 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1250 3, start1, cstart1,
1251 4, end1, cend1);
1252 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1253 5, start2, cstart2,
1254 6, end2, cend2);
0f216433 1255
ca003b26
MG
1256 while (cstart1 < cend1 && cstart2 < cend2)
1257 {
84fad130 1258 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
ca003b26 1259 return SCM_BOOL_F;
84fad130 1260 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
93ccaef0 1261 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1262 cstart1++;
1263 cstart2++;
1264 }
1265 if (cstart1 < cend1)
93ccaef0 1266 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1267 else if (cstart2 < cend2)
1268 return SCM_BOOL_F;
1269 else
1270 return SCM_BOOL_F;
1271}
1272#undef FUNC_NAME
1273
1274
1275SCM_DEFINE (scm_string_ci_le, "string-ci<=", 2, 4, 0,
1276 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1277 "Return @code{#f} if @var{s1} is greater to @var{s2}, a true\n"
1278 "value otherwise. The character comparison is done\n"
1279 "case-insensitively.")
1280#define FUNC_NAME s_scm_string_ci_le
1281{
1282 char * cstr1, * cstr2;
1283 int cstart1, cend1, cstart2, cend2;
1284
1285 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1286 3, start1, cstart1,
1287 4, end1, cend1);
1288 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1289 5, start2, cstart2,
1290 6, end2, cend2);
0f216433 1291
ca003b26
MG
1292 while (cstart1 < cend1 && cstart2 < cend2)
1293 {
84fad130 1294 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
93ccaef0 1295 return SCM_I_MAKINUM (cstart1);
84fad130 1296 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
ca003b26
MG
1297 return SCM_BOOL_F;
1298 cstart1++;
1299 cstart2++;
1300 }
1301 if (cstart1 < cend1)
1302 return SCM_BOOL_F;
1303 else if (cstart2 < cend2)
93ccaef0 1304 return SCM_I_MAKINUM (cstart1);
ca003b26 1305 else
93ccaef0 1306 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1307}
1308#undef FUNC_NAME
1309
1310
1311SCM_DEFINE (scm_string_ci_ge, "string-ci>=", 2, 4, 0,
1312 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1313 "Return @code{#f} if @var{s1} is less to @var{s2}, a true value\n"
1314 "otherwise. The character comparison is done\n"
1315 "case-insensitively.")
1316#define FUNC_NAME s_scm_string_ci_ge
1317{
1318 char * cstr1, * cstr2;
1319 int cstart1, cend1, cstart2, cend2;
1320
1321 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1322 3, start1, cstart1,
1323 4, end1, cend1);
1324 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1325 5, start2, cstart2,
1326 6, end2, cend2);
0f216433 1327
ca003b26
MG
1328 while (cstart1 < cend1 && cstart2 < cend2)
1329 {
84fad130 1330 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
ca003b26 1331 return SCM_BOOL_F;
84fad130 1332 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
93ccaef0 1333 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1334 cstart1++;
1335 cstart2++;
1336 }
1337 if (cstart1 < cend1)
93ccaef0 1338 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1339 else if (cstart2 < cend2)
1340 return SCM_BOOL_F;
1341 else
93ccaef0 1342 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1343}
1344#undef FUNC_NAME
1345
1346
1347SCM_DEFINE (scm_string_prefix_length, "string-prefix-length", 2, 4, 0,
1348 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1349 "Return the length of the longest common prefix of the two\n"
1350 "strings.")
1351#define FUNC_NAME s_scm_string_prefix_length
1352{
1353 char * cstr1, * cstr2;
1354 int cstart1, cend1, cstart2, cend2;
1355 int len = 0;
1356
1357 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1358 3, start1, cstart1,
1359 4, end1, cend1);
1360 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1361 5, start2, cstart2,
1362 6, end2, cend2);
1363 while (cstart1 < cend1 && cstart2 < cend2)
1364 {
1365 if (cstr1[cstart1] != cstr2[cstart2])
93ccaef0 1366 return SCM_I_MAKINUM (len);
ca003b26
MG
1367 len++;
1368 cstart1++;
1369 cstart2++;
1370 }
93ccaef0 1371 return SCM_I_MAKINUM (len);
ca003b26
MG
1372}
1373#undef FUNC_NAME
1374
1375
1376SCM_DEFINE (scm_string_prefix_length_ci, "string-prefix-length-ci", 2, 4, 0,
1377 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1378 "Return the length of the longest common prefix of the two\n"
1379 "strings, ignoring character case.")
1380#define FUNC_NAME s_scm_string_prefix_length_ci
1381{
1382 char * cstr1, * cstr2;
1383 int cstart1, cend1, cstart2, cend2;
1384 int len = 0;
1385
1386 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1387 3, start1, cstart1,
1388 4, end1, cend1);
1389 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1390 5, start2, cstart2,
1391 6, end2, cend2);
1392 while (cstart1 < cend1 && cstart2 < cend2)
1393 {
84fad130 1394 if (scm_c_downcase (cstr1[cstart1]) != scm_c_downcase (cstr2[cstart2]))
93ccaef0 1395 return SCM_I_MAKINUM (len);
ca003b26
MG
1396 len++;
1397 cstart1++;
1398 cstart2++;
1399 }
93ccaef0 1400 return SCM_I_MAKINUM (len);
ca003b26
MG
1401}
1402#undef FUNC_NAME
1403
1404
1405SCM_DEFINE (scm_string_suffix_length, "string-suffix-length", 2, 4, 0,
1406 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1407 "Return the length of the longest common suffix of the two\n"
1408 "strings.")
1409#define FUNC_NAME s_scm_string_suffix_length
1410{
1411 char * cstr1, * cstr2;
1412 int cstart1, cend1, cstart2, cend2;
1413 int len = 0;
1414
1415 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1416 3, start1, cstart1,
1417 4, end1, cend1);
1418 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1419 5, start2, cstart2,
1420 6, end2, cend2);
1421 while (cstart1 < cend1 && cstart2 < cend2)
1422 {
1423 cend1--;
1424 cend2--;
1425 if (cstr1[cend1] != cstr2[cend2])
93ccaef0 1426 return SCM_I_MAKINUM (len);
ca003b26
MG
1427 len++;
1428 }
93ccaef0 1429 return SCM_I_MAKINUM (len);
ca003b26
MG
1430}
1431#undef FUNC_NAME
1432
1433
1434SCM_DEFINE (scm_string_suffix_length_ci, "string-suffix-length-ci", 2, 4, 0,
1435 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1436 "Return the length of the longest common suffix of the two\n"
1437 "strings, ignoring character case.")
1438#define FUNC_NAME s_scm_string_suffix_length_ci
1439{
1440 char * cstr1, * cstr2;
1441 int cstart1, cend1, cstart2, cend2;
1442 int len = 0;
1443
1444 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1445 3, start1, cstart1,
1446 4, end1, cend1);
1447 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1448 5, start2, cstart2,
1449 6, end2, cend2);
1450 while (cstart1 < cend1 && cstart2 < cend2)
1451 {
1452 cend1--;
1453 cend2--;
84fad130 1454 if (scm_c_downcase (cstr1[cend1]) != scm_c_downcase (cstr2[cend2]))
93ccaef0 1455 return SCM_I_MAKINUM (len);
ca003b26
MG
1456 len++;
1457 }
93ccaef0 1458 return SCM_I_MAKINUM (len);
ca003b26
MG
1459}
1460#undef FUNC_NAME
1461
1462
1463SCM_DEFINE (scm_string_prefix_p, "string-prefix?", 2, 4, 0,
1464 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1465 "Is @var{s1} a prefix of @var{s2}?")
1466#define FUNC_NAME s_scm_string_prefix_p
1467{
1468 char * cstr1, * cstr2;
1469 int cstart1, cend1, cstart2, cend2;
1470 int len = 0, len1;
1471
1472 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1473 3, start1, cstart1,
1474 4, end1, cend1);
1475 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1476 5, start2, cstart2,
1477 6, end2, cend2);
1478 len1 = cend1 - cstart1;
1479 while (cstart1 < cend1 && cstart2 < cend2)
1480 {
1481 if (cstr1[cstart1] != cstr2[cstart2])
00874d5f 1482 return scm_from_bool (len == len1);
ca003b26
MG
1483 len++;
1484 cstart1++;
1485 cstart2++;
1486 }
00874d5f 1487 return scm_from_bool (len == len1);
ca003b26
MG
1488}
1489#undef FUNC_NAME
1490
1491
1492SCM_DEFINE (scm_string_prefix_ci_p, "string-prefix-ci?", 2, 4, 0,
1493 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1494 "Is @var{s1} a prefix of @var{s2}, ignoring character case?")
1495#define FUNC_NAME s_scm_string_prefix_ci_p
1496{
1497 char * cstr1, * cstr2;
1498 int cstart1, cend1, cstart2, cend2;
1499 int len = 0, len1;
1500
1501 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1502 3, start1, cstart1,
1503 4, end1, cend1);
1504 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1505 5, start2, cstart2,
1506 6, end2, cend2);
1507 len1 = cend1 - cstart1;
1508 while (cstart1 < cend1 && cstart2 < cend2)
1509 {
84fad130 1510 if (scm_c_downcase (cstr1[cstart1]) != scm_c_downcase (cstr2[cstart2]))
00874d5f 1511 return scm_from_bool (len == len1);
ca003b26
MG
1512 len++;
1513 cstart1++;
1514 cstart2++;
1515 }
00874d5f 1516 return scm_from_bool (len == len1);
ca003b26
MG
1517}
1518#undef FUNC_NAME
1519
1520
1521SCM_DEFINE (scm_string_suffix_p, "string-suffix?", 2, 4, 0,
1522 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1523 "Is @var{s1} a suffix of @var{s2}?")
1524#define FUNC_NAME s_scm_string_suffix_p
1525{
1526 char * cstr1, * cstr2;
1527 int cstart1, cend1, cstart2, cend2;
1528 int len = 0, len1;
1529
1530 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1531 3, start1, cstart1,
1532 4, end1, cend1);
1533 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1534 5, start2, cstart2,
1535 6, end2, cend2);
1536 len1 = cend1 - cstart1;
1537 while (cstart1 < cend1 && cstart2 < cend2)
1538 {
1539 cend1--;
1540 cend2--;
1541 if (cstr1[cend1] != cstr2[cend2])
00874d5f 1542 return scm_from_bool (len == len1);
ca003b26
MG
1543 len++;
1544 }
00874d5f 1545 return scm_from_bool (len == len1);
ca003b26
MG
1546}
1547#undef FUNC_NAME
1548
1549
1550SCM_DEFINE (scm_string_suffix_ci_p, "string-suffix-ci?", 2, 4, 0,
1551 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1552 "Is @var{s1} a suffix of @var{s2}, ignoring character case?")
1553#define FUNC_NAME s_scm_string_suffix_ci_p
1554{
1555 char * cstr1, * cstr2;
1556 int cstart1, cend1, cstart2, cend2;
1557 int len = 0, len1;
1558
1559 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1560 3, start1, cstart1,
1561 4, end1, cend1);
1562 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1563 5, start2, cstart2,
1564 6, end2, cend2);
1565 len1 = cend1 - cstart1;
1566 while (cstart1 < cend1 && cstart2 < cend2)
1567 {
1568 cend1--;
1569 cend2--;
84fad130 1570 if (scm_c_downcase (cstr1[cend1]) != scm_c_downcase (cstr2[cend2]))
00874d5f 1571 return scm_from_bool (len == len1);
ca003b26
MG
1572 len++;
1573 }
00874d5f 1574 return scm_from_bool (len == len1);
ca003b26
MG
1575}
1576#undef FUNC_NAME
1577
1578
1579/* FIXME::martin: The `S' is to avoid a name clash with the procedure
1580 in the core, which does not accept a predicate. */
1581SCM_DEFINE (scm_string_indexS, "string-index", 2, 2, 0,
1582 (SCM s, SCM char_pred, SCM start, SCM end),
1583 "Search through the string @var{s} from left to right, returning\n"
1584 "the index of the first occurence of a character which\n"
1585 "\n"
2d953700 1586 "@itemize @bullet\n"
ca003b26
MG
1587 "@item\n"
1588 "equals @var{char_pred}, if it is character,\n"
1589 "\n"
1590 "@item\n"
1591 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
1592 "\n"
1593 "@item\n"
1594 "is in the set @var{char_pred}, if it is a character set.\n"
1595 "@end itemize")
1596#define FUNC_NAME s_scm_string_indexS
1597{
1598 char * cstr;
1599 int cstart, cend;
1600
1601 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
1602 3, start, cstart,
1603 4, end, cend);
1604 if (SCM_CHARP (char_pred))
1605 {
1606 char cchr = SCM_CHAR (char_pred);
1607 while (cstart < cend)
1608 {
1609 if (cchr == cstr[cstart])
93ccaef0 1610 return SCM_I_MAKINUM (cstart);
ca003b26
MG
1611 cstart++;
1612 }
1613 }
1614 else if (SCM_CHARSETP (char_pred))
1615 {
1616 while (cstart < cend)
1617 {
1618 if (SCM_CHARSET_GET (char_pred, cstr[cstart]))
93ccaef0 1619 return SCM_I_MAKINUM (cstart);
ca003b26
MG
1620 cstart++;
1621 }
1622 }
1623 else
1624 {
1625 SCM_VALIDATE_PROC (2, char_pred);
1626 while (cstart < cend)
1627 {
1628 SCM res;
2c4df451 1629 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
00874d5f 1630 if (scm_is_true (res))
93ccaef0 1631 return SCM_I_MAKINUM (cstart);
ca003b26
MG
1632 cstart++;
1633 }
1634 }
1635 return SCM_BOOL_F;
1636}
1637#undef FUNC_NAME
1638
1639
1640SCM_DEFINE (scm_string_index_right, "string-index-right", 2, 2, 0,
1641 (SCM s, SCM char_pred, SCM start, SCM end),
1642 "Search through the string @var{s} from right to left, returning\n"
1643 "the index of the last occurence of a character which\n"
1644 "\n"
1645 "@itemize @bullet\n"
1646 "@item\n"
1647 "equals @var{char_pred}, if it is character,\n"
1648 "\n"
1649 "@item\n"
1650 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
1651 "\n"
1652 "@item\n"
1653 "is in the set if @var{char_pred} is a character set.\n"
1654 "@end itemize")
1655#define FUNC_NAME s_scm_string_index_right
1656{
1657 char * cstr;
1658 int cstart, cend;
1659
1660 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
1661 3, start, cstart,
1662 4, end, cend);
1663 if (SCM_CHARP (char_pred))
1664 {
1665 char cchr = SCM_CHAR (char_pred);
1666 while (cstart < cend)
1667 {
1668 cend--;
1669 if (cchr == cstr[cend])
93ccaef0 1670 return SCM_I_MAKINUM (cend);
ca003b26
MG
1671 }
1672 }
1673 else if (SCM_CHARSETP (char_pred))
1674 {
1675 while (cstart < cend)
1676 {
1677 cend--;
1678 if (SCM_CHARSET_GET (char_pred, cstr[cend]))
93ccaef0 1679 return SCM_I_MAKINUM (cend);
ca003b26
MG
1680 }
1681 }
1682 else
1683 {
1684 SCM_VALIDATE_PROC (2, char_pred);
1685 while (cstart < cend)
1686 {
1687 SCM res;
1688 cend--;
2c4df451 1689 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cend]));
00874d5f 1690 if (scm_is_true (res))
93ccaef0 1691 return SCM_I_MAKINUM (cend);
ca003b26
MG
1692 }
1693 }
0f216433 1694 return SCM_BOOL_F;
ca003b26
MG
1695}
1696#undef FUNC_NAME
1697
1698
1699SCM_DEFINE (scm_string_skip, "string-skip", 2, 2, 0,
1700 (SCM s, SCM char_pred, SCM start, SCM end),
1701 "Search through the string @var{s} from left to right, returning\n"
1702 "the index of the first occurence of a character which\n"
1703 "\n"
1704 "@itemize @bullet\n"
1705 "@item\n"
1706 "does not equal @var{char_pred}, if it is character,\n"
1707 "\n"
1708 "@item\n"
1709 "does not satisify the predicate @var{char_pred}, if it is a\n"
1710 "procedure,\n"
1711 "\n"
1712 "@item\n"
1713 "is not in the set if @var{char_pred} is a character set.\n"
1714 "@end itemize")
1715#define FUNC_NAME s_scm_string_skip
1716{
1717 char * cstr;
1718 int cstart, cend;
1719
1720 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
1721 3, start, cstart,
1722 4, end, cend);
1723 if (SCM_CHARP (char_pred))
1724 {
1725 char cchr = SCM_CHAR (char_pred);
1726 while (cstart < cend)
1727 {
1728 if (cchr != cstr[cstart])
93ccaef0 1729 return SCM_I_MAKINUM (cstart);
ca003b26
MG
1730 cstart++;
1731 }
1732 }
1733 else if (SCM_CHARSETP (char_pred))
1734 {
1735 while (cstart < cend)
1736 {
1737 if (!SCM_CHARSET_GET (char_pred, cstr[cstart]))
93ccaef0 1738 return SCM_I_MAKINUM (cstart);
ca003b26
MG
1739 cstart++;
1740 }
1741 }
1742 else
1743 {
1744 SCM_VALIDATE_PROC (2, char_pred);
1745 while (cstart < cend)
1746 {
1747 SCM res;
2c4df451 1748 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
00874d5f 1749 if (scm_is_false (res))
93ccaef0 1750 return SCM_I_MAKINUM (cstart);
ca003b26
MG
1751 cstart++;
1752 }
1753 }
1754 return SCM_BOOL_F;
1755}
1756#undef FUNC_NAME
1757
1758
1759SCM_DEFINE (scm_string_skip_right, "string-skip-right", 2, 2, 0,
1760 (SCM s, SCM char_pred, SCM start, SCM end),
1761 "Search through the string @var{s} from right to left, returning\n"
1762 "the index of the last occurence of a character which\n"
1763 "\n"
1764 "@itemize @bullet\n"
1765 "@item\n"
1766 "does not equal @var{char_pred}, if it is character,\n"
1767 "\n"
1768 "@item\n"
1769 "does not satisifie the predicate @var{char_pred}, if it is a\n"
1770 "procedure,\n"
1771 "\n"
1772 "@item\n"
1773 "is not in the set if @var{char_pred} is a character set.\n"
1774 "@end itemize")
1775#define FUNC_NAME s_scm_string_skip_right
1776{
1777 char * cstr;
1778 int cstart, cend;
1779
1780 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
1781 3, start, cstart,
1782 4, end, cend);
1783 if (SCM_CHARP (char_pred))
1784 {
1785 char cchr = SCM_CHAR (char_pred);
1786 while (cstart < cend)
1787 {
1788 cend--;
1789 if (cchr != cstr[cend])
93ccaef0 1790 return SCM_I_MAKINUM (cend);
ca003b26
MG
1791 }
1792 }
1793 else if (SCM_CHARSETP (char_pred))
1794 {
1795 while (cstart < cend)
1796 {
1797 cend--;
1798 if (!SCM_CHARSET_GET (char_pred, cstr[cend]))
93ccaef0 1799 return SCM_I_MAKINUM (cend);
ca003b26
MG
1800 }
1801 }
1802 else
1803 {
1804 SCM_VALIDATE_PROC (2, char_pred);
1805 while (cstart < cend)
1806 {
1807 SCM res;
1808 cend--;
2c4df451 1809 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cend]));
00874d5f 1810 if (scm_is_false (res))
93ccaef0 1811 return SCM_I_MAKINUM (cend);
ca003b26
MG
1812 }
1813 }
0f216433 1814 return SCM_BOOL_F;
ca003b26
MG
1815}
1816#undef FUNC_NAME
1817
1818
1819SCM_DEFINE (scm_string_count, "string-count", 2, 2, 0,
1820 (SCM s, SCM char_pred, SCM start, SCM end),
1821 "Return the count of the number of characters in the string\n"
1822 "@var{s} which\n"
1823 "\n"
1824 "@itemize @bullet\n"
1825 "@item\n"
1826 "equals @var{char_pred}, if it is character,\n"
1827 "\n"
1828 "@item\n"
1829 "satisifies the predicate @var{char_pred}, if it is a procedure.\n"
1830 "\n"
1831 "@item\n"
1832 "is in the set @var{char_pred}, if it is a character set.\n"
1833 "@end itemize")
1834#define FUNC_NAME s_scm_string_count
1835{
1836 char * cstr;
1837 int cstart, cend;
1838 int count = 0;
1839
1840 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
1841 3, start, cstart,
1842 4, end, cend);
1843 if (SCM_CHARP (char_pred))
1844 {
1845 char cchr = SCM_CHAR (char_pred);
1846 while (cstart < cend)
1847 {
1848 if (cchr == cstr[cstart])
1849 count++;
1850 cstart++;
1851 }
1852 }
1853 else if (SCM_CHARSETP (char_pred))
1854 {
1855 while (cstart < cend)
1856 {
1857 if (SCM_CHARSET_GET (char_pred, cstr[cstart]))
1858 count++;
1859 cstart++;
1860 }
1861 }
1862 else
1863 {
1864 SCM_VALIDATE_PROC (2, char_pred);
1865 while (cstart < cend)
1866 {
1867 SCM res;
2c4df451 1868 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
00874d5f 1869 if (scm_is_true (res))
ca003b26
MG
1870 count++;
1871 cstart++;
1872 }
1873 }
93ccaef0 1874 return SCM_I_MAKINUM (count);
ca003b26
MG
1875}
1876#undef FUNC_NAME
1877
1878
1879/* FIXME::martin: This should definitely get implemented more
1880 efficiently -- maybe with Knuth-Morris-Pratt, like in the reference
1881 implementation. */
1882SCM_DEFINE (scm_string_contains, "string-contains", 2, 4, 0,
1883 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1884 "Does string @var{s1} contain string @var{s2}? Return the index\n"
1885 "in @var{s1} where @var{s2} occurs as a substring, or false.\n"
1886 "The optional start/end indices restrict the operation to the\n"
1887 "indicated substrings.")
1888#define FUNC_NAME s_scm_string_contains
1889{
1890 char * cs1, * cs2;
1891 int cstart1, cend1, cstart2, cend2;
1892 int len2, i, j;
1893
1894 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cs1,
1895 3, start1, cstart1,
1896 4, end1, cend1);
1897 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cs2,
1898 5, start2, cstart2,
1899 6, end2, cend2);
1900 len2 = cend2 - cstart2;
1901 while (cstart1 <= cend1 - len2)
1902 {
1903 i = cstart1;
1904 j = cstart2;
1905 while (i < cend1 && j < cend2 && cs1[i] == cs2[j])
1906 {
1907 i++;
1908 j++;
1909 }
1910 if (j == cend2)
93ccaef0 1911 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1912 cstart1++;
1913 }
1914 return SCM_BOOL_F;
1915}
1916#undef FUNC_NAME
1917
1918
1919/* FIXME::martin: This should definitely get implemented more
1920 efficiently -- maybe with Knuth-Morris-Pratt, like in the reference
1921 implementation. */
1922SCM_DEFINE (scm_string_contains_ci, "string-contains-ci", 2, 4, 0,
1923 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1924 "Does string @var{s1} contain string @var{s2}? Return the index\n"
1925 "in @var{s1} where @var{s2} occurs as a substring, or false.\n"
1926 "The optional start/end indices restrict the operation to the\n"
1927 "indicated substrings. Character comparison is done\n"
1928 "case-insensitively.")
1929#define FUNC_NAME s_scm_string_contains_ci
1930{
1931 char * cs1, * cs2;
1932 int cstart1, cend1, cstart2, cend2;
1933 int len2, i, j;
1934
1935 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cs1,
1936 3, start1, cstart1,
1937 4, end1, cend1);
1938 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cs2,
1939 5, start2, cstart2,
1940 6, end2, cend2);
1941 len2 = cend2 - cstart2;
1942 while (cstart1 <= cend1 - len2)
1943 {
1944 i = cstart1;
1945 j = cstart2;
1946 while (i < cend1 && j < cend2 &&
84fad130 1947 scm_c_downcase (cs1[i]) == scm_c_downcase (cs2[j]))
ca003b26
MG
1948 {
1949 i++;
1950 j++;
1951 }
1952 if (j == cend2)
93ccaef0 1953 return SCM_I_MAKINUM (cstart1);
ca003b26
MG
1954 cstart1++;
1955 }
1956 return SCM_BOOL_F;
1957}
1958#undef FUNC_NAME
1959
1960
0f216433 1961/* Helper function for the string uppercase conversion functions.
ca003b26
MG
1962 * No argument checking is performed. */
1963static SCM
1964string_upcase_x (SCM v, int start, int end)
1965{
1966 unsigned long k;
1967
1968 for (k = start; k < end; ++k)
84fad130 1969 SCM_STRING_UCHARS (v) [k] = scm_c_upcase (SCM_STRING_UCHARS (v) [k]);
ca003b26
MG
1970
1971 return v;
1972}
1973
1974
1975/* FIXME::martin: The `S' is to avoid a name clash with the procedure
1976 in the core, which does not accept start/end indices */
0f216433 1977SCM_DEFINE (scm_string_upcase_xS, "string-upcase!", 1, 2, 0,
ca003b26
MG
1978 (SCM str, SCM start, SCM end),
1979 "Destructively upcase every character in @code{str}.\n"
1980 "\n"
1981 "@lisp\n"
1982 "(string-upcase! y)\n"
1983 "@result{} \"ARRDEFG\"\n"
1984 "y\n"
1985 "@result{} \"ARRDEFG\"\n"
1986 "@end lisp")
1987#define FUNC_NAME s_scm_string_upcase_xS
1988{
1989 char * cstr;
1990 int cstart, cend;
1991
1992 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
1993 2, start, cstart,
1994 3, end, cend);
1995 return string_upcase_x (str, cstart, cend);
1996}
1997#undef FUNC_NAME
1998
1999
2000/* FIXME::martin: The `S' is to avoid a name clash with the procedure
2001 in the core, which does not accept start/end indices */
0f216433 2002SCM_DEFINE (scm_string_upcaseS, "string-upcase", 1, 2, 0,
ca003b26
MG
2003 (SCM str, SCM start, SCM end),
2004 "Upcase every character in @code{str}.")
2005#define FUNC_NAME s_scm_string_upcaseS
2006{
2007 char * cstr;
2008 int cstart, cend;
2009
2010 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2011 2, start, cstart,
2012 3, end, cend);
2013 return string_upcase_x (scm_string_copy (str), cstart, cend);
2014}
2015#undef FUNC_NAME
2016
2017
0f216433 2018/* Helper function for the string lowercase conversion functions.
ca003b26
MG
2019 * No argument checking is performed. */
2020static SCM
2021string_downcase_x (SCM v, int start, int end)
2022{
2023 unsigned long k;
2024
2025 for (k = start; k < end; ++k)
84fad130 2026 SCM_STRING_UCHARS (v) [k] = scm_c_downcase (SCM_STRING_UCHARS (v) [k]);
ca003b26
MG
2027
2028 return v;
2029}
2030
2031
2032/* FIXME::martin: The `S' is to avoid a name clash with the procedure
2033 in the core, which does not accept start/end indices */
0f216433 2034SCM_DEFINE (scm_string_downcase_xS, "string-downcase!", 1, 2, 0,
ca003b26
MG
2035 (SCM str, SCM start, SCM end),
2036 "Destructively downcase every character in @var{str}.\n"
2037 "\n"
2038 "@lisp\n"
2039 "y\n"
2040 "@result{} \"ARRDEFG\"\n"
2041 "(string-downcase! y)\n"
2042 "@result{} \"arrdefg\"\n"
2043 "y\n"
2044 "@result{} \"arrdefg\"\n"
2045 "@end lisp")
2046#define FUNC_NAME s_scm_string_downcase_xS
2047{
2048 char * cstr;
2049 int cstart, cend;
2050
2051 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2052 2, start, cstart,
2053 3, end, cend);
2054 return string_downcase_x (str, cstart, cend);
2055}
2056#undef FUNC_NAME
2057
2058
2059/* FIXME::martin: The `S' is to avoid a name clash with the procedure
2060 in the core, which does not accept start/end indices */
0f216433 2061SCM_DEFINE (scm_string_downcaseS, "string-downcase", 1, 2, 0,
ca003b26
MG
2062 (SCM str, SCM start, SCM end),
2063 "Downcase every character in @var{str}.")
2064#define FUNC_NAME s_scm_string_downcaseS
2065{
2066 char * cstr;
2067 int cstart, cend;
2068
2069 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2070 2, start, cstart,
2071 3, end, cend);
2072 return string_downcase_x (scm_string_copy (str), cstart, cend);
2073}
2074#undef FUNC_NAME
2075
2076
0f216433 2077/* Helper function for the string capitalization functions.
ca003b26
MG
2078 * No argument checking is performed. */
2079static SCM
2080string_titlecase_x (SCM str, int start, int end)
2081{
bd7c7fc6 2082 unsigned char * sz;
ca003b26
MG
2083 int i, in_word = 0;
2084
bd7c7fc6 2085 sz = SCM_STRING_UCHARS (str);
ca003b26
MG
2086 for(i = start; i < end; i++)
2087 {
00874d5f 2088 if (scm_is_true (scm_char_alphabetic_p (SCM_MAKE_CHAR (sz[i]))))
ca003b26
MG
2089 {
2090 if (!in_word)
2091 {
84fad130 2092 sz[i] = scm_c_upcase(sz[i]);
ca003b26
MG
2093 in_word = 1;
2094 }
2095 else
2096 {
84fad130 2097 sz[i] = scm_c_downcase(sz[i]);
ca003b26
MG
2098 }
2099 }
2100 else
2101 in_word = 0;
2102 }
2103 return str;
2104}
2105
2106
0f216433 2107SCM_DEFINE (scm_string_titlecase_x, "string-titlecase!", 1, 2, 0,
ca003b26
MG
2108 (SCM str, SCM start, SCM end),
2109 "Destructively titlecase every first character in a word in\n"
2110 "@var{str}.")
2111#define FUNC_NAME s_scm_string_titlecase_x
2112{
2113 char * cstr;
2114 int cstart, cend;
2115
2116 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2117 2, start, cstart,
2118 3, end, cend);
2119 return string_titlecase_x (str, cstart, cend);
2120}
2121#undef FUNC_NAME
2122
2123
0f216433 2124SCM_DEFINE (scm_string_titlecase, "string-titlecase", 1, 2, 0,
ca003b26
MG
2125 (SCM str, SCM start, SCM end),
2126 "Titlecase every first character in a word in @var{str}.")
2127#define FUNC_NAME s_scm_string_titlecase
2128{
2129 char * cstr;
2130 int cstart, cend;
2131
2132 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2133 2, start, cstart,
2134 3, end, cend);
2135 return string_titlecase_x (scm_string_copy (str), cstart, cend);
2136}
2137#undef FUNC_NAME
2138
2139
2140/* Reverse the portion of @var{str} between str[cstart] (including)
2141 and str[cend] excluding. */
2142static void
2143string_reverse_x (char * str, int cstart, int cend)
2144{
2145 char tmp;
2146
2147 cend--;
2148 while (cstart < cend)
2149 {
2150 tmp = str[cstart];
2151 str[cstart] = str[cend];
2152 str[cend] = tmp;
2153 cstart++;
2154 cend--;
2155 }
2156}
2157
2158
0f216433 2159SCM_DEFINE (scm_string_reverse, "string-reverse", 1, 2, 0,
ca003b26
MG
2160 (SCM str, SCM start, SCM end),
2161 "Reverse the string @var{str}. The optional arguments\n"
2162 "@var{start} and @var{end} delimit the region of @var{str} to\n"
2163 "operate on.")
2164#define FUNC_NAME s_scm_string_reverse
2165{
2166 char * cstr;
2167 int cstart;
2168 int cend;
2169 SCM result;
2170
2171 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2172 2, start, cstart,
2173 3, end, cend);
2174 result = scm_string_copy (str);
2175 string_reverse_x (SCM_STRING_CHARS (result), cstart, cend);
2176 return result;
2177}
2178#undef FUNC_NAME
2179
2180
0f216433 2181SCM_DEFINE (scm_string_reverse_x, "string-reverse!", 1, 2, 0,
ca003b26
MG
2182 (SCM str, SCM start, SCM end),
2183 "Reverse the string @var{str} in-place. The optional arguments\n"
2184 "@var{start} and @var{end} delimit the region of @var{str} to\n"
2185 "operate on. The return value is unspecified.")
2186#define FUNC_NAME s_scm_string_reverse_x
2187{
2188 char * cstr;
2189 int cstart;
2190 int cend;
2191
2192 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2193 2, start, cstart,
2194 3, end, cend);
2195 string_reverse_x (SCM_STRING_CHARS (str), cstart, cend);
2196 return SCM_UNSPECIFIED;
2197}
2198#undef FUNC_NAME
2199
2200
0f216433 2201SCM_DEFINE (scm_string_append_shared, "string-append/shared", 0, 0, 1,
ca003b26
MG
2202 (SCM ls),
2203 "Like @code{string-append}, but the result may share memory\n"
2204 "with the argument strings.")
2205#define FUNC_NAME s_scm_string_append_shared
2206{
2207 long i;
2208
2209 SCM_VALIDATE_REST_ARGUMENT (ls);
2210
2211 /* Optimize the one-argument case. */
2212 i = scm_ilength (ls);
2213 if (i == 1)
2214 return SCM_CAR (ls);
2215 else
2216 return scm_string_append (ls);
2217}
2218#undef FUNC_NAME
2219
2220
0f216433 2221SCM_DEFINE (scm_string_concatenate, "string-concatenate", 1, 0, 0,
ca003b26
MG
2222 (SCM ls),
2223 "Append the elements of @var{ls} (which must be strings)\n"
2224 "together into a single string. Guaranteed to return a freshly\n"
2225 "allocated string.")
2226#define FUNC_NAME s_scm_string_concatenate
2227{
2228 long strings = scm_ilength (ls);
2229 SCM tmp, result;
2230 int len = 0;
2231 char * p;
2232
2233 /* Validate the string list. */
2234 if (strings < 0)
2235 SCM_WRONG_TYPE_ARG (1, ls);
2236
2237 /* Calculate the size of the result string. */
2238 tmp = ls;
2239 while (!SCM_NULLP (tmp))
2240 {
2241 SCM elt = SCM_CAR (tmp);
2242 SCM_VALIDATE_STRING (1, elt);
2243 len += SCM_STRING_LENGTH (elt);
2244 tmp = SCM_CDR (tmp);
2245 }
2246 result = scm_allocate_string (len);
2247
2248 /* Copy the list elements into the result. */
2249 p = SCM_STRING_CHARS (result);
2250 tmp = ls;
2251 while (!SCM_NULLP (tmp))
2252 {
2253 SCM elt = SCM_CAR (tmp);
2254 memmove (p, SCM_STRING_CHARS (elt),
2255 SCM_STRING_LENGTH (elt) * sizeof (char));
2256 p += SCM_STRING_LENGTH (elt);
2257 tmp = SCM_CDR (tmp);
2258 }
2259 return result;
2260}
2261#undef FUNC_NAME
2262
2263
0f216433 2264SCM_DEFINE (scm_string_concatenate_reverse, "string-concatenate-reverse", 1, 2, 0,
ca003b26
MG
2265 (SCM ls, SCM final_string, SCM end),
2266 "Without optional arguments, this procedure is equivalent to\n"
2267 "\n"
2268 "@smalllisp\n"
2269 "(string-concatenate (reverse ls))\n"
2270 "@end smalllisp\n"
2271 "\n"
2272 "If the optional argument @var{final_string} is specified, it is\n"
2273 "consed onto the beginning to @var{ls} before performing the\n"
8dddb4bc
MG
2274 "list-reverse and string-concatenate operations. If @var{end}\n"
2275 "is given, only the characters of @var{final_string} up to index\n"
2276 "@var{end} are used.\n"
ca003b26
MG
2277 "\n"
2278 "Guaranteed to return a freshly allocated string.")
8dddb4bc 2279#define FUNC_NAME s_scm_string_concatenate_reverse
ca003b26
MG
2280{
2281 long strings;
2282 SCM tmp, result;
1a161b8e 2283 size_t len = 0;
ca003b26 2284 char * p;
1a161b8e 2285 size_t cend = 0;
ca003b26
MG
2286
2287 /* Check the optional arguments and calculate the additional length
2288 of the result string. */
2289 if (!SCM_UNBNDP (final_string))
2290 {
2291 SCM_VALIDATE_STRING (2, final_string);
2292 if (!SCM_UNBNDP (end))
2293 {
1a161b8e
MV
2294 cend = scm_to_unsigned_integer (end,
2295 0, SCM_STRING_LENGTH (final_string));
ca003b26
MG
2296 }
2297 else
2298 {
2299 cend = SCM_STRING_LENGTH (final_string);
2300 }
2301 len += cend;
2302 }
2303 strings = scm_ilength (ls);
2304 /* Validate the string list. */
2305 if (strings < 0)
2306 SCM_WRONG_TYPE_ARG (1, ls);
2307
2308 /* Calculate the length of the result string. */
2309 tmp = ls;
2310 while (!SCM_NULLP (tmp))
2311 {
2312 SCM elt = SCM_CAR (tmp);
2313 SCM_VALIDATE_STRING (1, elt);
2314 len += SCM_STRING_LENGTH (elt);
2315 tmp = SCM_CDR (tmp);
2316 }
2317
2318 result = scm_allocate_string (len);
2319
2320 p = SCM_STRING_CHARS (result) + len;
2321
2322 /* Construct the result string, possibly by using the optional final
2323 string. */
2324 if (!SCM_UNBNDP (final_string))
2325 {
2326 p -= cend;
2327 memmove (p, SCM_STRING_CHARS (final_string), cend * sizeof (char));
2328 }
2329 tmp = ls;
2330 while (!SCM_NULLP (tmp))
2331 {
2332 SCM elt = SCM_CAR (tmp);
2333 p -= SCM_STRING_LENGTH (elt);
2334 memmove (p, SCM_STRING_CHARS (elt),
2335 SCM_STRING_LENGTH (elt) * sizeof (char));
2336 tmp = SCM_CDR (tmp);
2337 }
2338 return result;
2339}
2340#undef FUNC_NAME
2341
2342
0f216433 2343SCM_DEFINE (scm_string_concatenate_shared, "string-concatenate/shared", 1, 0, 0,
ca003b26
MG
2344 (SCM ls),
2345 "Like @code{string-concatenate}, but the result may share memory\n"
2346 "with the strings in the list @var{ls}.")
2347#define FUNC_NAME s_scm_string_concatenate_shared
2348{
2349 /* Optimize the one-string case. */
2350 long i = scm_ilength (ls);
2351 if (i == 1)
2352 {
2353 SCM_VALIDATE_STRING (1, SCM_CAR (ls));
2354 return SCM_CAR (ls);
2355 }
2356 return scm_string_concatenate (ls);
2357}
2358#undef FUNC_NAME
2359
2360
0f216433 2361SCM_DEFINE (scm_string_concatenate_reverse_shared, "string-concatenate-reverse/shared", 1, 2, 0,
ca003b26 2362 (SCM ls, SCM final_string, SCM end),
8dddb4bc 2363 "Like @code{string-concatenate-reverse}, but the result may\n"
ca003b26 2364 "share memory with the the strings in the @var{ls} arguments.")
8dddb4bc 2365#define FUNC_NAME s_scm_string_concatenate_reverse_shared
ca003b26
MG
2366{
2367 /* Just call the non-sharing version. */
8dddb4bc 2368 return scm_string_concatenate_reverse (ls, final_string, end);
ca003b26
MG
2369}
2370#undef FUNC_NAME
2371
2372
2373SCM_DEFINE (scm_string_map, "string-map", 2, 2, 0,
80fdeb4e 2374 (SCM proc, SCM s, SCM start, SCM end),
ca003b26
MG
2375 "@var{proc} is a char->char procedure, it is mapped over\n"
2376 "@var{s}. The order in which the procedure is applied to the\n"
2377 "string elements is not specified.")
2378#define FUNC_NAME s_scm_string_map
2379{
2380 char * cstr, *p;
2381 int cstart, cend;
2382 SCM result;
2383
80fdeb4e
MD
2384 SCM_VALIDATE_PROC (1, proc);
2385 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
ca003b26
MG
2386 3, start, cstart,
2387 4, end, cend);
ca003b26
MG
2388 result = scm_allocate_string (cend - cstart);
2389 p = SCM_STRING_CHARS (result);
2390 while (cstart < cend)
2391 {
84fad130
HWN
2392 unsigned int c = (unsigned char) cstr[cstart];
2393 SCM ch = scm_call_1 (proc, SCM_MAKE_CHAR (c));
ca003b26 2394 if (!SCM_CHARP (ch))
2c4df451 2395 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
ca003b26
MG
2396 cstart++;
2397 *p++ = SCM_CHAR (ch);
2398 }
2399 return result;
2400}
2401#undef FUNC_NAME
2402
2403
2404SCM_DEFINE (scm_string_map_x, "string-map!", 2, 2, 0,
80fdeb4e 2405 (SCM proc, SCM s, SCM start, SCM end),
ca003b26
MG
2406 "@var{proc} is a char->char procedure, it is mapped over\n"
2407 "@var{s}. The order in which the procedure is applied to the\n"
2408 "string elements is not specified. The string @var{s} is\n"
2409 "modified in-place, the return value is not specified.")
2410#define FUNC_NAME s_scm_string_map_x
2411{
2412 char * cstr, *p;
2413 int cstart, cend;
2414
80fdeb4e
MD
2415 SCM_VALIDATE_PROC (1, proc);
2416 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
ca003b26
MG
2417 3, start, cstart,
2418 4, end, cend);
ca003b26
MG
2419 p = SCM_STRING_CHARS (s) + cstart;
2420 while (cstart < cend)
2421 {
84fad130
HWN
2422 unsigned int c = (unsigned char) cstr[cstart];
2423 SCM ch = scm_call_1 (proc, SCM_MAKE_CHAR (c));
ca003b26 2424 if (!SCM_CHARP (ch))
2c4df451 2425 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
ca003b26
MG
2426 cstart++;
2427 *p++ = SCM_CHAR (ch);
2428 }
2429 return SCM_UNSPECIFIED;
2430}
2431#undef FUNC_NAME
2432
2433
2434SCM_DEFINE (scm_string_fold, "string-fold", 3, 2, 0,
2435 (SCM kons, SCM knil, SCM s, SCM start, SCM end),
2436 "Fold @var{kons} over the characters of @var{s}, with @var{knil}\n"
2437 "as the terminating element, from left to right. @var{kons}\n"
2438 "must expect two arguments: The actual character and the last\n"
2439 "result of @var{kons}' application.")
2440#define FUNC_NAME s_scm_string_fold
2441{
2442 char * cstr;
2443 int cstart, cend;
2444 SCM result;
2445
2446 SCM_VALIDATE_PROC (1, kons);
2447 SCM_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cstr,
2448 4, start, cstart,
2449 5, end, cend);
2450 result = knil;
2451 while (cstart < cend)
2452 {
84fad130
HWN
2453 unsigned int c = (unsigned char) cstr[cstart];
2454 result = scm_call_2 (kons, SCM_MAKE_CHAR (c), result);
ca003b26
MG
2455 cstart++;
2456 }
2457 return result;
2458}
2459#undef FUNC_NAME
2460
2461
2462SCM_DEFINE (scm_string_fold_right, "string-fold-right", 3, 2, 0,
2463 (SCM kons, SCM knil, SCM s, SCM start, SCM end),
2464 "Fold @var{kons} over the characters of @var{s}, with @var{knil}\n"
2465 "as the terminating element, from right to left. @var{kons}\n"
2466 "must expect two arguments: The actual character and the last\n"
2467 "result of @var{kons}' application.")
2468#define FUNC_NAME s_scm_string_fold_right
2469{
2470 char * cstr;
2471 int cstart, cend;
2472 SCM result;
2473
2474 SCM_VALIDATE_PROC (1, kons);
2475 SCM_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cstr,
2476 4, start, cstart,
2477 5, end, cend);
2478 result = knil;
2479 while (cstart < cend)
2480 {
84fad130
HWN
2481 unsigned int c = (unsigned char) cstr[cend - 1];
2482 result = scm_call_2 (kons, SCM_MAKE_CHAR (c), result);
ca003b26
MG
2483 cend--;
2484 }
2485 return result;
2486}
2487#undef FUNC_NAME
2488
2489
2490SCM_DEFINE (scm_string_unfold, "string-unfold", 4, 2, 0,
2491 (SCM p, SCM f, SCM g, SCM seed, SCM base, SCM make_final),
2d953700 2492 "@itemize @bullet\n"
ca003b26
MG
2493 "@item @var{g} is used to generate a series of @emph{seed}\n"
2494 "values from the initial @var{seed}: @var{seed}, (@var{g}\n"
2495 "@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}),\n"
2496 "@dots{}\n"
2497 "@item @var{p} tells us when to stop -- when it returns true\n"
2498 "when applied to one of these seed values.\n"
9401323e 2499 "@item @var{f} maps each seed value to the corresponding\n"
ca003b26
MG
2500 "character in the result string. These chars are assembled\n"
2501 "into the string in a left-to-right order.\n"
2502 "@item @var{base} is the optional initial/leftmost portion\n"
2503 "of the constructed string; it default to the empty\n"
2504 "string.\n"
2505 "@item @var{make_final} is applied to the terminal seed\n"
2506 "value (on which @var{p} returns true) to produce\n"
2507 "the final/rightmost portion of the constructed string.\n"
2508 "It defaults to @code{(lambda (x) "")}.\n"
2509 "@end itemize")
2510#define FUNC_NAME s_scm_string_unfold
2511{
2512 SCM res, ans;
2513
2514 SCM_VALIDATE_PROC (1, p);
2515 SCM_VALIDATE_PROC (2, f);
2516 SCM_VALIDATE_PROC (3, g);
2517 if (!SCM_UNBNDP (base))
2518 {
2519 SCM_VALIDATE_STRING (5, base);
2520 ans = base;
2521 }
2522 else
2523 ans = scm_allocate_string (0);
2524 if (!SCM_UNBNDP (make_final))
2525 SCM_VALIDATE_PROC (6, make_final);
2526
2c4df451 2527 res = scm_call_1 (p, seed);
00874d5f 2528 while (scm_is_false (res))
ca003b26
MG
2529 {
2530 SCM str;
2c4df451 2531 SCM ch = scm_call_1 (f, seed);
ca003b26 2532 if (!SCM_CHARP (ch))
2c4df451 2533 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
ca003b26
MG
2534 str = scm_allocate_string (1);
2535 *SCM_STRING_CHARS (str) = SCM_CHAR (ch);
2536
2c4df451
MG
2537 ans = scm_string_append (scm_list_2 (ans, str));
2538 seed = scm_call_1 (g, seed);
2539 res = scm_call_1 (p, seed);
ca003b26
MG
2540 }
2541 if (!SCM_UNBNDP (make_final))
2542 {
2c4df451
MG
2543 res = scm_call_1 (make_final, seed);
2544 return scm_string_append (scm_list_2 (ans, res));
ca003b26
MG
2545 }
2546 else
2547 return ans;
2548}
2549#undef FUNC_NAME
2550
2551
2552SCM_DEFINE (scm_string_unfold_right, "string-unfold-right", 4, 2, 0,
2553 (SCM p, SCM f, SCM g, SCM seed, SCM base, SCM make_final),
2d953700 2554 "@itemize @bullet\n"
ca003b26
MG
2555 "@item @var{g} is used to generate a series of @emph{seed}\n"
2556 "values from the initial @var{seed}: @var{seed}, (@var{g}\n"
2557 "@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}),\n"
2558 "@dots{}\n"
2559 "@item @var{p} tells us when to stop -- when it returns true\n"
2560 "when applied to one of these seed values.\n"
9401323e 2561 "@item @var{f} maps each seed value to the corresponding\n"
ca003b26
MG
2562 "character in the result string. These chars are assembled\n"
2563 "into the string in a right-to-left order.\n"
2564 "@item @var{base} is the optional initial/rightmost portion\n"
2565 "of the constructed string; it default to the empty\n"
2566 "string.\n"
2567 "@item @var{make_final} is applied to the terminal seed\n"
2568 "value (on which @var{p} returns true) to produce\n"
2569 "the final/leftmost portion of the constructed string.\n"
2570 "It defaults to @code{(lambda (x) "")}.\n"
2571 "@end itemize")
2572#define FUNC_NAME s_scm_string_unfold_right
2573{
2574 SCM res, ans;
2575
2576 SCM_VALIDATE_PROC (1, p);
2577 SCM_VALIDATE_PROC (2, f);
2578 SCM_VALIDATE_PROC (3, g);
2579 if (!SCM_UNBNDP (base))
2580 {
2581 SCM_VALIDATE_STRING (5, base);
2582 ans = base;
2583 }
2584 else
2585 ans = scm_allocate_string (0);
2586 if (!SCM_UNBNDP (make_final))
2587 SCM_VALIDATE_PROC (6, make_final);
2588
2c4df451 2589 res = scm_call_1 (p, seed);
00874d5f 2590 while (scm_is_false (res))
ca003b26
MG
2591 {
2592 SCM str;
2c4df451 2593 SCM ch = scm_call_1 (f, seed);
ca003b26 2594 if (!SCM_CHARP (ch))
2c4df451 2595 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
ca003b26
MG
2596 str = scm_allocate_string (1);
2597 *SCM_STRING_CHARS (str) = SCM_CHAR (ch);
2598
2c4df451
MG
2599 ans = scm_string_append (scm_list_2 (str, ans));
2600 seed = scm_call_1 (g, seed);
2601 res = scm_call_1 (p, seed);
ca003b26
MG
2602 }
2603 if (!SCM_UNBNDP (make_final))
2604 {
2c4df451
MG
2605 res = scm_call_1 (make_final, seed);
2606 return scm_string_append (scm_list_2 (res, ans));
ca003b26
MG
2607 }
2608 else
2609 return ans;
2610}
2611#undef FUNC_NAME
2612
2613
2614SCM_DEFINE (scm_string_for_each, "string-for-each", 2, 2, 0,
0f216433 2615 (SCM proc, SCM s, SCM start, SCM end),
ca003b26
MG
2616 "@var{proc} is mapped over @var{s} in left-to-right order. The\n"
2617 "return value is not specified.")
2618#define FUNC_NAME s_scm_string_for_each
2619{
2620 char * cstr;
2621 int cstart, cend;
2622
0f216433
TTN
2623 SCM_VALIDATE_PROC (1, proc);
2624 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
ca003b26
MG
2625 3, start, cstart,
2626 4, end, cend);
ca003b26
MG
2627 while (cstart < cend)
2628 {
84fad130
HWN
2629 unsigned int c = (unsigned char) cstr[cstart];
2630 scm_call_1 (proc, SCM_MAKE_CHAR (c));
ca003b26
MG
2631 cstart++;
2632 }
2633 return SCM_UNSPECIFIED;
2634}
2635#undef FUNC_NAME
2636
0f216433
TTN
2637SCM_DEFINE (scm_string_for_each_index, "string-for-each-index", 2, 2, 0,
2638 (SCM proc, SCM s, SCM start, SCM end),
2639 "@var{proc} is mapped over @var{s} in left-to-right order. The\n"
2640 "return value is not specified.")
2641#define FUNC_NAME s_scm_string_for_each
2642{
2643 char * cstr;
2644 int cstart, cend;
2645
2646 SCM_VALIDATE_PROC (1, proc);
2647 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
2648 3, start, cstart,
2649 4, end, cend);
2650 while (cstart < cend)
2651 {
93ccaef0 2652 scm_call_1 (proc, SCM_I_MAKINUM (cstart));
0f216433
TTN
2653 cstart++;
2654 }
2655 return SCM_UNSPECIFIED;
2656}
2657#undef FUNC_NAME
2658
ca003b26
MG
2659SCM_DEFINE (scm_xsubstring, "xsubstring", 2, 3, 0,
2660 (SCM s, SCM from, SCM to, SCM start, SCM end),
2661 "This is the @emph{extended substring} procedure that implements\n"
2662 "replicated copying of a substring of some string.\n"
2663 "\n"
2664 "@var{s} is a string, @var{start} and @var{end} are optional\n"
2665 "arguments that demarcate a substring of @var{s}, defaulting to\n"
2666 "0 and the length of @var{s}. Replicate this substring up and\n"
2667 "down index space, in both the positive and negative directions.\n"
2668 "@code{xsubstring} returns the substring of this string\n"
2669 "beginning at index @var{from}, and ending at @var{to}, which\n"
2670 "defaults to @var{from} + (@var{end} - @var{start}).")
2671#define FUNC_NAME s_scm_xsubstring
2672{
2673 char * cs, * p;
1a161b8e 2674 size_t cstart, cend, cfrom, cto;
ca003b26
MG
2675 SCM result;
2676
2677 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cs,
2678 4, start, cstart,
2679 5, end, cend);
1a161b8e
MV
2680 cfrom = scm_to_size_t (from);
2681 if (SCM_UNBNDP (to))
2682 cto = cfrom + (cend - cstart);
2683 else
2684 cto = scm_to_size_t (to);
ca003b26
MG
2685 if (cstart == cend && cfrom != cto)
2686 SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL);
0f216433 2687
ca003b26 2688 result = scm_allocate_string (cto - cfrom);
0f216433 2689
ca003b26
MG
2690 p = SCM_STRING_CHARS (result);
2691 while (cfrom < cto)
2692 {
2693 int t = ((cfrom < 0) ? -cfrom : cfrom) % (cend - cstart);
2694 if (cfrom < 0)
2695 *p = cs[(cend - cstart) - t];
2696 else
2697 *p = cs[t];
2698 cfrom++;
2699 p++;
2700 }
2701 return result;
2702}
2703#undef FUNC_NAME
2704
2705
2706SCM_DEFINE (scm_string_xcopy_x, "string-xcopy!", 4, 3, 0,
2707 (SCM target, SCM tstart, SCM s, SCM sfrom, SCM sto, SCM start, SCM end),
2708 "Exactly the same as @code{xsubstring}, but the extracted text\n"
2709 "is written into the string @var{target} starting at index\n"
2710 "@var{tstart}. The operation is not defined if @code{(eq?\n"
2711 "@var{target} @var{s})} or these arguments share storage -- you\n"
2712 "cannot copy a string on top of itself.")
2713#define FUNC_NAME s_scm_string_xcopy_x
2714{
2715 char * ctarget, * cs, * p;
1a161b8e 2716 size_t ctstart, csfrom, csto, cstart, cend;
ca003b26
MG
2717 SCM dummy = SCM_UNDEFINED;
2718 int cdummy;
2719
2720 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, target, ctarget,
2721 2, tstart, ctstart,
2722 2, dummy, cdummy);
2723 SCM_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cs,
2724 6, start, cstart,
2725 7, end, cend);
1a161b8e
MV
2726 csfrom = scm_to_size_t (sfrom);
2727 if (SCM_UNBNDP (sto))
2728 csto = csfrom + (cend - cstart);
2729 else
2730 csto = scm_to_size_t (sto);
ca003b26
MG
2731 if (cstart == cend && csfrom != csto)
2732 SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL);
2733 SCM_ASSERT_RANGE (1, tstart,
2734 ctstart + (csto - csfrom) <= SCM_STRING_LENGTH (target));
2735
2736 p = ctarget + ctstart;
2737 while (csfrom < csto)
2738 {
2739 int t = ((csfrom < 0) ? -csfrom : csfrom) % (cend - cstart);
2740 if (csfrom < 0)
2741 *p = cs[(cend - cstart) - t];
2742 else
2743 *p = cs[t];
2744 csfrom++;
2745 p++;
2746 }
2747 return SCM_UNSPECIFIED;
2748}
2749#undef FUNC_NAME
2750
2751
2752SCM_DEFINE (scm_string_replace, "string-replace", 2, 4, 0,
2753 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
2754 "Return the string @var{s1}, but with the characters\n"
2755 "@var{start1} @dots{} @var{end1} replaced by the characters\n"
2756 "@var{start2} @dots{} @var{end2} from @var{s2}.")
2757#define FUNC_NAME s_scm_string_replace
2758{
2759 char * cstr1, * cstr2, * p;
1a161b8e 2760 size_t cstart1, cend1, cstart2, cend2;
ca003b26
MG
2761 SCM result;
2762
2763 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
2764 3, start1, cstart1,
2765 4, end1, cend1);
2766 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
2767 5, start2, cstart2,
2768 6, end2, cend2);
2769 result = scm_allocate_string (cstart1 + (cend2 - cstart2) +
2770 SCM_STRING_LENGTH (s1) - cend1);
2771 p = SCM_STRING_CHARS (result);
653c7291
MG
2772 memmove (p, cstr1, cstart1 * sizeof (char));
2773 memmove (p + cstart1, cstr2 + cstart2, (cend2 - cstart2) * sizeof (char));
ca003b26
MG
2774 memmove (p + cstart1 + (cend2 - cstart2),
2775 cstr1 + cend1,
653c7291 2776 (SCM_STRING_LENGTH (s1) - cend1) * sizeof (char));
ca003b26
MG
2777 return result;
2778}
2779#undef FUNC_NAME
2780
2781
2782SCM_DEFINE (scm_string_tokenize, "string-tokenize", 1, 3, 0,
aa6a37ea 2783 (SCM s, SCM token_set, SCM start, SCM end),
ca003b26
MG
2784 "Split the string @var{s} into a list of substrings, where each\n"
2785 "substring is a maximal non-empty contiguous sequence of\n"
aa6a37ea 2786 "characters from the character set @var{token_set}, which\n"
c8519a82 2787 "defaults to @code{char-set:graphic} from module (srfi srfi-14).\n"
aa6a37ea
MV
2788 "If @var{start} or @var{end} indices are provided, they restrict\n"
2789 "@code{string-tokenize} to operating on the indicated substring\n"
2790 "of @var{s}.")
ca003b26
MG
2791#define FUNC_NAME s_scm_string_tokenize
2792{
2793 char * cstr;
1a161b8e 2794 size_t cstart, cend;
ca003b26
MG
2795 SCM result = SCM_EOL;
2796
c8519a82
MV
2797 static SCM charset_graphic = SCM_BOOL_F;
2798
ca003b26
MG
2799 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2800 3, start, cstart,
2801 4, end, cend);
c8519a82 2802
aa6a37ea 2803 if (SCM_UNBNDP (token_set))
ca003b26 2804 {
c8519a82 2805 if (charset_graphic == SCM_BOOL_F)
ca003b26 2806 {
c8519a82
MV
2807 SCM srfi_14_module = scm_c_resolve_module ("srfi srfi-14");
2808 SCM charset_graphic_var = scm_c_module_lookup (srfi_14_module,
2809 "char-set:graphic");
2810 charset_graphic =
2811 scm_permanent_object (SCM_VARIABLE_REF (charset_graphic_var));
ca003b26 2812 }
c8519a82 2813 token_set = charset_graphic;
ca003b26 2814 }
c8519a82
MV
2815
2816 if (SCM_CHARSETP (token_set))
ca003b26
MG
2817 {
2818 int idx;
2819
2820 while (cstart < cend)
2821 {
2822 while (cstart < cend)
2823 {
aa6a37ea 2824 if (SCM_CHARSET_GET (token_set, cstr[cend - 1]))
ca003b26
MG
2825 break;
2826 cend--;
2827 }
2828 if (cstart >= cend)
2829 break;
2830 idx = cend;
2831 while (cstart < cend)
2832 {
aa6a37ea 2833 if (!SCM_CHARSET_GET (token_set, cstr[cend - 1]))
ca003b26
MG
2834 break;
2835 cend--;
2836 }
36284627 2837 result = scm_cons (scm_mem2string (cstr + cend, idx - cend), result);
ca003b26
MG
2838 }
2839 }
aa6a37ea 2840 else SCM_WRONG_TYPE_ARG (2, token_set);
ca003b26
MG
2841 return result;
2842}
2843#undef FUNC_NAME
2844
2845
2846SCM_DEFINE (scm_string_filter, "string-filter", 2, 2, 0,
2847 (SCM s, SCM char_pred, SCM start, SCM end),
2848 "Filter the string @var{s}, retaining only those characters that\n"
2849 "satisfy the @var{char_pred} argument. If the argument is a\n"
2850 "procedure, it is applied to each character as a predicate, if\n"
2851 "it is a character, it is tested for equality and if it is a\n"
2852 "character set, it is tested for membership.")
2853#define FUNC_NAME s_scm_string_filter
2854{
2855 char * cstr;
1a161b8e 2856 size_t cstart, cend;
ca003b26
MG
2857 SCM result;
2858 int idx;
2859
2860 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2861 3, start, cstart,
2862 4, end, cend);
2863 if (SCM_CHARP (char_pred))
2864 {
2865 SCM ls = SCM_EOL;
2866 char chr;
0f216433 2867
ca003b26
MG
2868 chr = SCM_CHAR (char_pred);
2869 idx = cstart;
2870 while (idx < cend)
2871 {
2872 if (cstr[idx] == chr)
2873 ls = scm_cons (SCM_MAKE_CHAR (cstr[idx]), ls);
2874 idx++;
2875 }
2876 result = scm_reverse_list_to_string (ls);
2877 }
2878 else if (SCM_CHARSETP (char_pred))
2879 {
2880 SCM ls = SCM_EOL;
0f216433 2881
ca003b26
MG
2882 idx = cstart;
2883 while (idx < cend)
2884 {
2885 if (SCM_CHARSET_GET (char_pred, cstr[idx]))
2886 ls = scm_cons (SCM_MAKE_CHAR (cstr[idx]), ls);
2887 idx++;
2888 }
2889 result = scm_reverse_list_to_string (ls);
2890 }
2891 else
2892 {
2893 SCM ls = SCM_EOL;
2894
2895 SCM_VALIDATE_PROC (2, char_pred);
2896 idx = cstart;
2897 while (idx < cend)
2898 {
2899 SCM res;
2c4df451 2900 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[idx]));
00874d5f 2901 if (scm_is_true (res))
ca003b26
MG
2902 ls = scm_cons (SCM_MAKE_CHAR (cstr[idx]), ls);
2903 idx++;
2904 }
2905 result = scm_reverse_list_to_string (ls);
2906 }
2907 return result;
2908}
2909#undef FUNC_NAME
2910
2911
2912SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
2913 (SCM s, SCM char_pred, SCM start, SCM end),
2914 "Filter the string @var{s}, retaining only those characters that\n"
2915 "do not satisfy the @var{char_pred} argument. If the argument\n"
2916 "is a procedure, it is applied to each character as a predicate,\n"
2917 "if it is a character, it is tested for equality and if it is a\n"
2918 "character set, it is tested for membership.")
2919#define FUNC_NAME s_scm_string_delete
2920{
2921 char * cstr;
1a161b8e 2922 size_t cstart, cend;
ca003b26
MG
2923 SCM result;
2924 int idx;
2925
2926 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2927 3, start, cstart,
2928 4, end, cend);
2929 if (SCM_CHARP (char_pred))
2930 {
2931 SCM ls = SCM_EOL;
2932 char chr;
0f216433 2933
ca003b26
MG
2934 chr = SCM_CHAR (char_pred);
2935 idx = cstart;
2936 while (idx < cend)
2937 {
2938 if (cstr[idx] != chr)
2939 ls = scm_cons (SCM_MAKE_CHAR (cstr[idx]), ls);
2940 idx++;
2941 }
2942 result = scm_reverse_list_to_string (ls);
2943 }
2944 else if (SCM_CHARSETP (char_pred))
2945 {
2946 SCM ls = SCM_EOL;
0f216433 2947
ca003b26
MG
2948 idx = cstart;
2949 while (idx < cend)
2950 {
163a7e0d 2951 if (!SCM_CHARSET_GET (char_pred, cstr[idx]))
ca003b26
MG
2952 ls = scm_cons (SCM_MAKE_CHAR (cstr[idx]), ls);
2953 idx++;
2954 }
2955 result = scm_reverse_list_to_string (ls);
2956 }
2957 else
2958 {
2959 SCM ls = SCM_EOL;
2960
2961 SCM_VALIDATE_PROC (2, char_pred);
2962 idx = cstart;
2963 while (idx < cend)
2964 {
2965 SCM res;
2c4df451 2966 res = scm_call_1 (char_pred, SCM_MAKE_CHAR (cstr[idx]));
00874d5f 2967 if (scm_is_false (res))
ca003b26
MG
2968 ls = scm_cons (SCM_MAKE_CHAR (cstr[idx]), ls);
2969 idx++;
2970 }
2971 result = scm_reverse_list_to_string (ls);
2972 }
2973 return result;
2974}
2975#undef FUNC_NAME
2976
2977
2c4df451
MG
2978/* Initialize the SRFI-13 module. This function will be called by the
2979 loading Scheme module. */
ca003b26 2980void
653c7291 2981scm_init_srfi_13 (void)
ca003b26 2982{
2c4df451
MG
2983 /* We initialize the SRFI-14 module here, because the string
2984 primitives need the charset smob type created by that module. */
94451729 2985 scm_c_init_srfi_14 ();
2c4df451
MG
2986
2987 /* Install the string primitives. */
485efc12 2988#include "srfi/srfi-13.x"
ca003b26 2989}
2c4df451
MG
2990
2991/* End of srfi-13.c. */