* coop-defs.h: fix various preprocessor usages of new public
[bpt/guile.git] / libguile / sort.c
index 70de175..ab6a31f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
+/* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  */
 
 /* We need this to get the definitions for HAVE_ALLOCA_H, etc.  */
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+/* do we still need this here? */
 #include "libguile/scmconfig.h"
 
 /* AIX requires this to be the first thing in the file.  The #pragma
@@ -86,6 +91,7 @@ char *alloca ();
 #include "libguile/feature.h"
 #include "libguile/root.h"
 #include "libguile/vectors.h"
+#include "libguile/lang.h"
 
 #include "libguile/validate.h"
 #include "libguile/sort.h"
@@ -354,14 +360,6 @@ subr2less (SCM less, const void *a, const void *b)
   return SCM_NFALSEP (SCM_SUBRF (less) (*(SCM *) a, *(SCM *) b));
 }                              /* subr2less */
 
-static int 
-subr2oless (SCM less, const void *a, const void *b)
-{
-  return SCM_NFALSEP (SCM_SUBRF (less) (*(SCM *) a,
-                                       *(SCM *) b,
-                                       SCM_UNDEFINED));
-}                              /* subr2oless */
-
 static int 
 lsubrless (SCM less, const void *a, const void *b)
 {
@@ -378,7 +376,7 @@ closureless (SCM code, const void *a, const void *b)
                                      scm_cons (*(SCM *) b, SCM_EOL)),
                            SCM_ENV (code));
   /* Evaluate the closure body */
-  return SCM_NFALSEP (scm_eval_body (SCM_CDR (SCM_CODE (code)), env));
+  return !SCM_FALSEP (scm_eval_body (SCM_CLOSURE_BODY (code), env));
 }                              /* closureless */
 
 static int 
