There seems to be a bug in TRANSLATE-LOGICAL-PATHNAME when the logical pathname source includes constant elements in addition to wildcards.
Here is an example that demonstrates the problem:
CL-USER(1): (setf (logical-pathname-translations "L") '(("L:NATIVE;**;*.*" "/usr/lisp/abcl/native/**/*.*")))
((#P"L:NATIVE;**;*.*" #P"/usr/lisp/abcl/native/**/*.*"))
CL-USER(2): (translate-logical-pathname "L:NATIVE;TEST;FOO.FASL")
#P"/usr/lisp/abcl/native/native/test/foo.fasl"
;; ERROR. Should be #P"/usr/lisp/abcl/native/test/foo.fasl" ;; ;; With :wild-inferiors, the full directory path is copied instead of ;; just the part after the matching constant part. That results in ;; the "native" element appearing twice. ;;
The problem seems to be in the file "abcl/src/org/armedbear/lisp/ pathnames.lisp", in the function SYSTEM::TRANSLATE-DIRECTORY-COMPONENTS:
(defun translate-directory-components (source from to case) (cond ((null to) nil ) ((memq (car to) '(:absolute :relative)) (cons (car to) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) ((eq (car to) :wild) (if (eq (car from) :wild) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) (error "Unsupported case 1: ~S ~S ~S" source from to)) ) ((eq (car to) :wild-inferiors) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) (t ;; "If the piece in TO-WILDCARD is present and not wild, it is copied ;; into the result." (append (casify (car to) case) (translate-directory-components source from (cdr to) case)) ) ))
The final COND clause ("T") needs to be more sophisticated in what it does. If there are non-wildcard elements in the FROM, then it will need to eliminate the the common prefix between "source" and "from". In order to be a valid match, it I think it SHOULD be guaranteed that a non-wildcard "from" component is a leading subsequence or equal to "source" -- but I'm not fully familiar with the code, but a quick test seems to indicate that the following modified function covers at least the simpler cases of this issue. It adds a new clause checking for :WILD-INFERIORS in the FROM slot which performs the current function, and changes the T clause to properly manage the subsequence matching.
(defun translate-directory-components (source from to case) (cond ((null to) nil ) ((memq (car to) '(:absolute :relative)) (cons (car to) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) ((eq (car to) :wild) (if (eq (car from) :wild) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) (error "Unsupported case 1: ~S ~S ~S" source from to)) ) ((eq (car to) :wild-inferiors) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) ((eq (car from) :wild-inferiors) ;; "If the piece in TO-WILDCARD is present and not wild, and the FROM item ;; doesn't contain any constants, then just copy TO to the result." (append (casify (car to) case) (translate-directory-components source from (cdr to) case))) (t ;; "If the piece in TO-WILDCARD is present and not wild, then FROM should ;; be a subsequence of SOURCE. The common subsequence needs to be removed ;; in the recursive call. Special case handling for a full match is ;; also needed." (let ((pos (mismatch (car source) (car from) :test #'string- equal))) (append (casify (car to) case) (if (null pos) ;; A full match, pop both source and from (translate-directory-components (cdr source) (cdr from) (cdr to) case) (translate-directory-components (cons (subseq (car source) pos) (cdr source)) (cdr from) (cdr to) case)))) ) ))
Has this been fixed in trunk yet?
----- Original Message ----- From: "Thomas Russ" tar@ISI.EDU To: armedbear-devel@common-lisp.net Cc: "Thomas Russ" tar@ISI.EDU Sent: Monday, November 16, 2009 12:14 PM Subject: [armedbear-devel] Bug in translate-logical-pathname.
There seems to be a bug in TRANSLATE-LOGICAL-PATHNAME when the logical pathname source includes constant elements in addition to wildcards.
Here is an example that demonstrates the problem:
CL-USER(1): (setf (logical-pathname-translations "L") '(("L:NATIVE;**;*.*" "/usr/lisp/abcl/native/**/*.*")))
((#P"L:NATIVE;**;*.*" #P"/usr/lisp/abcl/native/**/*.*"))
CL-USER(2): (translate-logical-pathname "L:NATIVE;TEST;FOO.FASL")
#P"/usr/lisp/abcl/native/native/test/foo.fasl"
;; ERROR. Should be #P"/usr/lisp/abcl/native/test/foo.fasl" ;; ;; With :wild-inferiors, the full directory path is copied instead of ;; just the part after the matching constant part. That results in ;; the "native" element appearing twice. ;;
The problem seems to be in the file "abcl/src/org/armedbear/lisp/ pathnames.lisp", in the function SYSTEM::TRANSLATE-DIRECTORY-COMPONENTS:
(defun translate-directory-components (source from to case) (cond ((null to) nil ) ((memq (car to) '(:absolute :relative)) (cons (car to) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) ((eq (car to) :wild) (if (eq (car from) :wild) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) (error "Unsupported case 1: ~S ~S ~S" source from to)) ) ((eq (car to) :wild-inferiors) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) (t ;; "If the piece in TO-WILDCARD is present and not wild, it is copied ;; into the result." (append (casify (car to) case) (translate-directory-components source from (cdr to) case)) ) ))
The final COND clause ("T") needs to be more sophisticated in what it does. If there are non-wildcard elements in the FROM, then it will need to eliminate the the common prefix between "source" and "from". In order to be a valid match, it I think it SHOULD be guaranteed that a non-wildcard "from" component is a leading subsequence or equal to "source" -- but I'm not fully familiar with the code, but a quick test seems to indicate that the following modified function covers at least the simpler cases of this issue. It adds a new clause checking for :WILD-INFERIORS in the FROM slot which performs the current function, and changes the T clause to properly manage the subsequence matching.
(defun translate-directory-components (source from to case) (cond ((null to) nil ) ((memq (car to) '(:absolute :relative)) (cons (car to) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) ((eq (car to) :wild) (if (eq (car from) :wild) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) (error "Unsupported case 1: ~S ~S ~S" source from to)) ) ((eq (car to) :wild-inferiors) ;; Grab the next chunk from SOURCE. (append (casify (car source) case) (translate-directory-components (cdr source) (cdr from) (cdr to) case)) ) ((eq (car from) :wild-inferiors) ;; "If the piece in TO-WILDCARD is present and not wild, and the FROM item ;; doesn't contain any constants, then just copy TO to the result." (append (casify (car to) case) (translate-directory-components source from (cdr to) case))) (t ;; "If the piece in TO-WILDCARD is present and not wild, then FROM should ;; be a subsequence of SOURCE. The common subsequence needs to be removed ;; in the recursive call. Special case handling for a full match is ;; also needed." (let ((pos (mismatch (car source) (car from) :test #'string- equal))) (append (casify (car to) case) (if (null pos) ;; A full match, pop both source and from (translate-directory-components (cdr source) (cdr from) (cdr to) case) (translate-directory-components (cons (subseq (car source) pos) (cdr source)) (cdr from) (cdr to) case)))) ) ))
armedbear-devel mailing list armedbear-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/armedbear-devel
2009/11/23 logicmoo@gmail.com:
Has this been fixed in trunk yet?
Not that I know of. I am travelling so I can't produce a patch for this during this week.
Hi Thomas,
Just a minute ago, I committed a fix by replacing the current algorithm with a new one along the lines I described to you before. Your example works, hopefully any other uses too.
Bye,
Erik.
On Mon, Nov 16, 2009 at 9:14 PM, Thomas Russ tar@isi.edu wrote:
There seems to be a bug in TRANSLATE-LOGICAL-PATHNAME when the logical pathname source includes constant elements in addition to wildcards.
Here is an example that demonstrates the problem:
CL-USER(1): (setf (logical-pathname-translations "L") '(("L:NATIVE;**;*.*" "/usr/lisp/abcl/native/**/*.*")))
((#P"L:NATIVE;**;*.*" #P"/usr/lisp/abcl/native/**/*.*"))
CL-USER(2): (translate-logical-pathname "L:NATIVE;TEST;FOO.FASL")
#P"/usr/lisp/abcl/native/native/test/foo.fasl"
;; ERROR. Should be #P"/usr/lisp/abcl/native/test/foo.fasl" ;; ;; With :wild-inferiors, the full directory path is copied instead of ;; just the part after the matching constant part. That results in ;; the "native" element appearing twice. ;;
On Thu, Nov 26, 2009 at 12:14 AM, Erik Huelsmann ehuels@gmail.com wrote:
Hi Thomas,
Just a minute ago, I committed a fix by replacing the current algorithm with a new one along the lines I described to you before. Your example works, hopefully any other uses too.
By the way, if someone could write a number of test cases to verify that the algorithm actually does what it should, that would be great! I tested it manually, but adding it to the automated tests is a guarantee breakage doesn't go unnoticed.
Bye,
Erik.
On 11/26/09 3:58 PM, Erik Huelsmann wrote:
On Thu, Nov 26, 2009 at 12:14 AM, Erik Huelsmannehuels@gmail.com wrote:
Hi Thomas,
Just a minute ago, I committed a fix by replacing the current algorithm with a new one along the lines I described to you before. Your example works, hopefully any other uses too.
By the way, if someone could write a number of test cases to verify that the algorithm actually does what it should, that would be great! I tested it manually, but adding it to the automated tests is a guarantee breakage doesn't go unnoticed.
I definitely owe some explanation on how to add both Lisp and Java based tests to ABCL, so until I discharge my documentation debt, if anyone posts tests, I promise that I will make sure they make it into the tree in a reasonably timely fashion.
In general, as we fix things it would be nice to add tests so that things "stay fixed" in the future. But I am as guilty as anyone else at not sticking to this philosophy.
Mark
armedbear-devel@common-lisp.net