From af26ff8c2bc0741eaca3a3f3c59ddd60227f38a3 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku <kaz@kylheku.com> Date: Mon, 1 Nov 2021 07:19:58 -0700 Subject: rel-path, path-equal: native Windows fixes. The checks for native Windows are incorrect, plus there are some issues in the path-volume function. We cannot check for native Windows at macro-expansion time simply by calling (find #\\ path-sep-chars) because we compile on Cygwin where that is false. What we must do is check for being on Windows at macro-expansion time, and then in the "yes" branch of that decision, the code must perform the path-sep-char test at run-time. In the "no" branch, we can output smaller code that doesn't deal with Windows. * stdlib/copy-file.tl (if-windows, if-native-windows): New macro, which give a clear syntax to the above described testing. (path-split): Use if-native-windows. (path-volume): Use if-native-windows. In addition, fix some broken tests. The tests for a UNC path "//whatever" cannot just test that the first components are "", because that also matches the path "/". It has t be that the first two components are "", and there are more components. A similar issue occurs in the situation when there is a drive letter. We cannot conclude that if the component after the drive letter is "", then it's a drive absolute path, because that situation occurs in a path like "c:" which is relative. We also destructively manipulate the path to splice out the volume part and turn it into a simple relative or absolute path. This is because the path-simplify function deosn't deal with the volume prefix; its logic like eliminating .. navigations from root do not work if the prefix component is present. (rel-path): We handle a missing error case here: one path has volume prefix and the other doesn't. Also the error cases that can only occur on Windows are wrapped with if-windows to remove them at compile time. --- stdlib/copy-file.tl | 62 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 19 deletions(-) (limited to 'stdlib') diff --git a/stdlib/copy-file.tl b/stdlib/copy-file.tl index 258192fc..3198b76e 100644 --- a/stdlib/copy-file.tl +++ b/stdlib/copy-file.tl @@ -225,9 +225,20 @@ (t (push c out)))) (nreverse out))) +(eval-only + (defmacro if-windows (then : else) + (if (eql 2 (sizeof wchar)) + then + else)) + + (defmacro if-native-windows (then else) + (if-windows + ^(if (find #\\ path-sep-chars) ,then ,else) + else))) + (defun path-split (str) (let ((spl0 (sspl path-sep-chars str))) - (if (macro-time (find #\\ path-sep-chars)) + (if-native-windows (iflet ((head (car spl0)) (p (pos #\: head))) (list* [head 0..(succ p)] @@ -237,18 +248,25 @@ spl0))) (defun path-volume (comp) - (let ((head (car comp)) - (next (cadr comp))) - (if (macro-time (find #\\ path-sep-chars)) - (cond - ((and (equal head "") (equal next "")) - (let ((vol (caddr comp))) - (if (nequal "" vol) vol :abs))) - ((equal head "") :abs) - ((and (m^ #/[A-Za-z0-9]+:/ head) head) - (if (equal "" next) - ^(:abs . ,head) - ^(:rel . ,head)))) + (let ((head (car comp))) + (if-native-windows + (let ((next (cadr comp)) + (more (cddr comp))) + (cond + ((and (equal head "") (equal next "") more) + (let ((vol (car more))) + (cond + ((nequal "" vol) + (set (car comp) "") + (set (cdr comp) (cdr more)) + vol) + (t :abs)))) + ((and (m^ #/[A-Za-z0-9]+:/ head) head) + (set (car comp) next) + (set (cdr comp) more) + (if (and (equal "" next) more) + ^(:abs . ,head) + ^(:rel . ,head))))) (if (equal head "") :abs)))) (defun rel-path (from to) @@ -263,12 +281,18 @@ (if (meq :abs fvol tvol) (error "~s: mixture of absolute and volume paths ~s ~s given" 'rel-path from to)) - (when (and (consp fvol) (consp tvol)) - (if (neq (car fvol) (car tvol)) - (error "~s: mixture of volume absolute and relative paths ~s ~s given" - 'rel-path from to) - (error "~s: paths on different volumes ~s ~s given" - 'rel-path from to)))) + (if-windows + (progn + (when (and (consp fvol) (consp tvol)) + (if (neq (car fvol) (car tvol)) + (error "~s: mixture of volume absolute and relative paths \ + \ ~s ~s given" + 'rel-path from to))) + (when (neq (null fvol) (null tvol)) + (error "~s: mixture of volume and non-volume paths ~s ~s given" + 'rel-path from to)) + (error "~s: paths on different volumes ~s ~s given" + 'rel-path from to)))) (let* ((fcomp (path-simplify fspl)) (tcomp (path-simplify tspl)) (ncommon (mismatch fcomp tcomp))) -- cgit v1.2.3