guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Add "scandir" procedure


From: Nala Ginrut
Subject: Re: [PATCH] Add "scandir" procedure
Date: Sun, 28 Aug 2011 04:18:13 +0800
User-agent: Heirloom mailx 12.4 7/29/08

>From a79c0db1ef1a932443e41ba6185b0d8c1a5774ed Mon Sep 17 00:00:00 2001
From: Nala Ginrut <address@hidden>
Date: Sun, 28 Aug 2011 03:19:15 +0800
Subject: [PATCH] Add scandir procedure

---
 libguile/_scm.h    |    3 ++
 libguile/filesys.c |   98 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/libguile/_scm.h b/libguile/_scm.h
index 48fb2cc..cd3f82c 100644
--- a/libguile/_scm.h
+++ b/libguile/_scm.h
@@ -166,6 +166,9 @@
 #define off_t_or_off64_t                CHOOSE_LARGEFILE(off_t,off64_t)
 #define open_or_open64                  CHOOSE_LARGEFILE(open,open64)
 #define readdir_or_readdir64            CHOOSE_LARGEFILE(readdir,readdir64)
+#define scandir_or_scandir64           CHOOSE_LARGEFILE(scandir,scandir64)
+#define alphasort_or_alphasort64       CHOOSE_LARGEFILE(alphasort,alphasort64)
+#define versionsort_or_versionsort64   
CHOOSE_LARGEFILE(versionsort,versionsort64)
 #if SCM_HAVE_READDIR64_R == 1
 # define readdir_r_or_readdir64_r       CHOOSE_LARGEFILE(readdir_r,readdir64_r)
 #else
diff --git a/libguile/filesys.c b/libguile/filesys.c
index f600328..d4bf2f4 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1670,6 +1670,104 @@ SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
 }
 #undef FUNC_NAME
 
+SCM_DEFINE (scm_scandir, "scandir", 1, 2, 0,
+           (SCM dir, SCM filter, SCM sort),
+           "Return a list which contains all files and directories' name of 
the "
+           "@var{dir}. The @var{sort} is the sort method of the result.\n"
+           "The second arg @var{filter} is a proc with 2 args and return #t "
+           "for keeping this result, and vice versa.\n"
+           "If @var{sort} is unspecified, @code{alplasort} would be default.\n"
+           "The optional @var{sort} must be symbol and could be:"
+           "@defvar{asort} ==> for alphasort\n"
+           "@defvar{vsort} ==> for versionsort")
+#define FUNC_NAME s_scm_scandir
+{
+  struct dirent_or_dirent64 **rdent;
+  int sort_type = 0;
+  int has_filter = 0;
+  int n = 0 ,i = 0;
+  SCM flag;
+  SCM ret = SCM_EOL;
+  SCM *prev;
+  SCM str;
+
+  SCM_VALIDATE_STRING (1, dir);
+
+  if (!SCM_UNBNDP (filter))
+    {
+      SCM_ASSERT (scm_is_true (scm_procedure_p (filter)),
+                 filter ,SCM_ARG2 ,FUNC_NAME);
+      has_filter = 1;
+    }
+  
+  if (!SCM_UNBNDP (sort))
+    {
+      SCM_ASSERT (scm_symbol_p(sort) ,sort ,SCM_ARG3 ,FUNC_NAME);
+      
+      if (scm_is_true (scm_eq_p (sort, scm_from_latin1_symbol ("asort"))))
+       sort_type = 0;  
+      else if (scm_is_true (scm_eq_p (sort, scm_from_latin1_symbol ("vsort"))))
+       sort_type = 1;
+      else
+       scm_error (scm_from_latin1_symbol ("invalid-sort-type"),
+                  "scandir", "Scandir got an invalid sort type: ~S",
+                  scm_list_1 (sort), scm_list_1 (sort));
+    }
+
+  scm_dynwind_begin (0);
+  errno = 0;
+
+  switch (sort_type)
+    {  
+    case 0: 
+      SCM_SYSCALL(n = scandir_or_scandir64 (scm_to_locale_string (dir), 
+                                           &rdent, NULL, 
alphasort_or_alphasort64));
+      break;
+    case 1:
+      SCM_SYSCALL(n = scandir_or_scandir64 (scm_to_locale_string (dir), 
+                                           &rdent, NULL, 
versionsort_or_versionsort64))        ;
+      break;
+    default:
+      SCM_SYSERROR;
+    }
+
+  if (has_filter)
+    {
+      for (prev = &ret;i<n;i++)
+       {
+         str = rdent[i]? scm_from_locale_stringn (rdent[i]->d_name ,NAMLEN 
(rdent[i])) : SCM_EOF_VAL;
+         flag = scm_call_1 (filter ,str);
+         free (rdent[i]);
+
+         if (scm_is_true (flag))
+           {
+             *prev = scm_cons (str ,SCM_EOL);
+             prev = SCM_CDRLOC (*prev);
+           }
+         
+       }
+    }
+  else
+    {
+      for (prev = &ret;i<n;i++)
+       {
+         str = rdent[i]? scm_from_locale_stringn (rdent[i]->d_name ,NAMLEN 
(rdent[i])) : SCM_EOF_VAL;
+         *prev = scm_cons (str ,SCM_EOL);
+         prev = SCM_CDRLOC (*prev);
+         free (rdent[i]);
+       }
+    }
+
+  if (errno != 0)
+    SCM_SYSERROR;
+
+  scm_dynwind_end ();
+
+  free (rdent);
+  
+  return ret;
+}
+#undef FUNC_NAME
 
 /* FIXME: The glibc manual has a portability note that readdir_r may not
    null-terminate its return string.  The circumstances outlined for this
-- 
1.7.0.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]