1 /* Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
50 #define var_start(x, y) va_start(x, y)
53 #define var_start(x, y) va_start(x)
59 /* SCM_P won't help us deal with varargs here. */
62 scm_listify (SCM elt
, ...)
65 scm_listify (elt
, va_alist
)
77 while (elt
!= SCM_UNDEFINED
)
79 *pos
= scm_cons (elt
, SCM_EOL
);
80 pos
= SCM_CDRLOC (*pos
);
81 elt
= va_arg (foo
, SCM
);
87 SCM_PROC(s_list
, "list", 0, 0, 1, scm_list
);
96 SCM_PROC (s_list_star
, "list*", 1, 0, 1, scm_list_star
);
99 scm_list_star (SCM arg
, SCM rest
)
103 SCM prev
= arg
= scm_cons (arg
, rest
);
104 while (SCM_NIMP (SCM_CDR (rest
)))
107 rest
= SCM_CDR (rest
);
109 SCM_SETCDR (prev
, SCM_CAR (rest
));
117 /* general questions about lists --- null?, list?, length, etc. */
119 SCM_PROC(s_null_p
, "null?", 1, 0, 0, scm_null_p
);
124 return SCM_NULLP(x
) ? SCM_BOOL_T
: SCM_BOOL_F
;
127 SCM_PROC(s_list_p
, "list?", 1, 0, 0, scm_list_p
);
132 if (scm_ilength(x
)<0)
139 /* Return the length of SX, or -1 if it's not a proper list.
140 This uses the "tortoise and hare" algorithm to detect "infinitely
141 long" lists (i.e. lists with cycles in their cdrs), and returns -1
142 if it does find one. */
148 register SCM tortoise
= sx
;
149 register SCM hare
= sx
;
152 if SCM_IMP(hare
) return SCM_NULLP(hare
) ? i
: -1;
153 if SCM_NCONSP(hare
) return -1;
154 hare
= SCM_CDR(hare
);
156 if SCM_IMP(hare
) return SCM_NULLP(hare
) ? i
: -1;
157 if SCM_NCONSP(hare
) return -1;
158 hare
= SCM_CDR(hare
);
160 /* For every two steps the hare takes, the tortoise takes one. */
161 tortoise
= SCM_CDR(tortoise
);
163 while (hare
!= tortoise
);
165 /* If the tortoise ever catches the hare, then the list must contain
170 SCM_PROC(s_length
, "length", 1, 0, 0, scm_length
);
177 SCM_ASSERT(i
>= 0, x
, SCM_ARG1
, s_length
);
178 return SCM_MAKINUM (i
);
183 /* appending lists */
185 SCM_PROC (s_append
, "append", 0, 0, 1, scm_append
);
191 SCM
*lloc
= &res
, arg
;
193 SCM_ASSERT(SCM_NULLP(args
), args
, SCM_ARGn
, s_append
);
196 SCM_ASSERT(SCM_CONSP(args
), args
, SCM_ARGn
, s_append
);
199 args
= SCM_CDR(args
);
202 SCM_ASSERT(SCM_NULLP(args
), args
, SCM_ARGn
, s_append
);
205 SCM_ASSERT(SCM_CONSP(args
), args
, SCM_ARGn
, s_append
);
206 for(;SCM_NIMP(arg
);arg
= SCM_CDR(arg
)) {
207 SCM_ASSERT(SCM_CONSP(arg
), arg
, SCM_ARGn
, s_append
);
208 *lloc
= scm_cons(SCM_CAR(arg
), SCM_EOL
);
209 lloc
= SCM_CDRLOC(*lloc
);
211 SCM_ASSERT(SCM_NULLP(arg
), arg
, SCM_ARGn
, s_append
);
216 SCM_PROC (s_append_x
, "append!", 0, 0, 1, scm_append_x
);
223 if SCM_NULLP(args
) return SCM_EOL
;
225 args
= SCM_CDR(args
);
226 if SCM_NULLP(args
) return arg
;
227 if SCM_NULLP(arg
) goto tail
;
228 SCM_ASSERT(SCM_NIMP(arg
) && SCM_CONSP(arg
), arg
, SCM_ARG1
, s_append_x
);
229 SCM_SETCDR (scm_last_pair (arg
), scm_append_x (args
));
234 SCM_PROC(s_last_pair
, "last-pair", 1, 0, 0, scm_last_pair
);
239 register SCM res
= sx
;
245 SCM_ASSERT(SCM_NIMP(res
) && SCM_CONSP(res
), res
, SCM_ARG1
, s_last_pair
);
248 if (SCM_IMP(x
) || SCM_NCONSP(x
)) return res
;
251 if (SCM_IMP(x
) || SCM_NCONSP(x
)) return res
;
254 SCM_ASSERT(x
!= sx
, sx
, SCM_ARG1
, s_last_pair
);
259 /* reversing lists */
261 SCM_PROC (s_reverse
, "reverse", 1, 0, 0, scm_reverse
);
270 SCM_ASSERT (SCM_CONSP (p
), ls
, SCM_ARG1
, s_reverse
);
271 res
= scm_cons (SCM_CAR (p
), res
);
275 SCM_ASSERT (SCM_CONSP (p
), ls
, SCM_ARG1
, s_reverse
);
276 res
= scm_cons (SCM_CAR (p
), res
);
280 scm_misc_error (s_reverse
, "Circular structure: %S", SCM_LIST1 (ls
));
282 SCM_ASSERT (SCM_NULLP (p
), ls
, SCM_ARG1
, s_reverse
);
286 SCM_PROC (s_reverse_x
, "reverse!", 1, 1, 0, scm_reverse_x
);
288 scm_reverse_x (ls
, new_tail
)
293 SCM_ASSERT (scm_ilength (ls
) >= 0, ls
, SCM_ARG1
, s_reverse_x
);
294 if (SCM_UNBNDP (new_tail
))
297 SCM_ASSERT (scm_ilength (new_tail
) >= 0, new_tail
, SCM_ARG2
, s_reverse_x
);
299 while (SCM_NIMP (ls
))
301 old_tail
= SCM_CDR (ls
);
302 SCM_SETCDR (ls
, new_tail
);
311 /* indexing lists by element number */
313 SCM_PROC(s_list_ref
, "list-ref", 2, 0, 0, scm_list_ref
);
320 SCM_ASSERT(SCM_INUMP(k
), k
, SCM_ARG2
, s_list_ref
);
322 SCM_ASSERT(i
>= 0, k
, SCM_ARG2
, s_list_ref
);
324 SCM_ASRTGO(SCM_NIMP(lst
) && SCM_CONSP(lst
), erout
);
327 erout
: SCM_ASSERT(SCM_NIMP(lst
) && SCM_CONSP(lst
),
328 SCM_NULLP(lst
)?k
:lst
, SCM_NULLP(lst
)?SCM_OUTOFRANGE
:SCM_ARG1
, s_list_ref
);
332 SCM_PROC(s_list_set_x
, "list-set!", 3, 0, 0, scm_list_set_x
);
334 scm_list_set_x(lst
, k
, val
)
340 SCM_ASSERT(SCM_INUMP(k
), k
, SCM_ARG2
, s_list_set_x
);
342 SCM_ASSERT(i
>= 0, k
, SCM_ARG2
, s_list_set_x
);
344 SCM_ASRTGO(SCM_NIMP(lst
) && SCM_CONSP(lst
), erout
);
347 erout
: SCM_ASSERT(SCM_NIMP(lst
) && SCM_CONSP(lst
),
348 SCM_NULLP(lst
)?k
:lst
, SCM_NULLP(lst
)?SCM_OUTOFRANGE
:SCM_ARG1
, s_list_set_x
);
349 SCM_SETCAR (lst
, val
);
354 SCM_PROC(s_list_cdr_ref
, "list-cdr-ref", 2, 0, 0, scm_list_tail
);
355 SCM_PROC(s_list_tail
, "list-tail", 2, 0, 0, scm_list_tail
);
357 scm_list_tail(lst
, k
)
362 SCM_ASSERT(SCM_INUMP(k
), k
, SCM_ARG2
, s_list_tail
);
365 SCM_ASSERT(SCM_NIMP(lst
) && SCM_CONSP(lst
), lst
, SCM_ARG1
, s_list_tail
);
372 SCM_PROC(s_list_cdr_set_x
, "list-cdr-set!", 3, 0, 0, scm_list_cdr_set_x
);
374 scm_list_cdr_set_x(lst
, k
, val
)
380 SCM_ASSERT(SCM_INUMP(k
), k
, SCM_ARG2
, s_list_cdr_set_x
);
382 SCM_ASSERT(i
>= 0, k
, SCM_ARG2
, s_list_cdr_set_x
);
384 SCM_ASRTGO(SCM_NIMP(lst
) && SCM_CONSP(lst
), erout
);
387 erout
: SCM_ASSERT(SCM_NIMP(lst
) && SCM_CONSP(lst
),
388 SCM_NULLP(lst
)?k
:lst
, SCM_NULLP(lst
)?SCM_OUTOFRANGE
:SCM_ARG1
, s_list_cdr_set_x
);
389 SCM_SETCDR (lst
, val
);
395 /* copying lists, perhaps partially */
397 SCM_PROC(s_list_head
, "list-head", 2, 0, 0, scm_list_head
);
399 scm_list_head(lst
, k
)
407 SCM_ASSERT(SCM_INUMP(k
), k
, SCM_ARG2
, s_list_head
);
413 SCM_ASSERT(SCM_NIMP(lst
) && SCM_CONSP(lst
), lst
, SCM_ARG1
, s_list_head
);
414 *pos
= scm_cons (SCM_CAR (lst
), SCM_EOL
);
415 pos
= SCM_CDRLOC (*pos
);
422 SCM_PROC (s_list_copy
, "list-copy", 1, 0, 0, scm_list_copy
);
435 while (SCM_NIMP (from_here
) && SCM_CONSP (from_here
))
438 c
= scm_cons (SCM_CAR (from_here
), SCM_CDR (from_here
));
440 fill_here
= SCM_CDRLOC (c
);
441 from_here
= SCM_CDR (from_here
);
447 /* membership tests (memq, memv, etc.) */
449 SCM_PROC (s_sloppy_memq
, "sloppy-memq", 2, 0, 0, scm_sloppy_memq
);
451 scm_sloppy_memq(x
, lst
)
455 for(; SCM_NIMP(lst
) && SCM_CONSP (lst
); lst
= SCM_CDR(lst
))
464 SCM_PROC (s_sloppy_memv
, "sloppy-memv", 2, 0, 0, scm_sloppy_memv
);
466 scm_sloppy_memv(x
, lst
)
470 for(; SCM_NIMP(lst
) && SCM_CONSP (lst
); lst
= SCM_CDR(lst
))
472 if (SCM_BOOL_F
!= scm_eqv_p (SCM_CAR(lst
), x
))
479 SCM_PROC (s_sloppy_member
, "sloppy-member", 2, 0, 0, scm_sloppy_member
);
481 scm_sloppy_member (x
, lst
)
485 for(; SCM_NIMP(lst
) && SCM_CONSP (lst
); lst
= SCM_CDR(lst
))
487 if (SCM_BOOL_F
!= scm_equal_p (SCM_CAR(lst
), x
))
495 SCM_PROC(s_memq
, "memq", 2, 0, 0, scm_memq
);
502 SCM_ASSERT (scm_ilength (lst
) >= 0, lst
, SCM_ARG2
, s_memq
);
503 answer
= scm_sloppy_memq (x
, lst
);
504 return (answer
== SCM_EOL
) ? SCM_BOOL_F
: answer
;
509 SCM_PROC(s_memv
, "memv", 2, 0, 0, scm_memv
);
516 SCM_ASSERT (scm_ilength (lst
) >= 0, lst
, SCM_ARG2
, s_memv
);
517 answer
= scm_sloppy_memv (x
, lst
);
518 return (answer
== SCM_EOL
) ? SCM_BOOL_F
: answer
;
522 SCM_PROC(s_member
, "member", 2, 0, 0, scm_member
);
529 SCM_ASSERT (scm_ilength (lst
) >= 0, lst
, SCM_ARG2
, s_member
);
530 answer
= scm_sloppy_member (x
, lst
);
531 return (answer
== SCM_EOL
) ? SCM_BOOL_F
: answer
;
536 /* deleting elements from a list (delq, etc.) */
538 SCM_PROC(s_delq_x
, "delq!", 2, 0, 0, scm_delq_x
);
540 scm_delq_x (item
, lst
)
547 for (prev
= &lst
, walk
= lst
;
548 SCM_NIMP (walk
) && SCM_CONSP (walk
);
549 walk
= SCM_CDR (walk
))
551 if (SCM_CAR (walk
) == item
)
552 *prev
= SCM_CDR (walk
);
554 prev
= SCM_CDRLOC (walk
);
561 SCM_PROC(s_delv_x
, "delv!", 2, 0, 0, scm_delv_x
);
563 scm_delv_x (item
, lst
)
570 for (prev
= &lst
, walk
= lst
;
571 SCM_NIMP (walk
) && SCM_CONSP (walk
);
572 walk
= SCM_CDR (walk
))
574 if (SCM_BOOL_F
!= scm_eqv_p (SCM_CAR (walk
), item
))
575 *prev
= SCM_CDR (walk
);
577 prev
= SCM_CDRLOC (walk
);
585 SCM_PROC(s_delete_x
, "delete!", 2, 0, 0, scm_delete_x
);
587 scm_delete_x (item
, lst
)
594 for (prev
= &lst
, walk
= lst
;
595 SCM_NIMP (walk
) && SCM_CONSP (walk
);
596 walk
= SCM_CDR (walk
))
598 if (SCM_BOOL_F
!= scm_equal_p (SCM_CAR (walk
), item
))
599 *prev
= SCM_CDR (walk
);
601 prev
= SCM_CDRLOC (walk
);
611 SCM_PROC (s_delq
, "delq", 2, 0, 0, scm_delq
);
619 copy
= scm_list_copy (lst
);
620 return scm_delq_x (item
, copy
);
623 SCM_PROC (s_delv
, "delv", 2, 0, 0, scm_delv
);
631 copy
= scm_list_copy (lst
);
632 return scm_delv_x (item
, copy
);
635 SCM_PROC (s_delete
, "delete", 2, 0, 0, scm_delete
);
637 scm_delete (item
, lst
)
643 copy
= scm_list_copy (lst
);
644 return scm_delete_x (item
, copy
);
648 SCM_PROC(s_delq1_x
, "delq1!", 2, 0, 0, scm_delq1_x
);
650 scm_delq1_x (item
, lst
)
657 for (prev
= &lst
, walk
= lst
;
658 SCM_NIMP (walk
) && SCM_CONSP (walk
);
659 walk
= SCM_CDR (walk
))
661 if (SCM_CAR (walk
) == item
)
663 *prev
= SCM_CDR (walk
);
667 prev
= SCM_CDRLOC (walk
);
674 SCM_PROC(s_delv1_x
, "delv1!", 2, 0, 0, scm_delv1_x
);
676 scm_delv1_x (item
, lst
)
683 for (prev
= &lst
, walk
= lst
;
684 SCM_NIMP (walk
) && SCM_CONSP (walk
);
685 walk
= SCM_CDR (walk
))
687 if (SCM_BOOL_F
!= scm_eqv_p (SCM_CAR (walk
), item
))
689 *prev
= SCM_CDR (walk
);
693 prev
= SCM_CDRLOC (walk
);
700 SCM_PROC(s_delete1_x
, "delete1!", 2, 0, 0, scm_delete1_x
);
702 scm_delete1_x (item
, lst
)
709 for (prev
= &lst
, walk
= lst
;
710 SCM_NIMP (walk
) && SCM_CONSP (walk
);
711 walk
= SCM_CDR (walk
))
713 if (SCM_BOOL_F
!= scm_equal_p (SCM_CAR (walk
), item
))
715 *prev
= SCM_CDR (walk
);
719 prev
= SCM_CDRLOC (walk
);