(unparse #'unparse-unix-namestring)
(unparse-native #'unparse-native-unix-namestring)
(unparse-host #'unparse-unix-host)
- (unparse-directory #'unparse-unix-directory)
+ (unparse-directory #'unparse-physical-directory)
(unparse-file #'unparse-unix-file)
(unparse-enough #'unparse-unix-enough)
(unparse-directory-separator "/")
(unparse #'unparse-win32-namestring)
(unparse-native #'unparse-native-win32-namestring)
(unparse-host #'unparse-win32-host)
- (unparse-directory #'unparse-win32-directory)
+ (unparse-directory #'unparse-physical-directory)
(unparse-file #'unparse-win32-file)
(unparse-enough #'unparse-win32-enough)
(unparse-directory-separator "\\")
(simplify-namestring #'simplify-win32-namestring)
- (customary-case :upper))))
+ (customary-case :lower))))
(defparameter *win32-host* (make-win32-host))
(defun make-win32-host-load-form (host)
(declare (ignore host))
((member :unspecific) '(:relative))
(list
(collect ((results))
- (results (pop directory))
- (dolist (piece directory)
- (cond ((member piece '(:wild :wild-inferiors :up :back))
- (results piece))
- ((or (simple-string-p piece) (pattern-p piece))
- (results (maybe-diddle-case piece diddle-case)))
- ((stringp piece)
- (results (maybe-diddle-case (coerce piece 'simple-string)
- diddle-case)))
- (t
- (error "~S is not allowed as a directory component." piece))))
+ (let ((root (pop directory)))
+ (if (member root '(:relative :absolute))
+ (results root)
+ (error "List of directory components must start with ~S or ~S."
+ :absolute :relative)))
+ (when directory
+ (let ((next (pop directory)))
+ (if (or (eq :home next)
+ (typep next '(cons (eql :home) (cons string null))))
+ (results next)
+ (push next directory)))
+ (dolist (piece directory)
+ (cond ((member piece '(:wild :wild-inferiors :up :back))
+ (results piece))
+ ((or (simple-string-p piece) (pattern-p piece))
+ (results (maybe-diddle-case piece diddle-case)))
+ ((stringp piece)
+ (results (maybe-diddle-case (coerce piece 'simple-string)
+ diddle-case)))
+ (t
+ (error "~S is not allowed as a directory component." piece)))))
(results)))
(simple-string
`(:absolute ,(maybe-diddle-case directory diddle-case)))
(cond
(junk-allowed
(handler-case
- (%parse-namestring namestr host defaults start end nil)
+ (%parse-native-namestring namestr host defaults start end nil as-directory)
(namestring-parse-error (condition)
(values nil (namestring-parse-error-offset condition)))))
(t
(frob %pathname-directory directory-components-match)
(frob %pathname-name)
(frob %pathname-type)
- (or (eq (%pathname-host wildname) *unix-host*)
+ (or (eq (%pathname-host wildname) *physical-host*)
(frob %pathname-version)))))))
;;; Place the substitutions into the pattern and return the string or pattern
(defun translate-pathname (source from-wildname to-wildname &key)
#!+sb-doc
"Use the source pathname to translate the from-wildname's wild and
- unspecified elements into a completed to-pathname based on the to-wildname."
+unspecified elements into a completed to-pathname based on the to-wildname."
(declare (type pathname-designator source from-wildname to-wildname))
(with-pathname (source source)
(with-pathname (from from-wildname)
;;; a new one if necessary.
(defun intern-logical-host (thing)
(declare (values logical-host))
- (with-locked-hash-table (*logical-hosts*)
+ (with-locked-system-table (*logical-hosts*)
(or (find-logical-host thing nil)
(let* ((name (logical-word-or-lose thing))
(new (make-logical-host :name name)))
;;; loaded yet.
(defvar *logical-pathname-defaults*)
+(defun logical-namestring-p (x)
+ (and (stringp x)
+ (ignore-errors
+ (typep (pathname x) 'logical-pathname))))
+
+(deftype logical-namestring ()
+ `(satisfies logical-namestring-p))
+
(defun logical-pathname (pathspec)
#!+sb-doc
"Converts the pathspec argument to a logical-pathname and returns it."
(values logical-pathname))
(if (typep pathspec 'logical-pathname)
pathspec
- (let ((res (parse-namestring pathspec nil *logical-pathname-defaults*)))
- (when (eq (%pathname-host res)
- (%pathname-host *logical-pathname-defaults*))
- (error "This logical namestring does not specify a host:~% ~S"
- pathspec))
- res)))
+ (flet ((oops (problem)
+ (error 'simple-type-error
+ :datum pathspec
+ :expected-type 'logical-namestring
+ :format-control "~S is not a valid logical namestring:~% ~A"
+ :format-arguments (list pathspec problem))))
+ (let ((res (handler-case
+ (parse-namestring pathspec nil *logical-pathname-defaults*)
+ (error (e) (oops e)))))
+ (when (eq (%pathname-host res)
+ (%pathname-host *logical-pathname-defaults*))
+ (oops "no host specified"))
+ res))))
\f
;;;; logical pathname unparsing
(defun load-logical-pathname-translations (host)
#!+sb-doc
+ "Reads logical pathname translations from SYS:SITE;HOST.TRANSLATIONS.NEWEST,
+with HOST replaced by the supplied parameter. Returns T on success.
+
+If HOST is already defined as logical pathname host, no file is loaded and NIL
+is returned.
+
+The file should contain a single form, suitable for use with
+\(SETF LOGICAL-PATHNAME-TRANSLATIONS).
+
+Note: behaviour of this function is higly implementation dependent, and
+historically it used to be a no-op in SBcL -- the current approach is somewhat
+experimental and subject to change."
(declare (type string host)
(values (member t nil)))
(if (find-logical-host host nil)
;; This host is already defined, all is well and good.
nil
;; ANSI: "The specific nature of the search is
- ;; implementation-defined." SBCL: doesn't search at all
- ;;
- ;; FIXME: now that we have a SYS host that the system uses, it
- ;; might be cute to search in "SYS:TRANSLATIONS;<name>.LISP"
- (error "logical host ~S not found" host)))
+ ;; implementation-defined."
+ (prog1 t
+ (setf (logical-pathname-translations host)
+ (with-open-file (lpt (make-pathname :host "SYS"
+ :directory '(:absolute "SITE")
+ :name host
+ :type "TRANSLATIONS"
+ :version :newest))
+ (read lpt))))))
(defun !pathname-cold-init ()
(let* ((sys *default-pathname-defaults*)
`(("SYS:SRC;**;*.*.*" ,src)
("SYS:CONTRIB;**;*.*.*" ,contrib)
("SYS:OUTPUT;**;*.*.*" ,output)))))
+
+(defun set-sbcl-source-location (pathname)
+ "Initialize the SYS logical host based on PATHNAME, which should be
+the top-level directory of the SBCL sources. This will replace any
+existing translations for \"SYS:SRC;\", \"SYS:CONTRIB;\", and
+\"SYS:OUTPUT;\". Other \"SYS:\" translations are preserved."
+ (let ((truename (truename pathname))
+ (current-translations
+ (remove-if (lambda (translation)
+ (or (pathname-match-p "SYS:SRC;" translation)
+ (pathname-match-p "SYS:CONTRIB;" translation)
+ (pathname-match-p "SYS:OUTPUT;" translation)))
+ (logical-pathname-translations "SYS")
+ :key #'first)))
+ (flet ((physical-target (component)
+ (merge-pathnames
+ (make-pathname :directory (list :relative component
+ :wild-inferiors)
+ :name :wild
+ :type :wild)
+ truename)))
+ (setf (logical-pathname-translations "SYS")
+ `(("SYS:SRC;**;*.*.*" ,(physical-target "src"))
+ ("SYS:CONTRIB;**;*.*.*" ,(physical-target "contrib"))
+ ("SYS:OUTPUT;**;*.*.*" ,(physical-target "output"))
+ ,@current-translations)))))