Changeset 14362
- Timestamp:
- 01/28/13 13:24:57 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/asdf.lisp
r14361 r14362 1 ;; -*- mode: Common-Lisp; Base: 10 ; Syntax: ANSI-Common-Lisp -*-2 ;;; This is ASDF 2.26.1 43.1: Another System Definition Facility.1 ;;; -*- mode: Common-Lisp; Base: 10 ; Syntax: ANSI-Common-Lisp -*- 2 ;;; This is ASDF 2.26.158.1: Another System Definition Facility. 3 3 ;;; 4 4 ;;; Feedback, bug reports, and patches are all welcome: … … 61 61 #+(or abcl clisp cmu) 62 62 (eval-when (:load-toplevel :compile-toplevel :execute) 63 (unless (member :asdf 2.27*features*)63 (unless (member :asdf3 *features*) 64 64 (let* ((existing-version 65 65 (when (find-package :asdf) … … 82 82 ;; 83 83 ;; CAUTION: we must handle the first few packages specially for hot-upgrade. 84 ;; asdf/package will be frozen as of 2.2784 ;; asdf/package will be frozen as of ASDF 3 85 85 ;; to forever export the same exact symbols. 86 86 ;; Any other symbol must be import-from'ed … … 423 423 recycle mix reexport 424 424 unintern) 425 (declare (ignorable documentation))425 #+(or gcl2.6 genera) (declare (ignore documentation)) 426 426 (macrolet ((when-fishy (&body body) `(when-package-fishiness ,@body)) 427 427 (fishy (&rest info) `(note-package-fishiness ,@info))) … … 592 592 (when (and accessible (eq ustat :external)) 593 593 (ensure-exported name sym u))))))) 594 #-(or gcl genera) (setf (documentation package t) documentation) #+gcl documentation 594 #-(or gcl2.6 genera) 595 (when documentation (setf (documentation package t) documentation)) 595 596 (loop :for p :in (set-difference (package-use-list package) (append mix use)) 596 597 :do (fishy :use (package-names p)) (unuse-package p package)) … … 708 709 (remove "asdf" excl::*autoload-package-name-alist* 709 710 :test 'equalp :key 'car)) 710 711 711 #+gcl 712 712 ;; Debian's GCL 2.7 has bugs with compiling multiple-value stuff, … … 737 737 (:recycle :asdf/common-lisp :asdf) 738 738 #+allegro (:intern #:*acl-warn-save*) 739 #+cormanlisp (:shadow #:user-homedir-pathname) 739 740 #+cormanlisp 740 741 (:export … … 775 776 (defun make-broadcast-stream () *error-output*) 776 777 (defun translate-logical-pathname (x) x) 778 (defun user-homedir-pathname (&optional host) 779 (declare (ignore host)) 780 (parse-namestring (format nil "~A\\" (cl:user-homedir-pathname)))) 777 781 (defun file-namestring (p) 778 782 (setf p (pathname p)) … … 858 862 859 863 860 ;;;; compatfmt: avoid fancy format directives when unsupported 861 864 ;;;; Looping 862 865 (defmacro loop* (&rest rest) 863 866 #-genera `(loop ,@rest) 864 867 #+genera `(lisp:loop ,@rest)) ;; In genera, CL:LOOP can't destructure, so we use LOOP*. Sigh. 865 868 869 870 ;;;; compatfmt: avoid fancy format directives when unsupported 866 871 (eval-when (:load-toplevel :compile-toplevel :execute) 867 (defun strcat (&rest strings) 868 (apply 'concatenate 'string strings))) 872 (defun remove-substrings (substrings string) 873 (let ((length (length string)) (stream nil)) 874 (labels ((emit (start end) 875 (when (and (zerop start) (= end length)) 876 (return-from remove-substrings string)) 877 (unless stream (setf stream (make-string-output-stream))) 878 (write-string string stream :start start :end end)) 879 (recurse (substrings start end) 880 (cond 881 ((= start end)) 882 ((null substrings) (emit start end)) 883 (t (let* ((sub (first substrings)) 884 (found (search sub string)) 885 (more (rest substrings))) 886 (cond 887 (found 888 (recurse more start found) 889 (recurse more (+ found (length sub)) end)) 890 (t 891 (recurse more start end)))))))) 892 (recurse substrings 0 length)) 893 (if stream (get-output-stream-string stream) "")))) 869 894 870 895 (defmacro compatfmt (format) 871 896 #+(or gcl genera) 872 (loop* :for (unsupported . replacement) 873 :in (append 874 '(("~3i~_" . "")) 875 #+(or genera gcl2.6) '(("~@<" . "") ("; ~@;" . "; ") ("~@:>" . "") ("~:>" . ""))) :do 876 (loop :for found = (search unsupported format) :while found :do 877 (setf format (strcat (subseq format 0 found) replacement 878 (subseq format (+ found (length unsupported))))))) 879 format) 897 (remove-substrings `("~3i~_" #+(or genera gcl2.6) ,@'("~@<" "~@;" "~@:>" "~:>")) format) 898 #-(or gcl genera) format) 899 900 880 901 ;;;; ------------------------------------------------------------------------- 881 902 ;;;; General Purpose Utilities for ASDF … … 885 906 (:use :asdf/common-lisp :asdf/package) 886 907 ;; import and reexport a few things defined in :asdf/common-lisp 887 (:import-from :asdf/common-lisp #: strcat #:compatfmt #:loop*908 (:import-from :asdf/common-lisp #:compatfmt #:loop* #:remove-substrings 888 909 #+ecl #:use-ecl-byte-compiler-p #+mcl #:probe-posix) 889 (:export #: nil #:strcat #:compatfmt #:loop*910 (:export #:compatfmt #:loop* #:remove-substrings #:compatfmt 890 911 #+ecl #:use-ecl-byte-compiler-p #+mcl #:probe-posix) 891 912 (:export … … 896 917 #:while-collecting #:appendf #:length=n-p #:remove-plist-keys #:remove-plist-key ;; lists and plists 897 918 #:emptyp ;; sequences 898 #: first-char #:last-char #:split-string ;; strings919 #:strcat #:first-char #:last-char #:split-string ;; strings 899 920 #:string-prefix-p #:string-enclosed-p #:string-suffix-p 900 921 #:find-class* ;; CLOS … … 959 980 ;;; Magic debugging help. See contrib/debug.lisp 960 981 (defvar *asdf-debug-utility* 961 '(ignore-errors (merge-pathnames "cl/asdf/contrib/debug.lisp" (user-homedir-pathname))) 982 '(or (ignore-errors 983 (symbol-call :asdf :system-relative-pathname :asdf-driver "contrib/debug.lisp")) 984 (merge-pathnames "cl/asdf/contrib/debug.lisp" (user-homedir-pathname))) 962 985 "form that evaluates to the pathname to your favorite debugging utilities") 963 986 … … 1041 1064 1042 1065 ;;; Strings 1066 (defun* strcat (&rest strings) 1067 (apply 'concatenate 'string strings)) 1043 1068 1044 1069 (defun* first-char (s) … … 1282 1307 `(call-with-muffled-uninteresting-conditions #'(lambda () ,@body) ,conditions)) 1283 1308 1309 1310 ;;;; --------------------------------------------------------------------------- 1311 ;;;; Access to the Operating System 1312 1313 (asdf/package:define-package :asdf/os 1314 (:recycle :asdf/os :asdf) 1315 (:use :asdf/common-lisp :asdf/package :asdf/utility) 1316 (:export 1317 #:featurep #:os-unix-p #:os-windows-p #:os-genera-p #:detect-os ;; features 1318 #:getenv #:getenvp ;; environment variables 1319 #:implementation-identifier ;; implementation identifier 1320 #:implementation-type #:*implementation-type* 1321 #:operating-system #:architecture #:lisp-version-string 1322 #:hostname #:getcwd #:chdir 1323 ;; Windows shortcut support 1324 #:read-null-terminated-string #:read-little-endian 1325 #:parse-file-location-info #:parse-windows-shortcut)) 1326 (in-package :asdf/os) 1327 1328 ;;; Features 1329 (eval-when (:compile-toplevel :load-toplevel :execute) 1330 (defun* featurep (x &optional (*features* *features*)) 1331 (cond 1332 ((atom x) (and (member x *features*) t)) 1333 ((eq :not (car x)) (assert (null (cddr x))) (not (featurep (cadr x)))) 1334 ((eq :or (car x)) (some #'featurep (cdr x))) 1335 ((eq :and (car x)) (every #'featurep (cdr x))) 1336 (t (error "Malformed feature specification ~S" x)))) 1337 1338 (defun* os-unix-p () 1339 (or #+abcl (featurep :unix) 1340 #+(and (not abcl) (or unix cygwin darwin)) t)) 1341 1342 (defun* os-windows-p () 1343 (or #+abcl (featurep :windows) 1344 #+(and (not (or unix cygwin darwin)) (or win32 windows mswindows mingw32)) t)) 1345 1346 (defun* os-genera-p () 1347 (or #+genera t)) 1348 1349 (defun* detect-os () 1350 (flet ((yes (yes) (pushnew yes *features*)) 1351 (no (no) (setf *features* (remove no *features*)))) 1352 (cond 1353 ((os-unix-p) (yes :os-unix) (no :os-windows) (no :genera)) 1354 ((os-windows-p) (yes :os-windows) (no :os-unix) (no :genera)) 1355 ((os-genera-p) (no :os-unix) (no :os-windows) (yes :genera)) 1356 (t (error "Congratulations for trying XCVB on an operating system~%~ 1357 that is neither Unix, nor Windows, nor even Genera.~%Now you port it."))))) 1358 1359 (detect-os)) 1360 1361 ;;;; Environment variables: getting them, and parsing them. 1362 1363 (defun* getenv (x) 1364 (declare (ignorable x)) 1365 #+(or abcl clisp ecl xcl) (ext:getenv x) 1366 #+allegro (sys:getenv x) 1367 #+clozure (ccl:getenv x) 1368 #+(or cmu scl) (cdr (assoc x ext:*environment-list* :test #'string=)) 1369 #+cormanlisp 1370 (let* ((buffer (ct:malloc 1)) 1371 (cname (ct:lisp-string-to-c-string x)) 1372 (needed-size (win:getenvironmentvariable cname buffer 0)) 1373 (buffer1 (ct:malloc (1+ needed-size)))) 1374 (prog1 (if (zerop (win:getenvironmentvariable cname buffer1 needed-size)) 1375 nil 1376 (ct:c-string-to-lisp-string buffer1)) 1377 (ct:free buffer) 1378 (ct:free buffer1))) 1379 #+gcl (system:getenv x) 1380 #+genera nil 1381 #+lispworks (lispworks:environment-variable x) 1382 #+mcl (ccl:with-cstrs ((name x)) 1383 (let ((value (_getenv name))) 1384 (unless (ccl:%null-ptr-p value) 1385 (ccl:%get-cstring value)))) 1386 #+mkcl (#.(or (find-symbol* 'getenv :si nil) (find-symbol* 'getenv :mk-ext nil)) x) 1387 #+sbcl (sb-ext:posix-getenv x) 1388 #-(or abcl allegro clisp clozure cmu cormanlisp ecl gcl genera lispworks mcl mkcl sbcl scl xcl) 1389 (error "~S is not supported on your implementation" 'getenv)) 1390 1391 (defun* getenvp (x) 1392 "Predicate that is true if the named variable is present in the libc environment, 1393 then returning the non-empty string value of the variable" 1394 (let ((g (getenv x))) (and (not (emptyp g)) g))) 1395 1396 1397 ;;;; implementation-identifier 1398 ;; 1399 ;; produce a string to identify current implementation. 1400 ;; Initially stolen from SLIME's SWANK, completely rewritten since. 1401 ;; We're back to runtime checking, for the sake of e.g. ABCL. 1402 1403 (defun* first-feature (feature-sets) 1404 (dolist (x feature-sets) 1405 (multiple-value-bind (short long feature-expr) 1406 (if (consp x) 1407 (values (first x) (second x) (cons :or (rest x))) 1408 (values x x x)) 1409 (when (featurep feature-expr) 1410 (return (values short long)))))) 1411 1412 (defun* implementation-type () 1413 (first-feature 1414 '(:abcl (:acl :allegro) (:ccl :clozure) :clisp (:corman :cormanlisp) 1415 (:cmu :cmucl :cmu) :ecl :gcl 1416 (:lwpe :lispworks-personal-edition) (:lw :lispworks) 1417 :mcl :mkcl :sbcl :scl (:smbx :symbolics) :xcl))) 1418 1419 (defvar *implementation-type* (implementation-type)) 1420 1421 (defun* operating-system () 1422 (first-feature 1423 '(:cygwin (:win :windows :mswindows :win32 :mingw32) ;; try cygwin first! 1424 (:linux :linux :linux-target) ;; for GCL at least, must appear before :bsd 1425 (:macosx :macosx :darwin :darwin-target :apple) ; also before :bsd 1426 (:solaris :solaris :sunos) (:bsd :bsd :freebsd :netbsd :openbsd) :unix 1427 :genera))) 1428 1429 (defun* architecture () 1430 (first-feature 1431 '((:x64 :x86-64 :x86_64 :x8664-target :amd64 (:and :word-size=64 :pc386)) 1432 (:x86 :x86 :i386 :i486 :i586 :i686 :pentium3 :pentium4 :pc386 :iapx386 :x8632-target) 1433 (:ppc64 :ppc64 :ppc64-target) (:ppc32 :ppc32 :ppc32-target :ppc :powerpc) 1434 :hppa64 :hppa :sparc64 (:sparc32 :sparc32 :sparc) 1435 :mipsel :mipseb :mips :alpha (:arm :arm :arm-target) :imach 1436 ;; Java comes last: if someone uses C via CFFI or otherwise JNA or JNI, 1437 ;; we may have to segregate the code still by architecture. 1438 (:java :java :java-1.4 :java-1.5 :java-1.6 :java-1.7)))) 1439 1440 #+clozure 1441 (defun* ccl-fasl-version () 1442 ;; the fasl version is target-dependent from CCL 1.8 on. 1443 (or (let ((s 'ccl::target-fasl-version)) 1444 (and (fboundp s) (funcall s))) 1445 (and (boundp 'ccl::fasl-version) 1446 (symbol-value 'ccl::fasl-version)) 1447 (error "Can't determine fasl version."))) 1448 1449 (defun* lisp-version-string () 1450 (let ((s (lisp-implementation-version))) 1451 (car ; as opposed to OR, this idiom prevents some unreachable code warning 1452 (list 1453 #+allegro 1454 (format nil "~A~@[~A~]~@[~A~]~@[~A~]" 1455 excl::*common-lisp-version-number* 1456 ;; M means "modern", as opposed to ANSI-compatible mode (which I consider default) 1457 (and (eq excl:*current-case-mode* :case-sensitive-lower) "M") 1458 ;; Note if not using International ACL 1459 ;; see http://www.franz.com/support/documentation/8.1/doc/operators/excl/ics-target-case.htm 1460 (excl:ics-target-case (:-ics "8")) 1461 (and (member :smp *features*) "S")) 1462 #+armedbear (format nil "~a-fasl~a" s system::*fasl-version*) 1463 #+clisp 1464 (subseq s 0 (position #\space s)) ; strip build information (date, etc.) 1465 #+clozure 1466 (format nil "~d.~d-f~d" ; shorten for windows 1467 ccl::*openmcl-major-version* 1468 ccl::*openmcl-minor-version* 1469 (logand (ccl-fasl-version) #xFF)) 1470 #+cmu (substitute #\- #\/ s) 1471 #+scl (format nil "~A~A" s 1472 ;; ANSI upper case vs lower case. 1473 (ecase ext:*case-mode* (:upper "") (:lower "l"))) 1474 #+ecl (format nil "~A~@[-~A~]" s 1475 (let ((vcs-id (ext:lisp-implementation-vcs-id))) 1476 (subseq vcs-id 0 (min (length vcs-id) 8)))) 1477 #+gcl (subseq s (1+ (position #\space s))) 1478 #+genera 1479 (multiple-value-bind (major minor) (sct:get-system-version "System") 1480 (format nil "~D.~D" major minor)) 1481 #+mcl (subseq s 8) ; strip the leading "Version " 1482 s)))) 1483 1484 (defun* implementation-identifier () 1485 (substitute-if 1486 #\_ #'(lambda (x) (find x " /:;&^\\|?<>(){}[]$#`'\"")) 1487 (format nil "~(~a~@{~@[-~a~]~}~)" 1488 (or (implementation-type) (lisp-implementation-type)) 1489 (or (lisp-version-string) (lisp-implementation-version)) 1490 (or (operating-system) (software-type)) 1491 (or (architecture) (machine-type))))) 1492 1493 1494 ;;;; Other system information 1495 1496 (defun* hostname () 1497 ;; Note: untested on RMCL 1498 #+(or abcl clozure cmucl ecl genera lispworks mcl mkcl sbcl scl xcl) (machine-instance) 1499 #+cormanlisp "localhost" ;; is there a better way? Does it matter? 1500 #+allegro (symbol-call :excl.osi :gethostname) 1501 #+clisp (first (split-string (machine-instance) :separator " ")) 1502 #+gcl (system:gethostname)) 1503 1504 1505 ;;; Current directory 1506 1507 (defun* getcwd () 1508 "Get the current working directory as per POSIX getcwd(3), as a pathname object" 1509 (or #+abcl (parse-namestring 1510 (java:jstatic "getProperty" "java.lang.System" "user.dir") :ensure-directory t) 1511 #+allegro (excl::current-directory) 1512 #+clisp (ext:default-directory) 1513 #+clozure (ccl:current-directory) 1514 #+(or cmu scl) (ext:parse-unix-namestring 1515 (nth-value 1 (unix:unix-current-directory)) :ensure-directory t) 1516 #+cormanlisp (pathname (pl::get-current-directory)) ;; Q: what type does it return? 1517 #+ecl (ext:getcwd) 1518 #+gcl (parse-namestring ;; this is a joke. Isn't there a better way? 1519 (first (symbol-call :asdf/driver :run-program '("/bin/pwd") :output :lines))) 1520 #+genera *default-pathname-defaults* ;; on a Lisp OS, it *is* canonical! 1521 #+lispworks (system:current-directory) 1522 #+mkcl (mk-ext:getcwd) 1523 #+sbcl (sb-ext:parse-native-namestring (sb-unix:posix-getcwd/)) 1524 #+xcl (extensions:current-directory) 1525 (error "getcwd not supported on your implementation"))) 1526 1527 (defun* chdir (x) 1528 "Change current directory, as per POSIX chdir(2)" 1529 (declare (ignorable x)) 1530 (or #+abcl (java:jstatic "setProperty" "java.lang.System" "user.dir" (namestring x)) 1531 #+allegro (excl:chdir x) 1532 #+clisp (ext:cd x) 1533 #+clozure (setf (ccl:current-directory) x) 1534 #+(or cmu scl) (unix:unix-chdir (ext:unix-namestring x)) 1535 #+cormanlisp (unless (zerop (win32::_chdir (namestring x))) 1536 (error "Could not set current directory to ~A" x)) 1537 #+ecl (ext:chdir x) 1538 #+genera (setf *default-pathname-defaults* (pathname x)) 1539 #+lispworks (hcl:change-directory x) 1540 #+mkcl (mk-ext:chdir x) 1541 #+sbcl (symbol-call :sb-posix :chdir (sb-ext:native-namestring x)) 1542 (error "chdir not supported on your implementation"))) 1543 1544 1545 ;;;; ----------------------------------------------------------------- 1546 ;;;; Windows shortcut support. Based on: 1547 ;;;; 1548 ;;;; Jesse Hager: The Windows Shortcut File Format. 1549 ;;;; http://www.wotsit.org/list.asp?fc=13 1550 1551 #-(or clisp genera) ; CLISP doesn't need it, and READ-SEQUENCE annoys old Genera. 1552 (progn 1553 (defparameter *link-initial-dword* 76) 1554 (defparameter *link-guid* #(1 20 2 0 0 0 0 0 192 0 0 0 0 0 0 70)) 1555 1556 (defun* read-null-terminated-string (s) 1557 (with-output-to-string (out) 1558 (loop :for code = (read-byte s) 1559 :until (zerop code) 1560 :do (write-char (code-char code) out)))) 1561 1562 (defun* read-little-endian (s &optional (bytes 4)) 1563 (loop :for i :from 0 :below bytes 1564 :sum (ash (read-byte s) (* 8 i)))) 1565 1566 (defun* parse-file-location-info (s) 1567 (let ((start (file-position s)) 1568 (total-length (read-little-endian s)) 1569 (end-of-header (read-little-endian s)) 1570 (fli-flags (read-little-endian s)) 1571 (local-volume-offset (read-little-endian s)) 1572 (local-offset (read-little-endian s)) 1573 (network-volume-offset (read-little-endian s)) 1574 (remaining-offset (read-little-endian s))) 1575 (declare (ignore total-length end-of-header local-volume-offset)) 1576 (unless (zerop fli-flags) 1577 (cond 1578 ((logbitp 0 fli-flags) 1579 (file-position s (+ start local-offset))) 1580 ((logbitp 1 fli-flags) 1581 (file-position s (+ start 1582 network-volume-offset 1583 #x14)))) 1584 (strcat (read-null-terminated-string s) 1585 (progn 1586 (file-position s (+ start remaining-offset)) 1587 (read-null-terminated-string s)))))) 1588 1589 (defun* parse-windows-shortcut (pathname) 1590 (with-open-file (s pathname :element-type '(unsigned-byte 8)) 1591 (handler-case 1592 (when (and (= (read-little-endian s) *link-initial-dword*) 1593 (let ((header (make-array (length *link-guid*)))) 1594 (read-sequence header s) 1595 (equalp header *link-guid*))) 1596 (let ((flags (read-little-endian s))) 1597 (file-position s 76) ;skip rest of header 1598 (when (logbitp 0 flags) 1599 ;; skip shell item id list 1600 (let ((length (read-little-endian s 2))) 1601 (file-position s (+ length (file-position s))))) 1602 (cond 1603 ((logbitp 1 flags) 1604 (parse-file-location-info s)) 1605 (t 1606 (when (logbitp 2 flags) 1607 ;; skip description string 1608 (let ((length (read-little-endian s 2))) 1609 (file-position s (+ length (file-position s))))) 1610 (when (logbitp 3 flags) 1611 ;; finally, our pathname 1612 (let* ((length (read-little-endian s 2)) 1613 (buffer (make-array length))) 1614 (read-sequence buffer s) 1615 (map 'string #'code-char buffer))))))) 1616 (end-of-file (c) 1617 (declare (ignore c)) 1618 nil))))) 1619 1620 1284 1621 ;;;; ------------------------------------------------------------------------- 1285 1622 ;;;; Portability layer around Common Lisp pathnames … … 1287 1624 (asdf/package:define-package :asdf/pathname 1288 1625 (:recycle :asdf/pathname :asdf) 1289 (:use :asdf/common-lisp :asdf/package :asdf/utility )1626 (:use :asdf/common-lisp :asdf/package :asdf/utility :asdf/os) 1290 1627 (:export 1291 1628 #:*resolve-symlinks* 1292 ;; Making and mergingpathnames, portably1629 ;; Making pathnames, portably 1293 1630 #:normalize-pathname-directory-component #:denormalize-pathname-directory-component 1294 #:pathname-equal 1295 #:merge-pathname-directory-components #:make-pathname* #:*unspecific-pathname-type* 1631 #:merge-pathname-directory-components #:*unspecific-pathname-type* #:make-pathname* 1296 1632 #:make-pathname-component-logical #:make-pathname-logical 1297 1633 #:merge-pathnames* 1634 ;; Predicates 1635 #:pathname-equal #:logical-pathname-p #:physical-pathname-p 1636 #:absolute-pathname-p #:relative-pathname-p #:hidden-pathname-p #:file-pathname-p 1298 1637 ;; Directories 1299 1638 #:pathname-directory-pathname #:pathname-parent-directory-pathname 1300 #:directory-pathname-p #:ensure-directory-pathname #:file-pathname-p 1301 ;; Absolute vs relative pathnames 1302 #:ensure-pathname-absolute 1303 #:relativize-directory-component #:relativize-pathname-directory 1304 ;; Parsing filenames and lists thereof 1639 #:directory-pathname-p #:ensure-directory-pathname 1640 ;; defaults 1641 #:nil-pathname #:with-pathname-defaults #:*nil-pathname* 1642 ;; Parsing filenames 1305 1643 #:component-name-to-pathname-components 1306 1644 #:split-name-type #:parse-unix-namestring #:unix-namestring 1307 1645 #:split-unix-namestring-directory-components 1308 #:subpathname #:subpathname* #:subpathp 1646 #:native-namestring #:parse-native-namestring 1647 #:subpathname #:subpathname* 1648 ;; Wildcard pathnames 1649 #:*wild* #:*wild-file* #:*wild-directory* #:*wild-inferiors* #:*wild-path* #:wilden 1650 ;; probe filesystem 1651 #:truename* #:safe-file-write-date #:probe-file* 1652 #:directory* #:filter-logical-directory-results #:directory-files #:subdirectories 1653 #:collect-sub*directories 1654 ;; Absolute vs relative pathnames 1655 #:ensure-pathname-absolute 1656 #:pathname-root #:pathname-host-pathname 1657 #:subpathp 1309 1658 ;; Resolving symlinks somewhat 1310 1659 #:truenamize #:resolve-symlinks #:resolve-symlinks* 1311 ;; Wildcard pathnames1312 #:*wild* #:*wild-file* #:*wild-directory* #:*wild-inferiors* #:*wild-path* #:wilden1313 ;; Pathname host and its root1314 #:absolute-pathname-p #:relative-pathname-p #:hidden-pathname-p1315 #:pathname-root #:directory-separator-for-host1316 #:directorize-pathname-host-device1317 ;; defaults1318 #:nil-pathname #:with-pathname-defaults1319 ;; probe filesystem1320 #:truename* #:probe-file* #:safe-file-write-date1321 #:subdirectories #:directory-files #:directory*1322 #:filter-logical-directory-results #:collect-sub*directories1323 ;; Simple filesystem operations1324 #:ensure-all-directories-exist1325 #:rename-file-overwriting-target1326 #:delete-file-if-exists1327 ;; Translate a pathname1328 #:translate-pathname*1329 ;; temporary1330 #:add-pathname-suffix #:tmpize-pathname1331 #:call-with-staging-pathname #:with-staging-pathname1332 ;; physical pathnames1333 #:logical-pathname-p #:physical-pathname-p #:sane-physical-pathname #:root-pathname1334 ;; Windows shortcut support1335 #:read-null-terminated-string #:read-little-endian1336 #:parse-file-location-info #:parse-windows-shortcut1337 1660 ;; Checking constraints 1338 1661 #:ensure-pathname 1339 #:absolutize-pathnames 1340 ;; Output translations 1662 ;; merging with cwd 1663 #:get-pathname-defaults #:call-with-current-directory #:with-current-directory 1664 ;; Environment pathnames 1665 #:inter-directory-separator #:split-native-pathnames-string 1666 #:getenv-pathname #:getenv-pathnames 1667 #:getenv-absolute-directory #:getenv-absolute-directories 1668 #:lisp-implementation-directory #:lisp-implementation-pathname-p 1669 ;; Translate a pathname 1670 #:relativize-directory-component #:relativize-pathname-directory 1671 #:directory-separator-for-host #:directorize-pathname-host-device 1672 #:translate-pathname* 1341 1673 #:*output-translation-function*)) 1342 1674 … … 1410 1742 #+(or clisp ecl #|These haven't been tested:|# cormanlisp mcl) nil) 1411 1743 1412 (defun* make-pathname* (&rest keys &key (directory nil directoryp)1413 host (device () devicep) name type version defaults1744 (defun* make-pathname* (&rest keys &key (directory nil #+gcl2.6 directoryp) 1745 host (device () #+allegro devicep) name type version defaults 1414 1746 #+scl &allow-other-keys) 1415 1747 "Takes arguments like CL:MAKE-PATHNAME in the CLHS, and 1416 1748 tries hard to make a pathname that will actually behave as documented, 1417 1749 despite the peculiarities of each implementation" 1418 (declare (ignorable host device d evicepname type version defaults))1750 (declare (ignorable host device directory name type version defaults)) 1419 1751 (apply 'make-pathname 1420 1752 (append 1421 1753 #+allegro (when (and devicep (null device)) `(:device :unspecific)) 1754 #+gcl2.6 1422 1755 (when directoryp 1423 1756 `(:directory ,(denormalize-pathname-directory-component directory))) … … 1442 1775 :version (make-pathname-component-logical (pathname-version pathname)))) 1443 1776 1444 1445 ;;; Some pathname predicates1446 1447 (defun* pathname-equal (p1 p2)1448 (when (stringp p1) (setf p1 (pathname p1)))1449 (when (stringp p2) (setf p2 (pathname p2)))1450 (flet ((normalize-component (x)1451 (unless (member x '(nil :unspecific :newest (:relative)) :test 'equal)1452 x)))1453 (macrolet ((=? (&rest accessors)1454 (flet ((frob (x)1455 (reduce 'list (cons 'normalize-component accessors)1456 :initial-value x :from-end t)))1457 `(equal ,(frob 'p1) ,(frob 'p2)))))1458 (or (and (null p1) (null p2))1459 (and (pathnamep p1) (pathnamep p2)1460 (and (=? pathname-host)1461 (=? pathname-device)1462 (=? normalize-pathname-directory-component pathname-directory)1463 (=? pathname-name)1464 (=? pathname-type)1465 (=? pathname-version)))))))1466 1467 (defun* logical-pathname-p (x)1468 (typep x 'logical-pathname))1469 1470 (defun* physical-pathname-p (x)1471 (and (pathnamep x) (not (logical-pathname-p x))))1472 1473 (defun* absolute-pathname-p (pathspec)1474 "If PATHSPEC is a pathname or namestring object that parses as a pathname1475 possessing an :ABSOLUTE directory component, return the (parsed) pathname.1476 Otherwise return NIL"1477 (and pathspec1478 (typep pathspec '(or null pathname string))1479 (let ((pathname (pathname pathspec)))1480 (and (eq :absolute (car (normalize-pathname-directory-component1481 (pathname-directory pathname))))1482 pathname))))1483 1484 (defun* relative-pathname-p (pathspec)1485 "If PATHSPEC is a pathname or namestring object that parses as a pathname1486 possessing a :RELATIVE or NIL directory component, return the (parsed) pathname.1487 Otherwise return NIL"1488 (and pathspec1489 (typep pathspec '(or null pathname string))1490 (let* ((pathname (pathname pathspec))1491 (directory (normalize-pathname-directory-component1492 (pathname-directory pathname))))1493 (when (or (null directory) (eq :relative (car directory)))1494 pathname))))1495 1496 (defun* hidden-pathname-p (pathname)1497 "Return a boolean that is true if the pathname is hidden as per Unix style,1498 i.e. its name starts with a dot."1499 (and pathname (equal (first-char (pathname-name pathname)) #\.)))1500 1501 1502 ;;;; merging pathnames1503 1777 (defun* merge-pathnames* (specified &optional (defaults *default-pathname-defaults*)) 1504 1778 "MERGE-PATHNAMES* is like MERGE-PATHNAMES except that … … 1524 1798 (version (or (pathname-version specified) (pathname-version defaults)))) 1525 1799 (labels ((unspecific-handler (p) 1526 (if ( logical-pathname-p p) #'make-pathname-component-logical #'identity)))1800 (if (typep p 'logical-pathname) #'make-pathname-component-logical #'identity))) 1527 1801 (multiple-value-bind (host device directory unspecific-handler) 1528 1802 (ecase (first directory) … … 1542 1816 :version (funcall unspecific-handler version)))))) 1543 1817 1544 ;;; Directories 1818 1819 ;;; Some pathname predicates 1820 1821 (defun* pathname-equal (p1 p2) 1822 (when (stringp p1) (setf p1 (pathname p1))) 1823 (when (stringp p2) (setf p2 (pathname p2))) 1824 (flet ((normalize-component (x) 1825 (unless (member x '(nil :unspecific :newest (:relative)) :test 'equal) 1826 x))) 1827 (macrolet ((=? (&rest accessors) 1828 (flet ((frob (x) 1829 (reduce 'list (cons 'normalize-component accessors) 1830 :initial-value x :from-end t))) 1831 `(equal ,(frob 'p1) ,(frob 'p2))))) 1832 (or (and (null p1) (null p2)) 1833 (and (pathnamep p1) (pathnamep p2) 1834 (and (=? pathname-host) 1835 (=? pathname-device) 1836 (=? normalize-pathname-directory-component pathname-directory) 1837 (=? pathname-name) 1838 (=? pathname-type) 1839 (=? pathname-version))))))) 1840 1841 (defun* logical-pathname-p (x) 1842 (typep x 'logical-pathname)) 1843 1844 (defun* physical-pathname-p (x) 1845 (and (pathnamep x) (not (logical-pathname-p x)))) 1846 1847 (defun* absolute-pathname-p (pathspec) 1848 "If PATHSPEC is a pathname or namestring object that parses as a pathname 1849 possessing an :ABSOLUTE directory component, return the (parsed) pathname. 1850 Otherwise return NIL" 1851 (and pathspec 1852 (typep pathspec '(or null pathname string)) 1853 (let ((pathname (pathname pathspec))) 1854 (and (eq :absolute (car (normalize-pathname-directory-component 1855 (pathname-directory pathname)))) 1856 pathname)))) 1857 1858 (defun* relative-pathname-p (pathspec) 1859 "If PATHSPEC is a pathname or namestring object that parses as a pathname 1860 possessing a :RELATIVE or NIL directory component, return the (parsed) pathname. 1861 Otherwise return NIL" 1862 (and pathspec 1863 (typep pathspec '(or null pathname string)) 1864 (let* ((pathname (pathname pathspec)) 1865 (directory (normalize-pathname-directory-component 1866 (pathname-directory pathname)))) 1867 (when (or (null directory) (eq :relative (car directory))) 1868 pathname)))) 1869 1870 (defun* hidden-pathname-p (pathname) 1871 "Return a boolean that is true if the pathname is hidden as per Unix style, 1872 i.e. its name starts with a dot." 1873 (and pathname (equal (first-char (pathname-name pathname)) #\.))) 1874 1875 (defun* file-pathname-p (pathname) 1876 "Does PATHNAME represent a file, i.e. has a non-null NAME component? 1877 1878 Accepts NIL, a string (converted through PARSE-NAMESTRING) or a PATHNAME. 1879 1880 Note that this does _not_ check to see that PATHNAME points to an 1881 actually-existing file. 1882 1883 Returns the (parsed) PATHNAME when true" 1884 (when pathname 1885 (let* ((pathname (pathname pathname)) 1886 (name (pathname-name pathname))) 1887 (when (not (member name '(nil :unspecific "") :test 'equal)) 1888 pathname)))) 1889 1890 1891 ;;; Directory pathnames 1545 1892 (defun* pathname-directory-pathname (pathname) 1546 1893 "Returns a new pathname with same HOST, DEVICE, DIRECTORY as PATHNAME, … … 1576 1923 t))))) 1577 1924 1578 (defun* file-pathname-p (pathname) 1579 "Does PATHNAME represent a file, i.e. has a non-null NAME component? 1580 1581 Accepts NIL, a string (converted through PARSE-NAMESTRING) or a PATHNAME. 1582 1583 Note that this does _not_ check to see that PATHNAME points to an 1584 actually-existing file. 1585 1586 Returns the (parsed) PATHNAME when true" 1587 (when pathname 1588 (let* ((pathname (pathname pathname)) 1589 (name (pathname-name pathname))) 1590 (when (not (member name '(nil :unspecific "") :test 'equal)) 1591 pathname)))) 1592 1593 (defun* ensure-directory-pathname (pathspec) 1925 (defun* ensure-directory-pathname (pathspec &optional (on-error 'error)) 1594 1926 "Converts the non-wild pathname designator PATHSPEC to directory form." 1595 1927 (cond … … 1597 1929 (ensure-directory-pathname (pathname pathspec))) 1598 1930 ((not (pathnamep pathspec)) 1599 ( error (compatfmt "~@<Invalid pathname designator ~S~@:>") pathspec))1931 (call-function on-error (compatfmt "~@<Invalid pathname designator ~S~@:>") pathspec)) 1600 1932 ((wild-pathname-p pathspec) 1601 ( error (compatfmt "~@<Can't reliably convert wild pathname ~3i~_~S~@:>") pathspec))1933 (call-function on-error (compatfmt "~@<Can't reliably convert wild pathname ~3i~_~S~@:>") pathspec)) 1602 1934 ((directory-pathname-p pathspec) 1603 1935 pathspec) … … 1608 1940 (list (file-namestring pathspec))) 1609 1941 :name nil :type nil :version nil :defaults pathspec)))) 1942 1943 1944 ;;; defaults 1945 (defun* nil-pathname (&optional (defaults *default-pathname-defaults*)) 1946 "A pathname that is as neutral as possible for use as defaults 1947 when merging, making or parsing pathnames" 1948 ;; 19.2.2.2.1 says a NIL host can mean a default host; 1949 ;; see also "valid physical pathname host" in the CLHS glossary, that suggests 1950 ;; strings and lists of strings or :unspecific 1951 ;; But CMUCL decides to die on NIL. 1952 (make-pathname* :directory nil :name nil :type nil :version nil :device nil 1953 :host (or #+cmu lisp::*unix-host*) 1954 ;; the default shouldn't matter, but we really want something physical 1955 :defaults defaults)) 1956 1957 (defvar *nil-pathname* (nil-pathname (translate-logical-pathname (user-homedir-pathname)))) 1958 1959 (defmacro with-pathname-defaults ((&optional defaults) &body body) 1960 `(let ((*default-pathname-defaults* ,(or defaults '*nil-pathname*))) ,@body)) 1961 1962 1963 ;;; Parsing filenames and lists thereof 1964 (defun* split-unix-namestring-directory-components 1965 (unix-namestring &key ensure-directory dot-dot) 1966 "Splits the path string UNIX-NAMESTRING, returning four values: 1967 A flag that is either :absolute or :relative, indicating 1968 how the rest of the values are to be interpreted. 1969 A directory path --- a list of strings and keywords, suitable for 1970 use with MAKE-PATHNAME when prepended with the flag value. 1971 Directory components with an empty name or the name . are removed. 1972 Any directory named .. is read as DOT-DOT, or :BACK if it's NIL (not :UP). 1973 A last-component, either a file-namestring including type extension, 1974 or NIL in the case of a directory pathname. 1975 A flag that is true iff the unix-style-pathname was just 1976 a file-namestring without / path specification. 1977 ENSURE-DIRECTORY forces the namestring to be interpreted as a directory pathname: 1978 the third return value will be NIL, and final component of the namestring 1979 will be treated as part of the directory path. 1980 1981 An empty string is thus read as meaning a pathname object with all fields nil. 1982 1983 Note that : characters will NOT be interpreted as host specification. 1984 Absolute pathnames are only appropriate on Unix-style systems. 1985 1986 The intention of this function is to support structured component names, 1987 e.g., \(:file \"foo/bar\"\), which will be unpacked to relative pathnames." 1988 (check-type unix-namestring string) 1989 (check-type dot-dot (member nil :back :up)) 1990 (if (and (not (find #\/ unix-namestring)) (not ensure-directory) 1991 (plusp (length unix-namestring))) 1992 (values :relative () unix-namestring t) 1993 (let* ((components (split-string unix-namestring :separator "/")) 1994 (last-comp (car (last components)))) 1995 (multiple-value-bind (relative components) 1996 (if (equal (first components) "") 1997 (if (equal (first-char unix-namestring) #\/) 1998 (values :absolute (cdr components)) 1999 (values :relative nil)) 2000 (values :relative components)) 2001 (setf components (remove-if #'(lambda (x) (member x '("" ".") :test #'equal)) 2002 components)) 2003 (setf components (substitute (or dot-dot :back) ".." components :test #'equal)) 2004 (cond 2005 ((equal last-comp "") 2006 (values relative components nil nil)) ; "" already removed from components 2007 (ensure-directory 2008 (values relative components nil nil)) 2009 (t 2010 (values relative (butlast components) last-comp nil))))))) 2011 2012 (defun* split-name-type (filename) 2013 "Split a filename into two values NAME and TYPE that are returned. 2014 We assume filename has no directory component. 2015 The last . if any separates name and type from from type, 2016 except that if there is only one . and it is in first position, 2017 the whole filename is the NAME with an empty type. 2018 NAME is always a string. 2019 For an empty type, *UNSPECIFIC-PATHNAME-TYPE* is returned." 2020 (check-type filename string) 2021 (assert (plusp (length filename))) 2022 (destructuring-bind (name &optional (type *unspecific-pathname-type*)) 2023 (split-string filename :max 2 :separator ".") 2024 (if (equal name "") 2025 (values filename *unspecific-pathname-type*) 2026 (values name type)))) 2027 2028 (defun* parse-unix-namestring (name &rest keys &key type defaults dot-dot ensure-directory 2029 &allow-other-keys) 2030 "Coerce NAME into a PATHNAME using standard Unix syntax. 2031 2032 Unix syntax is used whether or not the underlying system is Unix; 2033 on such non-Unix systems it is only usable but for relative pathnames; 2034 but especially to manipulate relative pathnames portably, it is of crucial 2035 to possess a portable pathname syntax independent of the underlying OS. 2036 This is what PARSE-UNIX-NAMESTRING provides, and why we use it in ASDF. 2037 2038 When given a PATHNAME object, just return it untouched. 2039 When given NIL, just return NIL. 2040 When given a non-null SYMBOL, first downcase its name and treat it as a string. 2041 When given a STRING, portably decompose it into a pathname as below. 2042 2043 #\\/ separates directory components. 2044 2045 The last #\\/-separated substring is interpreted as follows: 2046 1- If TYPE is :DIRECTORY or ENSURE-DIRECTORY is true, 2047 the string is made the last directory component, and NAME and TYPE are NIL. 2048 if the string is empty, it's the empty pathname with all slots NIL. 2049 2- If TYPE is NIL, the substring is file-namestring, and its NAME and TYPE 2050 are separated by SPLIT-NAME-TYPE. 2051 3- If TYPE is a string, it is the given TYPE, and the whole string is the NAME. 2052 2053 Directory components with an empty name the name . are removed. 2054 Any directory named .. is read as DOT-DOT, 2055 which must be one of :BACK or :UP and defaults to :BACK. 2056 2057 HOST, DEVICE and VERSION components are taken from DEFAULTS, 2058 which itself defaults to *NIL-PATHNAME*, also used if DEFAULTS in NIL. 2059 No host or device can be specified in the string itself, 2060 which makes it unsuitable for absolute pathnames outside Unix. 2061 2062 For relative pathnames, these components (and hence the defaults) won't matter 2063 if you use MERGE-PATHNAMES* but will matter if you use MERGE-PATHNAMES, 2064 which is an important reason to always use MERGE-PATHNAMES*. 2065 2066 Arbitrary keys are accepted, and the parse result is passed to ENSURE-PATHNAME 2067 with those keys, removing TYPE DEFAULTS and DOT-DOT. 2068 When you're manipulating pathnames that are supposed to make sense portably 2069 even though the OS may not be Unixish, we recommend you use :WANT-RELATIVE T 2070 to throw an error if the pathname is absolute" 2071 (block nil 2072 (check-type type (or null string (eql :directory))) 2073 (when ensure-directory 2074 (setf type :directory)) 2075 (etypecase name 2076 ((or null pathname) (return name)) 2077 (symbol 2078 (setf name (string-downcase name))) 2079 (string)) 2080 (multiple-value-bind (relative path filename file-only) 2081 (split-unix-namestring-directory-components 2082 name :dot-dot dot-dot :ensure-directory (eq type :directory)) 2083 (multiple-value-bind (name type) 2084 (cond 2085 ((or (eq type :directory) (null filename)) 2086 (values nil nil)) 2087 (type 2088 (values filename type)) 2089 (t 2090 (split-name-type filename))) 2091 (apply 'ensure-pathname 2092 (make-pathname* 2093 :directory (unless file-only (cons relative path)) 2094 :name name :type type 2095 :defaults (or defaults *nil-pathname*)) 2096 (remove-plist-keys '(:type :dot-dot :defaults) keys)))))) 2097 2098 (defun* unix-namestring (pathname) 2099 "Given a non-wild PATHNAME, return a Unix-style namestring for it. 2100 If the PATHNAME is NIL or a STRING, return it unchanged. 2101 2102 This only considers the DIRECTORY, NAME and TYPE components of the pathname. 2103 This is a portable solution for representing relative pathnames, 2104 But unless you are running on a Unix system, it is not a general solution 2105 to representing native pathnames. 2106 2107 An error is signaled if the argument is not NULL, a STRING or a PATHNAME, 2108 or if it is a PATHNAME but some of its components are not recognized." 2109 (etypecase pathname 2110 ((or null string) pathname) 2111 (pathname 2112 (with-output-to-string (s) 2113 (flet ((err () (error "Not a valid unix-namestring ~S" pathname))) 2114 (let* ((dir (normalize-pathname-directory-component (pathname-directory pathname))) 2115 (name (pathname-name pathname)) 2116 (type (pathname-type pathname)) 2117 (type (and (not (eq type :unspecific)) type))) 2118 (cond 2119 ((eq dir ())) 2120 ((eq dir '(:relative)) (princ "./" s)) 2121 ((consp dir) 2122 (destructuring-bind (relabs &rest dirs) dir 2123 (or (member relabs '(:relative :absolute)) (err)) 2124 (when (eq relabs :absolute) (princ #\/ s)) 2125 (loop :for x :in dirs :do 2126 (cond 2127 ((member x '(:back :up)) (princ "../" s)) 2128 ((equal x "") (err)) 2129 ;;((member x '("." "..") :test 'equal) (err)) 2130 ((stringp x) (format s "~A/" x)) 2131 (t (err)))))) 2132 (t (err))) 2133 (cond 2134 (name 2135 (or (and (stringp name) (or (null type) (stringp type))) (err)) 2136 (format s "~A~@[.~A~]" name type)) 2137 (t 2138 (or (null type) (err)))))))))) 2139 2140 (defun* native-namestring (x) 2141 "From a non-wildcard CL pathname, a return namestring suitable for passing to the operating system" 2142 (when x 2143 (let ((p (pathname x))) 2144 #+clozure (with-pathname-defaults () (ccl:native-translated-namestring p)) ; see ccl bug 978 2145 #+(or cmu scl) (ext:unix-namestring p nil) 2146 #+sbcl (sb-ext:native-namestring p) 2147 #-(or clozure cmu sbcl scl) 2148 (if (os-unix-p) (unix-namestring p) 2149 (namestring p))))) 2150 2151 (defun* parse-native-namestring (string &rest constraints &key ensure-directory &allow-other-keys) 2152 "From a native namestring suitable for use by the operating system, return 2153 a CL pathname satisfying all the specified constraints as per ENSURE-PATHNAME" 2154 (check-type string (or string null)) 2155 (let* ((pathname 2156 (when string 2157 (with-pathname-defaults () 2158 #+clozure (ccl:native-to-pathname string) 2159 #+sbcl (sb-ext:parse-native-namestring string) 2160 #-(or clozure sbcl) 2161 (if (os-unix-p) 2162 (parse-unix-namestring string :ensure-directory ensure-directory) 2163 (parse-namestring string))))) 2164 (pathname 2165 (if ensure-directory 2166 (and pathname (ensure-directory-pathname pathname)) 2167 pathname))) 2168 (apply 'ensure-pathname pathname constraints))) 2169 2170 (defun* subpathname (pathname subpath &key type) 2171 "This function takes a PATHNAME and a SUBPATH and a TYPE. 2172 If SUBPATH is already a PATHNAME object (not namestring), 2173 and is an absolute pathname at that, it is returned unchanged; 2174 otherwise, SUBPATH is turned into a relative pathname with given TYPE 2175 as per PARSE-UNIX-NAMESTRING with :WANT-RELATIVE T :TYPE TYPE, 2176 then it is merged with the PATHNAME-DIRECTORY-PATHNAME of PATHNAME." 2177 (or (and (pathnamep subpath) (absolute-pathname-p subpath)) 2178 (merge-pathnames* (parse-unix-namestring subpath :type type :want-relative t) 2179 (pathname-directory-pathname pathname)))) 2180 2181 (defun* subpathname* (pathname subpath &key type) 2182 "returns NIL if the base pathname is NIL, otherwise like SUBPATHNAME." 2183 (and pathname 2184 (subpathname (ensure-directory-pathname pathname) subpath :type type))) 1610 2185 1611 2186 … … 1631 2206 1632 2207 ;;; Probing the filesystem 1633 (defun* nil-pathname (&optional (defaults *default-pathname-defaults*))1634 ;; 19.2.2.2.1 says a NIL host can mean a default host;1635 ;; see also "valid physical pathname host" in the CLHS glossary, that suggests1636 ;; strings and lists of strings or :unspecific1637 ;; But CMUCL decides to die on NIL.1638 (make-pathname* :directory nil :name nil :type nil :version nil :device nil1639 :host (or #+cmu lisp::*unix-host*)1640 ;; the default shouldn't matter, but we really want something physical1641 :defaults defaults))1642 1643 (defmacro with-pathname-defaults ((&optional defaults) &body body)1644 `(let ((*default-pathname-defaults* ,(or defaults '(nil-pathname)))) ,@body))1645 1646 2208 (defun* truename* (p) 1647 2209 ;; avoids both logical-pathname merging and physical resolution issues 1648 (and p (ignore-errors (with-pathname-defaults () (truename p))))) 2210 (and p (handler-case (with-pathname-defaults () (truename p)) (file-error () nil)))) 2211 2212 (defun* safe-file-write-date (pathname) 2213 ;; If FILE-WRITE-DATE returns NIL, it's possible that 2214 ;; the user or some other agent has deleted an input file. 2215 ;; Also, generated files will not exist at the time planning is done 2216 ;; and calls compute-action-stamp which calls safe-file-write-date. 2217 ;; So it is very possible that we can't get a valid file-write-date, 2218 ;; and we can survive and we will continue the planning 2219 ;; as if the file were very old. 2220 ;; (or should we treat the case in a different, special way?) 2221 (handler-case (file-write-date pathname) (file-error () nil))) 1649 2222 1650 2223 (defun* probe-file* (p &key truename) … … 1657 2230 (null nil) 1658 2231 (string (probe-file* (parse-namestring p) :truename truename)) 1659 (pathname (unless (wild-pathname-p p) 1660 (let ((foundtrue 1661 #.(or #+(or allegro clozure cmu cormanlisp ecl lispworks mkcl sbcl scl) 1662 '(probe-file p) 1663 #+clisp (if-let (it (find-symbol* '#:probe-pathname :ext nil)) 1664 `(ignore-errors (,it p))) 1665 #+gcl2.6 1666 '(or (probe-file p) 1667 (and (directory-pathname-p p) 1668 (ignore-errors 1669 (ensure-directory-pathname 1670 (truename* (subpathname 1671 (ensure-directory-pathname p) ".")))))) 1672 '(truename* p)))) 1673 (cond 1674 (truename foundtrue) 1675 (foundtrue p) 1676 (t nil)))))))) 1677 1678 (defun* safe-file-write-date (pathname) 1679 ;; If FILE-WRITE-DATE returns NIL, it's possible that 1680 ;; the user or some other agent has deleted an input file. 1681 ;; Also, generated files will not exist at the time planning is done 1682 ;; and calls compute-action-stamp which calls safe-file-write-date. 1683 ;; So it is very possible that we can't get a valid file-write-date, 1684 ;; and we can survive and we will continue the planning 1685 ;; as if the file were very old. 1686 ;; (or should we treat the case in a different, special way?) 1687 (and (probe-file* pathname) (ignore-errors (file-write-date pathname)))) 2232 (pathname 2233 (handler-case 2234 (or 2235 #+allegro 2236 (probe-file p :follow-symlinks truename) 2237 #-(or allegro clisp gcl2.6) 2238 (if truename 2239 (probe-file p) 2240 (and (ignore-errors 2241 #+(or cmu scl) (unix:unix-stat (ext:unix-namestring (translate-logical-pathname p))) 2242 #+(and lispworks unix) (system:get-file-stat p) 2243 #+sbcl (sb-unix:unix-stat (sb-ext:native-namestring (translate-logical-pathname p))) 2244 #-(or cmu (and lispworks unix) sbcl scl) 2245 (file-write-date p)) 2246 p)) 2247 #+(or clisp gcl2.6) 2248 #.(flet ((probe (probe) 2249 `(let ((foundtrue ,probe)) 2250 (cond 2251 (truename foundtrue) 2252 (foundtrue p))))) 2253 #+gcl2.6 2254 (probe '(or (probe-file p) 2255 (and (directory-pathname-p p) 2256 (ignore-errors 2257 (ensure-directory-pathname 2258 (truename* (subpathname 2259 (ensure-directory-pathname p) "."))))))) 2260 #+clisp 2261 (let ((fs (find-symbol* '#:file-stat :posix nil)) 2262 (pp (find-symbol* '#:probe-pathname :ext nil)) 2263 (resolve (if pp 2264 `(ignore-errors (,pp p)) 2265 '(or (truename* p) 2266 (truename* (ensure-directory-pathname p)))))) 2267 (if fs 2268 `(if truename 2269 ,resolve 2270 (and (,fs p) p)) 2271 (probe resolve))))) 2272 (file-error () nil)))))) 1688 2273 1689 2274 (defun* directory* (pathname-spec &rest keys &key &allow-other-keys) … … 1779 2364 1780 2365 1781 ;;; Parsing filenames and lists thereof1782 (defun* split-unix-namestring-directory-components1783 (unix-namestring &key ensure-directory dot-dot)1784 "Splits the path string UNIX-NAMESTRING, returning four values:1785 A flag that is either :absolute or :relative, indicating1786 how the rest of the values are to be interpreted.1787 A directory path --- a list of strings and keywords, suitable for1788 use with MAKE-PATHNAME when prepended with the flag value.1789 Directory components with an empty name or the name . are removed.1790 Any directory named .. is read as DOT-DOT, or :BACK if it's NIL (not :UP).1791 A last-component, either a file-namestring including type extension,1792 or NIL in the case of a directory pathname.1793 A flag that is true iff the unix-style-pathname was just1794 a file-namestring without / path specification.1795 ENSURE-DIRECTORY forces the namestring to be interpreted as a directory pathname:1796 the third return value will be NIL, and final component of the namestring1797 will be treated as part of the directory path.1798 1799 An empty string is thus read as meaning a pathname object with all fields nil.1800 1801 Note that : characters will NOT be interpreted as host specification.1802 Absolute pathnames are only appropriate on Unix-style systems.1803 1804 The intention of this function is to support structured component names,1805 e.g., \(:file \"foo/bar\"\), which will be unpacked to relative pathnames."1806 (check-type unix-namestring string)1807 (check-type dot-dot (member nil :back :up))1808 (if (and (not (find #\/ unix-namestring)) (not ensure-directory)1809 (plusp (length unix-namestring)))1810 (values :relative () unix-namestring t)1811 (let* ((components (split-string unix-namestring :separator "/"))1812 (last-comp (car (last components))))1813 (multiple-value-bind (relative components)1814 (if (equal (first components) "")1815 (if (equal (first-char unix-namestring) #\/)1816 (values :absolute (cdr components))1817 (values :relative nil))1818 (values :relative components))1819 (setf components (remove-if #'(lambda (x) (member x '("" ".") :test #'equal))1820 components))1821 (setf components (substitute (or dot-dot :back) ".." components :test #'equal))1822 (cond1823 ((equal last-comp "")1824 (values relative components nil nil)) ; "" already removed from components1825 (ensure-directory1826 (values relative components nil nil))1827 (t1828 (values relative (butlast components) last-comp nil)))))))1829 1830 (defun* split-name-type (filename)1831 "Split a filename into two values NAME and TYPE that are returned.1832 We assume filename has no directory component.1833 The last . if any separates name and type from from type,1834 except that if there is only one . and it is in first position,1835 the whole filename is the NAME with an empty type.1836 NAME is always a string.1837 For an empty type, *UNSPECIFIC-PATHNAME-TYPE* is returned."1838 (check-type filename string)1839 (assert (plusp (length filename)))1840 (destructuring-bind (name &optional (type *unspecific-pathname-type*))1841 (split-string filename :max 2 :separator ".")1842 (if (equal name "")1843 (values filename *unspecific-pathname-type*)1844 (values name type))))1845 1846 (defun* parse-unix-namestring (name &rest keys &key type defaults dot-dot ensure-directory1847 &allow-other-keys)1848 "Coerce NAME into a PATHNAME using standard Unix syntax.1849 1850 Unix syntax is used whether or not the underlying system is Unix;1851 on such non-Unix systems it is only usable but for relative pathnames;1852 but especially to manipulate relative pathnames portably, it is of crucial1853 to possess a portable pathname syntax independent of the underlying OS.1854 This is what PARSE-UNIX-NAMESTRING provides, and why we use it in ASDF.1855 1856 When given a PATHNAME object, just return it untouched.1857 When given NIL, just return NIL.1858 When given a non-null SYMBOL, first downcase its name and treat it as a string.1859 When given a STRING, portably decompose it into a pathname as below.1860 1861 #\\/ separates directory components.1862 1863 The last #\\/-separated substring is interpreted as follows:1864 1- If TYPE is :DIRECTORY or ENSURE-DIRECTORY is true,1865 the string is made the last directory component, and NAME and TYPE are NIL.1866 if the string is empty, it's the empty pathname with all slots NIL.1867 2- If TYPE is NIL, the substring is file-namestring, and its NAME and TYPE1868 are separated by SPLIT-NAME-TYPE.1869 3- If TYPE is a string, it is the given TYPE, and the whole string is the NAME.1870 1871 Directory components with an empty name the name . are removed.1872 Any directory named .. is read as DOT-DOT,1873 which must be one of :BACK or :UP and defaults to :BACK.1874 1875 HOST, DEVICE and VERSION components are taken from DEFAULTS,1876 which itself defaults to (ROOT-PATHNAME), also used if DEFAULTS in NIL.1877 No host or device can be specified in the string itself,1878 which makes it unsuitable for absolute pathnames outside Unix.1879 1880 For relative pathnames, these components (and hence the defaults) won't matter1881 if you use MERGE-PATHNAMES* but will matter if you use MERGE-PATHNAMES,1882 which is an important reason to always use MERGE-PATHNAMES*.1883 1884 Arbitrary keys are accepted, and the parse result is passed to ENSURE-PATHNAME1885 with those keys, removing TYPE DEFAULTS and DOT-DOT.1886 When you're manipulating pathnames that are supposed to make sense portably1887 even though the OS may not be Unixish, we recommend you use :WANT-RELATIVE T1888 to throw an error if the pathname is absolute"1889 (block nil1890 (check-type type (or null string (eql :directory)))1891 (when ensure-directory1892 (setf type :directory))1893 (etypecase name1894 ((or null pathname) (return name))1895 (symbol1896 (setf name (string-downcase name)))1897 (string))1898 (multiple-value-bind (relative path filename file-only)1899 (split-unix-namestring-directory-components1900 name :dot-dot dot-dot :ensure-directory (eq type :directory))1901 (multiple-value-bind (name type)1902 (cond1903 ((or (eq type :directory) (null filename))1904 (values nil nil))1905 (type1906 (values filename type))1907 (t1908 (split-name-type filename)))1909 (apply 'ensure-pathname1910 (make-pathname*1911 :directory (unless file-only (cons relative path))1912 :name name :type type1913 :defaults (or defaults (nil-pathname)))1914 (remove-plist-keys '(:type :dot-dot :defaults) keys))))))1915 1916 (defun* unix-namestring (pathname)1917 "Given a non-wild PATHNAME, return a Unix-style namestring for it.1918 If the PATHNAME is NIL or a STRING, return it unchanged.1919 1920 This only considers the DIRECTORY, NAME and TYPE components of the pathname.1921 This is a portable solution for representing relative pathnames,1922 But unless you are running on a Unix system, it is not a general solution1923 to representing native pathnames.1924 1925 An error is signaled if the argument is not NULL, a STRING or a PATHNAME,1926 or if it is a PATHNAME but some of its components are not recognized."1927 (etypecase pathname1928 ((or null string) pathname)1929 (pathname1930 (with-output-to-string (s)1931 (flet ((err () (error "Not a valid unix-namestring ~S" pathname)))1932 (let* ((dir (normalize-pathname-directory-component (pathname-directory pathname)))1933 (name (pathname-name pathname))1934 (type (pathname-type pathname))1935 (type (and (not (eq type :unspecific)) type)))1936 (cond1937 ((eq dir ()))1938 ((eq dir '(:relative)) (princ "./" s))1939 ((consp dir)1940 (destructuring-bind (relabs &rest dirs) dir1941 (or (member relabs '(:relative :absolute)) (err))1942 (when (eq relabs :absolute) (princ #\/ s))1943 (loop :for x :in dirs :do1944 (cond1945 ((member x '(:back :up)) (princ "../" s))1946 ((equal x "") (err))1947 ;;((member x '("." "..") :test 'equal) (err))1948 ((stringp x) (format s "~A/" x))1949 (t (err))))))1950 (t (err)))1951 (cond1952 (name1953 (or (and (stringp name) (or (null type) (stringp type))) (err))1954 (format s "~A~@[.~A~]" name type))1955 (t1956 (or (null type) (err))))))))))1957 1958 (defun* subpathname (pathname subpath &key type)1959 "This function takes a PATHNAME and a SUBPATH and a TYPE.1960 If SUBPATH is already a PATHNAME object (not namestring),1961 and is an absolute pathname at that, it is returned unchanged;1962 otherwise, SUBPATH is turned into a relative pathname with given TYPE1963 as per PARSE-UNIX-NAMESTRING with :WANT-RELATIVE T :TYPE TYPE,1964 then it is merged with the PATHNAME-DIRECTORY-PATHNAME of PATHNAME."1965 (or (and (pathnamep subpath) (absolute-pathname-p subpath))1966 (merge-pathnames* (parse-unix-namestring subpath :type type :want-relative t)1967 (pathname-directory-pathname pathname))))1968 1969 (defun* subpathname* (pathname subpath &key type)1970 "returns NIL if the base pathname is NIL, otherwise like SUBPATHNAME."1971 (and pathname1972 (subpathname (ensure-directory-pathname pathname) subpath :type type)))1973 1974 2366 ;;; Pathname host and its root 1975 2367 (defun* pathname-root (pathname) … … 1986 2378 ;; scheme-specific parts: port username password, not others: 1987 2379 . #.(or #+scl '(:parameters nil :query nil :fragment nil)))) 1988 1989 #-scl1990 (defun* directory-separator-for-host (&optional (pathname *default-pathname-defaults*))1991 (let ((foo (make-pathname* :directory '(:absolute "FOO") :defaults pathname)))1992 (last-char (namestring foo))))1993 1994 #-scl1995 (defun* directorize-pathname-host-device (pathname)1996 (let* ((root (pathname-root pathname))1997 (wild-root (wilden root))1998 (absolute-pathname (merge-pathnames* pathname root))1999 (separator (directory-separator-for-host root))2000 (root-namestring (namestring root))2001 (root-string2002 (substitute-if #\/2003 #'(lambda (x) (or (eql x #\:)2004 (eql x separator)))2005 root-namestring)))2006 (multiple-value-bind (relative path filename)2007 (split-unix-namestring-directory-components root-string :ensure-directory t)2008 (declare (ignore relative filename))2009 (let ((new-base2010 (make-pathname* :defaults root :directory `(:absolute ,@path))))2011 (translate-pathname absolute-pathname wild-root (wilden new-base))))))2012 2013 #+scl2014 (defun* directorize-pathname-host-device (pathname)2015 (let ((scheme (ext:pathname-scheme pathname))2016 (host (pathname-host pathname))2017 (port (ext:pathname-port pathname))2018 (directory (pathname-directory pathname)))2019 (flet ((specificp (x) (and x (not (eq x :unspecific)))))2020 (if (or (specificp port)2021 (and (specificp host) (plusp (length host)))2022 (specificp scheme))2023 (let ((prefix ""))2024 (when (specificp port)2025 (setf prefix (format nil ":~D" port)))2026 (when (and (specificp host) (plusp (length host)))2027 (setf prefix (strcat host prefix)))2028 (setf prefix (strcat ":" prefix))2029 (when (specificp scheme)2030 (setf prefix (strcat scheme prefix)))2031 (assert (and directory (eq (first directory) :absolute)))2032 (make-pathname* :directory `(:absolute ,prefix ,@(rest directory))2033 :defaults pathname)))2034 pathname)))2035 2380 2036 2381 (defun* subpathp (maybe-subpath base-pathname) … … 2043 2388 (and (relative-pathname-p enough) (pathname enough)))))) 2044 2389 2390 (defun* ensure-pathname-absolute (path &optional defaults (on-error 'error)) 2391 (cond 2392 ((absolute-pathname-p path)) 2393 ((stringp path) (ensure-pathname-absolute (pathname path) defaults)) 2394 ((not (pathnamep path)) (call-function on-error "not a valid pathname designator ~S" path)) 2395 ((let ((default-pathname (if (pathnamep defaults) defaults (call-function defaults)))) 2396 (or (if (absolute-pathname-p default-pathname) 2397 (absolute-pathname-p (merge-pathnames* path default-pathname)) 2398 (call-function on-error "Default pathname ~S is not an absolute pathname" 2399 default-pathname)) 2400 (call-function on-error "Failed to merge ~S with ~S into an absolute pathname" 2401 path default-pathname)))) 2402 (t (call-function on-error 2403 "Cannot ensure ~S is evaluated as an absolute pathname with defaults ~S" 2404 path defaults)))) 2405 2045 2406 2046 2407 ;;; Resolving symlinks somewhat 2047 (defun* truenamize (pathname &optional (defaults *default-pathname-defaults*))2408 (defun* truenamize (pathname) 2048 2409 "Resolve as much of a pathname as possible" 2049 2410 (block nil 2050 2411 (when (typep pathname '(or null logical-pathname)) (return pathname)) 2051 (let ((p (merge-pathnames* pathname defaults))) 2412 (let ((p pathname)) 2413 (unless (absolute-pathname-p p) 2414 (setf p (or (absolute-pathname-p (ensure-pathname-absolute p 'get-pathname-defaults nil)) 2415 (return p)))) 2052 2416 (when (logical-pathname-p p) (return p)) 2053 2417 (let ((found (probe-file* p :truename t))) 2054 2418 (when found (return found))) 2055 (unless (absolute-pathname-p p) 2056 (let ((true-defaults (truename* defaults))) 2057 (when true-defaults 2058 (setf p (merge-pathnames pathname true-defaults))))) 2059 (unless (absolute-pathname-p p) (return p)) 2060 (let ((sofar (probe-file* (pathname-root p) :truename t))) 2061 (unless sofar (return p)) 2062 (flet ((solution (directories) 2063 (merge-pathnames* 2064 (make-pathname* :host nil :device nil 2065 :directory `(:relative ,@directories) 2066 :name (pathname-name p) 2067 :type (pathname-type p) 2068 :version (pathname-version p)) 2069 sofar))) 2070 (loop :with directory = (normalize-pathname-directory-component 2071 (pathname-directory p)) 2072 :for dir :in (cdr directory) 2073 :for rest :on (cdr directory) 2074 :for more = (probe-file* 2075 (merge-pathnames* 2076 (make-pathname* :directory `(:relative ,dir)) 2077 sofar) :truename t) :do 2078 (if more 2079 (setf sofar more) 2080 (return (solution rest))) 2081 :finally 2082 (return (solution nil)))))))) 2419 (let* ((directory (normalize-pathname-directory-component (pathname-directory p))) 2420 (up-components (reverse (rest directory))) 2421 (down-components ())) 2422 (assert (eq :absolute (first directory))) 2423 (loop :while up-components :do 2424 (if-let (parent (probe-file* (make-pathname* :directory `(:absolute ,@(reverse up-components)) 2425 :name nil :type nil :version nil :defaults p))) 2426 (return (merge-pathnames* (make-pathname* :directory `(:relative ,@down-components) 2427 :defaults p) 2428 (ensure-directory-pathname parent))) 2429 (push (pop up-components) down-components)) 2430 :finally (return p)))))) 2083 2431 2084 2432 (defun* resolve-symlinks (path) … … 2093 2441 (and path (resolve-symlinks path)) 2094 2442 path)) 2095 2096 2097 ;;; absolute vs relative2098 (defun* ensure-pathname-absolute (path &optional defaults (on-error 'error))2099 (cond2100 ((absolute-pathname-p path))2101 ((stringp path) (ensure-pathname-absolute (pathname path) defaults))2102 ((not (pathnamep path)) (call-function on-error "not a valid pathname designator ~S" path))2103 ((absolute-pathname-p defaults)2104 (or (absolute-pathname-p (merge-pathnames* path defaults))2105 (call-function on-error "Failed to merge ~S with ~S into an absolute pathname"2106 path defaults)))2107 (t (call-function on-error2108 "Cannot ensure ~S is evaluated as an absolute pathname with defaults ~S"2109 path defaults))))2110 2111 (defun relativize-directory-component (directory-component)2112 (let ((directory (normalize-pathname-directory-component directory-component)))2113 (cond2114 ((stringp directory)2115 (list :relative directory))2116 ((eq (car directory) :absolute)2117 (cons :relative (cdr directory)))2118 (t2119 directory))))2120 2121 (defun* relativize-pathname-directory (pathspec)2122 (let ((p (pathname pathspec)))2123 (make-pathname*2124 :directory (relativize-directory-component (pathname-directory p))2125 :defaults p)))2126 2127 2128 ;;; Simple filesystem operations2129 (defun* ensure-all-directories-exist (pathnames)2130 (dolist (pathname pathnames)2131 (ensure-directories-exist (translate-logical-pathname pathname))))2132 2133 (defun* rename-file-overwriting-target (source target)2134 #+clisp ;; But for a bug in CLISP 2.48, we should use :if-exists :overwrite and be atomic2135 (posix:copy-file source target :method :rename)2136 #-clisp2137 (rename-file source target2138 #+clozure :if-exists #+clozure :rename-and-delete))2139 2140 (defun* delete-file-if-exists (x)2141 (when (probe-file* x)2142 (delete-file x)))2143 2144 ;;; Translate a pathname2145 (defun* (translate-pathname*) (path absolute-source destination &optional root source)2146 (declare (ignore source))2147 (cond2148 ((functionp destination)2149 (funcall destination path absolute-source))2150 ((eq destination t)2151 path)2152 ((not (pathnamep destination))2153 (error "Invalid destination"))2154 ((not (absolute-pathname-p destination))2155 (translate-pathname path absolute-source (merge-pathnames* destination root)))2156 (root2157 (translate-pathname (directorize-pathname-host-device path) absolute-source destination))2158 (t2159 (translate-pathname path absolute-source destination))))2160 2161 2162 ;;; Temporary pathnames2163 (defun* add-pathname-suffix (pathname suffix)2164 (make-pathname :name (strcat (pathname-name pathname) suffix)2165 :defaults pathname))2166 2167 (defun* tmpize-pathname (x)2168 (add-pathname-suffix x "-ASDF-TMP"))2169 2170 (defun* call-with-staging-pathname (pathname fun)2171 "Calls fun with a staging pathname, and atomically2172 renames the staging pathname to the pathname in the end.2173 Note: this protects only against failure of the program,2174 not against concurrent attempts.2175 For the latter case, we ought pick random suffix and atomically open it."2176 (let* ((pathname (pathname pathname))2177 (staging (tmpize-pathname pathname)))2178 (unwind-protect2179 (multiple-value-prog12180 (funcall fun staging)2181 (rename-file-overwriting-target staging pathname))2182 (delete-file-if-exists staging))))2183 2184 (defmacro with-staging-pathname ((pathname-var &optional (pathname-value pathname-var)) &body body)2185 `(call-with-staging-pathname ,pathname-value #'(lambda (,pathname-var) ,@body)))2186 2187 ;;; Basic pathnames2188 (defun* sane-physical-pathname (&key defaults (keep t) fallback want-existing)2189 (flet ((sanitize (x)2190 (setf x (and x (ignore-errors (translate-logical-pathname x))))2191 (when (pathnamep x)2192 (setf x2193 (ecase keep2194 ((t) x)2195 ((:directory) (pathname-directory-pathname x))2196 ((:root) (pathname-root x))2197 ((:host) (pathname-host-pathname x))2198 ((nil) (nil-pathname x))))2199 (when want-existing ;; CCL's probe-file will choke if d-p-d is logical2200 (setf x (probe-file* x)))2201 (and (physical-pathname-p x) x))))2202 (or (sanitize defaults)2203 (when fallback2204 (or (sanitize (nil-pathname))2205 (sanitize (ignore-errors (user-homedir-pathname)))))2206 (error "Could not find a sane a physical pathname~2207 ~@[ from ~S~]~@[~:*~@[ or~*~] fallbacks~]"2208 defaults fallback))))2209 2210 (defun* root-pathname ()2211 "On a Unix system, this will presumably be the root pathname /.2212 Otherwise, this will be the root of some implementation-dependent filesystem host."2213 (sane-physical-pathname :keep :root :fallback t))2214 2215 2216 ;;;; -----------------------------------------------------------------2217 ;;;; Windows shortcut support. Based on:2218 ;;;;2219 ;;;; Jesse Hager: The Windows Shortcut File Format.2220 ;;;; http://www.wotsit.org/list.asp?fc=132221 2222 #-(or clisp genera) ; CLISP doesn't need it, and READ-SEQUENCE annoys old Genera.2223 (progn2224 (defparameter *link-initial-dword* 76)2225 (defparameter *link-guid* #(1 20 2 0 0 0 0 0 192 0 0 0 0 0 0 70))2226 2227 (defun* read-null-terminated-string (s)2228 (with-output-to-string (out)2229 (loop :for code = (read-byte s)2230 :until (zerop code)2231 :do (write-char (code-char code) out))))2232 2233 (defun* read-little-endian (s &optional (bytes 4))2234 (loop :for i :from 0 :below bytes2235 :sum (ash (read-byte s) (* 8 i))))2236 2237 (defun* parse-file-location-info (s)2238 (let ((start (file-position s))2239 (total-length (read-little-endian s))2240 (end-of-header (read-little-endian s))2241 (fli-flags (read-little-endian s))2242 (local-volume-offset (read-little-endian s))2243 (local-offset (read-little-endian s))2244 (network-volume-offset (read-little-endian s))2245 (remaining-offset (read-little-endian s)))2246 (declare (ignore total-length end-of-header local-volume-offset))2247 (unless (zerop fli-flags)2248 (cond2249 ((logbitp 0 fli-flags)2250 (file-position s (+ start local-offset)))2251 ((logbitp 1 fli-flags)2252 (file-position s (+ start2253 network-volume-offset2254 #x14))))2255 (strcat (read-null-terminated-string s)2256 (progn2257 (file-position s (+ start remaining-offset))2258 (read-null-terminated-string s))))))2259 2260 (defun* parse-windows-shortcut (pathname)2261 (with-open-file (s pathname :element-type '(unsigned-byte 8))2262 (handler-case2263 (when (and (= (read-little-endian s) *link-initial-dword*)2264 (let ((header (make-array (length *link-guid*))))2265 (read-sequence header s)2266 (equalp header *link-guid*)))2267 (let ((flags (read-little-endian s)))2268 (file-position s 76) ;skip rest of header2269 (when (logbitp 0 flags)2270 ;; skip shell item id list2271 (let ((length (read-little-endian s 2)))2272 (file-position s (+ length (file-position s)))))2273 (cond2274 ((logbitp 1 flags)2275 (parse-file-location-info s))2276 (t2277 (when (logbitp 2 flags)2278 ;; skip description string2279 (let ((length (read-little-endian s 2)))2280 (file-position s (+ length (file-position s)))))2281 (when (logbitp 3 flags)2282 ;; finally, our pathname2283 (let* ((length (read-little-endian s 2))2284 (buffer (make-array length)))2285 (read-sequence buffer s)2286 (map 'string #'code-char buffer)))))))2287 (end-of-file (c)2288 (declare (ignore c))2289 nil)))))2290 2443 2291 2444 … … 2411 2564 2412 2565 2413 (defun absolutize-pathnames 2414 (pathnames &key type (resolve-symlinks *resolve-symlinks*) truename) 2415 "Given a list of PATHNAMES where each is in the context of the next ones, 2416 try to resolve these pathnames into an absolute pathname; first gently, then harder." 2417 (block nil 2418 (labels ((resolve (x) 2419 (or (when truename 2420 (absolute-pathname-p (truename* x))) 2421 (when resolve-symlinks 2422 (absolute-pathname-p (resolve-symlinks x))) 2423 (absolute-pathname-p x) 2424 (unless resolve-symlinks 2425 (absolute-pathname-p (resolve-symlinks x))) 2426 (unless truename 2427 (absolute-pathname-p (truename* x))) 2428 (return nil))) 2429 (tryone (x type rest) 2430 (resolve (or (absolute-pathname-p x) 2431 (subpathname (recurse rest :directory) x :type type)))) 2432 (recurse (pathnames type) 2433 (if (null pathnames) (return nil) 2434 (tryone (first pathnames) type (rest pathnames))))) 2435 (recurse pathnames type)))) 2436 2566 ;;; Environment pathnames 2567 (defun* inter-directory-separator () 2568 (if (os-unix-p) #\: #\;)) 2569 2570 (defun* split-native-pathnames-string (string &rest constraints &key &allow-other-keys) 2571 (loop :for namestring :in (split-string string :separator (string (inter-directory-separator))) 2572 :collect (apply 'parse-native-namestring namestring constraints))) 2573 2574 (defun* getenv-pathname (x &rest constraints &key on-error &allow-other-keys) 2575 (apply 'parse-native-namestring (getenvp x) 2576 :on-error (or on-error 2577 `(error "In (~S ~S), invalid pathname ~*~S: ~*~?" getenv-pathname ,x)) 2578 constraints)) 2579 (defun* getenv-pathnames (x &rest constraints &key on-error &allow-other-keys) 2580 (apply 'split-native-pathnames-string (getenvp x) 2581 :on-error (or on-error 2582 `(error "In (~S ~S), invalid pathname ~*~S: ~*~?" getenv-pathnames ,x)) 2583 constraints)) 2584 (defun* getenv-absolute-directory (x) 2585 (getenv-pathname x :want-absolute t :ensure-directory t)) 2586 (defun* getenv-absolute-directories (x) 2587 (getenv-pathnames x :want-absolute t :ensure-directory t)) 2588 2589 (defun* lisp-implementation-directory (&key truename) 2590 (let ((dir 2591 (ignore-errors 2592 #+clozure #p"ccl:" 2593 #+(or ecl mkcl) #p"SYS:" 2594 #+gcl system::*system-directory* 2595 #+sbcl (if-let (it (find-symbol* :sbcl-homedir-pathname :sb-int nil)) 2596 (funcall it) 2597 (getenv-pathname "SBCL_HOME" :ensure-directory t))))) 2598 (if (and dir truename) 2599 (truename* dir) 2600 dir))) 2601 2602 (defun* lisp-implementation-pathname-p (pathname) 2603 ;; Other builtin systems are those under the implementation directory 2604 (and (when pathname 2605 (if-let (impdir (lisp-implementation-directory)) 2606 (or (subpathp pathname impdir) 2607 (when *resolve-symlinks* 2608 (if-let (truename (truename* pathname)) 2609 (if-let (trueimpdir (truename* impdir)) 2610 (subpathp truename trueimpdir))))))) 2611 t)) 2612 2613 2614 ;;; Pathname defaults and current directory 2615 (defun* get-pathname-defaults (&optional (defaults *default-pathname-defaults*)) 2616 (or (absolute-pathname-p defaults) 2617 (merge-pathnames* defaults (getcwd)))) 2618 2619 (defun* call-with-current-directory (dir thunk) 2620 (if dir 2621 (let* ((dir (resolve-symlinks* (get-pathname-defaults (pathname-directory-pathname dir)))) 2622 (*default-pathname-defaults* dir) 2623 (cwd (getcwd))) 2624 (chdir dir) 2625 (unwind-protect 2626 (funcall thunk) 2627 (chdir cwd))) 2628 (funcall thunk))) 2629 2630 (defmacro with-current-directory ((&optional dir) &body body) 2631 "Call BODY while the POSIX current working directory is set to DIR" 2632 `(call-with-current-directory ,dir #'(lambda () ,@body))) 2633 2634 2635 ;;; Translate a pathname 2636 (defun relativize-directory-component (directory-component) 2637 (let ((directory (normalize-pathname-directory-component directory-component))) 2638 (cond 2639 ((stringp directory) 2640 (list :relative directory)) 2641 ((eq (car directory) :absolute) 2642 (cons :relative (cdr directory))) 2643 (t 2644 directory)))) 2645 2646 (defun* relativize-pathname-directory (pathspec) 2647 (let ((p (pathname pathspec))) 2648 (make-pathname* 2649 :directory (relativize-directory-component (pathname-directory p)) 2650 :defaults p))) 2651 2652 (defun* directory-separator-for-host (&optional (pathname *default-pathname-defaults*)) 2653 (let ((foo (make-pathname* :directory '(:absolute "FOO") :defaults pathname))) 2654 (last-char (namestring foo)))) 2655 2656 #-scl 2657 (defun* directorize-pathname-host-device (pathname) 2658 #+(or unix abcl) 2659 (when (and #+abcl (os-unix-p) (physical-pathname-p pathname)) 2660 (return-from directorize-pathname-host-device pathname)) 2661 (let* ((root (pathname-root pathname)) 2662 (wild-root (wilden root)) 2663 (absolute-pathname (merge-pathnames* pathname root)) 2664 (separator (directory-separator-for-host root)) 2665 (root-namestring (namestring root)) 2666 (root-string 2667 (substitute-if #\/ 2668 #'(lambda (x) (or (eql x #\:) 2669 (eql x separator))) 2670 root-namestring))) 2671 (multiple-value-bind (relative path filename) 2672 (split-unix-namestring-directory-components root-string :ensure-directory t) 2673 (declare (ignore relative filename)) 2674 (let ((new-base 2675 (make-pathname* :defaults root :directory `(:absolute ,@path)))) 2676 (translate-pathname absolute-pathname wild-root (wilden new-base)))))) 2677 2678 #+scl 2679 (defun* directorize-pathname-host-device (pathname) 2680 (let ((scheme (ext:pathname-scheme pathname)) 2681 (host (pathname-host pathname)) 2682 (port (ext:pathname-port pathname)) 2683 (directory (pathname-directory pathname))) 2684 (flet ((specificp (x) (and x (not (eq x :unspecific))))) 2685 (if (or (specificp port) 2686 (and (specificp host) (plusp (length host))) 2687 (specificp scheme)) 2688 (let ((prefix "")) 2689 (when (specificp port) 2690 (setf prefix (format nil ":~D" port))) 2691 (when (and (specificp host) (plusp (length host))) 2692 (setf prefix (strcat host prefix))) 2693 (setf prefix (strcat ":" prefix)) 2694 (when (specificp scheme) 2695 (setf prefix (strcat scheme prefix))) 2696 (assert (and directory (eq (first directory) :absolute))) 2697 (make-pathname* :directory `(:absolute ,prefix ,@(rest directory)) 2698 :defaults pathname))) 2699 pathname))) 2700 2701 (defun* (translate-pathname*) (path absolute-source destination &optional root source) 2702 (declare (ignore source)) 2703 (cond 2704 ((functionp destination) 2705 (funcall destination path absolute-source)) 2706 ((eq destination t) 2707 path) 2708 ((not (pathnamep destination)) 2709 (error "Invalid destination")) 2710 ((not (absolute-pathname-p destination)) 2711 (translate-pathname path absolute-source (merge-pathnames* destination root))) 2712 (root 2713 (translate-pathname (directorize-pathname-host-device path) absolute-source destination)) 2714 (t 2715 (translate-pathname path absolute-source destination)))) 2437 2716 2438 2717 ;;; Hook for output translations 2439 2718 (defvar *output-translation-function* 'identity) 2719 2720 2440 2721 ;;;; --------------------------------------------------------------------------- 2441 2722 ;;;; Utilities related to streams … … 2443 2724 (asdf/package:define-package :asdf/stream 2444 2725 (:recycle :asdf/stream) 2445 (:use :asdf/common-lisp :asdf/package :asdf/utility :asdf/ pathname)2726 (:use :asdf/common-lisp :asdf/package :asdf/utility :asdf/os :asdf/pathname) 2446 2727 (:export 2447 2728 #:*default-stream-element-type* #:*stderr* #:setup-stderr … … 2458 2739 #:detect-encoding #:*encoding-detection-hook* #:always-default-encoding 2459 2740 #:encoding-external-format #:*encoding-external-format-hook* #:default-encoding-external-format 2460 #:*default-encoding* #:*utf-8-external-format*)) 2741 #:*default-encoding* #:*utf-8-external-format* 2742 #:ensure-all-directories-exist 2743 #:rename-file-overwriting-target 2744 #:delete-file-if-exists 2745 #:*temporary-directory* #:temporary-directory #:default-temporary-directory 2746 #:setup-temporary-directory 2747 #:call-with-temporary-file #:with-temporary-file 2748 #:add-pathname-suffix #:tmpize-pathname 2749 #:call-with-staging-pathname #:with-staging-pathname)) 2461 2750 (in-package :asdf/stream) 2462 2751 … … 2791 3080 (funcall *encoding-external-format-hook* encoding)) 2792 3081 2793 ;;;; --------------------------------------------------------------------------- 2794 ;;;; Access to the Operating System 2795 2796 (asdf/package:define-package :asdf/os 2797 (:recycle :asdf/os :asdf) 2798 (:use :asdf/common-lisp :asdf/package :asdf/utility :asdf/pathname :asdf/stream) 2799 (:export 2800 #:featurep #:os-unix-p #:os-windows-p ;; features 2801 #:getenv #:getenvp ;; environment variables 2802 #:native-namestring #:parse-native-namestring 2803 #:inter-directory-separator #:split-native-pathnames-string 2804 #:getenv-pathname #:getenv-pathnames 2805 #:getenv-absolute-directory #:getenv-absolute-directories 2806 #:implementation-identifier ;; implementation identifier 2807 #:implementation-type #:*implementation-type* 2808 #:operating-system #:architecture #:lisp-version-string 2809 #:hostname #:user-homedir #:lisp-implementation-directory 2810 #:getcwd #:chdir #:call-with-current-directory #:with-current-directory 2811 #:*temporary-directory* #:temporary-directory #:default-temporary-directory 2812 #:setup-temporary-directory 2813 #:call-with-temporary-file #:with-temporary-file)) 2814 (in-package :asdf/os) 2815 2816 ;;; Features 2817 (eval-when (:compile-toplevel :load-toplevel :execute) 2818 (defun* featurep (x &optional (*features* *features*)) 2819 (cond 2820 ((atom x) (and (member x *features*) t)) 2821 ((eq :not (car x)) (assert (null (cddr x))) (not (featurep (cadr x)))) 2822 ((eq :or (car x)) (some #'featurep (cdr x))) 2823 ((eq :and (car x)) (every #'featurep (cdr x))) 2824 (t (error "Malformed feature specification ~S" x)))) 2825 2826 (defun* os-unix-p () 2827 (featurep '(:or :unix :cygwin :darwin))) 2828 2829 (defun* os-windows-p () 2830 (and (not (os-unix-p)) (featurep '(:or :win32 :windows :mswindows :mingw32)))) 2831 2832 (defun* os-genera-p () 2833 (featurep :genera)) 2834 2835 (defun* detect-os () 2836 (flet ((yes (yes) (pushnew yes *features*)) 2837 (no (no) (setf *features* (remove no *features*)))) 2838 (cond 2839 ((os-unix-p) (yes :os-unix) (no :os-windows)) 2840 ((os-windows-p) (yes :os-windows) (no :os-unix)) 2841 ((os-genera-p) (no :os-unix) (no :os-windows)) 2842 (t (error "Congratulations for trying XCVB on an operating system~%~ 2843 that is neither Unix, nor Windows, nor even Genera.~%Now you port it."))))) 2844 2845 (detect-os)) 2846 2847 ;;;; Environment variables: getting them, and parsing them. 2848 2849 (defun* getenv (x) 2850 (declare (ignorable x)) 2851 #+(or abcl clisp ecl xcl) (ext:getenv x) 2852 #+allegro (sys:getenv x) 2853 #+clozure (ccl:getenv x) 2854 #+(or cmu scl) (cdr (assoc x ext:*environment-list* :test #'string=)) 2855 #+cormanlisp 2856 (let* ((buffer (ct:malloc 1)) 2857 (cname (ct:lisp-string-to-c-string x)) 2858 (needed-size (win:getenvironmentvariable cname buffer 0)) 2859 (buffer1 (ct:malloc (1+ needed-size)))) 2860 (prog1 (if (zerop (win:getenvironmentvariable cname buffer1 needed-size)) 2861 nil 2862 (ct:c-string-to-lisp-string buffer1)) 2863 (ct:free buffer) 2864 (ct:free buffer1))) 2865 #+gcl (system:getenv x) 2866 #+genera nil 2867 #+lispworks (lispworks:environment-variable x) 2868 #+mcl (ccl:with-cstrs ((name x)) 2869 (let ((value (_getenv name))) 2870 (unless (ccl:%null-ptr-p value) 2871 (ccl:%get-cstring value)))) 2872 #+mkcl (#.(or (find-symbol* 'getenv :si nil) (find-symbol* 'getenv :mk-ext nil)) x) 2873 #+sbcl (sb-ext:posix-getenv x) 2874 #-(or abcl allegro clisp clozure cmu cormanlisp ecl gcl genera lispworks mcl mkcl sbcl scl xcl) 2875 (error "~S is not supported on your implementation" 'getenv)) 2876 2877 (defun* getenvp (x) 2878 "Predicate that is true if the named variable is present in the libc environment, 2879 then returning the non-empty string value of the variable" 2880 (let ((g (getenv x))) (and (not (emptyp g)) g))) 2881 2882 2883 ;;; Native vs Lisp syntax 2884 2885 (defun* native-namestring (x) 2886 "From a CL pathname, a return namestring suitable for passing to the operating system" 2887 (when x 2888 (let ((p (pathname x))) 2889 #+clozure (with-pathname-defaults ((root-pathname)) 2890 (ccl:native-translated-namestring p)) ; see ccl bug 978 2891 #+(or cmu scl) (ext:unix-namestring p nil) 2892 #+sbcl (sb-ext:native-namestring p) 2893 #-(or clozure cmu sbcl scl) 2894 (if (os-unix-p) (unix-namestring p) 2895 (namestring p))))) 2896 2897 (defun* parse-native-namestring (string &rest constraints &key ensure-directory &allow-other-keys) 2898 "From a native namestring suitable for use by the operating system, return 2899 a CL pathname satisfying all the specified constraints as per ENSURE-PATHNAME" 2900 (check-type string (or string null)) 2901 (let* ((pathname 2902 (when string 2903 (with-pathname-defaults ((root-pathname)) 2904 #+clozure (ccl:native-to-pathname string) 2905 #+sbcl (sb-ext:parse-native-namestring string) 2906 #-(or clozure sbcl) 2907 (if (os-unix-p) 2908 (parse-unix-namestring string :ensure-directory ensure-directory) 2909 (parse-namestring string))))) 2910 (pathname 2911 (if ensure-directory 2912 (and pathname (ensure-directory-pathname pathname)) 2913 pathname))) 2914 (apply 'ensure-pathname pathname constraints))) 2915 2916 2917 ;;; Native pathnames in environment 2918 (defun* inter-directory-separator () 2919 (if (os-unix-p) #\: #\;)) 2920 (defun* split-native-pathnames-string (string &rest constraints &key &allow-other-keys) 2921 (loop :for namestring :in (split-string string :separator (string (inter-directory-separator))) 2922 :collect (apply 'parse-native-namestring namestring constraints))) 2923 (defun* getenv-pathname (x &rest constraints &key on-error &allow-other-keys) 2924 (apply 'parse-native-namestring (getenvp x) 2925 :on-error (or on-error 2926 `(error "In (~S ~S), invalid pathname ~*~S: ~*~?" getenv-pathname ,x)) 2927 constraints)) 2928 (defun* getenv-pathnames (x &rest constraints &key on-error &allow-other-keys) 2929 (apply 'split-native-pathnames-string (getenvp x) 2930 :on-error (or on-error 2931 `(error "In (~S ~S), invalid pathname ~*~S: ~*~?" getenv-pathnames ,x)) 2932 constraints)) 2933 (defun* getenv-absolute-directory (x) 2934 (getenv-pathname x :want-absolute t :ensure-directory t)) 2935 (defun* getenv-absolute-directories (x) 2936 (getenv-pathnames x :want-absolute t :ensure-directory t)) 2937 2938 2939 ;;;; implementation-identifier 2940 ;; 2941 ;; produce a string to identify current implementation. 2942 ;; Initially stolen from SLIME's SWANK, completely rewritten since. 2943 ;; We're back to runtime checking, for the sake of e.g. ABCL. 2944 2945 (defun* first-feature (feature-sets) 2946 (dolist (x feature-sets) 2947 (multiple-value-bind (short long feature-expr) 2948 (if (consp x) 2949 (values (first x) (second x) (cons :or (rest x))) 2950 (values x x x)) 2951 (when (featurep feature-expr) 2952 (return (values short long)))))) 2953 2954 (defun* implementation-type () 2955 (first-feature 2956 '(:abcl (:acl :allegro) (:ccl :clozure) :clisp (:corman :cormanlisp) 2957 (:cmu :cmucl :cmu) :ecl :gcl 2958 (:lwpe :lispworks-personal-edition) (:lw :lispworks) 2959 :mcl :mkcl :sbcl :scl (:smbx :symbolics) :xcl))) 2960 2961 (defvar *implementation-type* (implementation-type)) 2962 2963 (defun* operating-system () 2964 (first-feature 2965 '(:cygwin (:win :windows :mswindows :win32 :mingw32) ;; try cygwin first! 2966 (:linux :linux :linux-target) ;; for GCL at least, must appear before :bsd 2967 (:macosx :macosx :darwin :darwin-target :apple) ; also before :bsd 2968 (:solaris :solaris :sunos) (:bsd :bsd :freebsd :netbsd :openbsd) :unix 2969 :genera))) 2970 2971 (defun* architecture () 2972 (first-feature 2973 '((:x64 :x86-64 :x86_64 :x8664-target :amd64 (:and :word-size=64 :pc386)) 2974 (:x86 :x86 :i386 :i486 :i586 :i686 :pentium3 :pentium4 :pc386 :iapx386 :x8632-target) 2975 (:ppc64 :ppc64 :ppc64-target) (:ppc32 :ppc32 :ppc32-target :ppc :powerpc) 2976 :hppa64 :hppa :sparc64 (:sparc32 :sparc32 :sparc) 2977 :mipsel :mipseb :mips :alpha (:arm :arm :arm-target) :imach 2978 ;; Java comes last: if someone uses C via CFFI or otherwise JNA or JNI, 2979 ;; we may have to segregate the code still by architecture. 2980 (:java :java :java-1.4 :java-1.5 :java-1.6 :java-1.7)))) 2981 2982 #+clozure 2983 (defun* ccl-fasl-version () 2984 ;; the fasl version is target-dependent from CCL 1.8 on. 2985 (or (let ((s 'ccl::target-fasl-version)) 2986 (and (fboundp s) (funcall s))) 2987 (and (boundp 'ccl::fasl-version) 2988 (symbol-value 'ccl::fasl-version)) 2989 (error "Can't determine fasl version."))) 2990 2991 (defun* lisp-version-string () 2992 (let ((s (lisp-implementation-version))) 2993 (car ; as opposed to OR, this idiom prevents some unreachable code warning 2994 (list 2995 #+allegro 2996 (format nil "~A~@[~A~]~@[~A~]~@[~A~]" 2997 excl::*common-lisp-version-number* 2998 ;; M means "modern", as opposed to ANSI-compatible mode (which I consider default) 2999 (and (eq excl:*current-case-mode* :case-sensitive-lower) "M") 3000 ;; Note if not using International ACL 3001 ;; see http://www.franz.com/support/documentation/8.1/doc/operators/excl/ics-target-case.htm 3002 (excl:ics-target-case (:-ics "8")) 3003 (and (member :smp *features*) "S")) 3004 #+armedbear (format nil "~a-fasl~a" s system::*fasl-version*) 3005 #+clisp 3006 (subseq s 0 (position #\space s)) ; strip build information (date, etc.) 3007 #+clozure 3008 (format nil "~d.~d-f~d" ; shorten for windows 3009 ccl::*openmcl-major-version* 3010 ccl::*openmcl-minor-version* 3011 (logand (ccl-fasl-version) #xFF)) 3012 #+cmu (substitute #\- #\/ s) 3013 #+scl (format nil "~A~A" s 3014 ;; ANSI upper case vs lower case. 3015 (ecase ext:*case-mode* (:upper "") (:lower "l"))) 3016 #+ecl (format nil "~A~@[-~A~]" s 3017 (let ((vcs-id (ext:lisp-implementation-vcs-id))) 3018 (subseq vcs-id 0 (min (length vcs-id) 8)))) 3019 #+gcl (subseq s (1+ (position #\space s))) 3020 #+genera 3021 (multiple-value-bind (major minor) (sct:get-system-version "System") 3022 (format nil "~D.~D" major minor)) 3023 #+mcl (subseq s 8) ; strip the leading "Version " 3024 s)))) 3025 3026 (defun* implementation-identifier () 3027 (substitute-if 3028 #\_ #'(lambda (x) (find x " /:;&^\\|?<>(){}[]$#`'\"")) 3029 (format nil "~(~a~@{~@[-~a~]~}~)" 3030 (or (implementation-type) (lisp-implementation-type)) 3031 (or (lisp-version-string) (lisp-implementation-version)) 3032 (or (operating-system) (software-type)) 3033 (or (architecture) (machine-type))))) 3034 3035 3036 ;;;; Other system information 3037 3038 (defun* hostname () 3039 ;; Note: untested on RMCL 3040 #+(or abcl clozure cmucl ecl genera lispworks mcl mkcl sbcl scl xcl) (machine-instance) 3041 #+cormanlisp "localhost" ;; is there a better way? Does it matter? 3042 #+allegro (symbol-call :excl.osi :gethostname) 3043 #+clisp (first (split-string (machine-instance) :separator " ")) 3044 #+gcl (system:gethostname)) 3045 3046 (defun* user-homedir () 3047 (truenamize 3048 (pathname-directory-pathname 3049 #+cormanlisp (ensure-directory-pathname (user-homedir-pathname)) 3050 #+mcl (current-user-homedir-pathname) 3051 #-(or cormanlisp mcl) (user-homedir-pathname)))) 3052 3053 (defun* lisp-implementation-directory (&key truename) 3054 (let ((dir 3055 (ignore-errors 3056 #+clozure #p"ccl:" 3057 #+(or ecl mkcl) #p"SYS:" 3058 #+gcl system::*system-directory* 3059 #+sbcl (if-let (it (find-symbol* :sbcl-homedir-pathname :sb-int nil)) 3060 (funcall it) 3061 (getenv-pathname "SBCL_HOME" :ensure-directory t))))) 3062 (if (and dir truename) 3063 (truename* dir) 3064 dir))) 3065 3066 3067 ;;; Current directory 3068 3069 (defun* getcwd () 3070 "Get the current working directory as per POSIX getcwd(3), as a pathname object" 3071 (or #+abcl (parse-native-namestring 3072 (java:jstatic "getProperty" "java.lang.System" "user.dir") :ensure-directory t) 3073 #+allegro (excl::current-directory) 3074 #+clisp (ext:default-directory) 3075 #+clozure (ccl:current-directory) 3076 #+(or cmu scl) (parse-native-namestring 3077 (nth-value 1 (unix:unix-current-directory)) :ensure-directory t) 3078 #+cormanlisp (pathname (pl::get-current-directory)) ;; Q: what type does it return? 3079 #+ecl (ext:getcwd) 3080 #+gcl (parse-native-namestring ;; this is a joke. Isn't there a better way? 3081 (first (symbol-call :asdf/driver :run-program '("/bin/pwd") :output :lines))) 3082 #+genera *default-pathname-defaults* ;; on a Lisp OS, it *is* canonical! 3083 #+lispworks (system:current-directory) 3084 #+mkcl (mk-ext:getcwd) 3085 #+sbcl (parse-native-namestring (sb-unix:posix-getcwd/)) 3086 #+xcl (extensions:current-directory) 3087 (error "getcwd not supported on your implementation"))) 3088 3089 (defun* chdir (x) 3090 "Change current directory, as per POSIX chdir(2)" 3091 #-(or clisp clozure) (when (pathnamep x) (setf x (native-namestring x))) 3092 (or #+clisp (ext:cd x) 3093 #+clozure (setf (ccl:current-directory) x) 3094 #+cormanlisp (unless (zerop (win32::_chdir x)) 3095 (error "Could not set current directory to ~A" x)) 3096 #+sbcl (symbol-call :sb-posix :chdir x) 3097 (error "chdir not supported on your implementation"))) 3098 3099 (defun* call-with-current-directory (dir thunk) 3100 (if dir 3101 (let* ((dir (truename (merge-pathnames (pathname-directory-pathname dir)))) 3102 (*default-pathname-defaults* dir) 3103 (cwd (getcwd))) 3104 (chdir dir) 3105 (unwind-protect 3106 (funcall thunk) 3107 (chdir cwd))) 3108 (funcall thunk))) 3109 3110 (defmacro with-current-directory ((dir) &body body) 3111 "Call BODY while the POSIX current working directory is set to DIR" 3112 `(call-with-current-directory ,dir #'(lambda () ,@body))) 3082 3083 ;;; Simple filesystem operations 3084 (defun* ensure-all-directories-exist (pathnames) 3085 (dolist (pathname pathnames) 3086 (ensure-directories-exist (translate-logical-pathname pathname)))) 3087 3088 (defun* rename-file-overwriting-target (source target) 3089 #+clisp ;; But for a bug in CLISP 2.48, we should use :if-exists :overwrite and be atomic 3090 (posix:copy-file source target :method :rename) 3091 #-clisp 3092 (rename-file source target 3093 #+clozure :if-exists #+clozure :rename-and-delete)) 3094 3095 (defun* delete-file-if-exists (x) 3096 (handler-case (delete-file x) (file-error () nil))) 3113 3097 3114 3098 3115 3099 ;;; Using temporary files 3116 3117 3100 (defun* default-temporary-directory () 3118 3101 (or … … 3122 3105 (when (os-windows-p) 3123 3106 (getenv-pathname "TEMP" :ensure-directory t)) 3124 (subpathname (user-homedir ) "tmp/")))3107 (subpathname (user-homedir-pathname) "tmp/"))) 3125 3108 3126 3109 (defvar *temporary-directory* nil) … … 3182 3165 ,@(when element-type `(:element-type ,element-type)) 3183 3166 ,@(when external-format `(:external-format external-format))))) 3167 3168 ;;; Temporary pathnames 3169 (defun* add-pathname-suffix (pathname suffix) 3170 (make-pathname :name (strcat (pathname-name pathname) suffix) 3171 :defaults pathname)) 3172 3173 (defun* tmpize-pathname (x) 3174 (add-pathname-suffix x "-ASDF-TMP")) 3175 3176 (defun* call-with-staging-pathname (pathname fun) 3177 "Calls fun with a staging pathname, and atomically 3178 renames the staging pathname to the pathname in the end. 3179 Note: this protects only against failure of the program, 3180 not against concurrent attempts. 3181 For the latter case, we ought pick random suffix and atomically open it." 3182 (let* ((pathname (pathname pathname)) 3183 (staging (tmpize-pathname pathname))) 3184 (unwind-protect 3185 (multiple-value-prog1 3186 (funcall fun staging) 3187 (rename-file-overwriting-target staging pathname)) 3188 (delete-file-if-exists staging)))) 3189 3190 (defmacro with-staging-pathname ((pathname-var &optional (pathname-value pathname-var)) &body body) 3191 `(call-with-staging-pathname ,pathname-value #'(lambda (,pathname-var) ,@body))) 3192 3184 3193 3185 3194 ;;;; ------------------------------------------------------------------------- … … 3503 3512 ;;; Some universal image restore hooks 3504 3513 (map () 'register-image-restore-hook 3505 '(setup-temporary-directory setup-stderr setup-command-line-arguments)) 3514 '(setup-temporary-directory setup-stderr setup-command-line-arguments 3515 #+abcl detect-os)) 3506 3516 ;;;; ------------------------------------------------------------------------- 3507 3517 ;;;; run-program initially from xcvb-driver. … … 3908 3918 #:check-lisp-compile-results #:check-lisp-compile-warnings 3909 3919 #:*uninteresting-compiler-conditions* #:*uninteresting-loader-conditions* 3910 #:*deferred-warnings*3911 3920 ;; Functions & Macros 3912 3921 #:get-optimization-settings #:proclaim-optimization-settings … … 3916 3925 #:reify-deferred-warnings #:reify-undefined-warning #:unreify-deferred-warnings 3917 3926 #:reset-deferred-warnings #:save-deferred-warnings #:check-deferred-warnings 3918 #:with-saved-deferred-warnings #:warnings-file-p #:warnings-file-type 3927 #:with-saved-deferred-warnings #:warnings-file-p #:warnings-file-type #:*warnings-file-type* 3919 3928 #:call-with-asdf-compilation-unit #:with-asdf-compilation-unit 3920 3929 #:current-lisp-file-pathname #:load-pathname … … 4003 4012 #+clisp '(clos::simple-gf-replacing-method-warning)) 4004 4013 "Additional conditions that may be skipped while loading") 4005 4006 (defvar *deferred-warnings* ()4007 "Warnings the handling of which is deferred until the end of the compilation unit")4008 4014 4009 4015 ;;;; ----- Filtering conditions while building ----- … … 4075 4081 4076 4082 ;;;; Deferred-warnings treatment, originally implemented by Douglas Katzman. 4083 ;; 4084 ;; To support an implementation, three functions must be implemented: 4085 ;; reify-deferred-warnings unreify-deferred-warnings reset-deferred-warnings 4086 ;; See their respective docstrings. 4077 4087 4078 4088 (defun reify-simple-sexp (sexp) … … 4139 4149 4140 4150 (defun reify-deferred-warnings () 4151 "return a portable S-expression, portably readable and writeable in any Common Lisp implementation 4152 using READ within a WITH-SAFE-IO-SYNTAX, that represents the warnings currently deferred by 4153 WITH-COMPILATION-UNIT. One of three functions required for deferred-warnings support in ASDF." 4141 4154 #+clozure 4142 4155 (mapcar 'reify-deferred-warning … … 4160 4173 4161 4174 (defun unreify-deferred-warnings (reified-deferred-warnings) 4175 "given a S-expression created by REIFY-DEFERRED-WARNINGS, reinstantiate the corresponding 4176 deferred warnings as to be handled at the end of the current WITH-COMPILATION-UNIT. 4177 Handle any warning that has been resolved already, 4178 such as an undefined function that has been defined since. 4179 One of three functions required for deferred-warnings support in ASDF." 4162 4180 (declare (ignorable reified-deferred-warnings)) 4163 4181 #+clozure … … 4194 4212 4195 4213 (defun reset-deferred-warnings () 4214 "Reset the set of deferred warnings to be handled at the end of the current WITH-COMPILATION-UNIT. 4215 One of three functions required for deferred-warnings support in ASDF." 4196 4216 #+clozure 4197 4217 (if-let (dw ccl::*outstanding-deferred-warnings*) … … 4221 4241 ((:clozure :ccl) "ccl-warnings"))) 4222 4242 4243 (defvar *warnings-file-type* (warnings-file-type) 4244 "Type for warnings files") 4245 4223 4246 (defun* warnings-file-p (file &optional implementation-type) 4224 (if-let (type (warnings-file-type implementation-type)) 4247 (if-let (type (if implementation-type 4248 (warnings-file-type implementation-type) 4249 *warnings-file-type*)) 4225 4250 (equal (pathname-type file) type))) 4226 4251 … … 4273 4298 (if warnings-file 4274 4299 (with-compilation-unit (:override t) 4275 (let ((*deferred-warnings* ()) 4276 #+sbcl (sb-c::*undefined-warnings* nil)) 4300 (let (#+sbcl (sb-c::*undefined-warnings* nil)) 4277 4301 (multiple-value-prog1 4278 4302 (with-muffled-compiler-conditions () … … 4501 4525 `(,(subpathname* (get-folder-path :local-appdata) "common-lisp/config/") 4502 4526 ,(subpathname* (get-folder-path :appdata) "common-lisp/config/"))) 4503 ,(subpathname (user-homedir ) ".config/common-lisp/"))))4527 ,(subpathname (user-homedir-pathname) ".config/common-lisp/")))) 4504 4528 (remove-duplicates (remove-if-not #'absolute-pathname-p dirs) 4505 4529 :from-end t :test 'equal))) … … 4679 4703 (let ((p (make-pathname* :directory '(:relative)))) 4680 4704 (if wilden (wilden p) p)))) 4681 ((eql :home) (user-homedir ))4705 ((eql :home) (user-homedir-pathname)) 4682 4706 ((eql :here) (resolve-absolute-location 4683 4707 *here-directory* :ensure-directory t :wilden nil)) … … 4685 4709 *user-cache* :ensure-directory t :wilden nil))) 4686 4710 :wilden (and wilden (not (pathnamep x))) 4711 :resolve-symlinks *resolve-symlinks* 4687 4712 :want-absolute t)) 4688 4713 … … 4692 4717 4693 4718 (defun* (resolve-location) (x &key ensure-directory wilden directory) 4694 (when directory (setf ensure-directory t)) ;; :directory backward compatibility, until 2014-01-16.4695 ( if (atom x)4696 (resolve-absolute-location x :ensure-directory ensure-directory :wilden wilden)4697 (loop* :with (first . rest) = x4698 :with path = (resolve-absolute-location4699 first :ensure-directory (and (or ensure-directory rest) t)4700 :wilden (and wilden (null rest)))4701 :for (element . morep) :on rest4702 :for dir = (and (or morep ensure-directory) t)4703 :for wild = (and wilden (not morep))4704 :do (setf path (merge-pathnames*4705 (resolve-relative-location4706 element :ensure-directory dir :wilden wild)4707 path))4708 :finally (return path))))4719 ;; :directory backward compatibility, until 2014-01-16: accept directory as well as ensure-directory 4720 (loop* :with dirp = (or directory ensure-directory) 4721 :with (first . rest) = (if (atom x) (list x) x) 4722 :with path = (resolve-absolute-location 4723 first :ensure-directory (and (or dirp rest) t) 4724 :wilden (and wilden (null rest))) 4725 :for (element . morep) :on rest 4726 :for dir = (and (or morep dirp) t) 4727 :for wild = (and wilden (not morep)) 4728 :for sub = (merge-pathnames* 4729 (resolve-relative-location 4730 element :ensure-directory dir :wilden wild) 4731 path) 4732 :do (setf path (if (absolute-pathname-p sub) (resolve-symlinks* sub) sub)) 4733 :finally (return path))) 4709 4734 4710 4735 (defun* location-designator-p (x) … … 4791 4816 :asdf/pathname :asdf/stream :asdf/os :asdf/image 4792 4817 :asdf/run-program :asdf/lisp-build 4793 :asdf/configuration ))4818 :asdf/configuration :asdf/backward-driver)) 4794 4819 ;;;; ------------------------------------------------------------------------- 4795 4820 ;;;; Handle upgrade as forward- and backward-compatibly as possible … … 4829 4854 ;; "2.345.0.7" would be your seventh local modification of official release 2.345 4830 4855 ;; "2.345.6.7" would be your seventh local modification of development version 2.345.6 4831 (asdf-version "2.26.1 43.1")4856 (asdf-version "2.26.158.1") 4832 4857 (existing-asdf (find-class (find-symbol* :component :asdf nil) nil)) 4833 4858 (existing-version *asdf-version*) … … 4964 4989 #:component-description #:component-long-description 4965 4990 #:component-version #:version-satisfies 4966 #:component-properties #:component-property ;; backward-compatibility only. DO NOT USE!4967 4991 #:component-inline-methods ;; backward-compatibility only. DO NOT USE! 4968 4992 #:component-operation-times ;; For internal use only. … … 4973 4997 #:module-default-component-class 4974 4998 #:module-components ;; backward-compatibility. DO NOT USE. 4999 #:sub-components 4975 5000 4976 5001 ;; Internals we'd like to share with the ASDF package, especially for upgrade purposes … … 4996 5021 pathname, because an absolute pathname may be interpreted relative to 4997 5022 another pathname in a degenerate way.")) 4998 (defgeneric* component-property (component property))4999 #-gcl2.65000 (defgeneric* (setf component-property) (new-value component property))5001 5023 (defgeneric* component-external-format (component)) 5002 5024 (defgeneric* component-encoding (component)) … … 5050 5072 :accessor component-operation-times) 5051 5073 (around-compile :initarg :around-compile) 5074 (properties) ;; Only for backward-compatibility during upgrades from ASDF2. DO NOT USE. 5052 5075 (%encoding :accessor %component-encoding :initform nil :initarg :encoding) 5053 ;; ASDF3: get rid of these "component properties" ? 5054 (properties :accessor component-properties :initarg :properties 5055 :initform nil) 5056 ;; For backward-compatibility, this slot is part of component rather than child-component 5076 ;; For backward-compatibility, this slot is part of component rather than child-component. ASDF4: don't. 5057 5077 (parent :initarg :parent :initform nil :reader component-parent) 5058 5078 (build-operation … … 5177 5197 5178 5198 5179 ;;;; General component-property - ASDF3: remove? Define clean subclasses, not messy "properties".5180 5181 (defmethod component-property ((c component) property)5182 (cdr (assoc property (slot-value c 'properties) :test #'equal)))5183 5184 (defmethod (setf component-property) (new-value (c component) property)5185 (let ((a (assoc property (slot-value c 'properties) :test #'equal)))5186 (if a5187 (setf (cdr a) new-value)5188 (setf (slot-value c 'properties)5189 (acons property new-value (slot-value c 'properties)))))5190 new-value)5191 5192 5193 5199 ;;;; Encodings 5194 5200 … … 5224 5230 (defmethod version-satisfies ((cver string) version) 5225 5231 (version-compatible-p cver version)) 5232 5233 5234 ;;; all sub-components (of a given type) 5235 5236 (defun* sub-components (component &key (type t)) 5237 (while-collecting (c) 5238 (labels ((recurse (x) 5239 (when (if-let (it (component-if-feature x)) (featurep it) t) 5240 (when (typep x type) 5241 (c x)) 5242 (when (typep x 'parent-component) 5243 (map () #'recurse (component-children x)))))) 5244 (recurse component)))) 5226 5245 ;;;; ------------------------------------------------------------------------- 5227 5246 ;;;; Systems … … 5238 5257 #:system-defsystem-depends-on 5239 5258 #:component-build-pathname #:build-pathname 5259 #:component-entry-point #:entry-point 5240 5260 #:find-system #:builtin-system-p)) ;; forward-reference, defined in find-system 5241 5261 (in-package :asdf/system) … … 5244 5264 (defgeneric* (system-source-file) (system) 5245 5265 (:documentation "Return the source file in which system is defined.")) 5246 (defgeneric* builtin-system-p (system))5247 5266 (defgeneric* component-build-pathname (component)) 5267 5268 (defgeneric* component-entry-point (component)) 5269 (defmethod component-entry-point ((c component)) 5270 (declare (ignorable c)) 5271 nil) 5272 5248 5273 5249 5274 ;;;; The system class … … 5255 5280 5256 5281 (defclass system (module proto-system) 5257 ;; Backward-compatibility: inherit from module. ASDF 3: only inherit from parent-component.5282 ;; Backward-compatibility: inherit from module. ASDF4: only inherit from parent-component. 5258 5283 (;; {,long-}description is now inherited from component, but we add the legacy accessors 5259 5284 (description :accessor system-description) … … 5263 5288 (licence :accessor system-licence :initarg :licence 5264 5289 :accessor system-license :initarg :license) 5290 (builtin-system-p :accessor builtin-system-p :initform nil :initarg :builtin-system-p) 5265 5291 (build-pathname 5266 5292 :initform nil :initarg :build-pathname :accessor component-build-pathname) 5293 (entry-point 5294 :initform nil :initarg :entry-point :accessor component-entry-point) 5267 5295 (source-file :initform nil :initarg :source-file :accessor system-source-file) 5268 5296 (defsystem-depends-on :reader system-defsystem-depends-on :initarg :defsystem-depends-on))) … … 5308 5336 nil) 5309 5337 ;;;; ------------------------------------------------------------------------- 5338 ;;;; Stamp cache 5339 5340 (asdf/package:define-package :asdf/cache 5341 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade) 5342 (:export #:get-file-stamp #:compute-file-stamp #:register-file-stamp 5343 #:consult-asdf-cache #:do-asdf-cache 5344 #:call-with-asdf-cache #:with-asdf-cache #:*asdf-cache*)) 5345 (in-package :asdf/cache) 5346 5347 ;;; This stamp cache is useful for: 5348 ;; * consistency of stamps used within a single run 5349 ;; * fewer accesses to the filesystem 5350 ;; * the ability to test with fake timestamps, without touching files 5351 5352 (defvar *asdf-cache* nil) 5353 5354 (defun set-asdf-cache-entry (key value-list) 5355 (apply 'values 5356 (if *asdf-cache* 5357 (setf (gethash key *asdf-cache*) value-list) 5358 value-list))) 5359 5360 (defun consult-asdf-cache (key thunk) 5361 (if *asdf-cache* 5362 (multiple-value-bind (results foundp) (gethash key *asdf-cache*) 5363 (if foundp 5364 (apply 'values results) 5365 (set-asdf-cache-entry key (multiple-value-list (funcall thunk))))) 5366 (funcall thunk))) 5367 5368 (defmacro do-asdf-cache (key &body body) 5369 `(consult-asdf-cache ,key #'(lambda () ,@body))) 5370 5371 (defun call-with-asdf-cache (thunk &key override) 5372 (if (and *asdf-cache* (not override)) 5373 (funcall thunk) 5374 (let ((*asdf-cache* (make-hash-table :test 'equal))) 5375 (funcall thunk)))) 5376 5377 (defmacro with-asdf-cache ((&key override) &body body) 5378 `(call-with-asdf-cache #'(lambda () ,@body) :override ,override)) 5379 5380 (defun compute-file-stamp (file) 5381 (safe-file-write-date file)) 5382 5383 (defun register-file-stamp (file &optional (stamp (compute-file-stamp file))) 5384 (set-asdf-cache-entry `(get-file-stamp ,file) (list stamp))) 5385 5386 (defun get-file-stamp (file) 5387 (do-asdf-cache `(get-file-stamp ,file) (compute-file-stamp file))) 5388 ;;;; ------------------------------------------------------------------------- 5310 5389 ;;;; Finding systems 5311 5390 … … 5313 5392 (:recycle :asdf/find-system :asdf) 5314 5393 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 5315 :asdf/component :asdf/system )5394 :asdf/component :asdf/system :asdf/cache) 5316 5395 (:export 5317 5396 #:remove-entry-from-registry #:coerce-entry-to-directory 5318 5397 #:coerce-name #:primary-system-name 5319 #:find-system #:locate-system #:load- sysdef#:with-system-definitions5398 #:find-system #:locate-system #:load-asd #:with-system-definitions 5320 5399 #:system-registered-p #:register-system #:registered-systems #:clear-system #:map-systems 5321 5400 #:system-definition-error #:missing-component #:missing-requires #:missing-parent … … 5324 5403 #:*system-definition-search-functions* #:search-for-system-definition 5325 5404 #:*central-registry* #:probe-asd #:sysdef-central-registry-search 5326 #: make-temporary-package #:find-system-if-being-defined #:*systems-being-defined*5405 #:find-system-if-being-defined #:*systems-being-defined* 5327 5406 #:contrib-sysdef-search #:sysdef-find-asdf ;; backward compatibility symbols, functions removed 5328 5407 #:system-find-preloaded-system #:register-preloaded-system #:*preloaded-systems* … … 5402 5481 (setf (gethash name *defined-systems*) 5403 5482 (cons (if-let (file (ignore-errors (system-source-file system))) 5404 ( safe-file-write-datefile))5483 (get-file-stamp file)) 5405 5484 system))))) 5406 5485 … … 5465 5544 (block nil 5466 5545 (when (directory-pathname-p defaults) 5467 (let* ((file (probe-file* 5468 (absolutize-pathnames 5469 (list (make-pathname :name name :type "asd") 5470 defaults *default-pathname-defaults* (getcwd)) 5471 :resolve-symlinks truename) 5472 :truename truename))) 5473 (when file 5474 (return file))) 5546 (if-let (file (probe-file* 5547 (ensure-pathname-absolute 5548 (parse-unix-namestring name :type "asd") 5549 #'(lambda () (ensure-pathname-absolute defaults 'get-pathname-defaults nil)) 5550 nil) 5551 :truename truename)) 5552 (return file)) 5475 5553 #-(or clisp genera) ; clisp doesn't need it, plain genera doesn't have read-sequence(!) 5476 5554 (when (os-windows-p) … … 5532 5610 (subseq *central-registry* (1+ position)))))))))) 5533 5611 5534 (defun* make-temporary-package ()5535 (make-package (fresh-package-name :prefix :asdf :index 0) :use '(:cl :asdf/interface)))5536 5537 5612 (defmethod find-system ((name null) &optional (error-p t)) 5538 5613 (declare (ignorable name)) … … 5552 5627 (defun* call-with-system-definitions (thunk) 5553 5628 (if *systems-being-defined* 5554 ( funcallthunk)5629 (call-with-asdf-cache thunk) 5555 5630 (let ((*systems-being-defined* (make-hash-table :test 'equal))) 5556 ( funcallthunk))))5631 (call-with-asdf-cache thunk)))) 5557 5632 5558 5633 (defmacro with-system-definitions ((&optional) &body body) 5559 5634 `(call-with-system-definitions #'(lambda () ,@body))) 5560 5635 5561 (defun* load- sysdef (name pathname)5636 (defun* load-asd (pathname &key name (external-format (encoding-external-format (detect-encoding pathname)))) 5562 5637 ;; Tries to load system definition with canonical NAME from PATHNAME. 5563 5638 (with-system-definitions () 5564 (let ((package (make-temporary-package))) ;; ASDF3: get rid of that. 5565 (unwind-protect 5566 (handler-bind 5567 ((error #'(lambda (condition) 5568 (error 'load-system-definition-error 5569 :name name :pathname pathname 5570 :condition condition)))) 5571 (let ((*package* package) 5572 (*default-pathname-defaults* 5573 ;; resolve logical-pathnames so they won't wreak havoc in parsing namestrings. 5574 (pathname-directory-pathname (translate-logical-pathname pathname))) 5575 (external-format (encoding-external-format (detect-encoding pathname)))) 5576 (asdf-message (compatfmt "~&~@<; ~@;Loading system definition from ~A into ~A~@:>~%") 5577 pathname package) 5578 (with-muffled-loader-conditions () 5579 (load* pathname :external-format external-format)))) 5580 (delete-package package))))) 5639 (let ((*package* (find-package :asdf-user)) 5640 (*default-pathname-defaults* 5641 ;; resolve logical-pathnames so they won't wreak havoc in parsing namestrings. 5642 (pathname-directory-pathname (translate-logical-pathname pathname)))) 5643 (handler-bind 5644 ((error #'(lambda (condition) 5645 (error 'load-system-definition-error 5646 :name name :pathname pathname 5647 :condition condition)))) 5648 (asdf-message (compatfmt "~&~@<; ~@;Loading system definition~@[ for ~A~] from ~A~@:>~%") 5649 name pathname) 5650 (with-muffled-loader-conditions () 5651 (load* pathname :external-format external-format)))))) 5581 5652 5582 5653 (defun* locate-system (name) … … 5625 5696 (translate-logical-pathname pathname) 5626 5697 (translate-logical-pathname previous-pathname)))) 5627 (stamp<= ( safe-file-write-datepathname) previous-time))))5698 (stamp<= (get-file-stamp pathname) previous-time)))) 5628 5699 ;; only load when it's a pathname that is different or has newer content 5629 (load- sysdef name pathname)))5700 (load-asd pathname :name name))) 5630 5701 (let ((in-memory (system-registered-p name))) ; try again after loading from disk if needed 5631 5702 (return … … 5633 5704 (in-memory 5634 5705 (when pathname 5635 (setf (car in-memory) ( safe-file-write-datepathname)))5706 (setf (car in-memory) (get-file-stamp pathname))) 5636 5707 (cdr in-memory)) 5637 5708 (error-p … … 5656 5727 (register-preloaded-system "asdf-driver") 5657 5728 5658 ;;;; Beware of builtin systems5659 (defmethod builtin-system-p ((s system))5660 (or5661 ;; For most purposes, asdf itself specially counts as builtin.5662 ;; if you want to link it or do something forbidden to builtins,5663 ;; specify separate dependencies on asdf-driver and asdf-defsystem.5664 (equal "asdf" (coerce-name s))5665 ;; Other builtin systems are those under the implementation directory5666 (let* ((system (find-system s nil))5667 (sysdir (and system (component-pathname system)))5668 (truesysdir (truename* sysdir))5669 (impdir (lisp-implementation-directory))5670 (trueimpdir (truename* impdir)))5671 (and sysdir impdir5672 (or (subpathp sysdir impdir)5673 (subpathp truesysdir trueimpdir))))))5674 5729 ;;;; ------------------------------------------------------------------------- 5675 5730 ;;;; Finding components … … 5866 5921 (:recycle :asdf/action :asdf) 5867 5922 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 5868 :asdf/component :asdf/system :asdf/find-system :asdf/find-component :asdf/operation)5923 :asdf/component :asdf/system #:asdf/cache :asdf/find-system :asdf/find-component :asdf/operation) 5869 5924 (:intern #:stamp #:done-p) 5870 5925 (:export 5871 5926 #:action #:define-convenience-action-methods 5872 #:explain #: operation-description5927 #:explain #:action-description 5873 5928 #:downward-operation #:upward-operation #:sibling-operation 5874 5929 #:component-depends-on #:component-self-dependencies … … 5878 5933 #:perform #:perform-with-restarts #:retry #:accept #:feature 5879 5934 #:traverse-actions #:traverse-sub-actions #:required-components ;; in plan 5880 #:action-path #:find-action 5881 )) 5935 #:action-path #:find-action)) 5882 5936 (in-package :asdf/action) 5883 5937 … … 5913 5967 `(apply 'make-operation ,operation :original-initargs ,rest ,rest) 5914 5968 `(make-operation ,operation)) 5915 `( find-component () ,component))5969 `(or (find-component () ,component) ,if-no-component)) 5916 5970 ,if-no-operation)) 5917 5971 (defmethod ,function ((,operation operation) ,component ,@more-args) 5918 5972 (if (typep ,component 'component) 5919 (error "No defined method for ~S on ~S" ',function ,component) 5973 (error "No defined method for ~S on ~/asdf-action:format-action/" 5974 ',function (cons ,operation ,component)) 5920 5975 (let ((,found (find-component () ,component))) 5921 5976 (if ,found … … 5926 5981 ;;;; self-description 5927 5982 5928 (defgeneric* operation-description (operation component) ;; ASDF3: rename to action-description5983 (defgeneric* action-description (operation component) 5929 5984 (:documentation "returns a phrase that describes performing this operation 5930 5985 on this component, e.g. \"loading /a/b/c\". 5931 5986 You can put together sentences using this phrase.")) 5932 (defmethod operation-description (operation component)5987 (defmethod action-description (operation component) 5933 5988 (format nil (compatfmt "~@<~A on ~A~@:>") 5934 5989 (type-of operation) component)) 5935 5990 (defgeneric* (explain) (operation component)) 5936 5991 (defmethod explain ((o operation) (c component)) 5937 (asdf-message (compatfmt "~&~@<; ~@;~A~:>~%") ( operation-description o c)))5992 (asdf-message (compatfmt "~&~@<; ~@;~A~:>~%") (action-description o c))) 5938 5993 (define-convenience-action-methods explain (operation component)) 5939 5994 … … 5941 5996 (assert (null colon-p)) (assert (null at-sign-p)) 5942 5997 (destructuring-bind (operation . component) action 5943 (princ ( operation-description operation component) stream)))5998 (princ (action-description operation component) stream))) 5944 5999 5945 6000 5946 6001 ;;;; Dependencies 5947 6002 5948 (defgeneric* component-depends-on (operation component) ;; ASDF 3: rename to component-dependencies6003 (defgeneric* component-depends-on (operation component) ;; ASDF4: rename to component-dependencies 5949 6004 (:documentation 5950 6005 "Returns a list of dependencies needed by the component to perform … … 5993 6048 :initform nil :initarg :downward-operation :reader upward-operation))) 5994 6049 ;; For backward-compatibility reasons, a system inherits from module and is a child-component 5995 ;; so we must guard against this case. ASDF 3: remove that.6050 ;; so we must guard against this case. ASDF4: remove that. 5996 6051 (defmethod component-depends-on ((o upward-operation) (c child-component)) 5997 6052 `(,@(if-let (p (component-parent c)) … … 6024 6079 6025 6080 (defmethod output-files :around (operation component) 6026 "Translate output files, unless asked not to "6081 "Translate output files, unless asked not to. Memoize the result." 6027 6082 operation component ;; hush genera, not convinced by declare ignorable(!) 6028 (values 6029 (multiple-value-bind (pathnames fixedp) (call-next-method) 6030 ;; 1- Make sure we have absolute pathnames 6031 (let* ((directory (pathname-directory-pathname 6032 (component-pathname (find-component () component)))) 6033 (absolute-pathnames 6034 (loop 6035 :for pathname :in pathnames 6036 :collect (ensure-pathname-absolute pathname directory)))) 6037 ;; 2- Translate those pathnames as required 6038 (if fixedp 6039 absolute-pathnames 6040 (mapcar *output-translation-function* absolute-pathnames)))) 6041 t)) 6083 (do-asdf-cache `(output-files ,operation ,component) 6084 (values 6085 (multiple-value-bind (pathnames fixedp) (call-next-method) 6086 ;; 1- Make sure we have absolute pathnames 6087 (let* ((directory (pathname-directory-pathname 6088 (component-pathname (find-component () component)))) 6089 (absolute-pathnames 6090 (loop 6091 :for pathname :in pathnames 6092 :collect (ensure-pathname-absolute pathname directory)))) 6093 ;; 2- Translate those pathnames as required 6094 (if fixedp 6095 absolute-pathnames 6096 (mapcar *output-translation-function* absolute-pathnames)))) 6097 t))) 6042 6098 (defmethod output-files ((o operation) (c component)) 6043 6099 (declare (ignorable o c)) … … 6049 6105 (first files))) 6050 6106 6107 (defmethod input-files :around (operation component) 6108 "memoize input files." 6109 (do-asdf-cache `(input-files ,operation ,component) 6110 (call-next-method))) 6111 6051 6112 (defmethod input-files ((o operation) (c parent-component)) 6052 6113 (declare (ignorable o c)) … … 6064 6125 ;;;; Done performing 6065 6126 6066 (defgeneric* component-operation-time (operation component)) ;; ASDF 3: hide it behind plan-action-stamp6127 (defgeneric* component-operation-time (operation component)) ;; ASDF4: hide it behind plan-action-stamp 6067 6128 (define-convenience-action-methods component-operation-time (operation component)) 6068 6129 6069 6070 (defgeneric* mark-operation-done (operation component)) ;; ASDF3: hide it behind (setf plan-action-stamp) 6130 (defgeneric* mark-operation-done (operation component)) ;; ASDF4: hide it behind (setf plan-action-stamp) 6071 6131 (defgeneric* compute-action-stamp (plan operation component &key just-done) 6072 6132 (:documentation "Has this action been successfully done already, … … 6138 6198 (lambda (s) 6139 6199 (format s (compatfmt "~@<Retry ~A.~@:>") 6140 ( operation-description operation component))))6200 (action-description operation component)))) 6141 6201 (accept () 6142 6202 :report 6143 6203 (lambda (s) 6144 6204 (format s (compatfmt "~@<Continue, treating ~A as having been successful.~@:>") 6145 ( operation-description operation component)))6205 (action-description operation component))) 6146 6206 (mark-operation-done operation component) 6147 6207 (return))))) … … 6202 6262 6203 6263 ;;; prepare-op 6204 (defmethod operation-description ((o prepare-op) (c component))6264 (defmethod action-description ((o prepare-op) (c component)) 6205 6265 (declare (ignorable o)) 6206 6266 (format nil (compatfmt "~@<loading dependencies of ~3i~_~A~@:>") c)) … … 6216 6276 6217 6277 ;;; compile-op 6218 (defmethod operation-description ((o compile-op) (c component))6278 (defmethod action-description ((o compile-op) (c component)) 6219 6279 (declare (ignorable o)) 6220 6280 (format nil (compatfmt "~@<compiling ~3i~_~A~@:>") c)) 6221 (defmethod operation-description ((o compile-op) (c parent-component))6281 (defmethod action-description ((o compile-op) (c parent-component)) 6222 6282 (declare (ignorable o)) 6223 6283 (format nil (compatfmt "~@<completing compilation for ~3i~_~A~@:>") c)) … … 6298 6358 (defmethod input-files ((o compile-op) (c system)) 6299 6359 (declare (ignorable o c)) 6300 ( unless (builtin-system-p c)6301 ( loop* :for (sub-o . sub-c)6302 :in (traverse-sub-actions6303 o c :other-systems nil6304 :keep-operation 'compile-op :keep-component 'cl-source-file)6305 :append (remove-if-not 'warnings-file-p6306 (output-files sub-o sub-c)))))6360 (when *warnings-file-type* 6361 (unless (builtin-system-p c) 6362 ;; The most correct way to do it would be to use: 6363 ;; (traverse-sub-actions o c :other-systems nil :keep-operation 'compile-op :keep-component 'cl-source-file) 6364 ;; but it's expensive and we don't care too much about file order or ASDF extensions. 6365 (loop :for sub :in (sub-components c :type 'cl-source-file) 6366 :nconc (remove-if-not 'warnings-file-p (output-files o sub)))))) 6307 6367 #+sbcl 6308 6368 (defmethod output-files ((o compile-op) (c system)) … … 6312 6372 6313 6373 ;;; load-op 6314 (defmethod operation-description ((o load-op) (c cl-source-file))6374 (defmethod action-description ((o load-op) (c cl-source-file)) 6315 6375 (declare (ignorable o)) 6316 6376 (format nil (compatfmt "~@<loading FASL for ~3i~_~A~@:>") c)) 6317 (defmethod operation-description ((o load-op) (c parent-component))6377 (defmethod action-description ((o load-op) (c parent-component)) 6318 6378 (declare (ignorable o)) 6319 6379 (format nil (compatfmt "~@<completing load for ~3i~_~A~@:>") c)) 6320 (defmethod operation-description ((o load-op) component)6380 (defmethod action-description ((o load-op) component) 6321 6381 (declare (ignorable o)) 6322 6382 (format nil (compatfmt "~@<loading ~3i~_~A~@:>") … … 6350 6410 6351 6411 ;;; prepare-source-op 6352 (defmethod operation-description ((o prepare-source-op) (c component))6412 (defmethod action-description ((o prepare-source-op) (c component)) 6353 6413 (declare (ignorable o)) 6354 6414 (format nil (compatfmt "~@<loading source for dependencies of ~3i~_~A~@:>") c)) … … 6364 6424 6365 6425 ;;; load-source-op 6366 (defmethod operation-description ((o load-source-op) c)6426 (defmethod action-description ((o load-source-op) c) 6367 6427 (declare (ignorable o)) 6368 6428 (format nil (compatfmt "~@<Loading source of ~3i~_~A~@:>") c)) 6369 (defmethod operation-description ((o load-source-op) (c parent-component))6429 (defmethod action-description ((o load-source-op) (c parent-component)) 6370 6430 (declare (ignorable o)) 6371 6431 (format nil (compatfmt "~@<Loaded source of ~3i~_~A~@:>") c)) … … 6408 6468 (:recycle :asdf/plan :asdf) 6409 6469 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 6410 :asdf/component :asdf/operation :asdf/system :asdf/find-system :asdf/find-component 6470 :asdf/component :asdf/operation :asdf/system 6471 :asdf/cache :asdf/find-system :asdf/find-component 6411 6472 :asdf/operation :asdf/action) 6412 6473 (:export … … 6600 6661 6601 6662 (defmethod compute-action-stamp (plan (o operation) (c component) &key just-done) 6602 ;; In a distant future, safe-file-write-dateand component-operation-time6663 ;; In a distant future, get-file-stamp and component-operation-time 6603 6664 ;; shall also be parametrized by the plan, or by a second model object. 6604 6665 (let* ((stamp-lookup #'(lambda (o c) … … 6615 6676 (dep-stamp (visit-dependencies plan o c stamp-lookup)) 6616 6677 ;; Time stamps from the files at hand, and whether any is missing 6617 (out-stamps (mapcar #'safe-file-write-dateout-files))6618 (in-stamps (mapcar #' safe-file-write-datein-files))6678 (out-stamps (mapcar (if just-done 'register-file-stamp 'get-file-stamp) out-files)) 6679 (in-stamps (mapcar #'get-file-stamp in-files)) 6619 6680 (missing-in 6620 6681 (loop :for f :in in-files :for s :in in-stamps :unless s :collect f)) … … 6633 6694 (warn "~A completed without ~:[~*~;~*its input file~:p~2:*~{ ~S~}~*~]~ 6634 6695 ~:[~; or ~]~:[~*~;~*its output file~:p~2:*~{ ~S~}~*~]" 6635 ( operation-description o c)6696 (action-description o c) 6636 6697 missing-in (length missing-in) (and missing-in missing-out) 6637 6698 missing-out (length missing-out))) … … 6780 6841 (plan-actions plan))) 6781 6842 6782 6783 (defmethod perform-plan ((steps list) &key)6843 (defmethod perform-plan :around (plan &key) 6844 (declare (ignorable plan)) 6784 6845 (let ((*package* *package*) 6785 6846 (*readtable* *readtable*)) 6786 (loop* :for (op . component) :in steps :do 6787 (perform-with-restarts op component)))) 6847 (with-compilation-unit () ;; backward-compatibility. 6848 (call-next-method)))) ;; Going forward, see deferred-warning support in lisp-build. 6849 6850 (defmethod perform-plan ((steps list) &key) 6851 (loop* :for (op . component) :in steps :do 6852 (perform-with-restarts op component))) 6788 6853 6789 6854 (defmethod plan-operates-on-p ((plan list) (component-path list)) … … 7032 7097 #:environment-output-translations #:process-output-translations 7033 7098 #:compute-output-translations 7099 #+abcl #:translate-jar-pathname 7034 7100 )) 7035 7101 (in-package :asdf/output-translations) … … 7486 7552 (defun* default-source-registry () 7487 7553 `(:source-registry 7488 #+sbcl (:directory ,(subpathname (user-homedir ) ".sbcl/systems/"))7554 #+sbcl (:directory ,(subpathname (user-homedir-pathname) ".sbcl/systems/")) 7489 7555 ,@(loop :for dir :in 7490 7556 `(,@(when (os-unix-p) 7491 7557 `(,(or (getenv-absolute-directory "XDG_DATA_HOME") 7492 (subpathname (user-homedir ) ".local/share/"))7558 (subpathname (user-homedir-pathname) ".local/share/")) 7493 7559 ,@(or (getenv-absolute-directories "XDG_DATA_DIRS") 7494 7560 '("/usr/local/share" "/usr/share")))) … … 7642 7708 (:recycle :asdf/backward-internals :asdf) 7643 7709 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 7644 :asdf/system :asdf/component :asdf/find-system :asdf/action) 7710 :asdf/system :asdf/component :asdf/operation 7711 :asdf/find-system :asdf/action :asdf/lisp-action) 7645 7712 (:export ;; for internal use 7713 #:load-sysdef #:make-temporary-package 7646 7714 #:%refresh-component-inline-methods 7647 7715 #:%resolve-if-component-dep-fails 7648 #:make-sub-operation)) 7716 #:make-sub-operation 7717 #:load-sysdef #:make-temporary-package)) 7649 7718 (in-package :asdf/backward-internals) 7650 7719 … … 7692 7761 (asdf-message "The system definition for ~S uses deprecated ~ 7693 7762 ASDF option :IF-COMPONENT-DEP-DAILS. ~ 7694 Starting with ASDF 2.27, please use :IF-FEATURE instead"7763 Starting with ASDF 3, please use :IF-FEATURE instead" 7695 7764 (coerce-name (component-system component))) 7696 7765 ;; This only supports the pattern of use of the "feature" seen in the wild … … 7698 7767 (check-type if-component-dep-fails (member :fail :ignore :try-next)) 7699 7768 (unless (eq if-component-dep-fails :fail) 7700 (loop :with o = (make- instance'compile-op)7769 (loop :with o = (make-operation 'compile-op) 7701 7770 :for c :in (component-children component) :do 7702 7771 (loop* :for (feature? feature) :in (component-depends-on o c) … … 7707 7776 (defun* make-sub-operation (c o dep-c dep-o) 7708 7777 (declare (ignore c o dep-c dep-o)) (asdf-upgrade-error))) 7778 7779 7780 ;;;; load-sysdef 7781 (defun* load-sysdef (name pathname) 7782 (load-asd pathname :name name)) 7783 7784 (defun* make-temporary-package () 7785 (make-package (fresh-package-name :prefix :asdf :index 0) :use '(:cl :asdf/interface))) 7786 7787 7709 7788 ;;;; ------------------------------------------------------------------------- 7710 7789 ;;;; Defsystem … … 7713 7792 (:recycle :asdf/defsystem :asdf) 7714 7793 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 7715 :asdf/component :asdf/system 7794 :asdf/component :asdf/system :asdf/cache 7716 7795 :asdf/find-system :asdf/find-component :asdf/lisp-action :asdf/operate 7717 7796 :asdf/backward-internals) … … 7740 7819 ;; If no absolute pathname was found, we return NIL. 7741 7820 (check-type pathname (or null string pathname)) 7742 (let ((pathname (parse-unix-namestring pathname :type :directory)) 7743 (load-pathname (load-pathname))) 7744 (when (or pathname load-pathname) 7745 (pathname-directory-pathname 7746 (absolutize-pathnames 7747 (list pathname load-pathname *default-pathname-defaults* (getcwd)) 7748 :resolve-symlinks *resolve-symlinks*))))) 7821 (resolve-symlinks* 7822 (ensure-pathname-absolute 7823 (parse-unix-namestring pathname :type :directory) 7824 #'(lambda () (ensure-pathname-absolute 7825 (load-pathname) 'get-pathname-defaults nil)) 7826 nil))) 7749 7827 7750 7828 … … 7811 7889 (destructuring-bind 7812 7890 (type name &rest rest &key 7891 (builtin-system-p () bspp) 7813 7892 ;; the following list of keywords is reproduced below in the 7814 7893 ;; remove-plist-keys form. important to keep them in sync … … 7818 7897 ;; list ends 7819 7898 &allow-other-keys) options 7820 (declare (ignorable perform explain output-files operation-done-p ))7899 (declare (ignorable perform explain output-files operation-done-p builtin-system-p)) 7821 7900 (check-component-input type name weakly-depends-on depends-on components) 7822 7901 (when (and parent … … 7826 7905 (class-for-type parent type)))) 7827 7906 (error 'duplicate-names :name name)) 7828 (when do-first (error "DO-FIRST is not supported anymore as of ASDF 2.27"))7907 (when do-first (error "DO-FIRST is not supported anymore as of ASDF 3")) 7829 7908 (let* ((args `(:name ,(coerce-name name) 7830 7909 :pathname ,pathname … … 7837 7916 (component (find-component parent name))) 7838 7917 (when weakly-depends-on 7839 ;; ASDF 3: deprecate this feature and remove it.7918 ;; ASDF4: deprecate this feature and remove it. 7840 7919 (appendf depends-on 7841 7920 (remove-if (complement #'(lambda (x) (find-system x nil))) weakly-depends-on))) … … 7847 7926 (component-pathname component) ; eagerly compute the absolute pathname 7848 7927 (let ((sysdir (system-source-directory (component-system component)))) ;; requires the previous 7928 (when (and (typep component 'system) (not bspp)) 7929 (setf (builtin-system-p component) (lisp-implementation-pathname-p sysdir))) 7849 7930 (setf version (normalize-version version sysdir))) 7850 7931 (when (and versionp version (not (parse-version version nil))) … … 7863 7944 :when serial :do (setf previous-component name))) 7864 7945 (compute-children-by-name component)) 7865 ;; Used by POIU. ASDF 3: rename to component-depends-on7946 ;; Used by POIU. ASDF4: rename to component-depends-on? 7866 7947 (setf (component-sibling-dependencies component) depends-on) 7867 7948 (%refresh-component-inline-methods component rest) … … 7884 7965 (registered (system-registered-p name)) 7885 7966 (registered! (if registered 7886 (rplaca registered ( safe-file-write-datesource-file))7967 (rplaca registered (get-file-stamp source-file)) 7887 7968 (register-system 7888 7969 (make-instance 'system :name name :source-file source-file)))) … … 7923 8004 #+ecl #:make-build 7924 8005 #:register-pre-built-system 7925 #:build-args #:name-suffix #:prologue-code #:epilogue-code #:static-library 7926 #:component-entry-point #:entry-point)) 8006 #:build-args #:name-suffix #:prologue-code #:epilogue-code #:static-library)) 7927 8007 (in-package :asdf/bundle) 7928 8008 … … 7982 8062 ;; All: create an executable file from the system and its dependencies 7983 8063 ((bundle-type :initform :program))) 7984 7985 (defgeneric* component-entry-point (component))7986 7987 (defmethod component-entry-point ((c component))7988 (declare (ignorable c))7989 nil)7990 7991 (defclass bundle-system (system)7992 ((entry-point7993 :initform nil :initarg :entry-point :accessor component-entry-point)))7994 8064 7995 8065 (defun* bundle-pathname-type (bundle-type) … … 8488 8558 (:recycle :asdf/backward-interface :asdf) 8489 8559 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 8490 :asdf/component :asdf/system :asdf/ operation :asdf/action8560 :asdf/component :asdf/system :asdf/find-system :asdf/operation :asdf/action 8491 8561 :asdf/lisp-build :asdf/operate :asdf/output-translations) 8492 8562 (:export … … 8554 8624 (centralize-lisp-binaries nil) 8555 8625 (default-toplevel-directory 8556 (subpathname (user-homedir ) ".fasls/")) ;; Use ".cache/common-lisp/" instead ???8626 (subpathname (user-homedir-pathname) ".fasls/")) ;; Use ".cache/common-lisp/" instead ??? 8557 8627 (include-per-user-information nil) 8558 8628 (map-all-source-files (or #+(or clisp ecl mkcl) t nil)) 8559 (source-to-target-mappings nil)) 8629 (source-to-target-mappings nil) 8630 (file-types (list (compile-file-type) 8631 #+ecl (compile-file-type :type :object) 8632 #+mkcl (compile-file-type :fasl-p nil) 8633 #+clisp "lib" #+sbcl "cfasl" 8634 #+sbcl "sbcl-warnings" #+clozure "ccl-warnings"))) 8560 8635 #+(or clisp ecl mkcl) 8561 8636 (when (null map-all-source-files) 8562 8637 (error "asdf:enable-asdf-binary-locations-compatibility doesn't support :map-all-source-files nil on CLISP, ECL and MKCL")) 8563 (let* (( fasl-type (compile-file-type))8564 (mapped-files (if map-all-source-files *wild-file*8565 (make-pathname :type fasl-type :defaults *wild-file*)))8638 (let* ((patterns (if map-all-source-files (list *wild-file*) 8639 (loop :for type :in file-types 8640 :collect (make-pathname :type type :defaults *wild-file*)))) 8566 8641 (destination-directory 8567 8642 (if centralize-lisp-binaries 8568 8643 `(,default-toplevel-directory 8569 8644 ,@(when include-per-user-information 8570 (cdr (pathname-directory (user-homedir ))))8645 (cdr (pathname-directory (user-homedir-pathname)))) 8571 8646 :implementation ,*wild-inferiors*) 8572 8647 `(:root ,*wild-inferiors* :implementation)))) … … 8576 8651 #+abcl (#p"jar:file:/**/*.jar!/**/*.*" (:function translate-jar-pathname)) 8577 8652 #+abcl (#p"/___jar___file___root___/**/*.*" (,@destination-directory)) 8578 ((:root ,*wild-inferiors* ,mapped-files) 8579 (,@destination-directory ,mapped-files)) 8653 ,@(loop :for pattern :in patterns 8654 :collect `((:root ,*wild-inferiors* ,pattern) 8655 (,@destination-directory ,pattern))) 8580 8656 (t t) 8581 8657 :ignore-inherited-configuration)))) … … 8610 8686 (asdf-message "; $ ~A~%" command) 8611 8687 (run-program command :force-shell t :ignore-error-status t :output *verbose-out*))) 8688 8612 8689 ;;;; --------------------------------------------------------------------------- 8613 8690 ;;;; Handle ASDF package upgrade, including implementation-dependent magic. … … 8622 8699 #:loaded-systems ; makes for annoying SLIME completion 8623 8700 #:output-files-for-system-and-operation) ; obsolete ASDF-BINARY-LOCATION function 8624 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade 8701 (:use :asdf/common-lisp :asdf/driver :asdf/upgrade :asdf/cache 8625 8702 :asdf/component :asdf/system :asdf/find-system :asdf/find-component 8626 8703 :asdf/operation :asdf/action :asdf/lisp-action … … 8643 8720 #:implementation-identifier #:implementation-type #:hostname 8644 8721 #:input-files #:output-files #:output-file #:perform 8645 #:operation-done-p #:explain #: component-sibling-dependencies8722 #:operation-done-p #:explain #:action-description #:component-sibling-dependencies 8646 8723 #:needed-in-image-p 8647 8724 ;; #:run-program ; we can't export it, because SB-GROVEL :use's both ASDF and SB-EXT. … … 8673 8750 #:component-version 8674 8751 #:component-parent 8675 #:component-property8676 8752 #:component-system 8677 8753 #:component-encoding … … 8693 8769 #:map-systems 8694 8770 8695 #:operation-description8696 8697 8771 #:*system-definition-search-functions* ; variables 8698 8772 #:*central-registry* … … 8706 8780 #:asdf-version 8707 8781 8708 #:operation-error #:compile-failed #:compile-warned #:compile-error 8782 #:compile-condition #:compile-file-error #:compile-warned-error #:compile-failed-error 8783 #:compile-warned-warning #:compile-failed-warning 8784 #:operation-error #:compile-failed #:compile-warned #:compile-error ;; backward compatibility 8709 8785 #:error-name 8710 8786 #:error-pathname … … 8739 8815 #:compile-file* 8740 8816 #:compile-file-pathname* 8817 #:*warnings-file-type* 8741 8818 #:enable-asdf-binary-locations-compatibility 8742 8819 #:*default-source-registries* … … 8759 8836 #:system-source-registry-directory)) 8760 8837 8838 ;;;; --------------------------------------------------------------------------- 8839 ;;;; ASDF-USER, where the action happens. 8840 8841 (asdf/package:define-package :asdf/user 8842 (:nicknames :asdf-user) 8843 (:use :asdf/common-lisp :asdf/package :asdf/interface)) 8761 8844 ;;;; ----------------------------------------------------------------------- 8762 8845 ;;;; ASDF Footer: last words and cleanup … … 8771 8854 (in-package :asdf/footer) 8772 8855 8773 ;;;; Configure8774 (setf asdf/utility:*asdf-debug-utility*8775 '(asdf/system:system-relative-pathname :asdf "contrib/debug.lisp"))8776 8777 8856 ;;;; Hook ASDF into the implementation's REQUIRE and other entry points. 8778 8857 8779 8858 #+(or abcl clisp clozure cmu ecl mkcl sbcl) 8780 (let ((x (and #+clisp (find-symbol* '#:*module-provider-functions* :custom nil)))) 8781 (when x 8782 (eval `(pushnew 'module-provide-asdf 8783 #+abcl sys::*module-provider-functions* 8784 #+clisp ,x 8785 #+clozure ccl:*module-provider-functions* 8786 #+(or cmu ecl) ext:*module-provider-functions* 8787 #+mkcl mk-ext:*module-provider-functions* 8788 #+sbcl sb-ext:*module-provider-functions*)))) 8859 (if-let (x (and #+clisp (find-symbol* '#:*module-provider-functions* :custom nil))) 8860 (eval `(pushnew 'module-provide-asdf 8861 #+abcl sys::*module-provider-functions* 8862 #+clisp ,x 8863 #+clozure ccl:*module-provider-functions* 8864 #+(or cmu ecl) ext:*module-provider-functions* 8865 #+mkcl mk-ext:*module-provider-functions* 8866 #+sbcl sb-ext:*module-provider-functions*))) 8789 8867 8790 8868 #+(or ecl mkcl) … … 8822 8900 (setf excl:*warn-on-nested-reader-conditionals* asdf/common-lisp::*acl-warn-save*))) 8823 8901 8824 (dolist (f '(:asdf :asdf2 :asdf 2.27)) (pushnew f *features*))8902 (dolist (f '(:asdf :asdf2 :asdf3)) (pushnew f *features*)) 8825 8903 8826 8904 (provide :asdf)
Note: See TracChangeset
for help on using the changeset viewer.