0.8.6.32:
[sbcl.git] / src / code / pprint.lisp
1 ;;;; Common Lisp pretty printer
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!PRETTY")
13 \f
14 ;;;; pretty streams
15
16 ;;; There are three different units for measuring character positions:
17 ;;;  COLUMN - offset (if characters) from the start of the current line
18 ;;;  INDEX  - index into the output buffer
19 ;;;  POSN   - some position in the stream of characters cycling through
20 ;;;           the output buffer
21 (deftype column ()
22   '(and fixnum unsigned-byte))
23 ;;; The INDEX type is picked up from the kernel package.
24 (deftype posn ()
25   'fixnum)
26
27 (defconstant initial-buffer-size 128)
28
29 (defconstant default-line-length 80)
30
31 (defstruct (pretty-stream (:include sb!kernel:ansi-stream
32                                     (out #'pretty-out)
33                                     (sout #'pretty-sout)
34                                     (misc #'pretty-misc))
35                           (:constructor make-pretty-stream (target))
36                           (:copier nil))
37   ;; Where the output is going to finally go.
38   (target (missing-arg) :type stream)
39   ;; Line length we should format to. Cached here so we don't have to keep
40   ;; extracting it from the target stream.
41   (line-length (or *print-right-margin*
42                    (sb!impl::line-length target)
43                    default-line-length)
44                :type column)
45   ;; A simple string holding all the text that has been output but not yet
46   ;; printed.
47   (buffer (make-string initial-buffer-size) :type simple-string)
48   ;; The index into BUFFER where more text should be put.
49   (buffer-fill-pointer 0 :type index)
50   ;; Whenever we output stuff from the buffer, we shift the remaining noise
51   ;; over. This makes it difficult to keep references to locations in
52   ;; the buffer. Therefore, we have to keep track of the total amount of
53   ;; stuff that has been shifted out of the buffer.
54   (buffer-offset 0 :type posn)
55   ;; The column the first character in the buffer will appear in. Normally
56   ;; zero, but if we end up with a very long line with no breaks in it we
57   ;; might have to output part of it. Then this will no longer be zero.
58   (buffer-start-column (or (sb!impl::charpos target) 0) :type column)
59   ;; The line number we are currently on. Used for *PRINT-LINES*
60   ;; abbreviations and to tell when sections have been split across
61   ;; multiple lines.
62   (line-number 0 :type index)
63   ;; the value of *PRINT-LINES* captured at object creation time. We
64   ;; use this, instead of the dynamic *PRINT-LINES*, to avoid
65   ;; weirdness like
66   ;;   (let ((*print-lines* 50))
67   ;;     (pprint-logical-block ..
68   ;;       (dotimes (i 10)
69   ;;         (let ((*print-lines* 8))
70   ;;           (print (aref possiblybigthings i) prettystream)))))
71   ;; terminating the output of the entire logical blockafter 8 lines.
72   (print-lines *print-lines* :type (or index null) :read-only t)
73   ;; Stack of logical blocks in effect at the buffer start.
74   (blocks (list (make-logical-block)) :type list)
75   ;; Buffer holding the per-line prefix active at the buffer start.
76   ;; Indentation is included in this. The length of this is stored
77   ;; in the logical block stack.
78   (prefix (make-string initial-buffer-size) :type simple-string)
79   ;; Buffer holding the total remaining suffix active at the buffer start.
80   ;; The characters are right-justified in the buffer to make it easier
81   ;; to output the buffer. The length is stored in the logical block
82   ;; stack.
83   (suffix (make-string initial-buffer-size) :type simple-string)
84   ;; Queue of pending operations. When empty, HEAD=TAIL=NIL. Otherwise,
85   ;; TAIL holds the first (oldest) cons and HEAD holds the last (newest)
86   ;; cons. Adding things to the queue is basically (setf (cdr head) (list
87   ;; new)) and removing them is basically (pop tail) [except that care must
88   ;; be taken to handle the empty queue case correctly.]
89   (queue-tail nil :type list)
90   (queue-head nil :type list)
91   ;; Block-start queue entries in effect at the queue head.
92   (pending-blocks nil :type list))
93 (def!method print-object ((pstream pretty-stream) stream)
94   ;; FIXME: CMU CL had #+NIL'ed out this code and done a hand-written
95   ;; FORMAT hack instead. Make sure that this code actually works instead
96   ;; of falling into infinite regress or something.
97   (print-unreadable-object (pstream stream :type t :identity t)))
98
99 #!-sb-fluid (declaim (inline index-posn posn-index posn-column))
100 (defun index-posn (index stream)
101   (declare (type index index) (type pretty-stream stream)
102            (values posn))
103   (+ index (pretty-stream-buffer-offset stream)))
104 (defun posn-index (posn stream)
105   (declare (type posn posn) (type pretty-stream stream)
106            (values index))
107   (- posn (pretty-stream-buffer-offset stream)))
108 (defun posn-column (posn stream)
109   (declare (type posn posn) (type pretty-stream stream)
110            (values posn))
111   (index-column (posn-index posn stream) stream))
112
113 ;;; Is it OK to do pretty printing on this stream at this time?
114 (defun print-pretty-on-stream-p (stream)
115   (and (pretty-stream-p stream)
116        *print-pretty*))
117 \f
118 ;;;; stream interface routines
119
120 (defun pretty-out (stream char)
121   (declare (type pretty-stream stream)
122            (type base-char char))
123   (cond ((char= char #\newline)
124          (enqueue-newline stream :literal))
125         (t
126          (ensure-space-in-buffer stream 1)
127          (let ((fill-pointer (pretty-stream-buffer-fill-pointer stream)))
128            (setf (schar (pretty-stream-buffer stream) fill-pointer) char)
129            (setf (pretty-stream-buffer-fill-pointer stream)
130                  (1+ fill-pointer))))))
131
132 (defun pretty-sout (stream string start end)
133   (declare (type pretty-stream stream)
134            (type simple-string string)
135            (type index start)
136            (type (or index null) end))
137   (let ((end (or end (length string))))
138     (unless (= start end)
139       (let ((newline (position #\newline string :start start :end end)))
140         (cond
141          (newline
142           (pretty-sout stream string start newline)
143           (enqueue-newline stream :literal)
144           (pretty-sout stream string (1+ newline) end))
145          (t
146           (let ((chars (- end start)))
147             (loop
148               (let* ((available (ensure-space-in-buffer stream chars))
149                      (count (min available chars))
150                      (fill-pointer (pretty-stream-buffer-fill-pointer stream))
151                      (new-fill-ptr (+ fill-pointer count)))
152                 (replace (pretty-stream-buffer stream)
153                          string
154                          :start1 fill-pointer :end1 new-fill-ptr
155                          :start2 start)
156                 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
157                 (decf chars count)
158                 (when (zerop count)
159                   (return))
160                 (incf start count))))))))))
161
162 (defun pretty-misc (stream op &optional arg1 arg2)
163   (declare (ignore stream op arg1 arg2)))
164 \f
165 ;;;; logical blocks
166
167 (defstruct (logical-block (:copier nil))
168   ;; The column this logical block started in.
169   (start-column 0 :type column)
170   ;; The column the current section started in.
171   (section-column 0 :type column)
172   ;; The length of the per-line prefix. We can't move the indentation
173   ;; left of this.
174   (per-line-prefix-end 0 :type index)
175   ;; The overall length of the prefix, including any indentation.
176   (prefix-length 0 :type index)
177   ;; The overall length of the suffix.
178   (suffix-length 0 :type index)
179   ;; The line number
180   (section-start-line 0 :type index))
181
182 (defun really-start-logical-block (stream column prefix suffix)
183   (let* ((blocks (pretty-stream-blocks stream))
184          (prev-block (car blocks))
185          (per-line-end (logical-block-per-line-prefix-end prev-block))
186          (prefix-length (logical-block-prefix-length prev-block))
187          (suffix-length (logical-block-suffix-length prev-block))
188          (block (make-logical-block
189                  :start-column column
190                  :section-column column
191                  :per-line-prefix-end per-line-end
192                  :prefix-length prefix-length
193                  :suffix-length suffix-length
194                  :section-start-line (pretty-stream-line-number stream))))
195     (setf (pretty-stream-blocks stream) (cons block blocks))
196     (set-indentation stream column)
197     (when prefix
198       (setf (logical-block-per-line-prefix-end block) column)
199       (replace (pretty-stream-prefix stream) prefix
200                :start1 (- column (length prefix)) :end1 column))
201     (when suffix
202       (let* ((total-suffix (pretty-stream-suffix stream))
203              (total-suffix-len (length total-suffix))
204              (additional (length suffix))
205              (new-suffix-len (+ suffix-length additional)))
206         (when (> new-suffix-len total-suffix-len)
207           (let ((new-total-suffix-len
208                  (max (* total-suffix-len 2)
209                       (+ suffix-length
210                          (floor (* additional 5) 4)))))
211             (setf total-suffix
212                   (replace (make-string new-total-suffix-len) total-suffix
213                            :start1 (- new-total-suffix-len suffix-length)
214                            :start2 (- total-suffix-len suffix-length)))
215             (setf total-suffix-len new-total-suffix-len)
216             (setf (pretty-stream-suffix stream) total-suffix)))
217         (replace total-suffix suffix
218                  :start1 (- total-suffix-len new-suffix-len)
219                  :end1 (- total-suffix-len suffix-length))
220         (setf (logical-block-suffix-length block) new-suffix-len))))
221   nil)
222
223 (defun set-indentation (stream column)
224   (let* ((prefix (pretty-stream-prefix stream))
225          (prefix-len (length prefix))
226          (block (car (pretty-stream-blocks stream)))
227          (current (logical-block-prefix-length block))
228          (minimum (logical-block-per-line-prefix-end block))
229          (column (max minimum column)))
230     (when (> column prefix-len)
231       (setf prefix
232             (replace (make-string (max (* prefix-len 2)
233                                        (+ prefix-len
234                                           (floor (* (- column prefix-len) 5)
235                                                  4))))
236                      prefix
237                      :end1 current))
238       (setf (pretty-stream-prefix stream) prefix))
239     (when (> column current)
240       (fill prefix #\space :start current :end column))
241     (setf (logical-block-prefix-length block) column)))
242
243 (defun really-end-logical-block (stream)
244   (let* ((old (pop (pretty-stream-blocks stream)))
245          (old-indent (logical-block-prefix-length old))
246          (new (car (pretty-stream-blocks stream)))
247          (new-indent (logical-block-prefix-length new)))
248     (when (> new-indent old-indent)
249       (fill (pretty-stream-prefix stream) #\space
250             :start old-indent :end new-indent)))
251   nil)
252 \f
253 ;;;; the pending operation queue
254
255 (defstruct (queued-op (:constructor nil)
256                       (:copier nil))
257   (posn 0 :type posn))
258
259 (defmacro enqueue (stream type &rest args)
260   (let ((constructor (symbolicate "MAKE-" type)))
261     (once-only ((stream stream)
262                 (entry `(,constructor :posn
263                                       (index-posn
264                                        (pretty-stream-buffer-fill-pointer
265                                         ,stream)
266                                        ,stream)
267                                       ,@args))
268                 (op `(list ,entry))
269                 (head `(pretty-stream-queue-head ,stream)))
270       `(progn
271          (if ,head
272              (setf (cdr ,head) ,op)
273              (setf (pretty-stream-queue-tail ,stream) ,op))
274          (setf (pretty-stream-queue-head ,stream) ,op)
275          ,entry))))
276
277 (defstruct (section-start (:include queued-op)
278                           (:constructor nil)
279                           (:copier nil))
280   (depth 0 :type index)
281   (section-end nil :type (or null newline block-end)))
282
283 (defstruct (newline (:include section-start)
284                     (:copier nil))
285   (kind (missing-arg)
286         :type (member :linear :fill :miser :literal :mandatory)))
287
288 (defun enqueue-newline (stream kind)
289   (let* ((depth (length (pretty-stream-pending-blocks stream)))
290          (newline (enqueue stream newline :kind kind :depth depth)))
291     (dolist (entry (pretty-stream-queue-tail stream))
292       (when (and (not (eq newline entry))
293                  (section-start-p entry)
294                  (null (section-start-section-end entry))
295                  (<= depth (section-start-depth entry)))
296         (setf (section-start-section-end entry) newline))))
297   (maybe-output stream (or (eq kind :literal) (eq kind :mandatory))))
298
299 (defstruct (indentation (:include queued-op)
300                         (:copier nil))
301   (kind (missing-arg) :type (member :block :current))
302   (amount 0 :type fixnum))
303
304 (defun enqueue-indent (stream kind amount)
305   (enqueue stream indentation :kind kind :amount amount))
306
307 (defstruct (block-start (:include section-start)
308                         (:copier nil))
309   (block-end nil :type (or null block-end))
310   (prefix nil :type (or null simple-string))
311   (suffix nil :type (or null simple-string)))
312
313 (defun start-logical-block (stream prefix per-line-p suffix)
314   ;; (In the PPRINT-LOGICAL-BLOCK form which calls us,
315   ;; :PREFIX and :PER-LINE-PREFIX have hairy defaulting behavior,
316   ;; and might end up being NIL.)
317   (declare (type (or null string) prefix))
318   ;; (But the defaulting behavior of PPRINT-LOGICAL-BLOCK :SUFFIX is
319   ;; trivial, so it should always be a string.)
320   (declare (type string suffix))
321   (when prefix
322     (setq prefix (coerce prefix 'simple-string))
323     (pretty-sout stream prefix 0 (length prefix)))
324   (let* ((pending-blocks (pretty-stream-pending-blocks stream))
325          (start (enqueue stream block-start
326                          :prefix (and per-line-p prefix)
327                          :suffix (coerce suffix 'simple-string)
328                          :depth (length pending-blocks))))
329     (setf (pretty-stream-pending-blocks stream)
330           (cons start pending-blocks))))
331
332 (defstruct (block-end (:include queued-op)
333                       (:copier nil))
334   (suffix nil :type (or null simple-string)))
335
336 (defun end-logical-block (stream)
337   (let* ((start (pop (pretty-stream-pending-blocks stream)))
338          (suffix (block-start-suffix start))
339          (end (enqueue stream block-end :suffix suffix)))
340     (when suffix
341       (pretty-sout stream suffix 0 (length suffix)))
342     (setf (block-start-block-end start) end)))
343
344 (defstruct (tab (:include queued-op)
345                 (:copier nil))
346   (sectionp nil :type (member t nil))
347   (relativep nil :type (member t nil))
348   (colnum 0 :type column)
349   (colinc 0 :type column))
350
351 (defun enqueue-tab (stream kind colnum colinc)
352   (multiple-value-bind (sectionp relativep)
353       (ecase kind
354         (:line (values nil nil))
355         (:line-relative (values nil t))
356         (:section (values t nil))
357         (:section-relative (values t t)))
358     (enqueue stream tab :sectionp sectionp :relativep relativep
359              :colnum colnum :colinc colinc)))
360 \f
361 ;;;; tab support
362
363 (defun compute-tab-size (tab section-start column)
364   (let ((origin (if (tab-sectionp tab) section-start 0))
365         (colnum (tab-colnum tab))
366         (colinc (tab-colinc tab)))
367     (cond ((tab-relativep tab)
368            (unless (<= colinc 1)
369              (let ((newposn (+ column colnum)))
370                (let ((rem (rem newposn colinc)))
371                  (unless (zerop rem)
372                    (incf colnum (- colinc rem))))))
373            colnum)
374           ((<= column (+ colnum origin))
375            (- (+ colnum origin) column))
376           (t
377            (- colinc
378               (rem (- column origin) colinc))))))
379
380 (defun index-column (index stream)
381   (let ((column (pretty-stream-buffer-start-column stream))
382         (section-start (logical-block-section-column
383                         (first (pretty-stream-blocks stream))))
384         (end-posn (index-posn index stream)))
385     (dolist (op (pretty-stream-queue-tail stream))
386       (when (>= (queued-op-posn op) end-posn)
387         (return))
388       (typecase op
389         (tab
390          (incf column
391                (compute-tab-size op
392                                  section-start
393                                  (+ column
394                                     (posn-index (tab-posn op)
395                                                     stream)))))
396         ((or newline block-start)
397          (setf section-start
398                (+ column (posn-index (queued-op-posn op)
399                                          stream))))))
400     (+ column index)))
401
402 (defun expand-tabs (stream through)
403   (let ((insertions nil)
404         (additional 0)
405         (column (pretty-stream-buffer-start-column stream))
406         (section-start (logical-block-section-column
407                         (first (pretty-stream-blocks stream)))))
408     (dolist (op (pretty-stream-queue-tail stream))
409       (typecase op
410         (tab
411          (let* ((index (posn-index (tab-posn op) stream))
412                 (tabsize (compute-tab-size op
413                                            section-start
414                                            (+ column index))))
415            (unless (zerop tabsize)
416              (push (cons index tabsize) insertions)
417              (incf additional tabsize)
418              (incf column tabsize))))
419         ((or newline block-start)
420          (setf section-start
421                (+ column (posn-index (queued-op-posn op) stream)))))
422       (when (eq op through)
423         (return)))
424     (when insertions
425       (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
426              (new-fill-ptr (+ fill-ptr additional))
427              (buffer (pretty-stream-buffer stream))
428              (new-buffer buffer)
429              (length (length buffer))
430              (end fill-ptr))
431         (when (> new-fill-ptr length)
432           (let ((new-length (max (* length 2)
433                                  (+ fill-ptr
434                                     (floor (* additional 5) 4)))))
435             (setf new-buffer (make-string new-length))
436             (setf (pretty-stream-buffer stream) new-buffer)))
437         (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
438         (decf (pretty-stream-buffer-offset stream) additional)
439         (dolist (insertion insertions)
440           (let* ((srcpos (car insertion))
441                  (amount (cdr insertion))
442                  (dstpos (+ srcpos additional)))
443             (replace new-buffer buffer :start1 dstpos :start2 srcpos :end2 end)
444             (fill new-buffer #\space :start (- dstpos amount) :end dstpos)
445             (decf additional amount)
446             (setf end srcpos)))
447         (unless (eq new-buffer buffer)
448           (replace new-buffer buffer :end1 end :end2 end))))))
449 \f
450 ;;;; stuff to do the actual outputting
451
452 (defun ensure-space-in-buffer (stream want)
453   (declare (type pretty-stream stream)
454            (type index want))
455   (let* ((buffer (pretty-stream-buffer stream))
456          (length (length buffer))
457          (fill-ptr (pretty-stream-buffer-fill-pointer stream))
458          (available (- length fill-ptr)))
459     (cond ((plusp available)
460            available)
461           ((> fill-ptr (pretty-stream-line-length stream))
462            (unless (maybe-output stream nil)
463              (output-partial-line stream))
464            (ensure-space-in-buffer stream want))
465           (t
466            (let* ((new-length (max (* length 2)
467                                    (+ length
468                                       (floor (* want 5) 4))))
469                   (new-buffer (make-string new-length)))
470              (setf (pretty-stream-buffer stream) new-buffer)
471              (replace new-buffer buffer :end1 fill-ptr)
472              (- new-length fill-ptr))))))
473
474 (defun maybe-output (stream force-newlines-p)
475   (declare (type pretty-stream stream))
476   (let ((tail (pretty-stream-queue-tail stream))
477         (output-anything nil))
478     (loop
479       (unless tail
480         (setf (pretty-stream-queue-head stream) nil)
481         (return))
482       (let ((next (pop tail)))
483         (etypecase next
484           (newline
485            (when (ecase (newline-kind next)
486                    ((:literal :mandatory :linear) t)
487                    (:miser (misering-p stream))
488                    (:fill
489                     (or (misering-p stream)
490                         (> (pretty-stream-line-number stream)
491                            (logical-block-section-start-line
492                             (first (pretty-stream-blocks stream))))
493                         (ecase (fits-on-line-p stream
494                                                (newline-section-end next)
495                                                force-newlines-p)
496                           ((t) nil)
497                           ((nil) t)
498                           (:dont-know
499                            (return))))))
500              (setf output-anything t)
501              (output-line stream next)))
502           (indentation
503            (unless (misering-p stream)
504              (set-indentation stream
505                               (+ (ecase (indentation-kind next)
506                                    (:block
507                                     (logical-block-start-column
508                                      (car (pretty-stream-blocks stream))))
509                                    (:current
510                                     (posn-column
511                                      (indentation-posn next)
512                                      stream)))
513                                  (indentation-amount next)))))
514           (block-start
515            (ecase (fits-on-line-p stream (block-start-section-end next)
516                                   force-newlines-p)
517              ((t)
518               ;; Just nuke the whole logical block and make it look
519               ;; like one nice long literal.
520               (let ((end (block-start-block-end next)))
521                 (expand-tabs stream end)
522                 (setf tail (cdr (member end tail)))))
523              ((nil)
524               (really-start-logical-block
525                stream
526                (posn-column (block-start-posn next) stream)
527                (block-start-prefix next)
528                (block-start-suffix next)))
529              (:dont-know
530               (return))))
531           (block-end
532            (really-end-logical-block stream))
533           (tab
534            (expand-tabs stream next))))
535       (setf (pretty-stream-queue-tail stream) tail))
536     output-anything))
537
538 (defun misering-p (stream)
539   (declare (type pretty-stream stream))
540   (and *print-miser-width*
541        (<= (- (pretty-stream-line-length stream)
542               (logical-block-start-column (car (pretty-stream-blocks stream))))
543            *print-miser-width*)))
544
545 (defun fits-on-line-p (stream until force-newlines-p)
546   (let ((available (pretty-stream-line-length stream)))
547     (when (and (not *print-readably*)
548                (pretty-stream-print-lines stream)
549                (= (pretty-stream-print-lines stream)
550                   (pretty-stream-line-number stream)))
551       (decf available 3) ; for the `` ..''
552       (decf available (logical-block-suffix-length
553                        (car (pretty-stream-blocks stream)))))
554     (cond (until
555            (<= (posn-column (queued-op-posn until) stream) available))
556           (force-newlines-p nil)
557           ((> (index-column (pretty-stream-buffer-fill-pointer stream) stream)
558               available)
559            nil)
560           (t
561            :dont-know))))
562
563 (defun output-line (stream until)
564   (declare (type pretty-stream stream)
565            (type newline until))
566   (let* ((target (pretty-stream-target stream))
567          (buffer (pretty-stream-buffer stream))
568          (kind (newline-kind until))
569          (literal-p (eq kind :literal))
570          (amount-to-consume (posn-index (newline-posn until) stream))
571          (amount-to-print
572           (if literal-p
573               amount-to-consume
574               (let ((last-non-blank
575                      (position #\space buffer :end amount-to-consume
576                                :from-end t :test #'char/=)))
577                 (if last-non-blank
578                     (1+ last-non-blank)
579                     0)))))
580     (write-string buffer target :end amount-to-print)
581     (let ((line-number (pretty-stream-line-number stream)))
582       (incf line-number)
583       (when (and (not *print-readably*)
584                  (pretty-stream-print-lines stream)
585                  (>= line-number (pretty-stream-print-lines stream)))
586         (write-string " .." target)
587         (let ((suffix-length (logical-block-suffix-length
588                               (car (pretty-stream-blocks stream)))))
589           (unless (zerop suffix-length)
590             (let* ((suffix (pretty-stream-suffix stream))
591                    (len (length suffix)))
592               (write-string suffix target
593                             :start (- len suffix-length)
594                             :end len))))
595         (throw 'line-limit-abbreviation-happened t))
596       (setf (pretty-stream-line-number stream) line-number)
597       (write-char #\newline target)
598       (setf (pretty-stream-buffer-start-column stream) 0)
599       (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
600              (block (first (pretty-stream-blocks stream)))
601              (prefix-len
602               (if literal-p
603                   (logical-block-per-line-prefix-end block)
604                   (logical-block-prefix-length block)))
605              (shift (- amount-to-consume prefix-len))
606              (new-fill-ptr (- fill-ptr shift))
607              (new-buffer buffer)
608              (buffer-length (length buffer)))
609         (when (> new-fill-ptr buffer-length)
610           (setf new-buffer
611                 (make-string (max (* buffer-length 2)
612                                   (+ buffer-length
613                                      (floor (* (- new-fill-ptr buffer-length)
614                                                5)
615                                             4)))))
616           (setf (pretty-stream-buffer stream) new-buffer))
617         (replace new-buffer buffer
618                  :start1 prefix-len :start2 amount-to-consume :end2 fill-ptr)
619         (replace new-buffer (pretty-stream-prefix stream)
620                  :end1 prefix-len)
621         (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
622         (incf (pretty-stream-buffer-offset stream) shift)
623         (unless literal-p
624           (setf (logical-block-section-column block) prefix-len)
625           (setf (logical-block-section-start-line block) line-number))))))
626
627 (defun output-partial-line (stream)
628   (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
629          (tail (pretty-stream-queue-tail stream))
630          (count
631           (if tail
632               (posn-index (queued-op-posn (car tail)) stream)
633               fill-ptr))
634          (new-fill-ptr (- fill-ptr count))
635          (buffer (pretty-stream-buffer stream)))
636     (when (zerop count)
637       (error "Output-partial-line called when nothing can be output."))
638     (write-string buffer (pretty-stream-target stream)
639                   :start 0 :end count)
640     (incf (pretty-stream-buffer-start-column stream) count)
641     (replace buffer buffer :end1 new-fill-ptr :start2 count :end2 fill-ptr)
642     (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
643     (incf (pretty-stream-buffer-offset stream) count)))
644
645 (defun force-pretty-output (stream)
646   (maybe-output stream nil)
647   (expand-tabs stream nil)
648   (write-string (pretty-stream-buffer stream)
649                 (pretty-stream-target stream)
650                 :end (pretty-stream-buffer-fill-pointer stream)))
651 \f
652 ;;;; user interface to the pretty printer
653
654 (defun pprint-newline (kind &optional stream)
655   #!+sb-doc
656   "Output a conditional newline to STREAM (which defaults to
657    *STANDARD-OUTPUT*) if it is a pretty-printing stream, and do
658    nothing if not. KIND can be one of:
659      :LINEAR - A line break is inserted if and only if the immediatly
660         containing section cannot be printed on one line.
661      :MISER - Same as LINEAR, but only if ``miser-style'' is in effect.
662         (See *PRINT-MISER-WIDTH*.)
663      :FILL - A line break is inserted if and only if either:
664        (a) the following section cannot be printed on the end of the
665            current line,
666        (b) the preceding section was not printed on a single line, or
667        (c) the immediately containing section cannot be printed on one
668            line and miser-style is in effect.
669      :MANDATORY - A line break is always inserted.
670    When a line break is inserted by any type of conditional newline, any
671    blanks that immediately precede the conditional newline are ommitted
672    from the output and indentation is introduced at the beginning of the
673    next line. (See PPRINT-INDENT.)"
674   (declare (type (member :linear :miser :fill :mandatory) kind)
675            (type (or stream (member t nil)) stream)
676            (values null))
677   (let ((stream (case stream
678                   ((t) *terminal-io*)
679                   ((nil) *standard-output*)
680                   (t stream))))
681     (when (print-pretty-on-stream-p stream)
682       (enqueue-newline stream kind)))
683   nil)
684
685 (defun pprint-indent (relative-to n &optional stream)
686   #!+sb-doc
687   "Specify the indentation to use in the current logical block if STREAM
688    (which defaults to *STANDARD-OUTPUT*) is it is a pretty-printing stream
689    and do nothing if not. (See PPRINT-LOGICAL-BLOCK.)  N is the indention
690    to use (in ems, the width of an ``m'') and RELATIVE-TO can be either:
691      :BLOCK - Indent relative to the column the current logical block
692         started on.
693      :CURRENT - Indent relative to the current column.
694    The new indention value does not take effect until the following line
695    break."
696   (declare (type (member :block :current) relative-to)
697            (type integer n)
698            (type (or stream (member t nil)) stream)
699            (values null))
700   (let ((stream (case stream
701                   ((t) *terminal-io*)
702                   ((nil) *standard-output*)
703                   (t stream))))
704     (when (print-pretty-on-stream-p stream)
705       (enqueue-indent stream relative-to n)))
706   nil)
707
708 (defun pprint-tab (kind colnum colinc &optional stream)
709   #!+sb-doc
710   "If STREAM (which defaults to *STANDARD-OUTPUT*) is a pretty-printing
711    stream, perform tabbing based on KIND, otherwise do nothing. KIND can
712    be one of:
713      :LINE - Tab to column COLNUM. If already past COLNUM tab to the next
714        multiple of COLINC.
715      :SECTION - Same as :LINE, but count from the start of the current
716        section, not the start of the line.
717      :LINE-RELATIVE - Output COLNUM spaces, then tab to the next multiple of
718        COLINC.
719      :SECTION-RELATIVE - Same as :LINE-RELATIVE, but count from the start
720        of the current section, not the start of the line."
721   (declare (type (member :line :section :line-relative :section-relative) kind)
722            (type unsigned-byte colnum colinc)
723            (type (or stream (member t nil)) stream)
724            (values null))
725   (let ((stream (case stream
726                   ((t) *terminal-io*)
727                   ((nil) *standard-output*)
728                   (t stream))))
729     (when (print-pretty-on-stream-p stream)
730       (enqueue-tab stream kind colnum colinc)))
731   nil)
732
733 (defun pprint-fill (stream list &optional (colon? t) atsign?)
734   #!+sb-doc
735   "Output LIST to STREAM putting :FILL conditional newlines between each
736    element. If COLON? is NIL (defaults to T), then no parens are printed
737    around the output. ATSIGN? is ignored (but allowed so that PPRINT-FILL
738    can be used with the ~/.../ format directive."
739   (declare (ignore atsign?))
740   (pprint-logical-block (stream list
741                                 :prefix (if colon? "(" "")
742                                 :suffix (if colon? ")" ""))
743     (pprint-exit-if-list-exhausted)
744     (loop
745       (output-object (pprint-pop) stream)
746       (pprint-exit-if-list-exhausted)
747       (write-char #\space stream)
748       (pprint-newline :fill stream))))
749
750 (defun pprint-linear (stream list &optional (colon? t) atsign?)
751   #!+sb-doc
752   "Output LIST to STREAM putting :LINEAR conditional newlines between each
753    element. If COLON? is NIL (defaults to T), then no parens are printed
754    around the output. ATSIGN? is ignored (but allowed so that PPRINT-LINEAR
755    can be used with the ~/.../ format directive."
756   (declare (ignore atsign?))
757   (pprint-logical-block (stream list
758                                 :prefix (if colon? "(" "")
759                                 :suffix (if colon? ")" ""))
760     (pprint-exit-if-list-exhausted)
761     (loop
762       (output-object (pprint-pop) stream)
763       (pprint-exit-if-list-exhausted)
764       (write-char #\space stream)
765       (pprint-newline :linear stream))))
766
767 (defun pprint-tabular (stream list &optional (colon? t) atsign? tabsize)
768   #!+sb-doc
769   "Output LIST to STREAM tabbing to the next column that is an even multiple
770    of TABSIZE (which defaults to 16) between each element. :FILL style
771    conditional newlines are also output between each element. If COLON? is
772    NIL (defaults to T), then no parens are printed around the output.
773    ATSIGN? is ignored (but allowed so that PPRINT-TABULAR can be used with
774    the ~/.../ format directive."
775   (declare (ignore atsign?))
776   (pprint-logical-block (stream list
777                                 :prefix (if colon? "(" "")
778                                 :suffix (if colon? ")" ""))
779     (pprint-exit-if-list-exhausted)
780     (loop
781       (output-object (pprint-pop) stream)
782       (pprint-exit-if-list-exhausted)
783       (write-char #\space stream)
784       (pprint-tab :section-relative 0 (or tabsize 16) stream)
785       (pprint-newline :fill stream))))
786 \f
787 ;;;; pprint-dispatch tables
788
789 (defvar *initial-pprint-dispatch*)
790 (defvar *building-initial-table* nil)
791
792 (defstruct (pprint-dispatch-entry (:copier nil))
793   ;; the type specifier for this entry
794   (type (missing-arg) :type t)
795   ;; a function to test to see whether an object is of this time.
796   ;; Pretty must just (LAMBDA (OBJ) (TYPEP OBJECT TYPE)) except that
797   ;; we handle the CONS type specially so that (CONS (MEMBER FOO))
798   ;; works. We don't bother computing this for entries in the CONS
799   ;; hash table, because we don't need it.
800   (test-fn nil :type (or function null))
801   ;; the priority for this guy
802   (priority 0 :type real)
803   ;; T iff one of the original entries.
804   (initial-p *building-initial-table* :type (member t nil))
805   ;; and the associated function
806   (fun (missing-arg) :type function))
807 (def!method print-object ((entry pprint-dispatch-entry) stream)
808   (print-unreadable-object (entry stream :type t)
809     (format stream "type=~S, priority=~S~@[ [initial]~]"
810             (pprint-dispatch-entry-type entry)
811             (pprint-dispatch-entry-priority entry)
812             (pprint-dispatch-entry-initial-p entry))))
813
814 (defstruct (pprint-dispatch-table (:copier nil))
815   ;; A list of all the entries (except for CONS entries below) in highest
816   ;; to lowest priority.
817   (entries nil :type list)
818   ;; A hash table mapping things to entries for type specifiers of the
819   ;; form (CONS (MEMBER <thing>)). If the type specifier is of this form,
820   ;; we put it in this hash table instead of the regular entries table.
821   (cons-entries (make-hash-table :test 'eql)))
822 (def!method print-object ((table pprint-dispatch-table) stream)
823   (print-unreadable-object (table stream :type t :identity t)))
824
825 (defun cons-type-specifier-p (spec)
826   (and (consp spec)
827        (eq (car spec) 'cons)
828        (cdr spec)
829        (null (cddr spec))
830        (let ((car (cadr spec)))
831          (and (consp car)
832               (let ((carcar (car car)))
833                 (or (eq carcar 'member)
834                     (eq carcar 'eql)))
835               (cdr car)
836               (null (cddr car))))))
837
838 (defun entry< (e1 e2)
839   (declare (type pprint-dispatch-entry e1 e2))
840   (if (pprint-dispatch-entry-initial-p e1)
841       (if (pprint-dispatch-entry-initial-p e2)
842           (< (pprint-dispatch-entry-priority e1)
843              (pprint-dispatch-entry-priority e2))
844           t)
845       (if (pprint-dispatch-entry-initial-p e2)
846           nil
847           (< (pprint-dispatch-entry-priority e1)
848              (pprint-dispatch-entry-priority e2)))))
849
850 (macrolet ((frob (x)
851              `(cons ',x (lambda (object) ,x))))
852   (defvar *precompiled-pprint-dispatch-funs*
853     (list (frob (typep object 'array))
854           (frob (and (consp object)
855                      (symbolp (car object))
856                      (fboundp (car object))))
857           (frob (typep object 'cons)))))
858
859 (defun compute-test-fn (type)
860   (let ((was-cons nil))
861     (labels ((compute-test-expr (type object)
862                (if (listp type)
863                    (case (car type)
864                      (cons
865                       (setq was-cons t)
866                       (destructuring-bind
867                           (&optional (car nil car-p) (cdr nil cdr-p))
868                           (cdr type)
869                         `(and (consp ,object)
870                               ,@(when car-p
871                                   `(,(compute-test-expr
872                                       car `(car ,object))))
873                               ,@(when cdr-p
874                                   `(,(compute-test-expr
875                                       cdr `(cdr ,object)))))))
876                      (not
877                       (destructuring-bind (type) (cdr type)
878                         `(not ,(compute-test-expr type object))))
879                      (and
880                       `(and ,@(mapcar (lambda (type)
881                                         (compute-test-expr type object))
882                                       (cdr type))))
883                      (or
884                       `(or ,@(mapcar (lambda (type)
885                                        (compute-test-expr type object))
886                                      (cdr type))))
887                      (t
888                       `(typep ,object ',type)))
889                    `(typep ,object ',type))))
890       (let ((expr (compute-test-expr type 'object)))
891         (cond ((cdr (assoc expr *precompiled-pprint-dispatch-funs*
892                            :test #'equal)))
893               (t
894                (compile nil `(lambda (object) ,expr))))))))
895
896 (defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*))
897   (declare (type (or pprint-dispatch-table null) table))
898   (let* ((orig (or table *initial-pprint-dispatch*))
899          (new (make-pprint-dispatch-table
900                :entries (copy-list (pprint-dispatch-table-entries orig))))
901          (new-cons-entries (pprint-dispatch-table-cons-entries new)))
902     (maphash (lambda (key value)
903                (setf (gethash key new-cons-entries) value))
904              (pprint-dispatch-table-cons-entries orig))
905     new))
906
907 (defun pprint-dispatch (object &optional (table *print-pprint-dispatch*))
908   (declare (type (or pprint-dispatch-table null) table))
909   (let* ((table (or table *initial-pprint-dispatch*))
910          (cons-entry
911           (and (consp object)
912                (gethash (car object)
913                         (pprint-dispatch-table-cons-entries table))))
914          (entry
915           (dolist (entry (pprint-dispatch-table-entries table) cons-entry)
916             (when (and cons-entry
917                        (entry< entry cons-entry))
918               (return cons-entry))
919             (when (funcall (pprint-dispatch-entry-test-fn entry) object)
920               (return entry)))))
921     (if entry
922         (values (pprint-dispatch-entry-fun entry) t)
923         (values (lambda (stream object)
924                   (output-ugly-object object stream))
925                 nil))))
926
927 (defun set-pprint-dispatch (type function &optional
928                             (priority 0) (table *print-pprint-dispatch*))
929   (declare (type (or null function) function)
930            (type real priority)
931            (type pprint-dispatch-table table))
932   (/show0 "entering SET-PPRINT-DISPATCH, TYPE=...")
933   (/hexstr type)
934   (if function
935       (if (cons-type-specifier-p type)
936           (setf (gethash (second (second type))
937                          (pprint-dispatch-table-cons-entries table))
938                 (make-pprint-dispatch-entry :type type
939                                             :priority priority
940                                             :fun function))
941           (let ((list (delete type (pprint-dispatch-table-entries table)
942                               :key #'pprint-dispatch-entry-type
943                               :test #'equal))
944                 (entry (make-pprint-dispatch-entry
945                         :type type
946                         :test-fn (compute-test-fn type)
947                         :priority priority
948                         :fun function)))
949             (do ((prev nil next)
950                  (next list (cdr next)))
951                 ((null next)
952                  (if prev
953                      (setf (cdr prev) (list entry))
954                      (setf list (list entry))))
955               (when (entry< (car next) entry)
956                 (if prev
957                     (setf (cdr prev) (cons entry next))
958                     (setf list (cons entry next)))
959                 (return)))
960             (setf (pprint-dispatch-table-entries table) list)))
961       (if (cons-type-specifier-p type)
962           (remhash (second (second type))
963                    (pprint-dispatch-table-cons-entries table))
964           (setf (pprint-dispatch-table-entries table)
965                 (delete type (pprint-dispatch-table-entries table)
966                         :key #'pprint-dispatch-entry-type
967                         :test #'equal))))
968   (/show0 "about to return NIL from SET-PPRINT-DISPATCH")
969   nil)
970 \f
971 ;;;; standard pretty-printing routines
972
973 (defun pprint-array (stream array)
974   (cond ((or (and (null *print-array*) (null *print-readably*))
975              (stringp array)
976              (bit-vector-p array))
977          (output-ugly-object array stream))
978         ((and *print-readably*
979               (not (array-readably-printable-p array)))
980          (let ((*print-readably* nil))
981            (error 'print-not-readable :object array)))
982         ((vectorp array)
983          (pprint-vector stream array))
984         (t
985          (pprint-multi-dim-array stream array))))
986
987 (defun pprint-vector (stream vector)
988   (pprint-logical-block (stream nil :prefix "#(" :suffix ")")
989     (dotimes (i (length vector))
990       (unless (zerop i)
991         (format stream " ~:_"))
992       (pprint-pop)
993       (output-object (aref vector i) stream))))
994
995 (defun pprint-multi-dim-array (stream array)
996   (funcall (formatter "#~DA") stream (array-rank array))
997   (with-array-data ((data array) (start) (end))
998     (declare (ignore end))
999     (labels ((output-guts (stream index dimensions)
1000                (if (null dimensions)
1001                    (output-object (aref data index) stream)
1002                    (pprint-logical-block
1003                        (stream nil :prefix "(" :suffix ")")
1004                      (let ((dim (car dimensions)))
1005                        (unless (zerop dim)
1006                          (let* ((dims (cdr dimensions))
1007                                 (index index)
1008                                 (step (reduce #'* dims))
1009                                 (count 0))
1010                            (loop
1011                              (pprint-pop)
1012                              (output-guts stream index dims)
1013                              (when (= (incf count) dim)
1014                                (return))
1015                              (write-char #\space stream)
1016                              (pprint-newline (if dims :linear :fill)
1017                                              stream)
1018                              (incf index step)))))))))
1019       (output-guts stream start (array-dimensions array)))))
1020
1021 (defun pprint-lambda-list (stream lambda-list &rest noise)
1022   (declare (ignore noise))
1023   (when (and (consp lambda-list)
1024              (member (car lambda-list) *backq-tokens*))
1025     ;; if this thing looks like a backquoty thing, then we don't want
1026     ;; to destructure it, we want to output it straight away.  [ this
1027     ;; is the exception to the normal processing: if we did this
1028     ;; generally we would find lambda lists such as (FUNCTION FOO)
1029     ;; being printed as #'FOO ]  -- CSR, 2003-12-07
1030     (output-object lambda-list stream)
1031     (return-from pprint-lambda-list nil))
1032   (pprint-logical-block (stream lambda-list :prefix "(" :suffix ")")
1033     (let ((state :required)
1034           (first t))
1035       (loop
1036         (pprint-exit-if-list-exhausted)
1037         (unless first
1038           (write-char #\space stream))
1039         (let ((arg (pprint-pop)))
1040           (unless first
1041             (case arg
1042               (&optional
1043                (setf state :optional)
1044                (pprint-newline :linear stream))
1045               ((&rest &body)
1046                (setf state :required)
1047                (pprint-newline :linear stream))
1048               (&key
1049                (setf state :key)
1050                (pprint-newline :linear stream))
1051               (&aux
1052                (setf state :optional)
1053                (pprint-newline :linear stream))
1054               (t
1055                (pprint-newline :fill stream))))
1056           (ecase state
1057             (:required
1058              (pprint-lambda-list stream arg))
1059             ((:optional :key)
1060              (pprint-logical-block
1061                  (stream arg :prefix "(" :suffix ")")
1062                (pprint-exit-if-list-exhausted)
1063                (if (eq state :key)
1064                    (pprint-logical-block
1065                        (stream (pprint-pop) :prefix "(" :suffix ")")
1066                      (pprint-exit-if-list-exhausted)
1067                      (output-object (pprint-pop) stream)
1068                      (pprint-exit-if-list-exhausted)
1069                      (write-char #\space stream)
1070                      (pprint-newline :fill stream)
1071                      (pprint-lambda-list stream (pprint-pop))
1072                      (loop
1073                        (pprint-exit-if-list-exhausted)
1074                        (write-char #\space stream)
1075                        (pprint-newline :fill stream)
1076                        (output-object (pprint-pop) stream)))
1077                    (pprint-lambda-list stream (pprint-pop)))
1078                (loop
1079                  (pprint-exit-if-list-exhausted)
1080                  (write-char #\space stream)
1081                  (pprint-newline :linear stream)
1082                  (output-object (pprint-pop) stream))))))
1083         (setf first nil)))))
1084
1085 (defun pprint-lambda (stream list &rest noise)
1086   (declare (ignore noise))
1087   (funcall (formatter
1088             ;; KLUDGE: This format string, and other format strings which also
1089             ;; refer to SB!PRETTY, rely on the current SBCL not-quite-ANSI
1090             ;; behavior of FORMATTER in order to make code which survives the
1091             ;; transition when SB!PRETTY is renamed to SB-PRETTY after cold
1092             ;; init. (ANSI says that the FORMATTER functions should be
1093             ;; equivalent to the format string, but the SBCL FORMATTER
1094             ;; functions contain references to package objects, not package
1095             ;; names, so they keep right on going if the packages are renamed.)
1096             ;; If our FORMATTER behavior is ever made more compliant, the code
1097             ;; here will have to change. -- WHN 19991207
1098             "~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1099            stream
1100            list))
1101
1102 (defun pprint-block (stream list &rest noise)
1103   (declare (ignore noise))
1104   (funcall (formatter "~:<~^~W~^~3I ~:_~W~1I~@{ ~_~W~}~:>") stream list))
1105
1106 (defun pprint-flet (stream list &rest noise)
1107   (declare (ignore noise))
1108   (funcall (formatter
1109             "~:<~^~W~^ ~@_~:<~@{~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~:@_~@{~W~^ ~_~}~:>~^ ~_~}~:>~1I~@:_~@{~W~^ ~_~}~:>")
1110            stream
1111            list))
1112
1113 (defun pprint-let (stream list &rest noise)
1114   (declare (ignore noise))
1115   (funcall (formatter "~:<~^~W~^ ~@_~:<~@{~:<~^~W~@{ ~_~W~}~:>~^ ~_~}~:>~1I~:@_~@{~W~^ ~_~}~:>")
1116            stream
1117            list))
1118
1119 (defun pprint-progn (stream list &rest noise)
1120   (declare (ignore noise))
1121   (funcall (formatter "~:<~^~W~@{ ~_~W~}~:>") stream list))
1122
1123 (defun pprint-progv (stream list &rest noise)
1124   (declare (ignore noise))
1125   (funcall (formatter "~:<~^~W~^~3I ~_~W~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1126            stream list))
1127
1128 (defun pprint-quote (stream list &rest noise)
1129   (declare (ignore noise))
1130   (if (and (consp list)
1131            (consp (cdr list))
1132            (null (cddr list)))
1133       (case (car list)
1134         (function
1135          (write-string "#'" stream)
1136          (output-object (cadr list) stream))
1137         (quote
1138          (write-char #\' stream)
1139          (output-object (cadr list) stream))
1140         (t
1141          (pprint-fill stream list)))
1142       (pprint-fill stream list)))
1143
1144 (defun pprint-setq (stream list &rest noise)
1145   (declare (ignore noise))
1146   (pprint-logical-block (stream list :prefix "(" :suffix ")")
1147     (pprint-exit-if-list-exhausted)
1148     (output-object (pprint-pop) stream)
1149     (pprint-exit-if-list-exhausted)
1150     (write-char #\space stream)
1151     (pprint-newline :miser stream)
1152     (if (and (consp (cdr list)) (consp (cddr list)))
1153         (loop
1154           (pprint-indent :current 2 stream)
1155           (output-object (pprint-pop) stream)
1156           (pprint-exit-if-list-exhausted)
1157           (write-char #\space stream)
1158           (pprint-newline :linear stream)
1159           (pprint-indent :current -2 stream)
1160           (output-object (pprint-pop) stream)
1161           (pprint-exit-if-list-exhausted)
1162           (write-char #\space stream)
1163           (pprint-newline :linear stream))
1164         (progn
1165           (pprint-indent :current 0 stream)
1166           (output-object (pprint-pop) stream)
1167           (pprint-exit-if-list-exhausted)
1168           (write-char #\space stream)
1169           (pprint-newline :linear stream)
1170           (output-object (pprint-pop) stream)))))
1171
1172 ;;; FIXME: could become SB!XC:DEFMACRO wrapped in EVAL-WHEN (COMPILE EVAL)
1173 (defmacro pprint-tagbody-guts (stream)
1174   `(loop
1175      (pprint-exit-if-list-exhausted)
1176      (write-char #\space ,stream)
1177      (let ((form-or-tag (pprint-pop)))
1178        (pprint-indent :block
1179                       (if (atom form-or-tag) 0 1)
1180                       ,stream)
1181        (pprint-newline :linear ,stream)
1182        (output-object form-or-tag ,stream))))
1183
1184 (defun pprint-tagbody (stream list &rest noise)
1185   (declare (ignore noise))
1186   (pprint-logical-block (stream list :prefix "(" :suffix ")")
1187     (pprint-exit-if-list-exhausted)
1188     (output-object (pprint-pop) stream)
1189     (pprint-tagbody-guts stream)))
1190
1191 (defun pprint-case (stream list &rest noise)
1192   (declare (ignore noise))
1193   (funcall (formatter
1194             "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~:/SB!PRETTY:PPRINT-FILL/~^~@{ ~_~W~}~:>~}~:>")
1195            stream
1196            list))
1197
1198 (defun pprint-defun (stream list &rest noise)
1199   (declare (ignore noise))
1200   (funcall (formatter
1201             "~:<~^~W~^ ~@_~:I~W~^ ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1202            stream
1203            list))
1204
1205 (defun pprint-destructuring-bind (stream list &rest noise)
1206   (declare (ignore noise))
1207   (funcall (formatter
1208             "~:<~^~W~^~3I ~_~:/SB!PRETTY:PPRINT-LAMBDA-LIST/~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1209            stream list))
1210
1211 (defun pprint-do (stream list &rest noise)
1212   (declare (ignore noise))
1213   (pprint-logical-block (stream list :prefix "(" :suffix ")")
1214     (pprint-exit-if-list-exhausted)
1215     (output-object (pprint-pop) stream)
1216     (pprint-exit-if-list-exhausted)
1217     (write-char #\space stream)
1218     (pprint-indent :current 0 stream)
1219     (funcall (formatter "~:<~@{~:<~^~W~^ ~@_~:I~W~@{ ~_~W~}~:>~^~:@_~}~:>")
1220              stream
1221              (pprint-pop))
1222     (pprint-exit-if-list-exhausted)
1223     (write-char #\space stream)
1224     (pprint-newline :linear stream)
1225     (pprint-linear stream (pprint-pop))
1226     (pprint-tagbody-guts stream)))
1227
1228 (defun pprint-dolist (stream list &rest noise)
1229   (declare (ignore noise))
1230   (pprint-logical-block (stream list :prefix "(" :suffix ")")
1231     (pprint-exit-if-list-exhausted)
1232     (output-object (pprint-pop) stream)
1233     (pprint-exit-if-list-exhausted)
1234     (pprint-indent :block 3 stream)
1235     (write-char #\space stream)
1236     (pprint-newline :fill stream)
1237     (funcall (formatter "~:<~^~W~^ ~:_~:I~W~@{ ~_~W~}~:>")
1238              stream
1239              (pprint-pop))
1240     (pprint-tagbody-guts stream)))
1241
1242 (defun pprint-typecase (stream list &rest noise)
1243   (declare (ignore noise))
1244   (funcall (formatter
1245             "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~W~^~@{ ~_~W~}~:>~}~:>")
1246            stream
1247            list))
1248
1249 (defun pprint-prog (stream list &rest noise)
1250   (declare (ignore noise))
1251   (pprint-logical-block (stream list :prefix "(" :suffix ")")
1252     (pprint-exit-if-list-exhausted)
1253     (output-object (pprint-pop) stream)
1254     (pprint-exit-if-list-exhausted)
1255     (write-char #\space stream)
1256     (pprint-newline :miser stream)
1257     (pprint-fill stream (pprint-pop))
1258     (pprint-tagbody-guts stream)))
1259
1260 (defun pprint-fun-call (stream list &rest noise)
1261   (declare (ignore noise))
1262   (funcall (formatter "~:<~^~W~^ ~:_~:I~@{~W~^ ~_~}~:>")
1263            stream
1264            list))
1265 \f
1266 ;;;; the interface seen by regular (ugly) printer and initialization routines
1267
1268 ;;; OUTPUT-PRETTY-OBJECT is called by OUTPUT-OBJECT when
1269 ;;; *PRINT-PRETTY* is true.
1270 (defun output-pretty-object (object stream)
1271   (with-pretty-stream (stream)
1272     (funcall (pprint-dispatch object) stream object)))
1273
1274 (defun !pprint-cold-init ()
1275   (/show0 "entering !PPRINT-COLD-INIT")
1276   (setf *initial-pprint-dispatch* (make-pprint-dispatch-table))
1277   (let ((*print-pprint-dispatch* *initial-pprint-dispatch*)
1278         (*building-initial-table* t))
1279     ;; printers for regular types
1280     (/show0 "doing SET-PPRINT-DISPATCH for regular types")
1281     (set-pprint-dispatch 'array #'pprint-array)
1282     (set-pprint-dispatch '(cons symbol)
1283                          #'pprint-fun-call -1)
1284     (set-pprint-dispatch 'cons #'pprint-fill -2)
1285     ;; cons cells with interesting things for the car
1286     (/show0 "doing SET-PPRINT-DISPATCH for CONS with interesting CAR")
1287
1288     (dolist (magic-form '((lambda pprint-lambda)
1289
1290                           ;; special forms
1291                           (block pprint-block)
1292                           (catch pprint-block)
1293                           (eval-when pprint-block)
1294                           (flet pprint-flet)
1295                           (function pprint-quote)
1296                           (labels pprint-flet)
1297                           (let pprint-let)
1298                           (let* pprint-let)
1299                           (locally pprint-progn)
1300                           (macrolet pprint-flet)
1301                           (multiple-value-call pprint-block)
1302                           (multiple-value-prog1 pprint-block)
1303                           (progn pprint-progn)
1304                           (progv pprint-progv)
1305                           (quote pprint-quote)
1306                           (return-from pprint-block)
1307                           (setq pprint-setq)
1308                           (symbol-macrolet pprint-let)
1309                           (tagbody pprint-tagbody)
1310                           (throw pprint-block)
1311                           (unwind-protect pprint-block)
1312
1313                           ;; macros
1314                           (case pprint-case)
1315                           (ccase pprint-case)
1316                           (ctypecase pprint-typecase)
1317                           (defconstant pprint-block)
1318                           (define-modify-macro pprint-defun)
1319                           (define-setf-expander pprint-defun)
1320                           (defmacro pprint-defun)
1321                           (defparameter pprint-block)
1322                           (defsetf pprint-defun)
1323                           (defstruct pprint-block)
1324                           (deftype pprint-defun)
1325                           (defun pprint-defun)
1326                           (defvar pprint-block)
1327                           (destructuring-bind pprint-destructuring-bind)
1328                           (do pprint-do)
1329                           (do* pprint-do)
1330                           (do-all-symbols pprint-dolist)
1331                           (do-external-symbols pprint-dolist)
1332                           (do-symbols pprint-dolist)
1333                           (dolist pprint-dolist)
1334                           (dotimes pprint-dolist)
1335                           (ecase pprint-case)
1336                           (etypecase pprint-typecase)
1337                           #+nil (handler-bind ...)
1338                           #+nil (handler-case ...)
1339                           #+nil (loop ...)
1340                           (multiple-value-bind pprint-progv)
1341                           (multiple-value-setq pprint-block)
1342                           (pprint-logical-block pprint-block)
1343                           (print-unreadable-object pprint-block)
1344                           (prog pprint-prog)
1345                           (prog* pprint-prog)
1346                           (prog1 pprint-block)
1347                           (prog2 pprint-progv)
1348                           (psetf pprint-setq)
1349                           (psetq pprint-setq)
1350                           #+nil (restart-bind ...)
1351                           #+nil (restart-case ...)
1352                           (setf pprint-setq)
1353                           (step pprint-progn)
1354                           (time pprint-progn)
1355                           (typecase pprint-typecase)
1356                           (unless pprint-block)
1357                           (when pprint-block)
1358                           (with-compilation-unit pprint-block)
1359                           #+nil (with-condition-restarts ...)
1360                           (with-hash-table-iterator pprint-block)
1361                           (with-input-from-string pprint-block)
1362                           (with-open-file pprint-block)
1363                           (with-open-stream pprint-block)
1364                           (with-output-to-string pprint-block)
1365                           (with-package-iterator pprint-block)
1366                           (with-simple-restart pprint-block)
1367                           (with-standard-io-syntax pprint-progn)))
1368
1369       (set-pprint-dispatch `(cons (eql ,(first magic-form)))
1370                            (symbol-function (second magic-form))))
1371
1372     ;; other pretty-print init forms
1373     (/show0 "about to call !BACKQ-PP-COLD-INIT")
1374     (sb!impl::!backq-pp-cold-init)
1375     (/show0 "leaving !PPRINT-COLD-INIT"))
1376
1377   (setf *print-pprint-dispatch* (copy-pprint-dispatch nil))
1378   (setf *print-pretty* t))