Reimplement pathname parsing stuff for new VMS parser.
authorChris Hanson <org/chris-hanson/cph>
Sat, 18 Jul 1987 03:02:54 +0000 (03:02 +0000)
committerChris Hanson <org/chris-hanson/cph>
Sat, 18 Jul 1987 03:02:54 +0000 (03:02 +0000)
v7/src/runtime/pathnm.scm
v7/src/runtime/unxpth.scm

index ec558658fb1aaed54e30b12f050f8a5b61e9747d..51e76777b2b3c6c7a462c1811956edf48f12084d 100644 (file)
@@ -1,6 +1,6 @@
 ;;; -*-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
index baaf6660150a1d41a897fef95bc0cb5351bdfbae..bed17eff309ad4831a7327ff84e906116b42204e 100644 (file)
@@ -1,6 +1,6 @@
 ;;; -*-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