-(defparameter *module-dirs* nil
- "A list of directories (as pathname designators) to search for files.
-
- Both SOD module files and Lisp extension files are searched for in this
- list. The search works by merging the requested pathname with each
- element of this list in turn. The list is prefixed by the pathname of the
- requesting file, so that it can refer to other files relative to wherever
- it was found.
-
- See FIND-FILE for the grubby details.")
-
-(defun find-file (lexer name what thunk)
- "Find a file called NAME on the module search path, and call THUNK on it.
-
- The file is searched for relative to the LEXER's current file, and also in
- the directories mentioned in the *MODULE-DIRS* list. If the file is
- found, then THUNK is invoked with two arguments: the name we used to find
- it (which might be relative to the starting directory) and the truename
- found by PROBE-FILE.
-
- If the file wasn't found, or there was some kind of error, then an error
- is signalled; WHAT should be a noun phrase describing the kind of thing we
- were looking for, suitable for inclusion in the error message.
-
- While FIND-FILE establishes condition handlers for its own purposes, THUNK
- is not invoked with any additional handlers defined."
-
- (handler-case
- (dolist (dir (cons (stream-pathname (lexer-stream lexer))
- *module-dirs*)
- (values nil nil))
- (let* ((path (merge-pathnames name dir))
- (probe (probe-file path)))
- (when probe
- (return (values path probe)))))
- (file-error (error)
- (error "Error searching for ~A ~S: ~A" what (namestring name) error))
- (:no-error (path probe)
- (cond ((null path)
- (error "Failed to find ~A ~S" what (namestring name)))
- (t
- (funcall thunk path probe))))))