~ chicken-core (chicken-5) 15da5479a2dfd74a4c9e2fba011e1b9c0764a491


commit 15da5479a2dfd74a4c9e2fba011e1b9c0764a491
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Mon Jul 5 14:35:48 2010 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Mon Jul 5 14:35:48 2010 +0200

    changed argument signature of find-files to use keywords (the old signature is still supported but deprecated

diff --git a/manual/Unit posix b/manual/Unit posix
index 74b8c9be..63fb5add 100644
--- a/manual/Unit posix	
+++ b/manual/Unit posix	
@@ -1085,34 +1085,43 @@ These variables contain error codes as returned by {{errno}}.
 
 ==== find-files
 
-<procedure>(find-files DIRECTORY [PREDICATE [ACTION [IDENTITY [LIMIT]]]])</procedure>
+<procedure>(find-files DIRECTORY #!key test action seed limit dotfiles follow-symlinks)</procedure>
 
 Recursively traverses the contents of {{DIRECTORY}} (which should be a
-string) and invokes the procedure {{ACTION}} for all files in which
-the procedure {{PREDICATE}} is true.  {{PREDICATE}} may be a procedure
-of one argument or a regular-expression string.  {{ACTION}} should be
-a procedure of two arguments: the currently encountered file and the
-result of the previous invocation of {{ACTION}}, or, if this is the
-first invocation, the value of {{IDENTITY}}. {{PREDICATE}} defaults to
-{{(constantly #t)}}, {{ACTION}} defaults to
-{{cons}}, {{IDENTITY}} defaults to {{()}}.  {{LIMIT}} should be a
-procedure of one argument that is called for each nested directory and
-which should return true, if that directory is to be traversed
-recursively. {{LIMIT}} may also be an exact integer that gives the
-maximum recursion depth. For example, a depth of {{0}} means that only
-files in the top-level, specified directory are to be traversed. In
-this case, all nested directories are ignored.  {{LIMIT}} may also be
-{{#f}} (the default), which is equivalent to {{(constantly #t)}}.
-
-Note that {{ACTION}} is called with the full pathname of each file,
+string) and invokes the procedure {{action}} for all files in which
+the procedure {{test}} is true.  {{test}} may be a procedure of one
+argument or a regular-expression string that will be matched with a
+full pathname using {{string-match}}.  {{action}} should be a
+procedure of two arguments: the currently encountered file and the
+result of the previous invocation of {{action}}, or, if this is the
+first invocation, the value of {{seed}}. {{test}} defaults to
+{{(constantly #t)}}, {{action}} defaults to {{cons}}, {{seed}}
+defaults to {{()}}.  {{limit}} should be a procedure of one argument
+that is called for each nested directory and which should return true,
+if that directory is to be traversed recursively. {{limit}} may also
+be an exact integer that gives the maximum recursion depth. For
+example, a depth of {{0}} means that only files in the top-level,
+specified directory are to be traversed. In this case, all nested
+directories are ignored.  {{limit}} may also be {{#f}} (the default),
+which is equivalent to {{(constantly #t)}}. 
+
+If {{dotfiles}} is given and true, then files starting with a "{{.}}"
+character will not be ignored (but note that "{{.}}" and "{{..}}"  are
+always ignored). if {{follow-symlinks}} is given and true, then the
+traversal of a symbolic link that points to a directory will
+recursively traverse the latter. By default, symbolic links are not
+followed.
+
+Note that {{action}} is called with the full pathname of each file,
 including the directory prefix.
 
-Also note that {{find-files}} will traverse symbolic links pointing to
-directories, which may lead to symlink loops or duplication of files.
-To avoid traversing symlinks, you can pass something like this as the
-{{LIMIT}} procedure:
+In older CHICKEN versions, {{find-files}} has a different argument
+signature:
 
- (lambda (x) (not (symbolic-link? x)))
+  (find-files DIRECTORY [TEST [ACTION [SEED [LIMIT]]]])
+
+This signature is still supported for compatibility reasons but is
+deprecated.
 
 === Getting the hostname and system information
 
diff --git a/posix-common.scm b/posix-common.scm
index a03861c9..b415879d 100644
--- a/posix-common.scm
+++ b/posix-common.scm
@@ -25,7 +25,7 @@
 
 
 (declare 
-  (hide ##sys#stat posix-error check-time-vector)
+  (hide ##sys#stat posix-error check-time-vector ##sys#find-files)
   (foreign-declare #<<EOF
 
 #include <signal.h>
@@ -204,7 +204,9 @@ EOF
       (let ([buffer (make-string 256)]
             [handle (##sys#make-pointer)]
             [entry (##sys#make-pointer)] )
-        (##core#inline "C_opendir" (##sys#make-c-string (##sys#expand-home-path spec) 'directory) handle)
+        (##core#inline 
+	 "C_opendir"
+	 (##sys#make-c-string (##sys#expand-home-path spec) 'directory) handle)
         (if (##sys#null-pointer? handle)
             (posix-error #:file-error 'directory "cannot open directory" spec)
             (let loop ()
@@ -251,18 +253,15 @@ EOF
 
 ;;; Find matching files:
 
-(define find-files
+(define ##sys#find-files
   (let ((glob glob)
 	(string-match string-match)
 	(make-pathname make-pathname)
 	(pathname-file pathname-file)
+	(symbolic-link? symbolic-link?)
 	(directory? directory?) )
-    (lambda (dir #!optional
-		 (pred (lambda _ #t))
-		 (action (lambda (x y) (cons x y))) ; we want cons inlined
-		 (id '())
-		 (limit #f) )
-	(##sys#check-string dir 'find-files)
+    (lambda (dir pred action id limit follow dot loc)
+	(##sys#check-string dir loc)
 	(let* ((depth 0)
 	       (lproc
 		(cond ((not limit) (lambda _ #t))
@@ -270,9 +269,10 @@ EOF
 		      (else limit) ) )
 	       (pproc
 		(if (or (string? pred) (regexp? pred))
-		    (lambda (x) (string-match pred x))
+		    (let ((pred (regexp pred))) ; force compilation
+		      (lambda (x) (string-match pred x)))
 		    pred) ) )
-	  (let loop ((fs (glob (make-pathname dir "*")))
+	  (let loop ((fs (glob (make-pathname dir (if dot "?*" "*"))))
 		     (r id) )
 	    (if (null? fs)
 		r
@@ -289,5 +289,21 @@ EOF
 			((pproc f) (loop rest (action f r)))
 			(else (loop rest r)) ) ) ) ) ) ) ) )
 
-
-;;; TODO: add more here...
+(define (find-files dir . args)
+  (cond ((or (null? args) (not (keyword? (car args))))
+	 ;; old signature - DEPRECATED
+	 (let-optionals args ((pred (lambda _ #t))
+			      (action (lambda (x y) (cons x y))) ; we want `cons' inlined
+			      (id '())
+			      (limit #f) )
+	   (##sys#find-files dir pred action id limit #t #f 'find-files)))
+	(else
+	 (apply 
+	  (lambda (#!key (test (lambda _ #t))
+			 (action (lambda (x y) (cons x y))) ; s.a.
+			 (seed '())
+			 (limit #f)
+			 (dotfiles #f)
+			 (follow-symlinks #t))
+	    (##sys#find-files dir test action seed limit follow-symlinks dotfiles 'find-files))
+	  args))))
Trap