Google
 

Trailing-Edge - PDP-10 Archives - clisp - clisp/upsala/filesys.clisp
There are no other files named filesys.clisp in the archive.
;;; **********************************************************************
;;; This code was written as part of the Spice Lisp project at
;;; Carnegie-Mellon University, and has been placed in the public domain.
;;; If you want to use this code or any part of Spice Lisp, please contact
;;; Scott Fahlman (FAHLMAN@CMUC). 
;;; **********************************************************************
;;;
;;; Ugly pathname functions for Spice Lisp.
;;;    these functions are part of the standard Spice Lisp environment.
;;;
;;; Written by Jim Large
;;;
;;; **********************************************************************

(in-package 'lisp)

(export '(pathname *default-pathname-defaults* parse-namestring merge-pathnames
	  make-pathname pathname-host pathname-device pathname-directory
	  pathname-name pathname-type pathname-version file-namestring
	  directory-namestring host-namestring enough-namestring
	  open close))
;;; Pathname structure

;;; *Default-Pathname-defaults* has all values unspecified except for the
;;;  host.  All pathnames must have a host.  "DEFAULT" is the default device
;;;  for spice.

;;; The pathname type is defined with a defstruct.
;;; This declaration implicitly defines the common lisp functions
;;; pathname-host, pathname-device ... pathname-version.

(defstruct (pathname
	    (:conc-name %pathname-)
	    (:print-function %print-pathname)
	    (:constructor
	     %make-pathname (host device directory name type version))
	    (:predicate pathnamep))
  host
  device
  directory
  name
  type
  version)

(defun %print-pathname (s stream d)
  (declare (ignore d))
  (format stream "#.(pathname ~S)" (namestring s)))

(defun make-pathname (&key (defaults *make-pathname-default-pathname*)
			   (host (%pathname-host defaults))
			   (device (%pathname-device defaults))
			   (directory (%pathname-directory defaults))
			   (name (%pathname-name defaults))
			   (type (%pathname-type defaults))
			   (version (%pathname-version defaults)))
  "Create a pathname from :host, :device, :directory, :name, :type and
  :version.  If any field is ommitted, it is obtained from :defaults as
  though by merge-pathname-defaults."
  (%make-pathname host device directory name type version))

(defvar *default-pathname-defaults* (%make-pathname nil nil nil nil nil nil)
  "This is the default pathname-defaults pathname; if any pathname primitive
  that needs a set of defaults is not given one, it uses this one.  As a
  general rule, however, each program should have its own pathname defaults
  rather than using this one.")
(defvar *make-pathname-default-pathname* *default-pathname-defaults*)

;;; These can not be done by the accessors because the pathname arg may be
;;;  a string or a symbol or etc.

(defun pathname-host (pathname)
  "Returns the host slot of pathname.  Pathname may be a string, symbol,
  or stream."
  (setq pathname (pathname pathname))
  (%pathname-host pathname))

(defun pathname-device (pathname)
  "Returns the device slot of pathname.  Pathname may be a string, symbol,
  or stream."
  (setq pathname (pathname pathname))
  (%pathname-device pathname))

(defun pathname-directory (pathname)
  "Returns the directory slot of pathname.  Pathname may be a string, symbol,
  or stream."
  (setq pathname (pathname pathname))
  (%pathname-directory pathname))

(defun pathname-name (pathname)
  "Returns the name slot of pathname.  Pathname may be a string, symbol,
  or stream."
  (setq pathname (pathname pathname))
  (%pathname-name pathname))

(defun pathname-type (pathname)
  "Returns the type slot of pathname.  Pathname may be a string, symbol,
  or stream."
  (setq pathname (pathname pathname))
  (%pathname-type pathname))

(defun pathname-version (pathname)
  "Returns the version slot of pathname.  Pathname may be a string, symbol,
  or stream."
  (setq pathname (pathname pathname))
  (%pathname-version pathname))
;;; Parse-Namestring  --  Public
;;;
;;;    Just lex the thing and flame out if it can't be done. 
;;;
(defun parse-namestring (thing &optional host 
			       (defaults *default-pathname-defaults*)
			       &key (start 0) end (junk-allowed nil))
  (declare (ignore host defaults))
  "Parses a string representation of a pathname into a pathname.  For
  details on the other silly arguments see the manual."
  (%sp-parse-namestring thing start end junk-allowed))


;;; Pathname  --  Public
;;;
;;;    Call parse-namestring, doo dah, doo dah...
;;;
(defun pathname (thing)
  "Turns Thing into a pathname.  Thing may be a string, symbol, stream,
  or pathname."
  (values (parse-namestring thing)))
;;; Merge-Pathnames  --  Public
;;;
;;; Returns a new pathname whose fields are the same as the fields in PATHNAME
;;;  except that () fields are filled in from defaults.  Type and Version field
;;;  are only done if name field has to be done (see manual for explanation).
;;;
(defun merge-pathnames (pathname &optional
				 (defaults *default-pathname-defaults*)
				 (default-version :newest))
  "Fills in unspecified slots of Pathname from Defaults (defaults to
  *default-pathname-defaults*).  If the version remains unspecified,
  gets it from Default-Version."
  ;;
  ;; finish hairy argument defaulting
  (setq pathname (pathname pathname))
  (setq defaults (pathname defaults))
  ;;
  ;; make a new pathname
  (let ((host (%pathname-host pathname))
	(device (%pathname-device pathname))
	(directory (%pathname-directory pathname))
	(name (%pathname-name pathname))
	(type (%pathname-type pathname))
	(version (%pathname-version pathname)))
;;the following is intended to avoid getting a default device from
;; the wrong host.  It is activated only if the pathname has an
;; explicit host spec.
    (if (and host (null device))
	(if (and (%pathname-host defaults)
		 (string-equal host (%pathname-host defaults)))
	    (setq device (%pathname-device defaults))
	    (setq device "DSK")))
    (if (null name)
	(if (null version) (setq version (%pathname-version defaults)))
	(if (null version) (setq version default-version)))
    (%make-pathname
     (or host (%pathname-host defaults))
     (or device (%pathname-device defaults))
     (or directory (%pathname-directory defaults))
     (or name (%pathname-name defaults))
     (or type (%pathname-type defaults))
     version)))
