;;; -*-Scheme-*-
;;;
-;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/pathnm.scm,v 13.42 1987/03/12 02:16:14 jinx Exp $
+;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/pathnm.scm,v 13.43 1987/07/18 03:02:54 cph Rel $
;;;
;;; Copyright (c) 1987 Massachusetts Institute of Technology
;;;
;;; components may have special meaning to certain directory
;;; operations.
-;;; * 'UNSPECIFIC, meaning that the component was supplied, but null.
-;;; This means about the same thing as "". (maybe it should be
-;;; eliminated in favor of that?)
-
;;; * #F, meaning that the component was not supplied. This has
;;; special meaning to `merge-pathnames', in which such components are
;;; substituted.
+;;; * 'UNSPECIFIC, which means the same thing as #F except that it is
+;;; never defaulted by `merge-pathnames'. Normally there is no way to
+;;; specify such a component value with `string->pathname'.
+
;;; A pathname consists of 5 components, not all necessarily
;;; meaningful, as follows:
;;; * The DEVICE is usually a physical device, as in the Twenex `ps:'.
;;; * The DIRECTORY is a list of components. If the first component
-;;; is the null string, then the directory path is absolute.
-;;; Otherwise it is relative.
+;;; is 'ROOT, then the directory path is absolute. Otherwise it is
+;;; relative. Two special components allowed only in directories are
+;;; the symbols 'SELF and 'UP which are equivalent to Unix' "." and
+;;; ".." respectively.
;;; * The NAME is the proper name part of the filename.
;;; * The VERSION is special. Unlike an ordinary component, it is
;;; never a string, but may be either a positive integer, 'NEWEST,
-;;; 'WILD, 'UNSPECIFIC, or #F. Many system procedures will default
+;;; 'UNSPECIFIC, 'WILD, or #F. Many system procedures will default
;;; the version to 'NEWEST, which means to search the directory for
;;; the highest version numbered file.
;;; This file requires the following procedures and variables which
;;; define the conventions for the particular file system in use:
-;;;
;;; (symbol->pathname symbol)
-;;; (string->pathname string)
+;;; (pathname-parse string (lambda (device directory name type version)))
;;; (pathname-unparse device directory name type version)
;;; (pathname-unparse-name name type version)
-;;; (simplify-directory directory)
+;;; (pathname-as-directory pathname)
;;; working-directory-package
;;; (access reset! working-directory-package)
;;; init-file-pathname
;;; (home-directory-pathname)
;;; (working-directory-pathname)
;;; (set-working-directory-pathname! name)
-;;;
+
;;; See the files unkpth.scm, vmspth.scm, or unxpth.scm for examples.
\f
;;;; Basic Pathnames
(eq? (environment-procedure object) make-pathname)))
(define (make-pathname device directory name type version)
- (define string #F)
+ (define string false)
(define (:print-self)
(unparse-with-brackets
(define (pathname-absolute? pathname)
(let ((directory (pathname-directory pathname)))
- (and (not (null? directory))
- (string-null? (car directory)))))
-\f
+ (and (pair? directory)
+ (eq? (car directory) 'ROOT))))\f
(define (pathname-new-device pathname device)
(pathname-components pathname
(lambda (old-device directory name type version)
(define (pathname-directory-path pathname)
(pathname-components pathname
(lambda (device directory name type version)
- (make-pathname device directory #F #F #F))))
+ (make-pathname device directory false false false))))
(define (pathname-directory-string pathname)
(pathname-components pathname
(lambda (device directory name type version)
- (pathname-unparse device directory #F #F #F))))
+ (pathname-unparse device directory false false false))))
(define (pathname-name-path pathname)
(pathname-components pathname
(lambda (device directory name type version)
- (make-pathname #F #F name type version))))
+ (make-pathname false false name type version))))
(define (pathname-name-string pathname)
(pathname-components pathname
(lambda (device directory name type version)
- (pathname-unparse #F #F name type version))))
+ (pathname-unparse false false name type version))))
\f
;;;; Parse and unparse.
((symbol? object) (symbol->pathname object))
(else (error "Unable to coerce into pathname" object))))
+(define (string->pathname string)
+ (parse-pathname string make-pathname))
+
(define (pathname->string pathname)
(or (access string pathname)
(let ((string (pathname-components pathname pathname-unparse)))
;;;; Merging pathnames
(define (merge-pathnames pathname default)
- (make-pathname (or (pathname-device pathname) (pathname-device default))
- (simplify-directory
- (let ((directory (pathname-directory pathname)))
- (cond ((null? directory) (pathname-directory default))
- ((string-null? (car directory)) directory)
- (else
- (append (pathname-directory default) directory)))))
- (or (pathname-name pathname) (pathname-name default))
- (or (pathname-type pathname) (pathname-type default))
- (or (pathname-version pathname) (pathname-version default))))
-
-(define (pathname-as-directory pathname)
- (let ((file (pathname-unparse-name (pathname-name pathname)
- (pathname-type pathname)
- (pathname-version pathname))))
- (if (string-null? file)
- pathname
- (make-pathname (pathname-device pathname)
- (append (pathname-directory pathname)
- (list file))
- #F #F #F))))
+ (make-pathname
+ (or (pathname-device pathname) (pathname-device default))
+ (simplify-directory
+ (let ((directory (pathname-directory pathname))
+ (default (pathname-directory default)))
+ (cond ((null? directory) default)
+ ((or (eq? directory 'UNSPECIFIC)
+ (null? default)
+ (eq? default 'UNSPECIFIC))
+ directory)
+ ((pair? directory)
+ (cond ((eq? (car directory) 'ROOT) directory)
+ ((pair? default) (append default directory))
+ (else (error "Illegal pathname directory" default))))
+ (else (error "Illegal pathname directory" directory)))))
+ (or (pathname-name pathname) (pathname-name default))
+ (or (pathname-type pathname) (pathname-type default))
+ (or (pathname-version pathname) (pathname-version default))))
+
+(define simplify-directory)
+(let ()
+
+(set! simplify-directory
+ (named-lambda (simplify-directory directory)
+ (cond ((not (pair? directory)) directory)
+ ((eq? (car directory) 'ROOT)
+ (cons 'ROOT (simplify-tail (simplify-root-tail (cdr directory)))))
+ (else (simplify-tail directory)))))
+
+(define (simplify-root-tail directory)
+ (if (and (pair? directory)
+ (memq (car directory) '(SELF UP)))
+ (simplify-root-tail (cdr directory))
+ directory))
+
+(define (simplify-tail directory)
+ (cond ((not (pair? directory)) directory)
+ ((eq? (car directory) 'SELF) (simplify-tail (cdr directory)))
+ ((not (pair? (cdr directory))) directory)
+ ((eq? (cadr directory) 'UP) (simplify-tail (cddr directory)))
+ (else (cons (car directory) (simplify-tail (cdr directory))))))
+
+)
(define (pathname->absolute-pathname pathname)
- (merge-pathnames pathname (working-directory-pathname)))
+ (merge-pathnames pathname (working-directory-pathname)))
\ No newline at end of file
;;; -*-Scheme-*-
;;;
-;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/unxpth.scm,v 1.2 1987/03/17 18:54:38 cph Exp $
+;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/unxpth.scm,v 1.3 1987/07/18 03:02:08 cph Exp $
;;;
;;; Copyright (c) 1987 Massachusetts Institute of Technology
;;;
(define (symbol->pathname symbol)
(string->pathname (string-downcase (symbol->string symbol))))
-(define string->pathname)
+(define parse-pathname)
+(define pathname-as-directory)
(define home-directory-pathname)
(let ()
-(set! string->pathname
- (named-lambda (string->pathname string)
- (parse-pathname string make-pathname)))
-
-(define (parse-pathname string receiver)
- (let ((components (divide-into-components (string-trim string))))
- (if (null? components)
- (receiver #F #F #F #F #F)
- (let ((components
- (append (expand-directory-prefixes (car components))
- (cdr components))))
- (parse-name (car (last-pair components))
- (lambda (name type version)
- (receiver #F
- (map (lambda (component)
- (if (string=? "*" component)
- 'WILD
- component))
- (except-last-pair components))
- name type version)))))))
-
-(define (divide-into-components string)
- (let ((end (string-length string)))
- (define (loop start)
- (let ((index (substring-find-next-char string start end #\/)))
- (if index
- (cons (substring string start index)
- (loop (1+ index)))
- (list (substring string start end)))))
- (loop 0)))
+(set! parse-pathname
+ (named-lambda (parse-pathname string receiver)
+ (let ((end (string-length string)))
+ (parse-device string 0 end
+ (lambda (device start)
+ (let ((components
+ (let ((components
+ (substring-components string start end #\/)))
+ (append (expand-directory-prefixes (car components))
+ (cdr components)))))
+ (parse-name (car (last-pair components))
+ (lambda (name type version)
+ (receiver device
+ (parse-directory-components
+ (except-last-pair components))
+ name type version)))))))))
+
+(define (parse-directory-components components)
+ (if (null? components)
+ '()
+ (cons (if (string-null? (car components))
+ 'ROOT
+ (parse-directory-component (car components)))
+ (map parse-directory-component (cdr components)))))
+
+(set! pathname-as-directory
+ (named-lambda (pathname-as-directory pathname)
+ (make-pathname
+ (pathname-device pathname)
+ (let ((directory (pathname-directory pathname)))
+ (let ((file (pathname-unparse-name (pathname-name pathname)
+ (pathname-type pathname)
+ (pathname-version pathname))))
+ (if (string-null? file)
+ directory
+ (let ((file-components (list (parse-directory-component file))))
+ (cond ((or (null? directory) (eq? directory 'UNSPECIFIC))
+ file-components)
+ ((pair? directory)
+ (append directory file-components))
+ (else (error "Illegal pathname directory" directory)))))))
+ false false false)))
\f
+(define (parse-device string start end receiver)
+ (let ((index (substring-find-next-char string start end #\:)))
+ (if index
+ (receiver (substring string start index) (1+ index))
+ (receiver false start))))
+
+(define (parse-directory-component component)
+ (cond ((string=? "*" component) 'WILD)
+ ((string=? "." component) 'SELF)
+ ((string=? ".." component) 'UP)
+ (else component)))
+
(define (expand-directory-prefixes string)
(if (string-null? string)
(list string)
(case (string-ref string 0)
((#\$)
- (divide-into-components
+ (string-components
(get-environment-variable
- (substring string 1 (string-length string)))))
+ (substring string 1 (string-length string)))
+ #\/))
((#\~)
(let ((user-name (substring string 1 (string-length string))))
- (divide-into-components
+ (string-components
(if (string-null? user-name)
(get-environment-variable "HOME")
- (get-user-home-directory user-name)))))
+ (get-user-home-directory user-name))
+ #\/)))
(else (list string)))))
(set! home-directory-pathname
(lambda ()
- (make-pathname #F
- (divide-into-components (get-environment-variable "HOME"))
- #F
- #F
- #F)))
+ (pathname-as-directory
+ (string->pathname (get-environment-variable "HOME")))))
(define get-environment-variable
(let ((primitive (make-primitive-procedure 'GET-ENVIRONMENT-VARIABLE)))
(lambda (user-name)
(or (primitive user-name)
(error "User has no home directory" user-name)))))
-
-(define (digits->number digits weight accumulator)
- (if (null? digits)
- accumulator
- (let ((value (char->digit (car digits) 10)))
- (and value
- (digits->number (cdr digits)
- (* weight 10)
- (+ (* weight value) accumulator))))))
\f
(define (parse-name string receiver)
(let ((start 0)
(substring-find-previous-char string start end #\.))
(define (parse-version start)
- (cond ((= start end) 'UNSPECIFIC)
+ (cond ((= start end) "")
((substring=? string start end "*" 0 1) 'WILD)
((substring-find-next-char string start end #\*)
(substring string start end))
(substring string start end))))))
(if (= start end)
- (receiver #F #F #F)
+ (receiver false false false)
(let ((index (find-next-dot start)))
(if index
(let ((start* (1+ index))
(name (wildify string start index)))
(if (= start* end)
- (receiver name 'UNSPECIFIC 'UNSPECIFIC)
+ (receiver name "" "")
(or (let ((index (find-next-dot start*)))
(and index
(let ((version (parse-version (1+ index))))
(let ((index (find-previous-dot start)))
(receiver (wildify string start index)
(wildify string (1+ index) end)
- #F)))))
- (receiver (wildify string start end) #F #F))))))
-
+ false)))))
+ (receiver (wildify string start end) false false))))))
+\f
(define (wildify string start end)
(if (substring=? string start end "*" 0 1)
'WILD
(substring string start end)))
+(define (string-components string delimiter)
+ (substring-components string start end delimiter))
+
+(define (substring-components string start end delimiter)
+ (define (loop start)
+ (let ((index (substring-find-next-char string start end delimiter)))
+ (if index
+ (cons (substring string start index)
+ (loop (1+ index)))
+ (list (substring string start end)))))
+ (loop start))
+
+(define (digits->number digits weight accumulator)
+ (if (null? digits)
+ accumulator
+ (let ((value (char->digit (car digits) 10)))
+ (and value
+ (digits->number (cdr digits)
+ (* weight 10)
+ (+ (* weight value) accumulator))))))
+
;;; end LET.
)
\f
(set! pathname-unparse
(named-lambda (pathname-unparse device directory name type version)
- (unparse-device
- device
- (unparse-directory directory
- (pathname-unparse-name name type version)))))
-
-(define (unparse-device device rest)
- (let ((device-string (unparse-component device)))
- (if device-string
- (string-append device-string ":" rest)
- rest)))
-
-(define (unparse-directory directory rest)
- (cond ((null? directory) rest)
+ (string-append (let ((device-string (unparse-component device)))
+ (if device-string
+ (string-append device-string ":")
+ ""))
+ (unparse-directory directory)
+ (pathname-unparse-name name type version))))
+
+(define (unparse-directory directory)
+ (define (loop directory)
+ (if (null? directory)
+ ""
+ (string-append (unparse-directory-component (car directory))
+ "/"
+ (loop (cdr directory)))))
+ (cond ((null? directory) "")
((pair? directory)
- (let loop ((directory directory))
- (let ((directory-string (unparse-component (car directory)))
- (rest (if (null? (cdr directory))
- rest
- (loop (cdr directory)))))
- (if directory-string
- (string-append directory-string "/" rest)
- rest))))
- (else
- (error "Unrecognizable directory" directory))))
+ (string-append (if (eq? (car directory) 'ROOT)
+ ""
+ (unparse-directory-component (car directory)))
+ "/"
+ (loop (cdr directory))))
+ (else (error "Illegal pathname directory" directory))))
+
+(define (unparse-directory-component component)
+ (cond ((eq? component 'WILD) "*")
+ ((eq? component 'SELF) ".")
+ ((eq? component 'UP) "..")
+ ((string? component) component)
+ (else (error "Illegal pathname directory component" component))))
\f
(set! pathname-unparse-name
(named-lambda (pathname-unparse-name name type version)
- (let ((name-string (unparse-component name))
- (type-string (unparse-component type))
- (version-string (unparse-version version)))
- (cond ((not name-string) "")
- ((not type-string) name-string)
- ((eq? type-string 'UNSPECIFIC) (string-append name-string "."))
- ((not version-string) (string-append name-string "." type-string))
- ((eq? version-string 'UNSPECIFIC)
- (string-append name-string "." type-string "."))
- (else
- (string-append name-string "." type-string "."
- version-string))))))
-
-(define (unparse-version version)
- (if (eq? version 'NEWEST)
- "0"
- (unparse-component version)))
+ (let ((name (unparse-component name))
+ (type (unparse-component type))
+ (version (unparse-version version)))
+ (cond ((not name) "")
+ ((not type) name)
+ ((not version) (string-append name "." type))
+ (else (string-append name "." type "." version))))))
(define (unparse-component component)
- (cond ((not component) #F)
- ((eq? component 'UNSPECIFIC) component)
+ (cond ((or (not component) (string? component)) component)
+ ((eq? component 'UNSPECIFIC) false)
((eq? component 'WILD) "*")
- ((string? component) component)
- ((and (integer? component) (> component 0))
- (list->string (number->digits component '())))
- (else (error "Unknown component" component))))
+ (else (error "Illegal pathname component" component))))
+
+(define (unparse-version version)
+ (cond ((or (not version) (string? version)) version)
+ ((eq? version 'UNSPECIFIC) false)
+ ((eq? version 'WILD) "*")
+ ((eq? version 'NEWEST) "0")
+ ((and (integer? version) (> version 0))
+ (list->string (number->digits version '())))
+ (else (error "Illegal pathname version" version))))
(define (number->digits number accumulator)
(if (zero? number)
;;; end LET.
)
\f
-;;;; Utility for merge pathnames
-
-(define (simplify-directory directory)
- (cond ((null? directory) directory)
- ((string=? (car directory) ".")
- (simplify-directory (cdr directory)))
- ((null? (cdr directory)) directory)
- ((string=? (cadr directory) "..")
- (simplify-directory (cddr directory)))
- (else
- (cons (car directory)
- (simplify-directory (cdr directory))))))
-\f
;;;; Working Directory
(define working-directory-pathname)
))
(define init-file-pathname
- (make-pathname #F #F ".scheme" "init" #F))
\ No newline at end of file
+ (string->pathname ".scheme.init"))
\ No newline at end of file