@@ -393,11 +391,10 @@ scm_cmp_function (SCM p)
   switch (SCM_TYP7 (p))
     {
     case scm_tc7_subr_2:
+    case scm_tc7_subr_2o:
     case scm_tc7_rpsubr:
     case scm_tc7_asubr:
       return subr2less;
-    case scm_tc7_subr_2o:
-      return subr2oless;
     case scm_tc7_lsubr:
       return lsubrless;
     case scm_tcs_closures:
@@ -424,19 +421,20 @@ SCM_DEFINE (scm_restricted_vector_sort_x, "restricted-vector-sort!", 4, 0, 0,
   size_t  vlen, spos, len, size = sizeof (SCM);
   SCM *vp;
 
-  SCM_VALIDATE_VECTOR (1,vec);
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_VECTOR (1, vec);
+  SCM_VALIDATE_NIM (2, less);
 
-  vp = SCM_VELTS (vec);                /* vector pointer */
+  vp = SCM_WRITABLE_VELTS (vec);               /* vector pointer */
   vlen = SCM_VECTOR_LENGTH (vec);
 
   SCM_VALIDATE_INUM_MIN_COPY (3, startpos, 0, spos);
-  SCM_ASSERT_RANGE (3,startpos, spos <= vlen);
-  SCM_VALIDATE_INUM_RANGE (4,endpos,0,vlen+1);
+  SCM_ASSERT_RANGE (3, startpos, spos <= vlen);
+  SCM_VALIDATE_INUM_RANGE (4, endpos,0, vlen+1);
   len = SCM_INUM (endpos) - spos;
 
   quicksort (&vp[spos], len, size, scm_cmp_function (less), less);
-  return SCM_UNSPECIFIED;
+  
+  return scm_return_first (SCM_UNSPECIFIED, vec);
   /* return vec; */
 }
 #undef FUNC_NAME
@@ -454,18 +452,18 @@ SCM_DEFINE (scm_sorted_p, "sorted?", 2, 0, 0,
 {
   long len, j;                 /* list/vector length, temp j */
   SCM item, rest;              /* rest of items loop variable */
-  SCM *vp;
+  SCM const *vp;
   cmp_fun_t cmp = scm_cmp_function (less);
 
-  if (SCM_NULLP (items))
+  if (SCM_NULL_OR_NIL_P (items))
     return SCM_BOOL_T;
 
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_NIM (2, less);
 
   if (SCM_CONSP (items))
     {
       len = scm_ilength (items); /* also checks that it's a pure list */
-      SCM_ASSERT_RANGE (1,items,len >= 0);
+      SCM_ASSERT_RANGE (1, items, len >= 0);
       if (len <= 1)
        return SCM_BOOL_T;
 
@@ -516,9 +514,10 @@ SCM_DEFINE (scm_sorted_p, "sorted?", 2, 0, 0,
    Note:  this does _not_ accept vectors. */
 SCM_DEFINE (scm_merge, "merge", 3, 0, 0, 
             (SCM alist, SCM blist, SCM less),
-           "Takes two lists @var{alist} and @var{blist} such that\n"
-           "@code{(sorted? alist less?)} and @code{(sorted? blist less?)} and\n"
-           "returns a new list in which the elements of @var{alist} and\n"
+           "Merge two already sorted lists into one.\n"
+           "Given two lists @var{alist} and @var{blist}, such that\n"
+           "@code{(sorted? alist less?)} and @code{(sorted? blist less?)},\n"
+           "return a new list in which the elements of @var{alist} and\n"
            "@var{blist} have been stably interleaved so that\n"
            "@code{(sorted? (merge alist blist less?) less?)}.\n"
            "Note:  this does _not_ accept vectors.")
@@ -527,16 +526,16 @@ SCM_DEFINE (scm_merge, "merge", 3, 0, 0,
   long alen, blen;             /* list lengths */
   SCM build, last;
   cmp_fun_t cmp = scm_cmp_function (less);
-  SCM_VALIDATE_NIM (3,less);
+  SCM_VALIDATE_NIM (3, less);
 
-  if (SCM_NULLP (alist))
+  if (SCM_NULL_OR_NIL_P (alist))
     return blist;
-  else if (SCM_NULLP (blist))
+  else if (SCM_NULL_OR_NIL_P (blist))
     return alist;
   else
     {
-      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (1,alist,alen);
-      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (2,blist,blen);
+      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (1, alist, alen);
+      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (2, blist, blen);
       if ((*cmp) (less, SCM_CARLOC (blist), SCM_CARLOC (alist)))
        {
          build = scm_cons (SCM_CAR (blist), SCM_EOL);
@@ -583,9 +582,9 @@ scm_merge_list_x (SCM alist, SCM blist,
 {
   SCM build, last;
 
-  if (SCM_NULLP (alist))
+  if (SCM_NULL_OR_NIL_P (alist))
     return blist;
-  else if (SCM_NULLP (blist))
+  else if (SCM_NULL_OR_NIL_P (blist))
     return alist;
   else
     {
@@ -639,15 +638,15 @@ SCM_DEFINE (scm_merge_x, "merge!", 3, 0, 0,
 {
   long alen, blen;             /* list lengths */
 
-  SCM_VALIDATE_NIM (3,less);
-  if (SCM_NULLP (alist))
+  SCM_VALIDATE_NIM (3, less);
+  if (SCM_NULL_OR_NIL_P (alist))
     return blist;
-  else if (SCM_NULLP (blist))
+  else if (SCM_NULL_OR_NIL_P (blist))
     return alist;
   else
     {
-      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (1,alist,alen);
-      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (2,blist,blen);
+      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (1, alist, alen);
+      SCM_VALIDATE_NONEMPTYLIST_COPYLEN (2, blist, blen);
       return scm_merge_list_x (alist, blist,
                               alen, blen,
                               scm_cmp_function (less),
@@ -714,14 +713,14 @@ SCM_DEFINE (scm_sort_x, "sort!", 2, 0, 0,
 #define FUNC_NAME s_scm_sort_x
 {
   long len;                    /* list/vector length */
-  if (SCM_NULLP(items))
-    return SCM_EOL;
+  if (SCM_NULL_OR_NIL_P (items))
+    return items;
 
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_NIM (2, less);
 
   if (SCM_CONSP (items))
     {
-      SCM_VALIDATE_LIST_COPYLEN (1,items,len);
+      SCM_VALIDATE_LIST_COPYLEN (1, items, len);
       return scm_merge_list_step (&items, scm_cmp_function (less), less, len);
     }
   else if (SCM_VECTORP (items))
@@ -747,19 +746,19 @@ SCM_DEFINE (scm_sort, "sort", 2, 0, 0,
            "elements.  This is not a stable sort.")
 #define FUNC_NAME s_scm_sort
 {
-  if (SCM_NULLP(items))
-    return SCM_EOL;
+  if (SCM_NULL_OR_NIL_P (items))
+    return items;
 
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_NIM (2, less);
   if (SCM_CONSP (items))
     {
       long len;
   
-      SCM_VALIDATE_LIST_COPYLEN (1,items,len);
+      SCM_VALIDATE_LIST_COPYLEN (1, items, len);
       items = scm_list_copy (items);
       return scm_merge_list_step (&items, scm_cmp_function (less), less, len);
     }
-#ifdef HAVE_ARRAYS
+#ifdef SCM_HAVE_ARRAYS
   /* support ordinary vectors even if arrays not available?  */
   else if (SCM_VECTORP (items))
     {
@@ -780,43 +779,55 @@ SCM_DEFINE (scm_sort, "sort", 2, 0, 0,
 #undef FUNC_NAME
 
 static void
-scm_merge_vector_x (void *const vecbase,
-                   void *const tempbase,
+scm_merge_vector_x (SCM vec,
+                   SCM * temp,
                    cmp_fun_t cmp,
                    SCM less,
                    long low,
                    long mid,
                    long high)
 {
-  register SCM *vp = (SCM *) vecbase;
-  register SCM *temp = (SCM *) tempbase;
   long it;             /* Index for temp vector */
   long i1 = low;       /* Index for lower vector segment */
   long i2 = mid + 1;   /* Index for upper vector segment */
 
   /* Copy while both segments contain more characters */
   for (it = low; (i1 <= mid) && (i2 <= high); ++it)
-    if ((*cmp) (less, &vp[i2], &vp[i1]))
-      temp[it] = vp[i2++];
-    else
-      temp[it] = vp[i1++];
-
-  /* Copy while first segment contains more characters */
-  while (i1 <= mid)
-    temp[it++] = vp[i1++];
-
-  /* Copy while second segment contains more characters */
-  while (i2 <= high)
-    temp[it++] = vp[i2++];
+    {
+      /*
+       Every call of LESS might invoke GC.  For full correctness, we
+       should reset the generation of vecbase and tempbase between
+       every call of less.
+
+       */
+      register SCM *vp = SCM_WRITABLE_VELTS(vec);
+      
+      if ((*cmp) (less, &vp[i2], &vp[i1]))
+       temp[it] = vp[i2++];
+      else
+       temp[it] = vp[i1++];
+    }
 
-  /* Copy back from temp to vp */
-  for (it = low; it <= high; ++it)
-    vp[it] = temp[it];
-}                              /* scm_merge_vector_x */
+  {
+    register SCM *vp = SCM_WRITABLE_VELTS(vec);
+    
+    /* Copy while first segment contains more characters */
+    while (i1 <= mid)
+      temp[it++] = vp[i1++];
+
+    /* Copy while second segment contains more characters */
+    while (i2 <= high)
+      temp[it++] = vp[i2++];
+
+    /* Copy back from temp to vp */
+    for (it = low; it <= high; ++it)
+      vp[it] = temp[it];
+  }
+}                              /* scm_merge_vector_x */
 
 static void
-scm_merge_vector_step (void *const vp,
-                      void *const temp,
+scm_merge_vector_step (SCM vp,
+                      SCM * temp,
                       cmp_fun_t cmp,
                       SCM less,
                       long low,
@@ -845,22 +856,27 @@ SCM_DEFINE (scm_stable_sort_x, "stable-sort!", 2, 0, 0,
 {
   long len;                    /* list/vector length */
 
-  if (SCM_NULLP (items))
-    return SCM_EOL;
+  if (SCM_NULL_OR_NIL_P (items))
+    return items;
 
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_NIM (2, less);
   if (SCM_CONSP (items))
     {
-      SCM_VALIDATE_LIST_COPYLEN (1,items,len);
+      SCM_VALIDATE_LIST_COPYLEN (1, items, len);
       return scm_merge_list_step (&items, scm_cmp_function (less), less, len);
     }
   else if (SCM_VECTORP (items))
     {
-      SCM *temp, *vp;
+      SCM *temp;
       len = SCM_VECTOR_LENGTH (items);
-      temp = malloc (len * sizeof(SCM));
-      vp = SCM_VELTS (items);
-      scm_merge_vector_step (vp,
+
+      /*
+        the following array does not contain any new references to
+        SCM objects, so we can get away with allocing it on the heap.
+      */
+      temp = scm_malloc (len * sizeof(SCM));
+
+      scm_merge_vector_step (items,
                             temp,
                             scm_cmp_function (less),
                             less,
@@ -875,7 +891,6 @@ SCM_DEFINE (scm_stable_sort_x, "stable-sort!", 2, 0, 0,
 #undef FUNC_NAME
 
 /* stable_sort manages lists and vectors */
-
 SCM_DEFINE (scm_stable_sort, "stable-sort", 2, 0, 0, 
             (SCM items, SCM less),
            "Sort the sequence @var{items}, which may be a list or a\n"
@@ -883,29 +898,28 @@ SCM_DEFINE (scm_stable_sort, "stable-sort", 2, 0, 0,
            "This is a stable sort.")
 #define FUNC_NAME s_scm_stable_sort
 {
-  long len;                    /* list/vector length */
-  if (SCM_NULLP (items))
-    return SCM_EOL;
 
-  SCM_VALIDATE_NIM (2,less);
+  if (SCM_NULL_OR_NIL_P (items))
+    return items;
+
+  SCM_VALIDATE_NIM (2, less);
   if (SCM_CONSP (items))
     {
-      SCM_VALIDATE_LIST_COPYLEN (1,items,len);
+      long len;                        /* list/vector length */      
+      SCM_VALIDATE_LIST_COPYLEN (1, items, len);
       items = scm_list_copy (items);
       return scm_merge_list_step (&items, scm_cmp_function (less), less, len);
     }
-#ifdef HAVE_ARRAYS
+#ifdef SCM_HAVE_ARRAYS
   /* support ordinary vectors even if arrays not available?  */
   else if (SCM_VECTORP (items))
     {
-      SCM retvec;
-      SCM *temp, *vp;
-      len = SCM_VECTOR_LENGTH (items);
-      retvec = scm_make_uve (len, scm_array_prototype (items));
+      long len = SCM_VECTOR_LENGTH (items);
+      SCM *temp = scm_malloc (len * sizeof (SCM));
+      SCM retvec = scm_make_uve (len, scm_array_prototype (items));
       scm_array_copy_x (items, retvec);
-      temp = malloc (len * sizeof (SCM));
-      vp = SCM_VELTS (retvec);
-      scm_merge_vector_step (vp,
+
+      scm_merge_vector_step (retvec,
                             temp,
                             scm_cmp_function (less),
                             less,
@@ -930,8 +944,8 @@ SCM_DEFINE (scm_sort_list_x, "sort-list!", 2, 0, 0,
 #define FUNC_NAME s_scm_sort_list_x
 {
   long len;
-  SCM_VALIDATE_LIST_COPYLEN (1,items,len);
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_LIST_COPYLEN (1, items, len);
+  SCM_VALIDATE_NIM (2, less);
   return scm_merge_list_step (&items, scm_cmp_function (less), less, len);
 }
 #undef FUNC_NAME
@@ -944,8 +958,8 @@ SCM_DEFINE (scm_sort_list, "sort-list", 2, 0, 0,
 #define FUNC_NAME s_scm_sort_list
 {
   long len;
-  SCM_VALIDATE_LIST_COPYLEN (1,items,len);
-  SCM_VALIDATE_NIM (2,less);
+  SCM_VALIDATE_LIST_COPYLEN (1, items, len);
+  SCM_VALIDATE_NIM (2, less);
   items = scm_list_copy (items);
   return scm_merge_list_step (&items, scm_cmp_function (less), less, len);
 }
@@ -954,9 +968,7 @@ SCM_DEFINE (scm_sort_list, "sort-list", 2, 0, 0,
 void
 scm_init_sort ()
 {
-#ifndef SCM_MAGIC_SNARFER
 #include "libguile/sort.x"
-#endif
 
   scm_add_feature ("sort");
 }