119 lines
4.0 KiB
Scheme
119 lines
4.0 KiB
Scheme
;;; More imports for the new library-search facility:
|
|
;;; HANDLE: with-handler
|
|
;;; LIST-LIB: any
|
|
;;; SCSH-LEVEL-0: directory-files open-input-file file-directory?
|
|
;;; SCSH-LEVEL-0: getenv
|
|
;;; SCSH-LEVEL-0: the file-name procs
|
|
|
|
(define default-lib-dirs '("/usr/local/lib/scsh/modules/"))
|
|
|
|
(define (set-default-lib-dirs! path-list)
|
|
(set! default-lib-dirs path-list))
|
|
|
|
;;; Search library dirs for FILE.
|
|
(define (find-library-file file lib-dirs script-file)
|
|
(letrec ((recur (lambda (dir)
|
|
; (format (error-output-port) "flf -- entering ~a\n" dir)
|
|
(let* ((f (string-append dir file))) ; Resolve it.
|
|
(or (check-file-for-open f) ; Found it.
|
|
(any (lambda (f) ; Search subdirs.
|
|
(let ((dir (string-append dir f "/")))
|
|
(and (file-directory?/safe dir) (recur dir))))
|
|
(directory-files/safe dir)))))))
|
|
(any (lambda (dir)
|
|
(cond ((eq? dir 'script-dir)
|
|
(let* ((script-dir (file-name-directory script-file))
|
|
(fname (string-append script-dir file)))
|
|
(check-file-for-open fname)))
|
|
|
|
;; Ends in / means recursive search.
|
|
((file-name-directory? dir)
|
|
(recur dir))
|
|
|
|
(else (check-file-for-open (absolute-file-name file dir)))))
|
|
lib-dirs)))
|
|
|
|
|
|
;;; (in-any-event abort-exp body ...)
|
|
;;; If *anything* goes wrong, bag the BODY forms, and eval ABORT-EXP instead.
|
|
|
|
(define-syntax in-any-event
|
|
(syntax-rules ()
|
|
((in-any-event abort-exp body ...)
|
|
(call-with-current-continuation
|
|
(lambda (ret)
|
|
(with-handler (lambda (condition more) (ret abort-exp))
|
|
(lambda () body ...)))))))
|
|
|
|
(define (check-file-for-open f)
|
|
(in-any-event #f (let ((iport (open-input-file f)))
|
|
(close-input-port iport)
|
|
f))) ; Any error, say false.
|
|
|
|
(define (directory-files/safe dir)
|
|
(in-any-event '() (directory-files dir))) ; Any error, say ().
|
|
|
|
(define (file-directory?/safe f)
|
|
(in-any-event #f (file-directory? f))) ; Any error, say false.
|
|
|
|
(define (resolve-dir-name dir)
|
|
(if (file-name-directory? dir)
|
|
(file-name-as-directory (resolve-file-name dir))
|
|
(resolve-file-name dir)))
|
|
|
|
;;; Expand out env vars & ~user home dir prefixes.
|
|
(define (expand-lib-dir dir)
|
|
(substitute-env-vars (resolve-dir-name dir)))
|
|
|
|
;;; Parse up the $SCSH_LIB_DIRS path list.
|
|
(define (parse-lib-dirs-env-var)
|
|
(let ((s (getenv "SCSH_LIB_DIRS")))
|
|
(if (not s)
|
|
default-lib-dirs
|
|
(with-current-input-port (make-string-input-port s)
|
|
(let recur ()
|
|
(let ((val (read)))
|
|
(cond ((eof-object? val) '())
|
|
((string? val) (cons val (recur)))
|
|
((not val) (append default-lib-dirs (recur)))
|
|
(else
|
|
(error
|
|
(format #f
|
|
(string-append
|
|
"Illegal path element in $SCSH_LIB_DIRS\n"
|
|
"$SCSH_LIB_DIRS: ~a\n"
|
|
"The following element is not a string or #f: ~a")
|
|
s val))))))))))
|
|
|
|
;; We don't want to try to parse $SCSH_LIB_DIRS until we actually
|
|
;; need the value -- if the user is using the -lp-default switch,
|
|
;; for example, a parse error shouldn't effect the startup.
|
|
(define %lib-dirs #f)
|
|
(define reinit-lib-dirs
|
|
(make-reinitializer (lambda () (set! %lib-dirs #f))))
|
|
|
|
(define (lib-dirs)
|
|
(if (not %lib-dirs) (set! %lib-dirs (parse-lib-dirs-env-var)))
|
|
%lib-dirs)
|
|
|
|
;; Don't export -- direct modification of %lib-dirs
|
|
(define (set-lib-dirs! val) (set! %lib-dirs val))
|
|
|
|
(define (lib-dirs-append-script-dir!)
|
|
(set-lib-dirs! (append (lib-dirs) '(script-dir))))
|
|
|
|
(define (lib-dirs-prepend-script-dir!)
|
|
(set-lib-dirs! (cons 'script-dir (lib-dirs))))
|
|
|
|
(define (reset-lib-dirs!)
|
|
(set-lib-dirs! default-lib-dirs))
|
|
|
|
(define (clear-lib-dirs!)
|
|
(set-lib-dirs! '()))
|
|
|
|
(define (lib-dirs-prepend! dir)
|
|
(set-lib-dirs! (cons dir (lib-dirs))))
|
|
|
|
(define (lib-dirs-append! dir)
|
|
(set-lib-dirs! (append (lib-dirs) (list dir))))
|