1 /* srfi-13.c --- SRFI-13 procedures for Guile
3 * Copyright (C) 2001, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
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.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "libguile/srfi-13.h"
31 #include "libguile/srfi-14.h"
33 /* SCM_VALIDATE_SUBSTRING_SPEC_COPY is deprecated since it encourages
34 messing with the internal representation of strings. We define our
35 own version since we use it so much and are messing with Guile
39 #define MY_VALIDATE_SUBSTRING_SPEC_COPY(pos_str, str, c_str, \
40 pos_start, start, c_start, \
41 pos_end, end, c_end) \
43 SCM_VALIDATE_STRING (pos_str, str); \
44 c_str = scm_i_string_chars (str); \
45 scm_i_get_substring_spec (scm_i_string_length (str), \
46 start, &c_start, end, &c_end); \
49 /* Expecting "unsigned char *c_str" */
50 #define MY_VALIDATE_SUBSTRING_SPEC_UCOPY(pos_str, str, c_str, \
51 pos_start, start, c_start, \
52 pos_end, end, c_end) \
54 const char *signed_c_str; \
55 MY_VALIDATE_SUBSTRING_SPEC_COPY(pos_str, str, signed_c_str, \
56 pos_start, start, c_start, \
57 pos_end, end, c_end); \
58 c_str = (unsigned char *) signed_c_str; \
61 #define MY_VALIDATE_SUBSTRING_SPEC(pos_str, str, \
62 pos_start, start, c_start, \
63 pos_end, end, c_end) \
65 SCM_VALIDATE_STRING (pos_str, str); \
66 scm_i_get_substring_spec (scm_i_string_length (str), \
67 start, &c_start, end, &c_end); \
70 SCM_DEFINE (scm_string_null_p, "string-null?", 1, 0, 0,
72 "Return @code{#t} if @var{str}'s length is zero, and\n"
73 "@code{#f} otherwise.\n"
75 "(string-null? \"\") @result{} #t\n"
76 "y @result{} \"foo\"\n"
77 "(string-null? y) @result{} #f\n"
79 #define FUNC_NAME s_scm_string_null_p
81 SCM_VALIDATE_STRING (1, str);
82 return scm_from_bool (scm_i_string_length (str) == 0);
90 scm_misc_error (NULL, "race condition detected", SCM_EOL);
94 SCM_DEFINE (scm_string_any, "string-any-c-code", 2, 2, 0,
95 (SCM char_pred, SCM s, SCM start, SCM end),
96 "Check if @var{char_pred} is true for any character in string @var{s}.\n"
98 "@var{char_pred} can be a character to check for any equal to that, or\n"
99 "a character set (@pxref{Character Sets}) to check for any in that set,\n"
100 "or a predicate procedure to call.\n"
102 "For a procedure, calls @code{(@var{char_pred} c)} are made\n"
103 "successively on the characters from @var{start} to @var{end}. If\n"
104 "@var{char_pred} returns true (ie.@: non-@code{#f}), @code{string-any}\n"
105 "stops and that return value is the return from @code{string-any}. The\n"
106 "call on the last character (ie.@: at @math{@var{end}-1}), if that\n"
107 "point is reached, is a tail call.\n"
109 "If there are no characters in @var{s} (ie.@: @var{start} equals\n"
110 "@var{end}) then the return is @code{#f}.\n")
111 #define FUNC_NAME s_scm_string_any
115 SCM res = SCM_BOOL_F;
117 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
121 if (SCM_CHARP (char_pred))
123 res = (memchr (cstr+cstart, (int) SCM_CHAR (char_pred),
125 ? SCM_BOOL_F : SCM_BOOL_T);
127 else if (SCM_CHARSETP (char_pred))
130 for (i = cstart; i < cend; i++)
131 if (SCM_CHARSET_GET (char_pred, cstr[i]))
139 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
140 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG1, FUNC_NAME);
142 while (cstart < cend)
144 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
145 if (scm_is_true (res))
147 cstr = scm_i_string_chars (s);
152 scm_remember_upto_here_1 (s);
158 SCM_DEFINE (scm_string_every, "string-every-c-code", 2, 2, 0,
159 (SCM char_pred, SCM s, SCM start, SCM end),
160 "Check if @var{char_pred} is true for every character in string\n"
163 "@var{char_pred} can be a character to check for every character equal\n"
164 "to that, or a character set (@pxref{Character Sets}) to check for\n"
165 "every character being in that set, or a predicate procedure to call.\n"
167 "For a procedure, calls @code{(@var{char_pred} c)} are made\n"
168 "successively on the characters from @var{start} to @var{end}. If\n"
169 "@var{char_pred} returns @code{#f}, @code{string-every} stops and\n"
170 "returns @code{#f}. The call on the last character (ie.@: at\n"
171 "@math{@var{end}-1}), if that point is reached, is a tail call and the\n"
172 "return from that call is the return from @code{string-every}.\n"
174 "If there are no characters in @var{s} (ie.@: @var{start} equals\n"
175 "@var{end}) then the return is @code{#t}.\n")
176 #define FUNC_NAME s_scm_string_every
180 SCM res = SCM_BOOL_T;
182 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
185 if (SCM_CHARP (char_pred))
187 char cchr = SCM_CHAR (char_pred);
189 for (i = cstart; i < cend; i++)
196 else if (SCM_CHARSETP (char_pred))
199 for (i = cstart; i < cend; i++)
200 if (!SCM_CHARSET_GET (char_pred, cstr[i]))
208 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
209 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG1, FUNC_NAME);
211 while (cstart < cend)
213 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
214 if (scm_is_false (res))
216 cstr = scm_i_string_chars (s);
221 scm_remember_upto_here_1 (s);
227 SCM_DEFINE (scm_string_tabulate, "string-tabulate", 2, 0, 0,
229 "@var{proc} is an integer->char procedure. Construct a string\n"
230 "of size @var{len} by applying @var{proc} to each index to\n"
231 "produce the corresponding string element. The order in which\n"
232 "@var{proc} is applied to the indices is not specified.")
233 #define FUNC_NAME s_scm_string_tabulate
239 scm_t_trampoline_1 proc_tramp;
241 proc_tramp = scm_trampoline_1 (proc);
242 SCM_ASSERT (proc_tramp, proc, SCM_ARG1, FUNC_NAME);
244 clen = scm_to_size_t (len);
245 SCM_ASSERT_RANGE (2, len, clen >= 0);
247 res = scm_i_make_string (clen, &p);
251 /* The RES string remains untouched since nobody knows about it
252 yet. No need to refetch P.
254 ch = proc_tramp (proc, scm_from_size_t (i));
256 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
257 *p++ = SCM_CHAR (ch);
265 SCM_DEFINE (scm_substring_to_list, "string->list", 1, 2, 0,
266 (SCM str, SCM start, SCM end),
267 "Convert the string @var{str} into a list of characters.")
268 #define FUNC_NAME s_scm_substring_to_list
272 SCM result = SCM_EOL;
274 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
277 while (cstart < cend)
280 result = scm_cons (SCM_MAKE_CHAR (cstr[cend]), result);
281 cstr = scm_i_string_chars (str);
283 scm_remember_upto_here_1 (str);
288 /* We export scm_substring_to_list as "string->list" since it is
289 compatible and more general. This function remains for the benefit
290 of C code that used it.
294 scm_string_to_list (SCM str)
296 return scm_substring_to_list (str, SCM_UNDEFINED, SCM_UNDEFINED);
299 SCM_DEFINE (scm_reverse_list_to_string, "reverse-list->string", 1, 0, 0,
301 "An efficient implementation of @code{(compose string->list\n"
305 "(reverse-list->string '(#\\a #\\B #\\c)) @result{} \"cBa\"\n"
307 #define FUNC_NAME s_scm_reverse_list_to_string
310 long i = scm_ilength (chrs);
314 SCM_WRONG_TYPE_ARG (1, chrs);
315 result = scm_i_make_string (i, &data);
320 while (i > 0 && scm_is_pair (chrs))
322 SCM elt = SCM_CAR (chrs);
324 SCM_VALIDATE_CHAR (SCM_ARGn, elt);
326 *data = SCM_CHAR (elt);
327 chrs = SCM_CDR (chrs);
337 SCM_SYMBOL (scm_sym_infix, "infix");
338 SCM_SYMBOL (scm_sym_strict_infix, "strict-infix");
339 SCM_SYMBOL (scm_sym_suffix, "suffix");
340 SCM_SYMBOL (scm_sym_prefix, "prefix");
343 append_string (char **sp, size_t *lp, SCM str)
346 len = scm_c_string_length (str);
349 memcpy (*sp, scm_i_string_chars (str), len);
354 SCM_DEFINE (scm_string_join, "string-join", 1, 2, 0,
355 (SCM ls, SCM delimiter, SCM grammar),
356 "Append the string in the string list @var{ls}, using the string\n"
357 "@var{delim} as a delimiter between the elements of @var{ls}.\n"
358 "@var{grammar} is a symbol which specifies how the delimiter is\n"
359 "placed between the strings, and defaults to the symbol\n"
364 "Insert the separator between list elements. An empty string\n"
365 "will produce an empty list.\n"
366 "@item string-infix\n"
367 "Like @code{infix}, but will raise an error if given the empty\n"
370 "Insert the separator after every list element.\n"
372 "Insert the separator before each list element.\n"
374 #define FUNC_NAME s_scm_string_join
377 #define GRAM_STRICT_INFIX 1
378 #define GRAM_SUFFIX 2
379 #define GRAM_PREFIX 3
382 int gram = GRAM_INFIX;
386 long strings = scm_ilength (ls);
388 /* Validate the string list. */
390 SCM_WRONG_TYPE_ARG (1, ls);
392 /* Validate the delimiter and record its length. */
393 if (SCM_UNBNDP (delimiter))
395 delimiter = scm_from_locale_string (" ");
399 del_len = scm_c_string_length (delimiter);
401 /* Validate the grammar symbol and remember the grammar. */
402 if (SCM_UNBNDP (grammar))
404 else if (scm_is_eq (grammar, scm_sym_infix))
406 else if (scm_is_eq (grammar, scm_sym_strict_infix))
407 gram = GRAM_STRICT_INFIX;
408 else if (scm_is_eq (grammar, scm_sym_suffix))
410 else if (scm_is_eq (grammar, scm_sym_prefix))
413 SCM_WRONG_TYPE_ARG (3, grammar);
415 /* Check grammar constraints and calculate the space required for
420 if (!scm_is_null (ls))
421 len = (strings > 0) ? ((strings - 1) * del_len) : 0;
423 case GRAM_STRICT_INFIX:
425 SCM_MISC_ERROR ("strict-infix grammar requires non-empty list",
427 len = (strings - 1) * del_len;
430 len = strings * del_len;
435 while (scm_is_pair (tmp))
437 len += scm_c_string_length (SCM_CAR (tmp));
441 result = scm_i_make_string (len, &p);
447 case GRAM_STRICT_INFIX:
448 while (scm_is_pair (tmp))
450 append_string (&p, &len, SCM_CAR (tmp));
451 if (!scm_is_null (SCM_CDR (tmp)) && del_len > 0)
452 append_string (&p, &len, delimiter);
457 while (scm_is_pair (tmp))
459 append_string (&p, &len, SCM_CAR (tmp));
461 append_string (&p, &len, delimiter);
466 while (scm_is_pair (tmp))
469 append_string (&p, &len, delimiter);
470 append_string (&p, &len, SCM_CAR (tmp));
478 #undef GRAM_STRICT_INFIX
485 /* There are a number of functions to consider here for Scheme and C:
487 string-copy STR [start [end]] ;; SRFI-13 variant of R5RS string-copy
488 substring/copy STR start [end] ;; Guile variant of R5RS substring
490 scm_string_copy (str) ;; Old function from Guile
491 scm_substring_copy (str, [start, [end]])
492 ;; C version of SRFI-13 string-copy
493 ;; and C version of substring/copy
495 The C function underlying string-copy is not exported to C
496 programs. scm_substring_copy is defined in strings.c as the
497 underlying function of substring/copy and allows an optional START
501 SCM scm_srfi13_substring_copy (SCM str, SCM start, SCM end);
503 SCM_DEFINE (scm_srfi13_substring_copy, "string-copy", 1, 2, 0,
504 (SCM str, SCM start, SCM end),
505 "Return a freshly allocated copy of the string @var{str}. If\n"
506 "given, @var{start} and @var{end} delimit the portion of\n"
507 "@var{str} which is copied.")
508 #define FUNC_NAME s_scm_srfi13_substring_copy
513 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
516 return scm_c_substring_copy (str, cstart, cend);
521 scm_string_copy (SCM str)
523 return scm_c_substring (str, 0, scm_c_string_length (str));
526 SCM_DEFINE (scm_string_copy_x, "string-copy!", 3, 2, 0,
527 (SCM target, SCM tstart, SCM s, SCM start, SCM end),
528 "Copy the sequence of characters from index range [@var{start},\n"
529 "@var{end}) in string @var{s} to string @var{target}, beginning\n"
530 "at index @var{tstart}. The characters are copied left-to-right\n"
531 "or right-to-left as needed -- the copy is guaranteed to work,\n"
532 "even if @var{target} and @var{s} are the same string. It is an\n"
533 "error if the copy operation runs off the end of the target\n"
535 #define FUNC_NAME s_scm_string_copy_x
539 size_t cstart, cend, ctstart, dummy, len;
540 SCM sdummy = SCM_UNDEFINED;
542 MY_VALIDATE_SUBSTRING_SPEC (1, target,
545 MY_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cstr,
549 SCM_ASSERT_RANGE (3, s, len <= scm_i_string_length (target) - ctstart);
551 ctarget = scm_i_string_writable_chars (target);
552 memmove (ctarget + ctstart, cstr + cstart, len);
553 scm_i_string_stop_writing ();
554 scm_remember_upto_here_1 (target);
556 return SCM_UNSPECIFIED;
560 SCM_DEFINE (scm_substring_move_x, "substring-move!", 5, 0, 0,
561 (SCM str1, SCM start1, SCM end1, SCM str2, SCM start2),
562 "Copy the substring of @var{str1} bounded by @var{start1} and @var{end1}\n"
563 "into @var{str2} beginning at position @var{start2}.\n"
564 "@var{str1} and @var{str2} can be the same string.")
565 #define FUNC_NAME s_scm_substring_move_x
567 return scm_string_copy_x (str2, start2, str1, start1, end1);
571 SCM_DEFINE (scm_string_take, "string-take", 2, 0, 0,
573 "Return the @var{n} first characters of @var{s}.")
574 #define FUNC_NAME s_scm_string_take
576 return scm_substring (s, SCM_INUM0, n);
581 SCM_DEFINE (scm_string_drop, "string-drop", 2, 0, 0,
583 "Return all but the first @var{n} characters of @var{s}.")
584 #define FUNC_NAME s_scm_string_drop
586 return scm_substring (s, n, SCM_UNDEFINED);
591 SCM_DEFINE (scm_string_take_right, "string-take-right", 2, 0, 0,
593 "Return the @var{n} last characters of @var{s}.")
594 #define FUNC_NAME s_scm_string_take_right
596 return scm_substring (s,
597 scm_difference (scm_string_length (s), n),
603 SCM_DEFINE (scm_string_drop_right, "string-drop-right", 2, 0, 0,
605 "Return all but the last @var{n} characters of @var{s}.")
606 #define FUNC_NAME s_scm_string_drop_right
608 return scm_substring (s,
610 scm_difference (scm_string_length (s), n));
615 SCM_DEFINE (scm_string_pad, "string-pad", 2, 3, 0,
616 (SCM s, SCM len, SCM chr, SCM start, SCM end),
617 "Take that characters from @var{start} to @var{end} from the\n"
618 "string @var{s} and return a new string, right-padded by the\n"
619 "character @var{chr} to length @var{len}. If the resulting\n"
620 "string is longer than @var{len}, it is truncated on the right.")
621 #define FUNC_NAME s_scm_string_pad
624 size_t cstart, cend, clen;
626 MY_VALIDATE_SUBSTRING_SPEC (1, s,
629 clen = scm_to_size_t (len);
631 if (SCM_UNBNDP (chr))
635 SCM_VALIDATE_CHAR (3, chr);
636 cchr = SCM_CHAR (chr);
638 if (clen < (cend - cstart))
639 return scm_c_substring (s, cend - clen, cend);
645 result = scm_i_make_string (clen, &dst);
646 memset (dst, cchr, (clen - (cend - cstart)));
647 memmove (dst + clen - (cend - cstart),
648 scm_i_string_chars (s) + cstart, cend - cstart);
655 SCM_DEFINE (scm_string_pad_right, "string-pad-right", 2, 3, 0,
656 (SCM s, SCM len, SCM chr, SCM start, SCM end),
657 "Take that characters from @var{start} to @var{end} from the\n"
658 "string @var{s} and return a new string, left-padded by the\n"
659 "character @var{chr} to length @var{len}. If the resulting\n"
660 "string is longer than @var{len}, it is truncated on the left.")
661 #define FUNC_NAME s_scm_string_pad_right
664 size_t cstart, cend, clen;
666 MY_VALIDATE_SUBSTRING_SPEC (1, s,
669 clen = scm_to_size_t (len);
671 if (SCM_UNBNDP (chr))
675 SCM_VALIDATE_CHAR (3, chr);
676 cchr = SCM_CHAR (chr);
678 if (clen < (cend - cstart))
679 return scm_c_substring (s, cstart, cstart + clen);
685 result = scm_i_make_string (clen, &dst);
686 memset (dst + (cend - cstart), cchr, clen - (cend - cstart));
687 memmove (dst, scm_i_string_chars (s) + cstart, cend - cstart);
694 SCM_DEFINE (scm_string_trim, "string-trim", 1, 3, 0,
695 (SCM s, SCM char_pred, SCM start, SCM end),
696 "Trim @var{s} by skipping over all characters on the left\n"
697 "that satisfy the parameter @var{char_pred}:\n"
701 "if it is the character @var{ch}, characters equal to\n"
702 "@var{ch} are trimmed,\n"
705 "if it is a procedure @var{pred} characters that\n"
706 "satisfy @var{pred} are trimmed,\n"
709 "if it is a character set, characters in that set are trimmed.\n"
712 "If called without a @var{char_pred} argument, all whitespace is\n"
714 #define FUNC_NAME s_scm_string_trim
719 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
722 if (SCM_UNBNDP (char_pred))
724 while (cstart < cend)
726 if (!isspace((int) (unsigned char) cstr[cstart]))
731 else if (SCM_CHARP (char_pred))
733 char chr = SCM_CHAR (char_pred);
734 while (cstart < cend)
736 if (chr != cstr[cstart])
741 else if (SCM_CHARSETP (char_pred))
743 while (cstart < cend)
745 if (!SCM_CHARSET_GET (char_pred, cstr[cstart]))
752 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
753 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
755 while (cstart < cend)
759 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
760 if (scm_is_false (res))
762 cstr = scm_i_string_chars (s);
766 return scm_c_substring (s, cstart, cend);
771 SCM_DEFINE (scm_string_trim_right, "string-trim-right", 1, 3, 0,
772 (SCM s, SCM char_pred, SCM start, SCM end),
773 "Trim @var{s} by skipping over all characters on the rightt\n"
774 "that satisfy the parameter @var{char_pred}:\n"
778 "if it is the character @var{ch}, characters equal to @var{ch}\n"
782 "if it is a procedure @var{pred} characters that satisfy\n"
783 "@var{pred} are trimmed,\n"
786 "if it is a character sets, all characters in that set are\n"
790 "If called without a @var{char_pred} argument, all whitespace is\n"
792 #define FUNC_NAME s_scm_string_trim_right
797 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
800 if (SCM_UNBNDP (char_pred))
802 while (cstart < cend)
804 if (!isspace((int) (unsigned char) cstr[cend - 1]))
809 else if (SCM_CHARP (char_pred))
811 char chr = SCM_CHAR (char_pred);
812 while (cstart < cend)
814 if (chr != cstr[cend - 1])
819 else if (SCM_CHARSETP (char_pred))
821 while (cstart < cend)
823 if (!SCM_CHARSET_GET (char_pred, cstr[cend - 1]))
830 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
831 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
833 while (cstart < cend)
837 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cend - 1]));
838 if (scm_is_false (res))
840 cstr = scm_i_string_chars (s);
844 return scm_c_substring (s, cstart, cend);
849 SCM_DEFINE (scm_string_trim_both, "string-trim-both", 1, 3, 0,
850 (SCM s, SCM char_pred, SCM start, SCM end),
851 "Trim @var{s} by skipping over all characters on both sides of\n"
852 "the string that satisfy the parameter @var{char_pred}:\n"
856 "if it is the character @var{ch}, characters equal to @var{ch}\n"
860 "if it is a procedure @var{pred} characters that satisfy\n"
861 "@var{pred} are trimmed,\n"
864 "if it is a character set, the characters in the set are\n"
868 "If called without a @var{char_pred} argument, all whitespace is\n"
870 #define FUNC_NAME s_scm_string_trim_both
875 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
878 if (SCM_UNBNDP (char_pred))
880 while (cstart < cend)
882 if (!isspace((int) (unsigned char) cstr[cstart]))
886 while (cstart < cend)
888 if (!isspace((int) (unsigned char) cstr[cend - 1]))
893 else if (SCM_CHARP (char_pred))
895 char chr = SCM_CHAR (char_pred);
896 while (cstart < cend)
898 if (chr != cstr[cstart])
902 while (cstart < cend)
904 if (chr != cstr[cend - 1])
909 else if (SCM_CHARSETP (char_pred))
911 while (cstart < cend)
913 if (!SCM_CHARSET_GET (char_pred, cstr[cstart]))
917 while (cstart < cend)
919 if (!SCM_CHARSET_GET (char_pred, cstr[cend - 1]))
926 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
927 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
929 while (cstart < cend)
933 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
934 if (scm_is_false (res))
936 cstr = scm_i_string_chars (s);
939 while (cstart < cend)
943 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cend - 1]));
944 if (scm_is_false (res))
946 cstr = scm_i_string_chars (s);
950 return scm_c_substring (s, cstart, cend);
955 SCM_DEFINE (scm_substring_fill_x, "string-fill!", 2, 2, 0,
956 (SCM str, SCM chr, SCM start, SCM end),
957 "Stores @var{chr} in every element of the given @var{str} and\n"
958 "returns an unspecified value.")
959 #define FUNC_NAME s_scm_substring_fill_x
966 /* Older versions of Guile provided the function
967 scm_substring_fill_x with the following order of arguments:
971 We accomodate this here by detecting such a usage and reordering
982 MY_VALIDATE_SUBSTRING_SPEC (1, str,
985 SCM_VALIDATE_CHAR_COPY (2, chr, c);
987 cstr = scm_i_string_writable_chars (str);
988 for (k = cstart; k < cend; k++)
990 scm_i_string_stop_writing ();
991 scm_remember_upto_here_1 (str);
993 return SCM_UNSPECIFIED;
998 scm_string_fill_x (SCM str, SCM chr)
1000 return scm_substring_fill_x (str, chr, SCM_UNDEFINED, SCM_UNDEFINED);
1003 SCM_DEFINE (scm_string_compare, "string-compare", 5, 4, 0,
1004 (SCM s1, SCM s2, SCM proc_lt, SCM proc_eq, SCM proc_gt, SCM start1, SCM end1, SCM start2, SCM end2),
1005 "Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the\n"
1006 "mismatch index, depending upon whether @var{s1} is less than,\n"
1007 "equal to, or greater than @var{s2}. The mismatch index is the\n"
1008 "largest index @var{i} such that for every 0 <= @var{j} <\n"
1009 "@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is,\n"
1010 "@var{i} is the first position that does not match.")
1011 #define FUNC_NAME s_scm_string_compare
1013 const unsigned char *cstr1, *cstr2;
1014 size_t cstart1, cend1, cstart2, cend2;
1017 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1020 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1023 SCM_VALIDATE_PROC (3, proc_lt);
1024 SCM_VALIDATE_PROC (4, proc_eq);
1025 SCM_VALIDATE_PROC (5, proc_gt);
1027 while (cstart1 < cend1 && cstart2 < cend2)
1029 if (cstr1[cstart1] < cstr2[cstart2])
1034 else if (cstr1[cstart1] > cstr2[cstart2])
1042 if (cstart1 < cend1)
1044 else if (cstart2 < cend2)
1050 scm_remember_upto_here_2 (s1, s2);
1051 return scm_call_1 (proc, scm_from_size_t (cstart1));
1056 SCM_DEFINE (scm_string_compare_ci, "string-compare-ci", 5, 4, 0,
1057 (SCM s1, SCM s2, SCM proc_lt, SCM proc_eq, SCM proc_gt, SCM start1, SCM end1, SCM start2, SCM end2),
1058 "Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the\n"
1059 "mismatch index, depending upon whether @var{s1} is less than,\n"
1060 "equal to, or greater than @var{s2}. The mismatch index is the\n"
1061 "largest index @var{i} such that for every 0 <= @var{j} <\n"
1062 "@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is,\n"
1063 "@var{i} is the first position that does not match. The\n"
1064 "character comparison is done case-insensitively.")
1065 #define FUNC_NAME s_scm_string_compare_ci
1067 const unsigned char *cstr1, *cstr2;
1068 size_t cstart1, cend1, cstart2, cend2;
1071 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1074 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1077 SCM_VALIDATE_PROC (3, proc_lt);
1078 SCM_VALIDATE_PROC (4, proc_eq);
1079 SCM_VALIDATE_PROC (5, proc_gt);
1081 while (cstart1 < cend1 && cstart2 < cend2)
1083 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1088 else if (scm_c_downcase (cstr1[cstart1])
1089 > scm_c_downcase (cstr2[cstart2]))
1098 if (cstart1 < cend1)
1100 else if (cstart2 < cend2)
1106 scm_remember_upto_here (s1, s2);
1107 return scm_call_1 (proc, scm_from_size_t (cstart1));
1112 SCM_DEFINE (scm_string_eq, "string=", 2, 4, 0,
1113 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1114 "Return @code{#f} if @var{s1} and @var{s2} are not equal, a true\n"
1116 #define FUNC_NAME s_scm_string_eq
1118 const char *cstr1, *cstr2;
1119 size_t cstart1, cend1, cstart2, cend2;
1121 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1124 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1128 if ((cend1 - cstart1) != (cend2 - cstart2))
1131 while (cstart1 < cend1)
1133 if (cstr1[cstart1] < cstr2[cstart2])
1135 else if (cstr1[cstart1] > cstr2[cstart2])
1141 scm_remember_upto_here_2 (s1, s2);
1142 return scm_from_size_t (cstart1);
1145 scm_remember_upto_here_2 (s1, s2);
1151 SCM_DEFINE (scm_string_neq, "string<>", 2, 4, 0,
1152 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1153 "Return @code{#f} if @var{s1} and @var{s2} are equal, a true\n"
1155 #define FUNC_NAME s_scm_string_neq
1157 const char *cstr1, *cstr2;
1158 size_t cstart1, cend1, cstart2, cend2;
1160 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1163 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1167 while (cstart1 < cend1 && cstart2 < cend2)
1169 if (cstr1[cstart1] < cstr2[cstart2])
1171 else if (cstr1[cstart1] > cstr2[cstart2])
1176 if (cstart1 < cend1)
1178 else if (cstart2 < cend2)
1184 scm_remember_upto_here_2 (s1, s2);
1185 return scm_from_size_t (cstart1);
1188 scm_remember_upto_here_2 (s1, s2);
1194 SCM_DEFINE (scm_string_lt, "string<", 2, 4, 0,
1195 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1196 "Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a\n"
1197 "true value otherwise.")
1198 #define FUNC_NAME s_scm_string_lt
1200 const unsigned char *cstr1, *cstr2;
1201 size_t cstart1, cend1, cstart2, cend2;
1203 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1206 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1210 while (cstart1 < cend1 && cstart2 < cend2)
1212 if (cstr1[cstart1] < cstr2[cstart2])
1214 else if (cstr1[cstart1] > cstr2[cstart2])
1219 if (cstart1 < cend1)
1221 else if (cstart2 < cend2)
1227 scm_remember_upto_here_2 (s1, s2);
1228 return scm_from_size_t (cstart1);
1231 scm_remember_upto_here_2 (s1, s2);
1237 SCM_DEFINE (scm_string_gt, "string>", 2, 4, 0,
1238 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1239 "Return @code{#f} if @var{s1} is less or equal to @var{s2}, a\n"
1240 "true value otherwise.")
1241 #define FUNC_NAME s_scm_string_gt
1243 const unsigned char *cstr1, *cstr2;
1244 size_t cstart1, cend1, cstart2, cend2;
1246 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1249 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1253 while (cstart1 < cend1 && cstart2 < cend2)
1255 if (cstr1[cstart1] < cstr2[cstart2])
1257 else if (cstr1[cstart1] > cstr2[cstart2])
1262 if (cstart1 < cend1)
1264 else if (cstart2 < cend2)
1270 scm_remember_upto_here_2 (s1, s2);
1271 return scm_from_size_t (cstart1);
1274 scm_remember_upto_here_2 (s1, s2);
1280 SCM_DEFINE (scm_string_le, "string<=", 2, 4, 0,
1281 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1282 "Return @code{#f} if @var{s1} is greater to @var{s2}, a true\n"
1284 #define FUNC_NAME s_scm_string_le
1286 const unsigned char *cstr1, *cstr2;
1287 size_t cstart1, cend1, cstart2, cend2;
1289 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1292 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1296 while (cstart1 < cend1 && cstart2 < cend2)
1298 if (cstr1[cstart1] < cstr2[cstart2])
1300 else if (cstr1[cstart1] > cstr2[cstart2])
1305 if (cstart1 < cend1)
1307 else if (cstart2 < cend2)
1313 scm_remember_upto_here_2 (s1, s2);
1314 return scm_from_size_t (cstart1);
1317 scm_remember_upto_here_2 (s1, s2);
1323 SCM_DEFINE (scm_string_ge, "string>=", 2, 4, 0,
1324 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1325 "Return @code{#f} if @var{s1} is less to @var{s2}, a true value\n"
1327 #define FUNC_NAME s_scm_string_ge
1329 const unsigned char *cstr1, *cstr2;
1330 size_t cstart1, cend1, cstart2, cend2;
1332 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1335 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1339 while (cstart1 < cend1 && cstart2 < cend2)
1341 if (cstr1[cstart1] < cstr2[cstart2])
1343 else if (cstr1[cstart1] > cstr2[cstart2])
1348 if (cstart1 < cend1)
1350 else if (cstart2 < cend2)
1356 scm_remember_upto_here_2 (s1, s2);
1357 return scm_from_size_t (cstart1);
1360 scm_remember_upto_here_2 (s1, s2);
1366 SCM_DEFINE (scm_string_ci_eq, "string-ci=", 2, 4, 0,
1367 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1368 "Return @code{#f} if @var{s1} and @var{s2} are not equal, a true\n"
1369 "value otherwise. The character comparison is done\n"
1370 "case-insensitively.")
1371 #define FUNC_NAME s_scm_string_ci_eq
1373 const char *cstr1, *cstr2;
1374 size_t cstart1, cend1, cstart2, cend2;
1376 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1379 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1383 while (cstart1 < cend1 && cstart2 < cend2)
1385 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1387 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
1392 if (cstart1 < cend1)
1394 else if (cstart2 < cend2)
1400 scm_remember_upto_here_2 (s1, s2);
1401 return scm_from_size_t (cstart1);
1404 scm_remember_upto_here_2 (s1, s2);
1410 SCM_DEFINE (scm_string_ci_neq, "string-ci<>", 2, 4, 0,
1411 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1412 "Return @code{#f} if @var{s1} and @var{s2} are equal, a true\n"
1413 "value otherwise. The character comparison is done\n"
1414 "case-insensitively.")
1415 #define FUNC_NAME s_scm_string_ci_neq
1417 const char *cstr1, *cstr2;
1418 size_t cstart1, cend1, cstart2, cend2;
1420 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1423 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1427 while (cstart1 < cend1 && cstart2 < cend2)
1429 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1431 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
1436 if (cstart1 < cend1)
1438 else if (cstart2 < cend2)
1444 scm_remember_upto_here_2 (s1, s2);
1445 return scm_from_size_t (cstart1);
1448 scm_remember_upto_here_2 (s1, s2);
1454 SCM_DEFINE (scm_string_ci_lt, "string-ci<", 2, 4, 0,
1455 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1456 "Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a\n"
1457 "true value otherwise. The character comparison is done\n"
1458 "case-insensitively.")
1459 #define FUNC_NAME s_scm_string_ci_lt
1461 const unsigned char *cstr1, *cstr2;
1462 size_t cstart1, cend1, cstart2, cend2;
1464 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1467 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1471 while (cstart1 < cend1 && cstart2 < cend2)
1473 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1475 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
1480 if (cstart1 < cend1)
1482 else if (cstart2 < cend2)
1488 scm_remember_upto_here_2 (s1, s2);
1489 return scm_from_size_t (cstart1);
1492 scm_remember_upto_here_2 (s1, s2);
1498 SCM_DEFINE (scm_string_ci_gt, "string-ci>", 2, 4, 0,
1499 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1500 "Return @code{#f} if @var{s1} is less or equal to @var{s2}, a\n"
1501 "true value otherwise. The character comparison is done\n"
1502 "case-insensitively.")
1503 #define FUNC_NAME s_scm_string_ci_gt
1505 const unsigned char *cstr1, *cstr2;
1506 size_t cstart1, cend1, cstart2, cend2;
1508 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1511 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1515 while (cstart1 < cend1 && cstart2 < cend2)
1517 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1519 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
1524 if (cstart1 < cend1)
1526 else if (cstart2 < cend2)
1532 scm_remember_upto_here_2 (s1, s2);
1533 return scm_from_size_t (cstart1);
1536 scm_remember_upto_here_2 (s1, s2);
1542 SCM_DEFINE (scm_string_ci_le, "string-ci<=", 2, 4, 0,
1543 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1544 "Return @code{#f} if @var{s1} is greater to @var{s2}, a true\n"
1545 "value otherwise. The character comparison is done\n"
1546 "case-insensitively.")
1547 #define FUNC_NAME s_scm_string_ci_le
1549 const unsigned char *cstr1, *cstr2;
1550 size_t cstart1, cend1, cstart2, cend2;
1552 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1555 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1559 while (cstart1 < cend1 && cstart2 < cend2)
1561 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1563 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
1568 if (cstart1 < cend1)
1570 else if (cstart2 < cend2)
1576 scm_remember_upto_here_2 (s1, s2);
1577 return scm_from_size_t (cstart1);
1580 scm_remember_upto_here_2 (s1, s2);
1586 SCM_DEFINE (scm_string_ci_ge, "string-ci>=", 2, 4, 0,
1587 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1588 "Return @code{#f} if @var{s1} is less to @var{s2}, a true value\n"
1589 "otherwise. The character comparison is done\n"
1590 "case-insensitively.")
1591 #define FUNC_NAME s_scm_string_ci_ge
1593 const unsigned char *cstr1, *cstr2;
1594 size_t cstart1, cend1, cstart2, cend2;
1596 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (1, s1, cstr1,
1599 MY_VALIDATE_SUBSTRING_SPEC_UCOPY (2, s2, cstr2,
1603 while (cstart1 < cend1 && cstart2 < cend2)
1605 if (scm_c_downcase (cstr1[cstart1]) < scm_c_downcase (cstr2[cstart2]))
1607 else if (scm_c_downcase (cstr1[cstart1]) > scm_c_downcase (cstr2[cstart2]))
1612 if (cstart1 < cend1)
1614 else if (cstart2 < cend2)
1620 scm_remember_upto_here_2 (s1, s2);
1621 return scm_from_size_t (cstart1);
1624 scm_remember_upto_here_2 (s1, s2);
1629 SCM_DEFINE (scm_substring_hash, "string-hash", 1, 3, 0,
1630 (SCM s, SCM bound, SCM start, SCM end),
1631 "Compute a hash value for @var{S}. the optional argument "
1632 "@var{bound} is a non-negative exact "
1633 "integer specifying the range of the hash function. "
1634 "A positive value restricts the return value to the "
1636 #define FUNC_NAME s_scm_substring_hash
1638 if (SCM_UNBNDP (bound))
1639 bound = scm_from_intmax (SCM_MOST_POSITIVE_FIXNUM);
1640 if (SCM_UNBNDP (start))
1642 return scm_hash (scm_substring_shared (s, start, end), bound);
1646 SCM_DEFINE (scm_substring_hash_ci, "string-hash-ci", 1, 3, 0,
1647 (SCM s, SCM bound, SCM start, SCM end),
1648 "Compute a hash value for @var{S}. the optional argument "
1649 "@var{bound} is a non-negative exact "
1650 "integer specifying the range of the hash function. "
1651 "A positive value restricts the return value to the "
1653 #define FUNC_NAME s_scm_substring_hash_ci
1655 return scm_substring_hash (scm_substring_downcase (s, start, end),
1657 SCM_UNDEFINED, SCM_UNDEFINED);
1661 SCM_DEFINE (scm_string_prefix_length, "string-prefix-length", 2, 4, 0,
1662 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1663 "Return the length of the longest common prefix of the two\n"
1665 #define FUNC_NAME s_scm_string_prefix_length
1667 const char *cstr1, *cstr2;
1668 size_t cstart1, cend1, cstart2, cend2;
1671 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1674 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1677 while (cstart1 < cend1 && cstart2 < cend2)
1679 if (cstr1[cstart1] != cstr2[cstart2])
1687 scm_remember_upto_here_2 (s1, s2);
1688 return scm_from_size_t (len);
1693 SCM_DEFINE (scm_string_prefix_length_ci, "string-prefix-length-ci", 2, 4, 0,
1694 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1695 "Return the length of the longest common prefix of the two\n"
1696 "strings, ignoring character case.")
1697 #define FUNC_NAME s_scm_string_prefix_length_ci
1699 const char *cstr1, *cstr2;
1700 size_t cstart1, cend1, cstart2, cend2;
1703 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1706 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1709 while (cstart1 < cend1 && cstart2 < cend2)
1711 if (scm_c_downcase (cstr1[cstart1]) != scm_c_downcase (cstr2[cstart2]))
1719 scm_remember_upto_here_2 (s1, s2);
1720 return scm_from_size_t (len);
1725 SCM_DEFINE (scm_string_suffix_length, "string-suffix-length", 2, 4, 0,
1726 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1727 "Return the length of the longest common suffix of the two\n"
1729 #define FUNC_NAME s_scm_string_suffix_length
1731 const char *cstr1, *cstr2;
1732 size_t cstart1, cend1, cstart2, cend2;
1735 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1738 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1741 while (cstart1 < cend1 && cstart2 < cend2)
1745 if (cstr1[cend1] != cstr2[cend2])
1751 scm_remember_upto_here_2 (s1, s2);
1752 return scm_from_size_t (len);
1757 SCM_DEFINE (scm_string_suffix_length_ci, "string-suffix-length-ci", 2, 4, 0,
1758 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1759 "Return the length of the longest common suffix of the two\n"
1760 "strings, ignoring character case.")
1761 #define FUNC_NAME s_scm_string_suffix_length_ci
1763 const char *cstr1, *cstr2;
1764 size_t cstart1, cend1, cstart2, cend2;
1767 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1770 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1773 while (cstart1 < cend1 && cstart2 < cend2)
1777 if (scm_c_downcase (cstr1[cend1]) != scm_c_downcase (cstr2[cend2]))
1783 scm_remember_upto_here_2 (s1, s2);
1784 return scm_from_size_t (len);
1789 SCM_DEFINE (scm_string_prefix_p, "string-prefix?", 2, 4, 0,
1790 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1791 "Is @var{s1} a prefix of @var{s2}?")
1792 #define FUNC_NAME s_scm_string_prefix_p
1794 const char *cstr1, *cstr2;
1795 size_t cstart1, cend1, cstart2, cend2;
1796 size_t len = 0, len1;
1798 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1801 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1804 len1 = cend1 - cstart1;
1805 while (cstart1 < cend1 && cstart2 < cend2)
1807 if (cstr1[cstart1] != cstr2[cstart2])
1815 scm_remember_upto_here_2 (s1, s2);
1816 return scm_from_bool (len == len1);
1821 SCM_DEFINE (scm_string_prefix_ci_p, "string-prefix-ci?", 2, 4, 0,
1822 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1823 "Is @var{s1} a prefix of @var{s2}, ignoring character case?")
1824 #define FUNC_NAME s_scm_string_prefix_ci_p
1826 const char *cstr1, *cstr2;
1827 size_t cstart1, cend1, cstart2, cend2;
1828 size_t len = 0, len1;
1830 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1833 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1836 len1 = cend1 - cstart1;
1837 while (cstart1 < cend1 && cstart2 < cend2)
1839 if (scm_c_downcase (cstr1[cstart1]) != scm_c_downcase (cstr2[cstart2]))
1847 scm_remember_upto_here_2 (s1, s2);
1848 return scm_from_bool (len == len1);
1853 SCM_DEFINE (scm_string_suffix_p, "string-suffix?", 2, 4, 0,
1854 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1855 "Is @var{s1} a suffix of @var{s2}?")
1856 #define FUNC_NAME s_scm_string_suffix_p
1858 const char *cstr1, *cstr2;
1859 size_t cstart1, cend1, cstart2, cend2;
1860 size_t len = 0, len1;
1862 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1865 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1868 len1 = cend1 - cstart1;
1869 while (cstart1 < cend1 && cstart2 < cend2)
1873 if (cstr1[cend1] != cstr2[cend2])
1879 scm_remember_upto_here_2 (s1, s2);
1880 return scm_from_bool (len == len1);
1885 SCM_DEFINE (scm_string_suffix_ci_p, "string-suffix-ci?", 2, 4, 0,
1886 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
1887 "Is @var{s1} a suffix of @var{s2}, ignoring character case?")
1888 #define FUNC_NAME s_scm_string_suffix_ci_p
1890 const char *cstr1, *cstr2;
1891 size_t cstart1, cend1, cstart2, cend2;
1892 size_t len = 0, len1;
1894 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cstr1,
1897 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cstr2,
1900 len1 = cend1 - cstart1;
1901 while (cstart1 < cend1 && cstart2 < cend2)
1905 if (scm_c_downcase (cstr1[cend1]) != scm_c_downcase (cstr2[cend2]))
1911 scm_remember_upto_here_2 (s1, s2);
1912 return scm_from_bool (len == len1);
1917 SCM_DEFINE (scm_string_index, "string-index", 2, 2, 0,
1918 (SCM s, SCM char_pred, SCM start, SCM end),
1919 "Search through the string @var{s} from left to right, returning\n"
1920 "the index of the first occurence of a character which\n"
1922 "@itemize @bullet\n"
1924 "equals @var{char_pred}, if it is character,\n"
1927 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
1930 "is in the set @var{char_pred}, if it is a character set.\n"
1932 #define FUNC_NAME s_scm_string_index
1935 size_t cstart, cend;
1937 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
1940 if (SCM_CHARP (char_pred))
1942 char cchr = SCM_CHAR (char_pred);
1943 while (cstart < cend)
1945 if (cchr == cstr[cstart])
1950 else if (SCM_CHARSETP (char_pred))
1952 while (cstart < cend)
1954 if (SCM_CHARSET_GET (char_pred, cstr[cstart]))
1961 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
1962 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
1964 while (cstart < cend)
1967 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
1968 if (scm_is_true (res))
1970 cstr = scm_i_string_chars (s);
1975 scm_remember_upto_here_1 (s);
1979 scm_remember_upto_here_1 (s);
1980 return scm_from_size_t (cstart);
1984 SCM_DEFINE (scm_string_index_right, "string-index-right", 2, 2, 0,
1985 (SCM s, SCM char_pred, SCM start, SCM end),
1986 "Search through the string @var{s} from right to left, returning\n"
1987 "the index of the last occurence of a character which\n"
1989 "@itemize @bullet\n"
1991 "equals @var{char_pred}, if it is character,\n"
1994 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
1997 "is in the set if @var{char_pred} is a character set.\n"
1999 #define FUNC_NAME s_scm_string_index_right
2002 size_t cstart, cend;
2004 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2007 if (SCM_CHARP (char_pred))
2009 char cchr = SCM_CHAR (char_pred);
2010 while (cstart < cend)
2013 if (cchr == cstr[cend])
2017 else if (SCM_CHARSETP (char_pred))
2019 while (cstart < cend)
2022 if (SCM_CHARSET_GET (char_pred, cstr[cend]))
2028 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
2029 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
2031 while (cstart < cend)
2035 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cend]));
2036 if (scm_is_true (res))
2038 cstr = scm_i_string_chars (s);
2042 scm_remember_upto_here_1 (s);
2046 scm_remember_upto_here_1 (s);
2047 return scm_from_size_t (cend);
2051 SCM_DEFINE (scm_string_rindex, "string-rindex", 2, 2, 0,
2052 (SCM s, SCM char_pred, SCM start, SCM end),
2053 "Search through the string @var{s} from right to left, returning\n"
2054 "the index of the last occurence of a character which\n"
2056 "@itemize @bullet\n"
2058 "equals @var{char_pred}, if it is character,\n"
2061 "satisifies the predicate @var{char_pred}, if it is a procedure,\n"
2064 "is in the set if @var{char_pred} is a character set.\n"
2066 #define FUNC_NAME s_scm_string_rindex
2068 return scm_string_index_right (s, char_pred, start, end);
2072 SCM_DEFINE (scm_string_skip, "string-skip", 2, 2, 0,
2073 (SCM s, SCM char_pred, SCM start, SCM end),
2074 "Search through the string @var{s} from left to right, returning\n"
2075 "the index of the first occurence of a character which\n"
2077 "@itemize @bullet\n"
2079 "does not equal @var{char_pred}, if it is character,\n"
2082 "does not satisify the predicate @var{char_pred}, if it is a\n"
2086 "is not in the set if @var{char_pred} is a character set.\n"
2088 #define FUNC_NAME s_scm_string_skip
2091 size_t cstart, cend;
2093 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2096 if (SCM_CHARP (char_pred))
2098 char cchr = SCM_CHAR (char_pred);
2099 while (cstart < cend)
2101 if (cchr != cstr[cstart])
2106 else if (SCM_CHARSETP (char_pred))
2108 while (cstart < cend)
2110 if (!SCM_CHARSET_GET (char_pred, cstr[cstart]))
2117 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
2118 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
2120 while (cstart < cend)
2123 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
2124 if (scm_is_false (res))
2126 cstr = scm_i_string_chars (s);
2131 scm_remember_upto_here_1 (s);
2135 scm_remember_upto_here_1 (s);
2136 return scm_from_size_t (cstart);
2141 SCM_DEFINE (scm_string_skip_right, "string-skip-right", 2, 2, 0,
2142 (SCM s, SCM char_pred, SCM start, SCM end),
2143 "Search through the string @var{s} from right to left, returning\n"
2144 "the index of the last occurence of a character which\n"
2146 "@itemize @bullet\n"
2148 "does not equal @var{char_pred}, if it is character,\n"
2151 "does not satisfy the predicate @var{char_pred}, if it is a\n"
2155 "is not in the set if @var{char_pred} is a character set.\n"
2157 #define FUNC_NAME s_scm_string_skip_right
2160 size_t cstart, cend;
2162 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2165 if (SCM_CHARP (char_pred))
2167 char cchr = SCM_CHAR (char_pred);
2168 while (cstart < cend)
2171 if (cchr != cstr[cend])
2175 else if (SCM_CHARSETP (char_pred))
2177 while (cstart < cend)
2180 if (!SCM_CHARSET_GET (char_pred, cstr[cend]))
2186 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
2187 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
2189 while (cstart < cend)
2193 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cend]));
2194 if (scm_is_false (res))
2196 cstr = scm_i_string_chars (s);
2200 scm_remember_upto_here_1 (s);
2204 scm_remember_upto_here_1 (s);
2205 return scm_from_size_t (cend);
2211 SCM_DEFINE (scm_string_count, "string-count", 2, 2, 0,
2212 (SCM s, SCM char_pred, SCM start, SCM end),
2213 "Return the count of the number of characters in the string\n"
2216 "@itemize @bullet\n"
2218 "equals @var{char_pred}, if it is character,\n"
2221 "satisifies the predicate @var{char_pred}, if it is a procedure.\n"
2224 "is in the set @var{char_pred}, if it is a character set.\n"
2226 #define FUNC_NAME s_scm_string_count
2229 size_t cstart, cend;
2232 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
2235 if (SCM_CHARP (char_pred))
2237 char cchr = SCM_CHAR (char_pred);
2238 while (cstart < cend)
2240 if (cchr == cstr[cstart])
2245 else if (SCM_CHARSETP (char_pred))
2247 while (cstart < cend)
2249 if (SCM_CHARSET_GET (char_pred, cstr[cstart]))
2256 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
2257 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
2259 while (cstart < cend)
2262 res = pred_tramp (char_pred, SCM_MAKE_CHAR (cstr[cstart]));
2263 if (scm_is_true (res))
2265 cstr = scm_i_string_chars (s);
2270 scm_remember_upto_here_1 (s);
2271 return scm_from_size_t (count);
2276 /* FIXME::martin: This should definitely get implemented more
2277 efficiently -- maybe with Knuth-Morris-Pratt, like in the reference
2279 SCM_DEFINE (scm_string_contains, "string-contains", 2, 4, 0,
2280 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
2281 "Does string @var{s1} contain string @var{s2}? Return the index\n"
2282 "in @var{s1} where @var{s2} occurs as a substring, or false.\n"
2283 "The optional start/end indices restrict the operation to the\n"
2284 "indicated substrings.")
2285 #define FUNC_NAME s_scm_string_contains
2287 const char *cs1, * cs2;
2288 size_t cstart1, cend1, cstart2, cend2;
2291 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cs1,
2294 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cs2,
2297 len2 = cend2 - cstart2;
2298 if (cend1 - cstart1 >= len2)
2299 while (cstart1 <= cend1 - len2)
2303 while (i < cend1 && j < cend2 && cs1[i] == cs2[j])
2310 scm_remember_upto_here_2 (s1, s2);
2311 return scm_from_size_t (cstart1);
2316 scm_remember_upto_here_2 (s1, s2);
2322 /* FIXME::martin: This should definitely get implemented more
2323 efficiently -- maybe with Knuth-Morris-Pratt, like in the reference
2325 SCM_DEFINE (scm_string_contains_ci, "string-contains-ci", 2, 4, 0,
2326 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
2327 "Does string @var{s1} contain string @var{s2}? Return the index\n"
2328 "in @var{s1} where @var{s2} occurs as a substring, or false.\n"
2329 "The optional start/end indices restrict the operation to the\n"
2330 "indicated substrings. Character comparison is done\n"
2331 "case-insensitively.")
2332 #define FUNC_NAME s_scm_string_contains_ci
2334 const char *cs1, * cs2;
2335 size_t cstart1, cend1, cstart2, cend2;
2338 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s1, cs1,
2341 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s2, cs2,
2344 len2 = cend2 - cstart2;
2345 if (cend1 - cstart1 >= len2)
2346 while (cstart1 <= cend1 - len2)
2350 while (i < cend1 && j < cend2 &&
2351 scm_c_downcase (cs1[i]) == scm_c_downcase (cs2[j]))
2358 scm_remember_upto_here_2 (s1, s2);
2359 return scm_from_size_t (cstart1);
2364 scm_remember_upto_here_2 (s1, s2);
2370 /* Helper function for the string uppercase conversion functions.
2371 * No argument checking is performed. */
2373 string_upcase_x (SCM v, size_t start, size_t end)
2378 dst = scm_i_string_writable_chars (v);
2379 for (k = start; k < end; ++k)
2380 dst[k] = scm_c_upcase (dst[k]);
2381 scm_i_string_stop_writing ();
2382 scm_remember_upto_here_1 (v);
2387 SCM_DEFINE (scm_substring_upcase_x, "string-upcase!", 1, 2, 0,
2388 (SCM str, SCM start, SCM end),
2389 "Destructively upcase every character in @code{str}.\n"
2392 "(string-upcase! y)\n"
2393 "@result{} \"ARRDEFG\"\n"
2395 "@result{} \"ARRDEFG\"\n"
2397 #define FUNC_NAME s_scm_substring_upcase_x
2400 size_t cstart, cend;
2402 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2405 return string_upcase_x (str, cstart, cend);
2410 scm_string_upcase_x (SCM str)
2412 return scm_substring_upcase_x (str, SCM_UNDEFINED, SCM_UNDEFINED);
2415 SCM_DEFINE (scm_substring_upcase, "string-upcase", 1, 2, 0,
2416 (SCM str, SCM start, SCM end),
2417 "Upcase every character in @code{str}.")
2418 #define FUNC_NAME s_scm_substring_upcase
2421 size_t cstart, cend;
2423 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2426 return string_upcase_x (scm_string_copy (str), cstart, cend);
2431 scm_string_upcase (SCM str)
2433 return scm_substring_upcase (str, SCM_UNDEFINED, SCM_UNDEFINED);
2436 /* Helper function for the string lowercase conversion functions.
2437 * No argument checking is performed. */
2439 string_downcase_x (SCM v, size_t start, size_t end)
2444 dst = scm_i_string_writable_chars (v);
2445 for (k = start; k < end; ++k)
2446 dst[k] = scm_c_downcase (dst[k]);
2447 scm_i_string_stop_writing ();
2448 scm_remember_upto_here_1 (v);
2453 SCM_DEFINE (scm_substring_downcase_x, "string-downcase!", 1, 2, 0,
2454 (SCM str, SCM start, SCM end),
2455 "Destructively downcase every character in @var{str}.\n"
2459 "@result{} \"ARRDEFG\"\n"
2460 "(string-downcase! y)\n"
2461 "@result{} \"arrdefg\"\n"
2463 "@result{} \"arrdefg\"\n"
2465 #define FUNC_NAME s_scm_substring_downcase_x
2468 size_t cstart, cend;
2470 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2473 return string_downcase_x (str, cstart, cend);
2478 scm_string_downcase_x (SCM str)
2480 return scm_substring_downcase_x (str, SCM_UNDEFINED, SCM_UNDEFINED);
2483 SCM_DEFINE (scm_substring_downcase, "string-downcase", 1, 2, 0,
2484 (SCM str, SCM start, SCM end),
2485 "Downcase every character in @var{str}.")
2486 #define FUNC_NAME s_scm_substring_downcase
2489 size_t cstart, cend;
2491 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2494 return string_downcase_x (scm_string_copy (str), cstart, cend);
2499 scm_string_downcase (SCM str)
2501 return scm_substring_downcase (str, SCM_UNDEFINED, SCM_UNDEFINED);
2504 /* Helper function for the string capitalization functions.
2505 * No argument checking is performed. */
2507 string_titlecase_x (SCM str, size_t start, size_t end)
2513 sz = (unsigned char *) scm_i_string_writable_chars (str);
2514 for(i = start; i < end; i++)
2516 if (scm_is_true (scm_char_alphabetic_p (SCM_MAKE_CHAR (sz[i]))))
2520 sz[i] = scm_c_upcase(sz[i]);
2525 sz[i] = scm_c_downcase(sz[i]);
2531 scm_i_string_stop_writing ();
2532 scm_remember_upto_here_1 (str);
2538 SCM_DEFINE (scm_string_titlecase_x, "string-titlecase!", 1, 2, 0,
2539 (SCM str, SCM start, SCM end),
2540 "Destructively titlecase every first character in a word in\n"
2542 #define FUNC_NAME s_scm_string_titlecase_x
2545 size_t cstart, cend;
2547 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2550 return string_titlecase_x (str, cstart, cend);
2555 SCM_DEFINE (scm_string_titlecase, "string-titlecase", 1, 2, 0,
2556 (SCM str, SCM start, SCM end),
2557 "Titlecase every first character in a word in @var{str}.")
2558 #define FUNC_NAME s_scm_string_titlecase
2561 size_t cstart, cend;
2563 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2566 return string_titlecase_x (scm_string_copy (str), cstart, cend);
2570 SCM_DEFINE (scm_string_capitalize_x, "string-capitalize!", 1, 0, 0,
2572 "Upcase the first character of every word in @var{str}\n"
2573 "destructively and return @var{str}.\n"
2576 "y @result{} \"hello world\"\n"
2577 "(string-capitalize! y) @result{} \"Hello World\"\n"
2578 "y @result{} \"Hello World\"\n"
2580 #define FUNC_NAME s_scm_string_capitalize_x
2582 return scm_string_titlecase_x (str, SCM_UNDEFINED, SCM_UNDEFINED);
2587 SCM_DEFINE (scm_string_capitalize, "string-capitalize", 1, 0, 0,
2589 "Return a freshly allocated string with the characters in\n"
2590 "@var{str}, where the first character of every word is\n"
2592 #define FUNC_NAME s_scm_string_capitalize
2594 return scm_string_capitalize_x (scm_string_copy (str));
2599 /* Reverse the portion of @var{str} between str[cstart] (including)
2600 and str[cend] excluding. */
2602 string_reverse_x (char * str, size_t cstart, size_t cend)
2609 while (cstart < cend)
2612 str[cstart] = str[cend];
2621 SCM_DEFINE (scm_string_reverse, "string-reverse", 1, 2, 0,
2622 (SCM str, SCM start, SCM end),
2623 "Reverse the string @var{str}. The optional arguments\n"
2624 "@var{start} and @var{end} delimit the region of @var{str} to\n"
2626 #define FUNC_NAME s_scm_string_reverse
2630 size_t cstart, cend;
2633 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, str, cstr,
2636 result = scm_string_copy (str);
2637 ctarget = scm_i_string_writable_chars (result);
2638 string_reverse_x (ctarget, cstart, cend);
2639 scm_i_string_stop_writing ();
2640 scm_remember_upto_here_1 (str);
2646 SCM_DEFINE (scm_string_reverse_x, "string-reverse!", 1, 2, 0,
2647 (SCM str, SCM start, SCM end),
2648 "Reverse the string @var{str} in-place. The optional arguments\n"
2649 "@var{start} and @var{end} delimit the region of @var{str} to\n"
2650 "operate on. The return value is unspecified.")
2651 #define FUNC_NAME s_scm_string_reverse_x
2654 size_t cstart, cend;
2656 MY_VALIDATE_SUBSTRING_SPEC (1, str,
2660 cstr = scm_i_string_writable_chars (str);
2661 string_reverse_x (cstr, cstart, cend);
2662 scm_i_string_stop_writing ();
2663 scm_remember_upto_here_1 (str);
2664 return SCM_UNSPECIFIED;
2669 SCM_DEFINE (scm_string_append_shared, "string-append/shared", 0, 0, 1,
2671 "Like @code{string-append}, but the result may share memory\n"
2672 "with the argument strings.")
2673 #define FUNC_NAME s_scm_string_append_shared
2675 /* If "rest" contains just one non-empty string, return that.
2676 If it's entirely empty strings, then return scm_nullstr.
2677 Otherwise use scm_string_concatenate. */
2679 SCM ret = scm_nullstr;
2680 int seen_nonempty = 0;
2683 SCM_VALIDATE_REST_ARGUMENT (rest);
2685 for (l = rest; scm_is_pair (l); l = SCM_CDR (l))
2688 if (scm_c_string_length (s) != 0)
2691 /* two or more non-empty strings, need full concat */
2692 return scm_string_append (rest);
2703 SCM_DEFINE (scm_string_concatenate, "string-concatenate", 1, 0, 0,
2705 "Append the elements of @var{ls} (which must be strings)\n"
2706 "together into a single string. Guaranteed to return a freshly\n"
2707 "allocated string.")
2708 #define FUNC_NAME s_scm_string_concatenate
2710 SCM_VALIDATE_LIST (SCM_ARG1, ls);
2711 return scm_string_append (ls);
2716 SCM_DEFINE (scm_string_concatenate_reverse, "string-concatenate-reverse", 1, 2, 0,
2717 (SCM ls, SCM final_string, SCM end),
2718 "Without optional arguments, this procedure is equivalent to\n"
2721 "(string-concatenate (reverse ls))\n"
2724 "If the optional argument @var{final_string} is specified, it is\n"
2725 "consed onto the beginning to @var{ls} before performing the\n"
2726 "list-reverse and string-concatenate operations. If @var{end}\n"
2727 "is given, only the characters of @var{final_string} up to index\n"
2728 "@var{end} are used.\n"
2730 "Guaranteed to return a freshly allocated string.")
2731 #define FUNC_NAME s_scm_string_concatenate_reverse
2733 if (!SCM_UNBNDP (end))
2734 final_string = scm_substring (final_string, SCM_INUM0, end);
2736 if (!SCM_UNBNDP (final_string))
2737 ls = scm_cons (final_string, ls);
2739 return scm_string_concatenate (scm_reverse (ls));
2744 SCM_DEFINE (scm_string_concatenate_shared, "string-concatenate/shared", 1, 0, 0,
2746 "Like @code{string-concatenate}, but the result may share memory\n"
2747 "with the strings in the list @var{ls}.")
2748 #define FUNC_NAME s_scm_string_concatenate_shared
2750 SCM_VALIDATE_LIST (SCM_ARG1, ls);
2751 return scm_string_append_shared (ls);
2756 SCM_DEFINE (scm_string_concatenate_reverse_shared, "string-concatenate-reverse/shared", 1, 2, 0,
2757 (SCM ls, SCM final_string, SCM end),
2758 "Like @code{string-concatenate-reverse}, but the result may\n"
2759 "share memory with the the strings in the @var{ls} arguments.")
2760 #define FUNC_NAME s_scm_string_concatenate_reverse_shared
2762 /* Just call the non-sharing version. */
2763 return scm_string_concatenate_reverse (ls, final_string, end);
2768 SCM_DEFINE (scm_string_map, "string-map", 2, 2, 0,
2769 (SCM proc, SCM s, SCM start, SCM end),
2770 "@var{proc} is a char->char procedure, it is mapped over\n"
2771 "@var{s}. The order in which the procedure is applied to the\n"
2772 "string elements is not specified.")
2773 #define FUNC_NAME s_scm_string_map
2776 size_t cstart, cend;
2778 scm_t_trampoline_1 proc_tramp = scm_trampoline_1 (proc);
2780 SCM_ASSERT (proc_tramp, proc, SCM_ARG1, FUNC_NAME);
2781 MY_VALIDATE_SUBSTRING_SPEC (2, s,
2784 result = scm_i_make_string (cend - cstart, &p);
2785 while (cstart < cend)
2787 SCM ch = proc_tramp (proc, scm_c_string_ref (s, cstart));
2788 if (!SCM_CHARP (ch))
2789 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
2791 *p++ = SCM_CHAR (ch);
2798 SCM_DEFINE (scm_string_map_x, "string-map!", 2, 2, 0,
2799 (SCM proc, SCM s, SCM start, SCM end),
2800 "@var{proc} is a char->char procedure, it is mapped over\n"
2801 "@var{s}. The order in which the procedure is applied to the\n"
2802 "string elements is not specified. The string @var{s} is\n"
2803 "modified in-place, the return value is not specified.")
2804 #define FUNC_NAME s_scm_string_map_x
2806 size_t cstart, cend;
2807 scm_t_trampoline_1 proc_tramp = scm_trampoline_1 (proc);
2809 SCM_ASSERT (proc_tramp, proc, SCM_ARG1, FUNC_NAME);
2810 MY_VALIDATE_SUBSTRING_SPEC (2, s,
2813 while (cstart < cend)
2815 SCM ch = proc_tramp (proc, scm_c_string_ref (s, cstart));
2816 if (!SCM_CHARP (ch))
2817 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
2818 scm_c_string_set_x (s, cstart, ch);
2821 return SCM_UNSPECIFIED;
2826 SCM_DEFINE (scm_string_fold, "string-fold", 3, 2, 0,
2827 (SCM kons, SCM knil, SCM s, SCM start, SCM end),
2828 "Fold @var{kons} over the characters of @var{s}, with @var{knil}\n"
2829 "as the terminating element, from left to right. @var{kons}\n"
2830 "must expect two arguments: The actual character and the last\n"
2831 "result of @var{kons}' application.")
2832 #define FUNC_NAME s_scm_string_fold
2835 size_t cstart, cend;
2838 SCM_VALIDATE_PROC (1, kons);
2839 MY_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cstr,
2843 while (cstart < cend)
2845 unsigned int c = (unsigned char) cstr[cstart];
2846 result = scm_call_2 (kons, SCM_MAKE_CHAR (c), result);
2847 cstr = scm_i_string_chars (s);
2851 scm_remember_upto_here_1 (s);
2857 SCM_DEFINE (scm_string_fold_right, "string-fold-right", 3, 2, 0,
2858 (SCM kons, SCM knil, SCM s, SCM start, SCM end),
2859 "Fold @var{kons} over the characters of @var{s}, with @var{knil}\n"
2860 "as the terminating element, from right to left. @var{kons}\n"
2861 "must expect two arguments: The actual character and the last\n"
2862 "result of @var{kons}' application.")
2863 #define FUNC_NAME s_scm_string_fold_right
2866 size_t cstart, cend;
2869 SCM_VALIDATE_PROC (1, kons);
2870 MY_VALIDATE_SUBSTRING_SPEC_COPY (3, s, cstr,
2874 while (cstart < cend)
2876 unsigned int c = (unsigned char) cstr[cend - 1];
2877 result = scm_call_2 (kons, SCM_MAKE_CHAR (c), result);
2878 cstr = scm_i_string_chars (s);
2882 scm_remember_upto_here_1 (s);
2888 SCM_DEFINE (scm_string_unfold, "string-unfold", 4, 2, 0,
2889 (SCM p, SCM f, SCM g, SCM seed, SCM base, SCM make_final),
2890 "@itemize @bullet\n"
2891 "@item @var{g} is used to generate a series of @emph{seed}\n"
2892 "values from the initial @var{seed}: @var{seed}, (@var{g}\n"
2893 "@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}),\n"
2895 "@item @var{p} tells us when to stop -- when it returns true\n"
2896 "when applied to one of these seed values.\n"
2897 "@item @var{f} maps each seed value to the corresponding\n"
2898 "character in the result string. These chars are assembled\n"
2899 "into the string in a left-to-right order.\n"
2900 "@item @var{base} is the optional initial/leftmost portion\n"
2901 "of the constructed string; it default to the empty\n"
2903 "@item @var{make_final} is applied to the terminal seed\n"
2904 "value (on which @var{p} returns true) to produce\n"
2905 "the final/rightmost portion of the constructed string.\n"
2906 "It defaults to @code{(lambda (x) "")}.\n"
2908 #define FUNC_NAME s_scm_string_unfold
2912 SCM_VALIDATE_PROC (1, p);
2913 SCM_VALIDATE_PROC (2, f);
2914 SCM_VALIDATE_PROC (3, g);
2915 if (!SCM_UNBNDP (base))
2917 SCM_VALIDATE_STRING (5, base);
2921 ans = scm_i_make_string (0, NULL);
2922 if (!SCM_UNBNDP (make_final))
2923 SCM_VALIDATE_PROC (6, make_final);
2925 res = scm_call_1 (p, seed);
2926 while (scm_is_false (res))
2930 SCM ch = scm_call_1 (f, seed);
2931 if (!SCM_CHARP (ch))
2932 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
2933 str = scm_i_make_string (1, &ptr);
2934 *ptr = SCM_CHAR (ch);
2936 ans = scm_string_append (scm_list_2 (ans, str));
2937 seed = scm_call_1 (g, seed);
2938 res = scm_call_1 (p, seed);
2940 if (!SCM_UNBNDP (make_final))
2942 res = scm_call_1 (make_final, seed);
2943 return scm_string_append (scm_list_2 (ans, res));
2951 SCM_DEFINE (scm_string_unfold_right, "string-unfold-right", 4, 2, 0,
2952 (SCM p, SCM f, SCM g, SCM seed, SCM base, SCM make_final),
2953 "@itemize @bullet\n"
2954 "@item @var{g} is used to generate a series of @emph{seed}\n"
2955 "values from the initial @var{seed}: @var{seed}, (@var{g}\n"
2956 "@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}),\n"
2958 "@item @var{p} tells us when to stop -- when it returns true\n"
2959 "when applied to one of these seed values.\n"
2960 "@item @var{f} maps each seed value to the corresponding\n"
2961 "character in the result string. These chars are assembled\n"
2962 "into the string in a right-to-left order.\n"
2963 "@item @var{base} is the optional initial/rightmost portion\n"
2964 "of the constructed string; it default to the empty\n"
2966 "@item @var{make_final} is applied to the terminal seed\n"
2967 "value (on which @var{p} returns true) to produce\n"
2968 "the final/leftmost portion of the constructed string.\n"
2969 "It defaults to @code{(lambda (x) "")}.\n"
2971 #define FUNC_NAME s_scm_string_unfold_right
2975 SCM_VALIDATE_PROC (1, p);
2976 SCM_VALIDATE_PROC (2, f);
2977 SCM_VALIDATE_PROC (3, g);
2978 if (!SCM_UNBNDP (base))
2980 SCM_VALIDATE_STRING (5, base);
2984 ans = scm_i_make_string (0, NULL);
2985 if (!SCM_UNBNDP (make_final))
2986 SCM_VALIDATE_PROC (6, make_final);
2988 res = scm_call_1 (p, seed);
2989 while (scm_is_false (res))
2993 SCM ch = scm_call_1 (f, seed);
2994 if (!SCM_CHARP (ch))
2995 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
2996 str = scm_i_make_string (1, &ptr);
2997 *ptr = SCM_CHAR (ch);
2999 ans = scm_string_append (scm_list_2 (str, ans));
3000 seed = scm_call_1 (g, seed);
3001 res = scm_call_1 (p, seed);
3003 if (!SCM_UNBNDP (make_final))
3005 res = scm_call_1 (make_final, seed);
3006 return scm_string_append (scm_list_2 (res, ans));
3014 SCM_DEFINE (scm_string_for_each, "string-for-each", 2, 2, 0,
3015 (SCM proc, SCM s, SCM start, SCM end),
3016 "@var{proc} is mapped over @var{s} in left-to-right order. The\n"
3017 "return value is not specified.")
3018 #define FUNC_NAME s_scm_string_for_each
3021 size_t cstart, cend;
3022 scm_t_trampoline_1 proc_tramp = scm_trampoline_1 (proc);
3024 SCM_ASSERT (proc_tramp, proc, SCM_ARG1, FUNC_NAME);
3025 MY_VALIDATE_SUBSTRING_SPEC_COPY (2, s, cstr,
3028 while (cstart < cend)
3030 unsigned int c = (unsigned char) cstr[cstart];
3031 proc_tramp (proc, SCM_MAKE_CHAR (c));
3032 cstr = scm_i_string_chars (s);
3036 scm_remember_upto_here_1 (s);
3037 return SCM_UNSPECIFIED;
3041 SCM_DEFINE (scm_string_for_each_index, "string-for-each-index", 2, 2, 0,
3042 (SCM proc, SCM s, SCM start, SCM end),
3043 "Call @code{(@var{proc} i)} for each index i in @var{s}, from\n"
3046 "For example, to change characters to alternately upper and\n"
3050 "(define str (string-copy \"studly\"))\n"
3051 "(string-for-each-index\n"
3053 " (string-set! str i\n"
3054 " ((if (even? i) char-upcase char-downcase)\n"
3055 " (string-ref str i))))\n"
3057 "str @result{} \"StUdLy\"\n"
3059 #define FUNC_NAME s_scm_string_for_each_index
3061 size_t cstart, cend;
3062 scm_t_trampoline_1 proc_tramp = scm_trampoline_1 (proc);
3064 SCM_ASSERT (proc_tramp, proc, SCM_ARG1, FUNC_NAME);
3065 MY_VALIDATE_SUBSTRING_SPEC (2, s,
3069 while (cstart < cend)
3071 proc_tramp (proc, scm_from_size_t (cstart));
3075 scm_remember_upto_here_1 (s);
3076 return SCM_UNSPECIFIED;
3080 SCM_DEFINE (scm_xsubstring, "xsubstring", 2, 3, 0,
3081 (SCM s, SCM from, SCM to, SCM start, SCM end),
3082 "This is the @emph{extended substring} procedure that implements\n"
3083 "replicated copying of a substring of some string.\n"
3085 "@var{s} is a string, @var{start} and @var{end} are optional\n"
3086 "arguments that demarcate a substring of @var{s}, defaulting to\n"
3087 "0 and the length of @var{s}. Replicate this substring up and\n"
3088 "down index space, in both the positive and negative directions.\n"
3089 "@code{xsubstring} returns the substring of this string\n"
3090 "beginning at index @var{from}, and ending at @var{to}, which\n"
3091 "defaults to @var{from} + (@var{end} - @var{start}).")
3092 #define FUNC_NAME s_scm_xsubstring
3096 size_t cstart, cend;
3100 MY_VALIDATE_SUBSTRING_SPEC (1, s,
3104 cfrom = scm_to_int (from);
3105 if (SCM_UNBNDP (to))
3106 cto = cfrom + (cend - cstart);
3108 cto = scm_to_int (to);
3109 if (cstart == cend && cfrom != cto)
3110 SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL);
3112 result = scm_i_make_string (cto - cfrom, &p);
3114 cs = scm_i_string_chars (s);
3117 size_t t = ((cfrom < 0) ? -cfrom : cfrom) % (cend - cstart);
3119 *p = cs[(cend - cstart) - t];
3126 scm_remember_upto_here_1 (s);
3132 SCM_DEFINE (scm_string_xcopy_x, "string-xcopy!", 4, 3, 0,
3133 (SCM target, SCM tstart, SCM s, SCM sfrom, SCM sto, SCM start, SCM end),
3134 "Exactly the same as @code{xsubstring}, but the extracted text\n"
3135 "is written into the string @var{target} starting at index\n"
3136 "@var{tstart}. The operation is not defined if @code{(eq?\n"
3137 "@var{target} @var{s})} or these arguments share storage -- you\n"
3138 "cannot copy a string on top of itself.")
3139 #define FUNC_NAME s_scm_string_xcopy_x
3143 size_t ctstart, cstart, cend;
3145 SCM dummy = SCM_UNDEFINED;
3148 MY_VALIDATE_SUBSTRING_SPEC (1, target,
3151 MY_VALIDATE_SUBSTRING_SPEC (3, s,
3154 csfrom = scm_to_int (sfrom);
3155 if (SCM_UNBNDP (sto))
3156 csto = csfrom + (cend - cstart);
3158 csto = scm_to_int (sto);
3159 if (cstart == cend && csfrom != csto)
3160 SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL);
3161 SCM_ASSERT_RANGE (1, tstart,
3162 ctstart + (csto - csfrom) <= scm_i_string_length (target));
3164 p = scm_i_string_writable_chars (target) + ctstart;
3165 cs = scm_i_string_chars (s);
3166 while (csfrom < csto)
3168 size_t t = ((csfrom < 0) ? -csfrom : csfrom) % (cend - cstart);
3170 *p = cs[(cend - cstart) - t];
3176 scm_i_string_stop_writing ();
3178 scm_remember_upto_here_2 (target, s);
3179 return SCM_UNSPECIFIED;
3184 SCM_DEFINE (scm_string_replace, "string-replace", 2, 4, 0,
3185 (SCM s1, SCM s2, SCM start1, SCM end1, SCM start2, SCM end2),
3186 "Return the string @var{s1}, but with the characters\n"
3187 "@var{start1} @dots{} @var{end1} replaced by the characters\n"
3188 "@var{start2} @dots{} @var{end2} from @var{s2}.")
3189 #define FUNC_NAME s_scm_string_replace
3191 const char *cstr1, *cstr2;
3193 size_t cstart1, cend1, cstart2, cend2;
3196 MY_VALIDATE_SUBSTRING_SPEC (1, s1,
3199 MY_VALIDATE_SUBSTRING_SPEC (2, s2,
3202 result = scm_i_make_string (cstart1 + (cend2 - cstart2) +
3203 scm_i_string_length (s1) - cend1, &p);
3204 cstr1 = scm_i_string_chars (s1);
3205 cstr2 = scm_i_string_chars (s2);
3206 memmove (p, cstr1, cstart1 * sizeof (char));
3207 memmove (p + cstart1, cstr2 + cstart2, (cend2 - cstart2) * sizeof (char));
3208 memmove (p + cstart1 + (cend2 - cstart2),
3210 (scm_i_string_length (s1) - cend1) * sizeof (char));
3211 scm_remember_upto_here_2 (s1, s2);
3217 SCM_DEFINE (scm_string_tokenize, "string-tokenize", 1, 3, 0,
3218 (SCM s, SCM token_set, SCM start, SCM end),
3219 "Split the string @var{s} into a list of substrings, where each\n"
3220 "substring is a maximal non-empty contiguous sequence of\n"
3221 "characters from the character set @var{token_set}, which\n"
3222 "defaults to @code{char-set:graphic}.\n"
3223 "If @var{start} or @var{end} indices are provided, they restrict\n"
3224 "@code{string-tokenize} to operating on the indicated substring\n"
3226 #define FUNC_NAME s_scm_string_tokenize
3229 size_t cstart, cend;
3230 SCM result = SCM_EOL;
3232 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
3236 if (SCM_UNBNDP (token_set))
3237 token_set = scm_char_set_graphic;
3239 if (SCM_CHARSETP (token_set))
3243 while (cstart < cend)
3245 while (cstart < cend)
3247 if (SCM_CHARSET_GET (token_set, cstr[cend - 1]))
3254 while (cstart < cend)
3256 if (!SCM_CHARSET_GET (token_set, cstr[cend - 1]))
3260 result = scm_cons (scm_c_substring (s, cend, idx), result);
3261 cstr = scm_i_string_chars (s);
3265 SCM_WRONG_TYPE_ARG (2, token_set);
3267 scm_remember_upto_here_1 (s);
3272 SCM_DEFINE (scm_string_split, "string-split", 2, 0, 0,
3274 "Split the string @var{str} into the a list of the substrings delimited\n"
3275 "by appearances of the character @var{chr}. Note that an empty substring\n"
3276 "between separator characters will result in an empty string in the\n"
3280 "(string-split \"root:x:0:0:root:/root:/bin/bash\" #\\:)\n"
3282 "(\"root\" \"x\" \"0\" \"0\" \"root\" \"/root\" \"/bin/bash\")\n"
3284 "(string-split \"::\" #\\:)\n"
3286 "(\"\" \"\" \"\")\n"
3288 "(string-split \"\" #\\:)\n"
3292 #define FUNC_NAME s_scm_string_split
3299 SCM_VALIDATE_STRING (1, str);
3300 SCM_VALIDATE_CHAR (2, chr);
3302 idx = scm_i_string_length (str);
3303 p = scm_i_string_chars (str);
3304 ch = SCM_CHAR (chr);
3308 while (idx > 0 && p[idx - 1] != ch)
3312 res = scm_cons (scm_c_substring (str, idx, last_idx), res);
3313 p = scm_i_string_chars (str);
3317 scm_remember_upto_here_1 (str);
3323 SCM_DEFINE (scm_string_filter, "string-filter", 2, 2, 0,
3324 (SCM s, SCM char_pred, SCM start, SCM end),
3325 "Filter the string @var{s}, retaining only those characters\n"
3326 "which satisfy @var{char_pred}.\n"
3328 "If @var{char_pred} is a procedure, it is applied to each\n"
3329 "character as a predicate, if it is a character, it is tested\n"
3330 "for equality and if it is a character set, it is tested for\n"
3332 #define FUNC_NAME s_scm_string_filter
3335 size_t cstart, cend;
3339 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
3343 /* The explicit loops below stripping leading and trailing non-matches
3344 mean we can return a substring if those are the only deletions, making
3345 string-filter as efficient as string-trim-both in that case. */
3347 if (SCM_CHARP (char_pred))
3352 chr = SCM_CHAR (char_pred);
3354 /* strip leading non-matches by incrementing cstart */
3355 while (cstart < cend && cstr[cstart] != chr)
3358 /* strip trailing non-matches by decrementing cend */
3359 while (cend > cstart && cstr[cend-1] != chr)
3362 /* count chars to keep */
3364 for (idx = cstart; idx < cend; idx++)
3365 if (cstr[idx] == chr)
3368 if (count == cend - cstart)
3370 /* whole of cstart to cend is to be kept, return a copy-on-write
3373 result = scm_i_substring (s, cstart, cend);
3376 result = scm_c_make_string (count, char_pred);
3378 else if (SCM_CHARSETP (char_pred))
3382 /* strip leading non-matches by incrementing cstart */
3383 while (cstart < cend && ! SCM_CHARSET_GET (char_pred, cstr[cstart]))
3386 /* strip trailing non-matches by decrementing cend */
3387 while (cend > cstart && ! SCM_CHARSET_GET (char_pred, cstr[cend-1]))
3390 /* count chars to be kept */
3392 for (idx = cstart; idx < cend; idx++)
3393 if (SCM_CHARSET_GET (char_pred, cstr[idx]))
3396 /* if whole of start to end kept then return substring */
3397 if (count == cend - cstart)
3398 goto result_substring;
3402 result = scm_i_make_string (count, &dst);
3403 cstr = scm_i_string_chars (s);
3405 /* decrement "count" in this loop as well as using idx, so that if
3406 another thread is simultaneously changing "s" there's no chance
3407 it'll make us copy more than count characters */
3408 for (idx = cstart; idx < cend && count != 0; idx++)
3410 if (SCM_CHARSET_GET (char_pred, cstr[idx]))
3421 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
3423 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
3428 ch = SCM_MAKE_CHAR (cstr[idx]);
3429 res = pred_tramp (char_pred, ch);
3430 if (scm_is_true (res))
3431 ls = scm_cons (ch, ls);
3432 cstr = scm_i_string_chars (s);
3435 result = scm_reverse_list_to_string (ls);
3438 scm_remember_upto_here_1 (s);
3444 SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
3445 (SCM s, SCM char_pred, SCM start, SCM end),
3446 "Delete characters satisfying @var{char_pred} from @var{s}.\n"
3448 "If @var{char_pred} is a procedure, it is applied to each\n"
3449 "character as a predicate, if it is a character, it is tested\n"
3450 "for equality and if it is a character set, it is tested for\n"
3452 #define FUNC_NAME s_scm_string_delete
3455 size_t cstart, cend;
3459 MY_VALIDATE_SUBSTRING_SPEC_COPY (1, s, cstr,
3463 /* The explicit loops below stripping leading and trailing matches mean we
3464 can return a substring if those are the only deletions, making
3465 string-delete as efficient as string-trim-both in that case. */
3467 if (SCM_CHARP (char_pred))
3472 chr = SCM_CHAR (char_pred);
3474 /* strip leading matches by incrementing cstart */
3475 while (cstart < cend && cstr[cstart] == chr)
3478 /* strip trailing matches by decrementing cend */
3479 while (cend > cstart && cstr[cend-1] == chr)
3482 /* count chars to be kept */
3484 for (idx = cstart; idx < cend; idx++)
3485 if (cstr[idx] != chr)
3488 if (count == cend - cstart)
3490 /* whole of cstart to cend is to be kept, return a copy-on-write
3493 result = scm_i_substring (s, cstart, cend);
3497 /* new string for retained portion */
3499 result = scm_i_make_string (count, &dst);
3500 cstr = scm_i_string_chars (s);
3502 /* decrement "count" in this loop as well as using idx, so that if
3503 another thread is simultaneously changing "s" there's no chance
3504 it'll make us copy more than count characters */
3505 for (idx = cstart; idx < cend && count != 0; idx++)
3507 if (cstr[idx] != chr)
3515 else if (SCM_CHARSETP (char_pred))
3519 /* strip leading matches by incrementing cstart */
3520 while (cstart < cend && SCM_CHARSET_GET (char_pred, cstr[cstart]))
3523 /* strip trailing matches by decrementing cend */
3524 while (cend > cstart && SCM_CHARSET_GET (char_pred, cstr[cend-1]))
3527 /* count chars to be kept */
3529 for (idx = cstart; idx < cend; idx++)
3530 if (! SCM_CHARSET_GET (char_pred, cstr[idx]))
3533 if (count == cend - cstart)
3534 goto result_substring;
3537 /* new string for retained portion */
3539 result = scm_i_make_string (count, &dst);
3540 cstr = scm_i_string_chars (s);
3542 /* decrement "count" in this loop as well as using idx, so that if
3543 another thread is simultaneously changing "s" there's no chance
3544 it'll make us copy more than count characters */
3545 for (idx = cstart; idx < cend && count != 0; idx++)
3547 if (! SCM_CHARSET_GET (char_pred, cstr[idx]))
3558 scm_t_trampoline_1 pred_tramp = scm_trampoline_1 (char_pred);
3559 SCM_ASSERT (pred_tramp, char_pred, SCM_ARG2, FUNC_NAME);
3564 SCM res, ch = SCM_MAKE_CHAR (cstr[idx]);
3565 res = pred_tramp (char_pred, ch);
3566 if (scm_is_false (res))
3567 ls = scm_cons (ch, ls);
3568 cstr = scm_i_string_chars (s);
3571 result = scm_reverse_list_to_string (ls);
3574 scm_remember_upto_here_1 (s);
3580 scm_init_srfi_13 (void)
3582 #include "libguile/srfi-13.x"
3585 /* End of srfi-13.c. */