#!+sb-doc
(setf (fdocumentation '*print-pprint-dispatch* 'variable)
"The pprint-dispatch-table that controls how to pretty-print objects.")
+(defvar *suppress-print-errors* nil
+ #!+sb-doc
+ "Suppress printer errors when the condition is of the type designated by this
+variable: an unreadable object representing the error is printed instead.")
(defmacro with-standard-io-syntax (&body body)
#!+sb-doc
"Bind the reader and printer control variables to values that enable READ
to reliably read the results of PRINT. These values are:
- *PACKAGE* the COMMON-LISP-USER package
- *PRINT-ARRAY* T
- *PRINT-BASE* 10
- *PRINT-CASE* :UPCASE
- *PRINT-CIRCLE* NIL
- *PRINT-ESCAPE* T
- *PRINT-GENSYM* T
- *PRINT-LENGTH* NIL
- *PRINT-LEVEL* NIL
- *PRINT-LINES* NIL
- *PRINT-MISER-WIDTH* NIL
- *PRINT-PPRINT-DISPATCH* the standard pprint dispatch table
- *PRINT-PRETTY* NIL
- *PRINT-RADIX* NIL
- *PRINT-READABLY* T
- *PRINT-RIGHT-MARGIN* NIL
- *READ-BASE* 10
- *READ-DEFAULT-FLOAT-FORMAT* SINGLE-FLOAT
- *READ-EVAL* T
- *READ-SUPPRESS* NIL
- *READTABLE* the standard readtable"
+
+ *PACKAGE* the COMMON-LISP-USER package
+ *PRINT-ARRAY* T
+ *PRINT-BASE* 10
+ *PRINT-CASE* :UPCASE
+ *PRINT-CIRCLE* NIL
+ *PRINT-ESCAPE* T
+ *PRINT-GENSYM* T
+ *PRINT-LENGTH* NIL
+ *PRINT-LEVEL* NIL
+ *PRINT-LINES* NIL
+ *PRINT-MISER-WIDTH* NIL
+ *PRINT-PPRINT-DISPATCH* the standard pprint dispatch table
+ *PRINT-PRETTY* NIL
+ *PRINT-RADIX* NIL
+ *PRINT-READABLY* T
+ *PRINT-RIGHT-MARGIN* NIL
+ *READ-BASE* 10
+ *READ-DEFAULT-FLOAT-FORMAT* SINGLE-FLOAT
+ *READ-EVAL* T
+ *READ-SUPPRESS* NIL
+ *READTABLE* the standard readtable
+ SB-EXT:*SUPPRESS-PRINT-ERRORS* NIL
+"
`(%with-standard-io-syntax (lambda () ,@body)))
(defun %with-standard-io-syntax (function)
(*read-default-float-format* 'single-float)
(*read-eval* t)
(*read-suppress* nil)
- (*readtable* *standard-readtable*))
+ (*readtable* *standard-readtable*)
+ (*suppress-print-errors* nil))
(funcall function)))
\f
;;;; routines to print objects
:right-margin *print-right-margin*
:miser-width *print-miser-width*
:lines *print-lines*
- :pprint-dispatch *print-pprint-dispatch*)))
+ :pprint-dispatch *print-pprint-dispatch*
+ :suppress-errors *suppress-print-errors*)))
(defun write (object &key
((:stream stream) *standard-output*)
*print-miser-width*)
((:lines *print-lines*) *print-lines*)
((:pprint-dispatch *print-pprint-dispatch*)
- *print-pprint-dispatch*))
+ *print-pprint-dispatch*)
+ ((:suppress-errors *suppress-print-errors*)
+ *suppress-print-errors*))
#!+sb-doc
"Output OBJECT to the specified stream, defaulting to *STANDARD-OUTPUT*."
(output-object object (out-synonym-of stream))
((:miser-width *print-miser-width*) *print-miser-width*)
((:lines *print-lines*) *print-lines*)
((:pprint-dispatch *print-pprint-dispatch*)
- *print-pprint-dispatch*))
+ *print-pprint-dispatch*)
+ ((:suppress-errors *suppress-print-errors*)
+ *suppress-print-errors*))
#!+sb-doc
"Return the printed representation of OBJECT as a string."
(stringify-object object))
(and (symbolp x)
(symbol-package x))))
+(defvar *in-print-error* nil)
+
;;; Output OBJECT to STREAM observing all printer control variables.
(defun output-object (object stream)
(labels ((print-it (stream)
(if *print-pretty*
(sb!pretty:output-pretty-object object stream)
(output-ugly-object object stream)))
+ (handle-it (stream)
+ (if *suppress-print-errors*
+ (handler-bind ((condition
+ (lambda (condition) nil
+ (when (typep condition *suppress-print-errors*)
+ (cond (*in-print-error*
+ (write-string "(error printing " stream)
+ (write-string *in-print-error* stream)
+ (write-string ")" stream))
+ (t
+ ;; Give outer handlers a chance.
+ (with-simple-restart
+ (continue "Suppress the error.")
+ (signal condition))
+ (let ((*print-readably* nil)
+ (*print-escape* t))
+ (write-string
+ "#<error printing a " stream)
+ (let ((*in-print-error* "type"))
+ (output-object (type-of object) stream))
+ (write-string ": " stream)
+ (let ((*in-print-error* "condition"))
+ (output-object condition stream))
+ (write-string ">" stream))))
+ (return-from handle-it object)))))
+ (print-it stream))
+ (print-it stream)))
(check-it (stream)
(multiple-value-bind (marker initiate)
(check-for-circularity object t)
;; otherwise
(if marker
(when (handle-circularity marker stream)
- (print-it stream))
- (print-it stream))))))
+ (handle-it stream))
+ (handle-it stream))))))
(cond (;; Maybe we don't need to bother with circularity detection.
(or (not *print-circle*)
(uniquely-identified-by-print-p object))
- (print-it stream))
+ (handle-it stream))
(;; If we have already started circularity detection, this
;; object might be a shared reference. If we have not, then
;; if it is a compound object it might contain a circular
(compound-object-p object))
(check-it stream))
(t
- (print-it stream)))))
+ (handle-it stream)))))
;;; a hack to work around recurring gotchas with printing while
;;; DEFGENERIC PRINT-OBJECT is being built