@end example
@end deffn
-@deffn procedure error:file-operation-error filename verb noun reason operator operands
+@deffn procedure error:file-operation index verb noun reason operator operands
This procedure signals a condition of type
-@code{condition-type:file-operation-error}. The fields of the condition
-are filled in from the corresponding arguments to the procedure.
+@code{condition-type:file-operation-error}. The fields of the
+condition are filled in from the corresponding arguments to the
+procedure, except that the filename is taken as the @var{index}th
+element of @var{operands}.
@end deffn
@deffn {condition type} condition-type:derived-file-error filename condition
(file-namestring pathname)
" > "
(->namestring temporary)))))
- (error:file-operation pathname
+ (error:file-operation 0
program
"file"
"[unknown]"
(string-append (quote-program program arguments)
" > "
(file-namestring pathname)))))
- (error:file-operation pathname
+ (error:file-operation 1
program
"file"
"[unknown]"
(file-namestring pathname)
" > "
(->namestring temporary)))))
- (error:file-operation pathname
+ (error:file-operation 0
program
"file"
"[unknown]"
(string-append program
" > "
(file-namestring pathname)))))
- (error:file-operation pathname
+ (error:file-operation 1
program
"file"
"[unknown]"
(if (file-exists-direct? pathname)
pathname
(dos/pathname->truename
- (error:file-operation pathname "find" "file" "file does not exist"
+ (error:file-operation 0 "find" "file" "file does not exist"
dos/pathname->truename (list pathname)))))
(define (dos/user-homedir-pathname host)
(signal-condition condition)
(default-handler condition)))))))
\f
-;; This is similar to condition-signaller, but error procedures
-;; created with this allow substitution of the INDEXth argument by
-;; using the USE-VALUE restart and allow retrying the operation by
-;; using the RETRY restart. The RETRY restart will return the
-;; original irritant, while USE-VALUE will return a value prompted for.
-
-(define (substitutable-value-condition-signaller
- type field-names default-handler
- index use-value-prompt use-value-message retry-message)
- (guarantee-condition-handler default-handler
- 'substitutable-value-condition-signaller)
- (let ((make-condition (condition-constructor type field-names))
- (arity (length field-names)))
- (letrec
- ((constructor
- (lambda field-values
- (if (not (fix:= arity (length field-values)))
- (error:wrong-number-of-arguments constructor
- arity
- field-values))
- (call-with-current-continuation
- (lambda (continuation)
- (let ((condition
- (apply make-condition
- (cons* continuation
- 'bound-restarts
- field-values))))
- (with-restart 'use-value
- (if (string? use-value-message)
- use-value-message
- (use-value-message condition))
- continuation
- (let ((prompt
- (if (string? use-value-prompt)
- use-value-prompt
- (use-value-prompt condition))))
- (lambda ()
- (values (prompt-for-evaluated-expression prompt))))
- (lambda ()
- (with-restart 'retry
- (if (string? retry-message)
- retry-message
- (retry-message condition))
- (lambda ()
- (continuation (list-ref field-values index)))
- values
- (lambda ()
- (signal-condition condition)
- (default-handler condition)))))))))))
- constructor)))
+;;;; File operation errors
+
+(define (error:file-operation index verb noun reason operator operands)
+ (call-with-current-continuation
+ (lambda (continuation)
+ (signal-file-operation continuation index verb noun reason
+ operator operands))))
+
+(define (signal-file-operation continuation index verb noun reason
+ operator operands)
+ (with-restart 'use-value
+ (string-append "New " noun
+ " name (an expression to be evaluated)")
+ (lambda (operand)
+ (within-continuation continuation
+ (lambda ()
+ (apply operator
+ (receive (head tail) (split-at operands index)
+ (append! head
+ (cons operand (cdr tail))))))))
+ (let ((prompt
+ (string-append "Try to " verb " a different " noun
+ ".")))
+ (lambda ()
+ (values (prompt-for-evaluated-expression prompt))))
+ (lambda ()
+ (with-restart 'retry
+ (string-append "Try to " verb " the same " noun
+ " again.")
+ (lambda ()
+ (within-continuation continuation
+ (lambda ()
+ (apply operator operands))))
+ values
+ (lambda ()
+ (let ((condition
+ (make-file-operation-error continuation 'bound-restarts
+ (list-ref operands index)
+ verb noun reason
+ operator operands)))
+ (signal-condition condition)
+ (standard-error-handler condition)))))))
\f
;;;; Basic Condition Types
(define make-simple-error)
(define make-simple-warning)
+(define make-file-operation-error)
(define error:bad-range-argument)
(define error:datum-out-of-range)
(define error:divide-by-zero)
-(define error:file-operation)
(define error:no-such-restart)
(define error:derived-file)
(define error:derived-port)
(write-string "No such " port)
(write-string noun port))))
(write-string "." port)))))
- (set! error:file-operation
- (let ((get-verb
- (condition-accessor condition-type:file-operation-error 'verb))
- (get-noun
- (condition-accessor condition-type:file-operation-error 'noun)))
- (substitutable-value-condition-signaller
- condition-type:file-operation-error
- '(filename verb noun reason operator operands)
- standard-error-handler
- 0
- (lambda (condition)
- (string-append "New "
- (get-noun condition)
- " name (an expression to be evaluated)"))
- (lambda (condition)
- (string-append "Try to "
- (get-verb condition)
- " a different "
- (get-noun condition)
- "."))
- (lambda (condition)
- (string-append "Try to "
- (get-verb condition)
- " the same "
- (get-noun condition)
- " again.")))))
+ (set! make-file-operation-error
+ (condition-constructor condition-type:file-operation-error
+ '(filename verb noun reason operator operands)))
(set! condition-type:variable-error
(make-condition-type 'variable-error condition-type:cell-error
(define (load-failure procedure pathname . arguments)
(apply procedure
- (error:file-operation pathname
+ (error:file-operation 0
"find" "file" "file does not exist"
procedure
(cons pathname arguments))
thunk)
(thunk))))
-(define (file-operation-signaller)
- (let ((signal
- (condition-signaller condition-type:file-operation-error
- '(filename verb noun reason operator operands))))
- (lambda (continuation operator operands index verb noun reason)
- (file-operation/use-value continuation operator operands index verb noun
- (lambda ()
- (file-operation/retry continuation operator operands verb noun
- (lambda ()
- (signal continuation (list-ref operands index)
- verb noun reason operator operands))))))))
-
-(define (file-operation/use-value continuation operator operands index
- verb noun thunk)
- (let ((continuation (continuation/next-continuation continuation)))
- (if (continuation-restartable? continuation)
- (with-restart 'use-value
- (string-append "Try to " verb " a different " noun ".")
- (lambda (operand)
- (within-continuation continuation
- (lambda ()
- (apply operator
- (substitute-element operands index operand)))))
- (let ((prompt
- (string-append "New "
- noun
- " name (an expression to be evaluated)")))
- (lambda ()
- (values (prompt-for-evaluated-expression prompt))))
- thunk)
- (thunk))))
-
-(define (file-operation/retry continuation operator operands verb noun thunk)
- (let ((continuation (continuation/next-continuation continuation)))
- (if (continuation-restartable? continuation)
- (with-restart 'retry
- (string-append "Try to " verb " the same " noun " again.")
- (lambda ()
- (within-continuation continuation
- (lambda ()
- (apply operator operands))))
- values
- thunk)
- (thunk))))
-
(define (substitute-element list index element)
- (let loop ((list list) (i 0))
- (if (= i index)
- (cons element (cdr list))
- (cons (car list) (loop (cdr list) (+ i 1))))))
+ (receive (head tail) (split-at list index)
+ (append! head
+ (cons element (cdr tail)))))
\f
;;;; Continuation Parsing
(define-error-handler 'out-of-file-handles
(let ((signal
(condition-signaller condition-type:out-of-file-handles
- '(operator operands)))
- (signal-file-operation (file-operation-signaller)))
+ '(operator operands))))
(lambda (continuation)
(let ((frame (continuation/first-subproblem continuation)))
(if (apply-frame? frame)
operator)
(eq? (ucode-primitive new-file-open-append-channel)
operator))
- (signal-file-operation continuation operator operands 0
- "open" "file" "channel table full")
+ (signal-file-operation continuation
+ 0 "open" "file" "channel table full"
+ operator operands)
(signal continuation operator operands))))))))
;++ This should identify the process, but that requires reverse lookup
(define system-call-error-handler
(let ((make-condition
(condition-constructor condition-type:system-call-error
- '(operator operands system-call error-type)))
- (signal-file-operation (file-operation-signaller)))
+ '(operator operands system-call error-type))))
(lambda (continuation error-code)
(let ((frame (continuation/first-subproblem continuation)))
(if (and (apply-frame? frame)
(receive (verb noun)
(file-primitive-description operator)
(if verb
- (signal-file-operation
- continuation operator operands 0 verb noun
- (error-type->string error-type))
+ (signal-file-operation continuation 0 verb noun
+ (error-type->string
+ error-type)
+ operator operands)
(error (make-condition)))))
(else
(error (make-condition)))))))))))
(or (%find-library-file pathname)
(if (if (default-object? required?) #t required?)
(system-library-pathname
- (error:file-operation pathname
+ (error:file-operation 0
"find"
"file"
"no such file in system library path"
((if (default-object? required?) #f required?)
(system-library-directory-pathname
(error:file-operation
- pathname
+ 0
"find"
"directory"
"no such directory in system library path"
(channel-close channel)
(file-open primitive
operator
- (error:file-operation filename "open" "file" reason
+ (error:file-operation 0 "open" "file" reason
operator (list filename))))
channel)))
write-condition-report
write-restart-report)
(export (runtime microcode-errors)
+ signal-file-operation
write-operator)
(export (runtime rep)
param:bound-restarts
(if (file-exists-direct? pathname)
pathname
(unix/pathname->truename
- (error:file-operation pathname "find" "file" "file does not exist"
+ (error:file-operation 0 "find" "file" "file does not exist"
unix/pathname->truename (list pathname)))))
(define (unix/user-homedir-pathname host)
;; relative lookups, either by changing directory just before each
;; lookup or using relative lookup system calls.
(if (not (file-directory? pathname))
- (error:file-operation name "enter" "directory"
+ (error:file-operation 0 "enter" "directory"
(if (file-exists?
(directory-pathname-as-file pathname))
"not a directory"