;;; Namestring & Friends

(defun file-namestring (pathname)
  "Returns the name, type, and version of PATHNAME as a string."
;there is a certain amount of magic involved in converting
;keywords into strings, so it is safest to make up a full
;pathname and then let namestring do the conversion
  (setq pathname (pathname pathname))
  (setq pathname (%make-pathname nil nil nil
				 (%pathname-name pathname)
				 (%pathname-type pathname)
				 (%pathname-version pathname)))
  (namestring pathname))

(defun directory-namestring (pathname)
  "Returns the device & directory parts of PATHNAME as a string."
;there is a certain amount of magic involved in converting
;keywords into strings, so it is safest to make up a full
;pathname and then let namestring do the conversion
  (setq pathname (pathname pathname))
  (setq pathname (%make-pathname nil 
				 (%pathname-device pathname)
				 (%pathname-directory pathname)
				 nil nil nil))
  (namestring pathname))

(defun host-namestring (pathname)
  "Returns the host part of PATHNAME as a string."
  (setq pathname (pathname pathname))
  (%pathname-host pathname))
;;; Enough-Namestring

(defun enough-namestring (pathname &optional
				   (defaults *default-pathname-defaults*))
  "Returns a string which uniquely identifies PATHNAME w.r.t. DEFAULTS." 
  (setq pathname (pathname pathname))
  (setq defaults (pathname defaults))
  (let* ((host (%pathname-host pathname))
	 (device (%pathname-device pathname))
	 (directory (%pathname-directory pathname))
	 (name (%pathname-name pathname))
	 (type (%pathname-type pathname))
	 (version (%pathname-version pathname)))
    (when (and host (path-equal host (%pathname-host defaults)))
      (setq host nil))
;note that we have to add the condition (null host), because
;merge-pathnames will not use a default device if the filespec
;includes an explicit host that is different from the default host
    (when (and device (null host)
	       (path-equal device (%pathname-device defaults)))
      (setq device nil))
    (when (and directory
	       (path-equal directory (%pathname-directory defaults)))
      (setq directory nil))
    (when (and name (path-equal name (%pathname-name defaults)))
      (setq name nil))
    (when (and type (path-equal type (%pathname-type defaults)))
      (setq type nil))
;we have to include the not name here because merge-pathnames will
;not use the default version if there is an explicit name
    (when (and version (not name)
               (version-equal version (%pathname-version defaults)))
      (setq version nil))
;unfortunately a..3 always specifies that the type is null.  There is
;no way to leave the type unspecified and also show the version.  So
;we supply the original type in this case.
    (when (and version (not type))
      (setq type (%pathname-type pathname)))
    (namestring (%make-pathname host device directory name type version))))

(defun path-equal (x y)
  (if (eq x :wild) (setq x "*"))
  (if (eq y :wild) (setq y "*"))
  (cond ((and (stringp x) (stringp y))
	 (string-equal x y))
	(t (eq x y))))

(defun version-equal (x y)
  (if (equal x "*") (setq x -3))
  (if (equal y "*") (setq y -3))
  (if (eq x :newest) (setq x 0))
  (if (eq y :newest) (setq y 0))
  (if (eq x :new-version) (setq x -1))
  (if (eq y :new-version) (setq y -1))
  (if (eq x :oldest) (setq x -2))
  (if (eq y :oldest) (setq y -2))
  (if (eq x :wild) (setq x -3))
  (if (eq y :wild) (setq y -3))
  (eq x y))

(defun set-terminal-modes (term &rest modes)
   (if (eq (length modes) 1)
       (%sp-set-terminal-modes term (car modes))
       (%sp-set-terminal-modes term modes)))

(defun open (filename &key (direction :input) (element-type 'string-char)
			  (if-exists :new-version)
			  (if-does-not-exist 
				(cond ((eq direction :probe) nil)
				      ((or (eq direction :input)
					   (memq if-exists
						'(:overwrite :append)))
				        :error)
				      (t :create))))
  "Return a stream which reads from or writes to Filename.
  Defined  keywords:
   :direction - one of :input, :output or :probe
   :element-type - Type of object to read or write, default String-Char
   :if-exists - one of :error, :new-version, :overwrite, :append or nil
   :if-does-not-exist - one of :error, :create or nil
  See the manual for details."
  (%sp-open filename direction (if (memq direction '(:input :probe))
				   :default
				   if-exists)
			       if-does-not-exist element-type))

(defun close (stream &key abort)
  "Closes the given stream.  No more I/O may be preformed, but inquiries
  may still be made.  If :Abort is non-nil, an attempt is made to clean
  up the side effects of having created the stream."
   (%sp-close stream (if abort #o4000 0)))