~ubuntu-branches/ubuntu/intrepid/ecl/intrepid

« back to all changes in this revision

Viewing changes to src/lsp/pprint.lsp

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2006-05-17 02:46:26 UTC
  • Revision ID: james.westby@ubuntu.com-20060517024626-lljr08ftv9g9vefl
Tags: upstream-0.9h-20060510
ImportĀ upstreamĀ versionĀ 0.9h-20060510

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;; -*- Package: PRETTY-PRINT -*-
 
2
;;;
 
3
;;; **********************************************************************
 
4
;;; This code was written as part of the CMU Common Lisp project at
 
5
;;; Carnegie Mellon University, and has been placed in the public domain.
 
6
;;;
 
7
;;; CMU Common Lisp pretty printer.
 
8
;;; Written by William Lott.  Algorithm stolen from Richard Waters' XP.
 
9
;;;
 
10
 
 
11
(in-package "SI")
 
12
 
 
13
;;;; Pretty streams
 
14
 
 
15
;;; There are three different units for measuring character positions:
 
16
;;;  COLUMN - offset (if characters) from the start of the current line.
 
17
;;;  INDEX - index into the output buffer.
 
18
;;;  POSN - some position in the stream of characters cycling through
 
19
;;;             the output buffer.
 
20
;;; 
 
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
(defclass pretty-stream (fundamental-character-output-stream) (
 
32
  ;;
 
33
  ;; Where the output is going to finally go.
 
34
  ;;
 
35
  (target :initarg :target :initform t :type stream
 
36
          :accessor pretty-stream-target)
 
37
  ;;
 
38
  ;; Line length we should format to.  Cached here so we don't have to keep
 
39
  ;; extracting it from the target stream.
 
40
  (line-length :initform (or *print-right-margin* default-line-length)
 
41
               :type column
 
42
               :accessor pretty-stream-line-length)
 
43
  ;;
 
44
  ;; A simple string holding all the text that has been output but not yet
 
45
  ;; printed.
 
46
  (buffer :initform (make-string initial-buffer-size) :type simple-string
 
47
          :accessor pretty-stream-buffer)
 
48
  ;;
 
49
  ;; The index into BUFFER where more text should be put.
 
50
  (buffer-fill-pointer :initform 0 :type index :accessor pretty-stream-buffer-fill-pointer)
 
51
  ;;
 
52
  ;; Whenever we output stuff from the buffer, we shift the remaining noise
 
53
  ;; over.  This makes it difficult to keep references to locations in
 
54
  ;; the buffer.  Therefore, we have to keep track of the total amount of
 
55
  ;; stuff that has been shifted out of the buffer.
 
56
  (buffer-offset :initform 0 :type posn :accessor pretty-stream-buffer-offset)
 
57
  ;;
 
58
  ;; The column the first character in the buffer will appear in.  Normally
 
59
  ;; zero, but if we end up with a very long line with no breaks in it we
 
60
  ;; might have to output part of it.  Then this will no longer be zero.
 
61
  (buffer-start-column :initarg :buffer-start-column :type column
 
62
                       :accessor pretty-stream-buffer-start-column)
 
63
  ;;
 
64
  ;; The line number we are currently on.  Used for *print-lines* abrevs and
 
65
  ;; to tell when sections have been split across multiple lines.
 
66
  (line-number :initform 0 :type index
 
67
               :accessor pretty-stream-line-number)
 
68
  ;;
 
69
  ;; Stack of logical blocks in effect at the buffer start.
 
70
  (blocks :initform (list (make-logical-block)) :type list
 
71
               :accessor pretty-stream-blocks)
 
72
  ;;
 
73
  ;; Buffer holding the per-line prefix active at the buffer start.
 
74
  ;; Indentation is included in this.  The length of this is stored
 
75
  ;; in the logical block stack.
 
76
  (prefix :initform (make-string initial-buffer-size) :type string
 
77
               :accessor pretty-stream-prefix)
 
78
  ;;
 
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 :initform (make-string initial-buffer-size) :type string
 
84
          :accessor pretty-stream-suffix)
 
85
  ;;
 
86
  ;; Queue of pending operations.  When empty, HEAD=TAIL=NIL.  Otherwise,
 
87
  ;; TAIL holds the first (oldest) cons and HEAD holds the last (newest)
 
88
  ;; cons.  Adding things to the queue is basically (setf (cdr head) (list
 
89
  ;; new)) and removing them is basically (pop tail) [except that care must
 
90
  ;; be taken to handle the empty queue case correctly.]
 
91
  (queue-tail :initform nil :type list :accessor pretty-stream-queue-tail)
 
92
  (queue-head :initform nil :type list :accessor pretty-stream-queue-head)
 
93
  ;;
 
94
  ;; Block-start queue entries in effect at the queue head.
 
95
  (pending-blocks :initform nil :type list :accessor pretty-stream-pending-blocks)
 
96
  ))
 
97
 
 
98
(defun pretty-stream-p (stream)
 
99
  (typep stream 'pretty-stream))
 
100
 
 
101
(defun make-pretty-stream (target)
 
102
  (make-instance 'pretty-stream :target target
 
103
                 :buffer-start-column (or (file-column target) 0)
 
104
                 ))
 
105
 
 
106
(defmethod print-object ((pretty-stream pretty-stream) stream)
 
107
  (print-unreadable-object (pstream stream :type t :identity t))
 
108
  #+nil
 
109
  (format stream "#<pretty stream {~8,'0X}>"
 
110
          (kernel:get-lisp-obj-address pstream)))
 
111
 
 
112
(declaim (inline index-posn posn-index posn-column))
 
113
(defun index-posn (index stream)
 
114
  (declare (type index index) (type pretty-stream stream)
 
115
           (values posn))
 
116
  (+ index (pretty-stream-buffer-offset stream)))
 
117
(defun posn-index (posn stream)
 
118
  (declare (type posn posn) (type pretty-stream stream)
 
119
           (values index))
 
120
  (- posn (pretty-stream-buffer-offset stream)))
 
121
(defun posn-column (posn stream)
 
122
  (declare (type posn posn) (type pretty-stream stream)
 
123
           (values posn))
 
124
  (index-column (posn-index posn stream) stream))
 
125
 
 
126
 
 
127
;;;; Stream interface routines.
 
128
 
 
129
(defmethod ext::stream-write-char ((stream pretty-stream) char)
 
130
  (pretty-out stream char))
 
131
 
 
132
(defmethod ext::stream-force-output ((stream pretty-stream))
 
133
  ;(force-pretty-output stream)
 
134
)
 
135
 
 
136
(defmethod ext::stream-clear-output ((stream pretty-stream))
 
137
  (clear-output (pretty-stream-target stream)))
 
138
 
 
139
(defun pretty-out (stream char)
 
140
  (declare (type pretty-stream stream)
 
141
           (type base-char char)
 
142
           (si::c-local))
 
143
  (cond ((char= char #\newline)
 
144
         (enqueue-newline stream :literal))
 
145
        (t
 
146
         (assure-space-in-buffer stream 1)
 
147
         (let ((fill-pointer (pretty-stream-buffer-fill-pointer stream)))
 
148
           (setf (schar (pretty-stream-buffer stream) fill-pointer) char)
 
149
           (setf (pretty-stream-buffer-fill-pointer stream)
 
150
                 (1+ fill-pointer))))))
 
151
 
 
152
(defun pretty-sout (stream string start end)
 
153
  (declare (type pretty-stream stream)
 
154
           (type simple-string string)
 
155
           (type index start)
 
156
           (type (or index null) end)
 
157
           (si::c-local))
 
158
  (let ((end (or end (length string))))
 
159
    (unless (= start end)
 
160
      (let ((newline (position #\newline string :start start :end end)))
 
161
        (cond
 
162
         (newline
 
163
          (pretty-sout stream string start newline)
 
164
          (enqueue-newline stream :literal)
 
165
          (pretty-sout stream string (1+ newline) end))
 
166
         (t
 
167
          (let ((chars (- end start)))
 
168
            (loop
 
169
              (let* ((available (assure-space-in-buffer stream chars))
 
170
                     (count (min available chars))
 
171
                     (fill-pointer (pretty-stream-buffer-fill-pointer stream))
 
172
                     (new-fill-ptr (+ fill-pointer count)))
 
173
                (replace (pretty-stream-buffer stream)
 
174
                         string
 
175
                         :start1 fill-pointer :end1 new-fill-ptr
 
176
                         :start2 start)
 
177
                (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
 
178
                (decf chars count)
 
179
                (when (zerop count)
 
180
                  (return))
 
181
                (incf start count))))))))))
 
182
 
 
183
 
 
184
;;;; Logical blocks.
 
185
 
 
186
(defstruct logical-block
 
187
  ;;
 
188
  ;; The column this logical block started in.
 
189
  (start-column 0 :type column)
 
190
  ;;
 
191
  ;; The column the current section started in.
 
192
  (section-column 0 :type column)
 
193
  ;;
 
194
  ;; The length of the per-line prefix.  We can't move the indentation
 
195
  ;; left of this.
 
196
  (per-line-prefix-end 0 :type index)
 
197
  ;;
 
198
  ;; The overall length of the prefix, including any indentation.
 
199
  (prefix-length 0 :type index)
 
200
  ;;
 
201
  ;; The overall length of the suffix.
 
202
  (suffix-length 0 :type index)
 
203
  ;; 
 
204
  ;; The line number 
 
205
  (section-start-line 0 :type index))
 
206
 
 
207
(defun really-start-logical-block (stream column prefix suffix)
 
208
  (declare (si::c-local))
 
209
  (let* ((blocks (pretty-stream-blocks stream))
 
210
         (prev-block (car blocks))
 
211
         (per-line-end (logical-block-per-line-prefix-end prev-block))
 
212
         (prefix-length (logical-block-prefix-length prev-block))
 
213
         (suffix-length (logical-block-suffix-length prev-block))
 
214
         (block (make-logical-block
 
215
                 :start-column column
 
216
                 :section-column column
 
217
                 :per-line-prefix-end per-line-end
 
218
                 :prefix-length prefix-length
 
219
                 :suffix-length suffix-length
 
220
                 :section-start-line (pretty-stream-line-number stream))))
 
221
    (setf (pretty-stream-blocks stream) (cons block blocks))
 
222
    (set-indentation stream column)
 
223
    (when prefix
 
224
      (setf (logical-block-per-line-prefix-end block) column)
 
225
      (replace (pretty-stream-prefix stream) prefix
 
226
               :start1 (- column (length prefix)) :end1 column))
 
227
    (when suffix
 
228
      (let* ((total-suffix (pretty-stream-suffix stream))
 
229
             (total-suffix-len (length total-suffix))
 
230
             (additional (length suffix))
 
231
             (new-suffix-len (+ suffix-length additional)))
 
232
        (when (> new-suffix-len total-suffix-len)
 
233
          (let ((new-total-suffix-len
 
234
                 (max (* total-suffix-len 2)
 
235
                      (+ suffix-length
 
236
                         (floor (* additional 5) 4)))))
 
237
            (setf total-suffix
 
238
                  (replace (make-string new-total-suffix-len) total-suffix
 
239
                           :start1 (- new-total-suffix-len suffix-length)
 
240
                           :start2 (- total-suffix-len suffix-length)))
 
241
            (setf total-suffix-len new-total-suffix-len)
 
242
            (setf (pretty-stream-suffix stream) total-suffix)))
 
243
        (replace total-suffix suffix
 
244
                 :start1 (- total-suffix-len new-suffix-len)
 
245
                 :end1 (- total-suffix-len suffix-length))
 
246
        (setf (logical-block-suffix-length block) new-suffix-len))))
 
247
  nil)
 
248
 
 
249
(defun set-indentation (stream column)
 
250
  (declare (si::c-local))
 
251
  (let* ((prefix (pretty-stream-prefix stream))
 
252
         (prefix-len (length prefix))
 
253
         (block (car (pretty-stream-blocks stream)))
 
254
         (current (logical-block-prefix-length block))
 
255
         (minimum (logical-block-per-line-prefix-end block))
 
256
         (column (max minimum column)))
 
257
    (when (> column prefix-len)
 
258
      (setf prefix
 
259
            (replace (make-string (max (* prefix-len 2)
 
260
                                       (+ prefix-len
 
261
                                          (floor (* (- column prefix-len) 5)
 
262
                                                 4))))
 
263
                     prefix
 
264
                     :end1 current))
 
265
      (setf (pretty-stream-prefix stream) prefix))
 
266
    (when (> column current)
 
267
      (fill prefix #\space :start current :end column))
 
268
    (setf (logical-block-prefix-length block) column)))
 
269
 
 
270
(defun really-end-logical-block (stream)
 
271
  (declare (si::c-local))
 
272
  (let* ((old (pop (pretty-stream-blocks stream)))
 
273
         (old-indent (logical-block-prefix-length old))
 
274
         (new (car (pretty-stream-blocks stream)))
 
275
         (new-indent (logical-block-prefix-length new)))
 
276
    (when (> new-indent old-indent)
 
277
      (fill (pretty-stream-prefix stream) #\space
 
278
            :start old-indent :end new-indent)))
 
279
  nil)
 
280
 
 
281
 
 
282
;;;; The pending operation queue.
 
283
 
 
284
(defstruct queued-op
 
285
  (posn 0 :type posn))
 
286
 
 
287
(eval-when (:compile-toplevel :execute)
 
288
(defmacro enqueue (stream type &rest args)
 
289
  (let ((constructor (intern (concatenate 'string
 
290
                                          "MAKE-"
 
291
                                          (symbol-name type)))))
 
292
    (once-only ((stream stream)
 
293
                (entry `(,constructor :posn
 
294
                                      (index-posn
 
295
                                       (pretty-stream-buffer-fill-pointer
 
296
                                        ,stream)
 
297
                                       ,stream)
 
298
                                      ,@args))
 
299
                (op `(list ,entry))
 
300
                (head `(pretty-stream-queue-head ,stream)))
 
301
      `(progn
 
302
         (if ,head
 
303
             (setf (cdr ,head) ,op)
 
304
             (setf (pretty-stream-queue-tail ,stream) ,op))
 
305
         (setf (pretty-stream-queue-head ,stream) ,op)
 
306
         ,entry))))
 
307
)
 
308
 
 
309
(defstruct (section-start
 
310
            (:include queued-op))
 
311
  (depth 0 :type index)
 
312
  (section-end nil :type (or null newline block-end)))
 
313
 
 
314
(defstruct (newline
 
315
            (:include section-start))
 
316
  (kind (required-argument)
 
317
        :type (member :linear :fill :miser :literal :mandatory)))
 
318
 
 
319
(defun enqueue-newline (stream kind)
 
320
  (declare (si::c-local))
 
321
  (let* ((depth (length (pretty-stream-pending-blocks stream)))
 
322
         (newline (enqueue stream newline :kind kind :depth depth)))
 
323
    (dolist (entry (pretty-stream-queue-tail stream))
 
324
      (when (and (not (eq newline entry))
 
325
                 (section-start-p entry)
 
326
                 (null (section-start-section-end entry))
 
327
                 (<= depth (section-start-depth entry)))
 
328
        (setf (section-start-section-end entry) newline))))
 
329
  (maybe-output stream (or (eq kind :literal) (eq kind :mandatory))))
 
330
 
 
331
(defstruct (indentation
 
332
            (:include queued-op))
 
333
  (kind (required-argument) :type (member :block :current))
 
334
  (amount 0 :type fixnum))
 
335
 
 
336
(defun enqueue-indent (stream kind amount)
 
337
  (declare (si::c-local))
 
338
  (enqueue stream indentation :kind kind :amount amount))
 
339
 
 
340
(defstruct (block-start
 
341
            (:include section-start))
 
342
  (block-end nil :type (or null block-end))
 
343
  (prefix nil :type (or null string))
 
344
  (suffix nil :type (or null string)))
 
345
 
 
346
(defun start-logical-block (stream prefix per-line-p suffix)
 
347
  (declare (si::c-local)
 
348
           (type string prefix))
 
349
  #+ecl
 
350
  (unless (stringp prefix)
 
351
    (error 'simple-type-error
 
352
           :format-control "Not a valid PPRINT-LOGICAL-BLOCK prefix: ~A"
 
353
           :format-arguments (list prefix)
 
354
           :datum prefix
 
355
           :expected-type 'string))
 
356
  #+ecl
 
357
  (unless (stringp suffix)
 
358
    (error 'simple-type-error
 
359
           :format-control "Not a valid PPRINT-LOGICAL-BLOCK suffix: ~A"
 
360
           :format-arguments (list suffix)
 
361
           :datum suffix
 
362
           :expected-type 'string))
 
363
  (let ((prefix-len (length prefix)))
 
364
    (when (plusp prefix-len)
 
365
      (pretty-sout stream prefix 0 prefix-len))
 
366
    (let* ((pending-blocks (pretty-stream-pending-blocks stream))
 
367
           (start (enqueue stream block-start
 
368
                           :prefix (and (plusp prefix-len) per-line-p prefix)
 
369
                           :suffix (and (plusp (length suffix)) suffix)
 
370
                           :depth (length pending-blocks))))
 
371
      (setf (pretty-stream-pending-blocks stream)
 
372
            (cons start pending-blocks)))))
 
373
 
 
374
(defstruct (block-end
 
375
            (:include queued-op))
 
376
  (suffix nil :type (or null string)))
 
377
 
 
378
(defun end-logical-block (stream)
 
379
  (declare (si::c-local))
 
380
  (let* ((start (pop (pretty-stream-pending-blocks stream)))
 
381
         (suffix (block-start-suffix start))
 
382
         (end (enqueue stream block-end :suffix suffix)))
 
383
    (when suffix
 
384
      (pretty-sout stream suffix 0 (length suffix)))
 
385
    (setf (block-start-block-end start) end)))
 
386
 
 
387
(defstruct (tab
 
388
            (:include queued-op))
 
389
  (sectionp nil :type (member t nil))
 
390
  (relativep nil :type (member t nil))
 
391
  (colnum 0 :type column)
 
392
  (colinc 0 :type column))
 
393
 
 
394
(defun enqueue-tab (stream kind colnum colinc)
 
395
  (declare (si::c-local))
 
396
  (multiple-value-bind
 
397
      (sectionp relativep)
 
398
      (ecase kind
 
399
        (:line (values nil nil))
 
400
        (:line-relative (values nil t))
 
401
        (:section (values t nil))
 
402
        (:section-relative (values t t)))
 
403
    (enqueue stream tab :sectionp sectionp :relativep relativep
 
404
             :colnum colnum :colinc colinc)))
 
405
 
 
406
 
 
407
;;;; Tab support.
 
408
 
 
409
(defun compute-tab-size (tab section-start column)
 
410
  (declare (si::c-local))
 
411
  (let ((colnum (tab-colnum tab))
 
412
        (colinc (tab-colinc tab)))
 
413
    (when (tab-sectionp tab)
 
414
      (setf column (- column section-start)))
 
415
    (cond ((tab-relativep tab)
 
416
           (unless (<= colinc 1)
 
417
             (let ((newposn (+ column colnum)))
 
418
               (let ((rem (rem newposn colinc)))
 
419
                 (unless (zerop rem)
 
420
                   (incf colnum (- colinc rem))))))
 
421
           colnum)
 
422
          ((< column colnum)
 
423
           (- colnum column))
 
424
          ((= column colnum)
 
425
           colinc)
 
426
          ((plusp colinc)
 
427
           (- colinc (rem (- column colnum) colinc)))
 
428
          (t
 
429
           0))))
 
430
 
 
431
(defun index-column (index stream)
 
432
  (declare (si::c-local))
 
433
  (let ((column (pretty-stream-buffer-start-column stream))
 
434
        (section-start (logical-block-section-column
 
435
                        (first (pretty-stream-blocks stream))))
 
436
        (end-posn (index-posn index stream)))
 
437
    (dolist (op (pretty-stream-queue-tail stream))
 
438
      (when (>= (queued-op-posn op) end-posn)
 
439
        (return))
 
440
      (typecase op
 
441
        (tab
 
442
         (incf column
 
443
               (compute-tab-size op
 
444
                                 section-start
 
445
                                 (+ column
 
446
                                    (posn-index (tab-posn op)
 
447
                                                    stream)))))
 
448
        ((or newline block-start)
 
449
         (setf section-start
 
450
               (+ column (posn-index (queued-op-posn op)
 
451
                                         stream))))))
 
452
    (+ column index)))
 
453
 
 
454
(defun expand-tabs (stream through)
 
455
  (declare (si::c-local))
 
456
  (let ((insertions nil)
 
457
        (additional 0)
 
458
        (column (pretty-stream-buffer-start-column stream))
 
459
        (section-start (logical-block-section-column
 
460
                        (first (pretty-stream-blocks stream)))))
 
461
    (dolist (op (pretty-stream-queue-tail stream))
 
462
      (typecase op
 
463
        (tab
 
464
         (let* ((index (posn-index (tab-posn op) stream))
 
465
                (tabsize (compute-tab-size op
 
466
                                           section-start
 
467
                                           (+ column index))))
 
468
           (unless (zerop tabsize)
 
469
             (push (cons index tabsize) insertions)
 
470
             (incf additional tabsize)
 
471
             (incf column tabsize))))
 
472
        ((or newline block-start)
 
473
         (setf section-start
 
474
               (+ column (posn-index (queued-op-posn op) stream)))))
 
475
      (when (eq op through)
 
476
        (return)))
 
477
    (when insertions
 
478
      (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
 
479
             (new-fill-ptr (+ fill-ptr additional))
 
480
             (buffer (pretty-stream-buffer stream))
 
481
             (new-buffer buffer)
 
482
             (length (length buffer))
 
483
             (end fill-ptr))
 
484
        (when (> new-fill-ptr length)
 
485
          (let ((new-length (max (* length 2)
 
486
                                 (+ fill-ptr
 
487
                                    (floor (* additional 5) 4)))))
 
488
            (setf new-buffer (make-string new-length))
 
489
            (setf (pretty-stream-buffer stream) new-buffer)))
 
490
        (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
 
491
        (decf (pretty-stream-buffer-offset stream) additional)
 
492
        (dolist (insertion insertions)
 
493
          (let* ((srcpos (car insertion))
 
494
                 (amount (cdr insertion))
 
495
                 (dstpos (+ srcpos additional)))
 
496
            (replace new-buffer buffer :start1 dstpos :start2 srcpos :end2 end)
 
497
            (fill new-buffer #\space :start (- dstpos amount) :end dstpos)
 
498
            (decf additional amount)
 
499
            (setf end srcpos)))
 
500
        (unless (eq new-buffer buffer)
 
501
          (replace new-buffer buffer :end1 end :end2 end))))))
 
502
 
 
503
 
 
504
;;;; Stuff to do the actual outputting.
 
505
 
 
506
(defun assure-space-in-buffer (stream want)
 
507
  (declare (type pretty-stream stream)
 
508
           (type index want)
 
509
           (si::c-local))
 
510
  (let* ((buffer (pretty-stream-buffer stream))
 
511
         (length (length buffer))
 
512
         (fill-ptr (pretty-stream-buffer-fill-pointer stream))
 
513
         (available (- length fill-ptr)))
 
514
    (cond ((plusp available)
 
515
           available)
 
516
          ((> fill-ptr (pretty-stream-line-length stream))
 
517
           (unless (maybe-output stream nil)
 
518
             (output-partial-line stream))
 
519
           (assure-space-in-buffer stream want))
 
520
          (t
 
521
           (let* ((new-length (max (* length 2)
 
522
                                   (+ length
 
523
                                      (floor (* want 5) 4))))
 
524
                  (new-buffer (make-string new-length)))
 
525
             (setf (pretty-stream-buffer stream) new-buffer)
 
526
             (replace new-buffer buffer :end1 fill-ptr)
 
527
             (- new-length fill-ptr))))))
 
528
 
 
529
(defun maybe-output (stream force-newlines-p)
 
530
  (declare (type pretty-stream stream)
 
531
           (si::c-local))
 
532
  (let ((tail (pretty-stream-queue-tail stream))
 
533
        (output-anything nil))
 
534
    (loop
 
535
      (unless tail
 
536
        (setf (pretty-stream-queue-head stream) nil)
 
537
        (return))
 
538
      (let ((next (pop tail)))
 
539
        (etypecase next
 
540
          (newline
 
541
           (when (ecase (newline-kind next)
 
542
                   ((:literal :mandatory :linear) t)
 
543
                   (:miser (misering-p stream))
 
544
                   (:fill
 
545
                    (or (misering-p stream)
 
546
                        (> (pretty-stream-line-number stream)
 
547
                           (logical-block-section-start-line
 
548
                            (first (pretty-stream-blocks stream))))
 
549
                        (ecase (fits-on-line-p stream
 
550
                                               (newline-section-end next)
 
551
                                               force-newlines-p)
 
552
                          ((t) nil)
 
553
                          ((nil) t)
 
554
                          (:dont-know
 
555
                           (return))))))
 
556
             (setf output-anything t)
 
557
             (output-line stream next)))
 
558
          (indentation
 
559
           (unless (misering-p stream)
 
560
             (set-indentation stream
 
561
                              (+ (ecase (indentation-kind next)
 
562
                                   (:block
 
563
                                    (logical-block-start-column
 
564
                                     (car (pretty-stream-blocks stream))))
 
565
                                   (:current
 
566
                                    (posn-column
 
567
                                     (indentation-posn next)
 
568
                                     stream)))
 
569
                                 (indentation-amount next)))))
 
570
          (block-start
 
571
           (ecase (fits-on-line-p stream (block-start-section-end next)
 
572
                                  force-newlines-p)
 
573
             ((t)
 
574
              ;; Just nuke the whole logical block and make it look like one
 
575
              ;; nice long literal.
 
576
              (let ((end (block-start-block-end next)))
 
577
                (expand-tabs stream end)
 
578
                (setf tail (cdr (member end tail)))))
 
579
             ((nil)
 
580
              (really-start-logical-block
 
581
               stream
 
582
               (posn-column (block-start-posn next) stream)
 
583
               (block-start-prefix next)
 
584
               (block-start-suffix next)))
 
585
             (:dont-know
 
586
              (return))))
 
587
          (block-end
 
588
           (really-end-logical-block stream))
 
589
          (tab
 
590
           (expand-tabs stream next))))
 
591
      (setf (pretty-stream-queue-tail stream) tail))
 
592
    output-anything))
 
593
 
 
594
(defun misering-p (stream)
 
595
  (declare (type pretty-stream stream)
 
596
           (si::c-local))
 
597
  (and *print-miser-width*
 
598
       (<= (- (pretty-stream-line-length stream)
 
599
              (logical-block-start-column (car (pretty-stream-blocks stream))))
 
600
           *print-miser-width*)))
 
601
 
 
602
(defun fits-on-line-p (stream until force-newlines-p)
 
603
  (declare (si::c-local))
 
604
  (let ((available (pretty-stream-line-length stream)))
 
605
    (when (and (not *print-readably*) *print-lines*
 
606
               (= *print-lines* (pretty-stream-line-number stream)))
 
607
      (decf available 3) ; for the `` ..''
 
608
      (decf available (logical-block-suffix-length
 
609
                       (car (pretty-stream-blocks stream)))))
 
610
    (cond (until
 
611
           (<= (posn-column (queued-op-posn until) stream) available))
 
612
          (force-newlines-p nil)
 
613
          ((> (index-column (pretty-stream-buffer-fill-pointer stream) stream)
 
614
              available)
 
615
           nil)
 
616
          (t
 
617
           :dont-know))))
 
618
 
 
619
(defun output-line (stream until)
 
620
  (declare (type pretty-stream stream)
 
621
           (type newline until)
 
622
           (si::c-local))
 
623
  (let* ((target (pretty-stream-target stream))
 
624
         (buffer (pretty-stream-buffer stream))
 
625
         (kind (newline-kind until))
 
626
         (literal-p (eq kind :literal))
 
627
         (amount-to-consume (posn-index (newline-posn until) stream))
 
628
         (amount-to-print
 
629
          (if literal-p
 
630
              amount-to-consume
 
631
              (let ((last-non-blank
 
632
                     (position #\space buffer :end amount-to-consume
 
633
                               :from-end t :test #'char/=)))
 
634
                (if last-non-blank
 
635
                    (1+ last-non-blank)
 
636
                    0)))))
 
637
    (write-string buffer target :end amount-to-print)
 
638
    (let ((line-number (pretty-stream-line-number stream)))
 
639
      (incf line-number)
 
640
      (when (and (not *print-readably*)
 
641
                 *print-lines* (>= line-number *print-lines*))
 
642
        (write-string " .." target)
 
643
        (let ((suffix-length (logical-block-suffix-length
 
644
                              (car (pretty-stream-blocks stream)))))
 
645
          (unless (zerop suffix-length)
 
646
            (let* ((suffix (pretty-stream-suffix stream))
 
647
                   (len (length suffix)))
 
648
              (write-string suffix target
 
649
                            :start (- len suffix-length)
 
650
                            :end len))))
 
651
        (throw 'line-limit-abbreviation-happened t))
 
652
      (setf (pretty-stream-line-number stream) line-number)
 
653
      (write-char #\newline target)
 
654
      (setf (pretty-stream-buffer-start-column stream) 0)
 
655
      (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
 
656
             (block (first (pretty-stream-blocks stream)))
 
657
             (prefix-len
 
658
              (if literal-p
 
659
                  (logical-block-per-line-prefix-end block)
 
660
                  (logical-block-prefix-length block)))
 
661
             (shift (- amount-to-consume prefix-len))
 
662
             (new-fill-ptr (- fill-ptr shift))
 
663
             (new-buffer buffer)
 
664
             (buffer-length (length buffer)))
 
665
        (when (> new-fill-ptr buffer-length)
 
666
          (setf new-buffer
 
667
                (make-string (max (* buffer-length 2)
 
668
                                  (+ buffer-length
 
669
                                     (floor (* (- new-fill-ptr buffer-length)
 
670
                                               5)
 
671
                                            4)))))
 
672
          (setf (pretty-stream-buffer stream) new-buffer))
 
673
        (replace new-buffer buffer
 
674
                 :start1 prefix-len :start2 amount-to-consume :end2 fill-ptr)
 
675
        (replace new-buffer (pretty-stream-prefix stream)
 
676
                 :end1 prefix-len)
 
677
        (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
 
678
        (incf (pretty-stream-buffer-offset stream) shift)
 
679
        (unless literal-p
 
680
          (setf (logical-block-section-column block) prefix-len)
 
681
          (setf (logical-block-section-start-line block) line-number))))))
 
682
 
 
683
(defun output-partial-line (stream)
 
684
  (declare (si::c-local))
 
685
  (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
 
686
         (tail (pretty-stream-queue-tail stream))
 
687
         (count
 
688
          (if tail
 
689
              (posn-index (queued-op-posn (car tail)) stream)
 
690
              fill-ptr))
 
691
         (new-fill-ptr (- fill-ptr count))
 
692
         (buffer (pretty-stream-buffer stream)))
 
693
    (when (zerop count)
 
694
      (error "Output-partial-line called when nothing can be output."))
 
695
    (write-string buffer (pretty-stream-target stream)
 
696
                  :start 0 :end count)
 
697
    (incf (pretty-stream-buffer-start-column stream) count)
 
698
    (replace buffer buffer :end1 new-fill-ptr :start2 count :end2 fill-ptr)
 
699
    (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
 
700
    (incf (pretty-stream-buffer-offset stream) count)))
 
701
 
 
702
(defun force-pretty-output (stream)
 
703
  (declare (si::c-local))
 
704
  (maybe-output stream nil)
 
705
  (expand-tabs stream nil)
 
706
  (write-string (pretty-stream-buffer stream)
 
707
                (pretty-stream-target stream)
 
708
                :end (pretty-stream-buffer-fill-pointer stream)))
 
709
 
 
710
 
 
711
;;;; Utilities.
 
712
 
 
713
(defun pprint-pop-helper (object count stream &aux code)
 
714
  (cond ((not (listp object))
 
715
         (write-string ". " stream)
 
716
         (write-object object stream)
 
717
         nil)
 
718
        ((and (not *print-readably*)
 
719
              (eql count *print-length*))
 
720
         (write-string "..." stream)
 
721
         nil)
 
722
        ((or (null object)
 
723
             (zerop count)
 
724
             (fixnump object)
 
725
             (characterp object)
 
726
             (and (symbolp object) (symbol-package object))
 
727
             (null *circle-counter*))
 
728
         t)
 
729
        ((eql 'NULL (setf code (gethash object *circle-stack* 'NULL)))
 
730
         ;; We visit this part of the list for the first time and thus we must
 
731
         ;; register it in the hash, or we are on the second pass and have
 
732
         ;; found a completely new list. This should not happend, but anyway
 
733
         ;; we try to print it.
 
734
         (search-print-circle object)
 
735
         t)
 
736
        ((and (null code) (integerp *circle-counter*))
 
737
         ;; This object is not visited twice.
 
738
         t)
 
739
        (t
 
740
         ;; In all other cases, WRITE-OBJECT
 
741
         (write-string ". " stream)
 
742
         (write-object object stream)
 
743
         nil)))
 
744
 
 
745
;;;; User interface to the pretty printer.
 
746
 
 
747
(defun check-print-level ()
 
748
  (declare (si::c-local))
 
749
  "Automatically handle *print-level* abbreviation.  If we are too deep, then
 
750
   a # is printed to STREAM and BODY is ignored."
 
751
  (cond ((or *print-readably* (null *print-level*))
 
752
         t)
 
753
        ((zerop *print-level*)
 
754
         nil)
 
755
        (t
 
756
         (setf *print-level* (1- *print-level*)))))
 
757
 
 
758
(defun search-print-circle (object)
 
759
  (declare (si::c-local))
 
760
  (let ((code (gethash object *circle-stack* -1)))
 
761
    (if (fixnump *circle-counter*)
 
762
        (cond ((or (eql code -1) (null code))
 
763
               ;; Is not referenced or was not found before
 
764
               0)
 
765
              ((eql code t)
 
766
               ;; Reference twice but had no code yet
 
767
               (setf (gethash object *circle-stack*)
 
768
                     (setf *circle-counter* (1+ *circle-counter*)))
 
769
               (- *circle-counter*))
 
770
              (t code))
 
771
        (cond ((eql code -1)
 
772
               ;; Was not found before
 
773
               (setf (gethash object *circle-stack*) nil)
 
774
               0)
 
775
              ((null code)
 
776
               ;; Second reference
 
777
               (setf (gethash object *circle-stack*) t)
 
778
               1)
 
779
              (t
 
780
               ;; Further references
 
781
               2)))))
 
782
 
 
783
(defun do-pprint-logical-block (function object stream prefix
 
784
                                per-line-prefix-p suffix)
 
785
  (declare (si::c-local))
 
786
  (unless (listp object)
 
787
    (write-object object stream)
 
788
    (return-from do-pprint-logical-block nil))
 
789
  (when (and (not *print-readably*) (eql *print-level* 0))
 
790
    (write-char #\# stream)
 
791
    (return-from do-pprint-logical-block nil))
 
792
  (unless (or (not *print-circle*)
 
793
              (fixnump object)
 
794
              (characterp object)
 
795
              (and (symbolp object) (symbol-package object)))
 
796
    (let (code)
 
797
      (cond ((not *circle-counter*)
 
798
             (let* ((hash (make-hash-table :test 'eq :size 1024
 
799
                                           :rehash-size 1.5
 
800
                                           :rehash-threshold 0.75))
 
801
                    (*circle-counter* t)
 
802
                    (*circle-stack* hash))
 
803
               (do-pprint-logical-block function object
 
804
                                        (make-pretty-stream (make-broadcast-stream))
 
805
                                        prefix per-line-prefix-p suffix)
 
806
               (setf *circle-counter* 0)
 
807
               (do-pprint-logical-block function object stream
 
808
                                        prefix per-line-prefix-p suffix))
 
809
             (return-from do-pprint-logical-block nil))
 
810
            ((zerop (setf code (search-print-circle object)))
 
811
             ;; Object was not referenced before: we must either traverse it
 
812
             ;; or print it.
 
813
             )
 
814
            ((minusp code)
 
815
             ;; First definition, we write the #n=... prefix
 
816
             (write-string "#" stream)
 
817
             (let ((*print-radix* nil) (*print-base* 10))
 
818
               (write-ugly-object (- code) stream))
 
819
             (write-string "=" stream))
 
820
            (t
 
821
             ;; Further references, we write the #n# tag and exit
 
822
             (write-string "#" stream)
 
823
             (let ((*print-radix* nil) (*print-base* 10))
 
824
               (write-ugly-object code stream))
 
825
             (write-string "#" stream)
 
826
             (return-from do-pprint-logical-block nil)))))
 
827
  (let ((*print-level* (and (not *print-readably*)
 
828
                            *print-level*
 
829
                            (1- *print-level*))))
 
830
    (start-logical-block stream prefix per-line-prefix-p suffix)
 
831
    (funcall function object stream)
 
832
    (end-logical-block stream))
 
833
  nil)
 
834
 
 
835
(defun pprint-logical-block-helper (function object stream prefix
 
836
                                    per-line-prefix-p suffix)
 
837
  (setf stream (case stream
 
838
                 ((nil) *standard-output*)
 
839
                 ((t) *terminal-io*)
 
840
                 (t stream)))
 
841
  (if (pretty-stream-p stream)
 
842
      (do-pprint-logical-block function object stream prefix
 
843
                               per-line-prefix-p suffix)
 
844
      (let ((stream (make-pretty-stream stream)))
 
845
        (catch 'line-limit-abbreviation-happened
 
846
          (do-pprint-logical-block function object stream prefix
 
847
                                   per-line-prefix-p suffix)
 
848
          (force-pretty-output stream))
 
849
        nil)))
 
850
 
 
851
(defmacro pprint-logical-block
 
852
          ((stream-symbol object &key (prefix "" prefix-p)
 
853
                          (per-line-prefix "" per-line-prefix-p)
 
854
                          (suffix "" suffix-p))
 
855
           &body body)
 
856
  "Group some output into a logical block.  STREAM-SYMBOL should be either a
 
857
   stream, T (for *TERMINAL-IO*), or NIL (for *STANDARD-OUTPUT*).  The printer
 
858
   control variable *PRINT-LEVEL* is automatically handled."
 
859
  (when per-line-prefix-p
 
860
    (when prefix-p
 
861
      (error "Cannot specify both a prefix and a per-line-prefix."))
 
862
    (setf prefix per-line-prefix))
 
863
  (let* ((object-var (gensym))
 
864
         (block-name (gensym "PPRINT-LOGICAL-BLOCK-"))
 
865
         (count-name (gensym "PPRINT-LOGICAL-BLOCK-LENGTH-"))
 
866
         (stream-var (case stream-symbol
 
867
                       ((nil) '*standard-output*)
 
868
                       ((t) '*terminal-io*)
 
869
                       (t stream-symbol)))
 
870
         (function
 
871
          `(ext::lambda-block ,block-name (,object-var ,stream-var
 
872
                                           &aux (,count-name 0))
 
873
            (macrolet ((pprint-pop ()
 
874
                         '(progn
 
875
                           (unless (pprint-pop-helper ,object-var ,count-name
 
876
                                                      ,stream-var)
 
877
                             (return-from ,block-name nil))
 
878
                           (incf ,count-name)
 
879
                           ,(if object `(pop ,object-var) nil)))
 
880
                       (pprint-exit-if-list-exhausted ()
 
881
                         ,(if object
 
882
                              `'(when (null ,object-var)
 
883
                                 (return-from ,block-name nil))
 
884
                              `'(return-from ,block-name nil))))
 
885
              ,@body))))
 
886
      `(pprint-logical-block-helper #',function ,object ,stream-symbol
 
887
                                    ,prefix ,per-line-prefix-p ,suffix)))
 
888
 
 
889
(defmacro pprint-exit-if-list-exhausted ()
 
890
  "Cause the closest enclosing use of PPRINT-LOGICAL-BLOCK to return
 
891
   if it's list argument is exhausted.  Can only be used inside
 
892
   PPRINT-LOGICAL-BLOCK, and only when the LIST argument to
 
893
   PPRINT-LOGICAL-BLOCK is supplied."
 
894
  (error "PPRINT-EXIT-IF-LIST-EXHAUSTED must be lexically inside ~
 
895
          PPRINT-LOGICAL-BLOCK."))
 
896
 
 
897
(defmacro pprint-pop ()
 
898
  "Return the next element from LIST argument to the closest enclosing
 
899
   use of PPRINT-LOGICAL-BLOCK, automatically handling *PRINT-LENGTH*
 
900
   and *PRINT-CIRCLE*.  Can only be used inside PPRINT-LOGICAL-BLOCK.
 
901
   If the LIST argument to PPRINT-LOGICAL-BLOCK was NIL, then nothing
 
902
   is poped, but the *PRINT-LENGTH* testing still happens."
 
903
  (error "PPRINT-POP must be lexically inside PPRINT-LOGICAL-BLOCK."))
 
904
 
 
905
(defun pprint-newline (kind &optional stream)
 
906
  "Output a conditional newline to STREAM (which defaults to
 
907
   *STANDARD-OUTPUT*) if it is a pretty-printing stream, and do
 
908
   nothing if not.  KIND can be one of:
 
909
     :LINEAR - A line break is inserted if and only if the immediatly
 
910
        containing section cannot be printed on one line.
 
911
     :MISER - Same as LINEAR, but only if ``miser-style'' is in effect.
 
912
        (See *PRINT-MISER-WIDTH*.)
 
913
     :FILL - A line break is inserted if and only if either:
 
914
       (a) the following section cannot be printed on the end of the
 
915
           current line,
 
916
       (b) the preceding section was not printed on a single line, or
 
917
       (c) the immediately containing section cannot be printed on one
 
918
           line and miser-style is in effect.
 
919
     :MANDATORY - A line break is always inserted.
 
920
   When a line break is inserted by any type of conditional newline, any
 
921
   blanks that immediately precede the conditional newline are ommitted
 
922
   from the output and indentation is introduced at the beginning of the
 
923
   next line.  (See PPRINT-INDENT.)"
 
924
  (declare (type (member :linear :miser :fill :mandatory) kind)
 
925
           (type (or stream (member t nil)) stream)
 
926
           (values null))
 
927
  #+ecl
 
928
  (unless (member kind '(:linear :miser :fill :mandatory))
 
929
    (error 'simple-type-error
 
930
           :format-control "~A is not a valid argument to PPRINT-NEWLINE"
 
931
           :format-arguments (list kind)
 
932
           :datum kind
 
933
           :expected-type '(member :linear :miser :fill :mandatory)))
 
934
  (let ((stream (case stream
 
935
                  ((t) *terminal-io*)
 
936
                  ((nil) *standard-output*)
 
937
                  (t stream))))
 
938
    (when (and (pretty-stream-p stream) *print-pretty*)
 
939
      (enqueue-newline stream kind)))
 
940
  nil)
 
941
 
 
942
(defun pprint-indent (relative-to n &optional stream)
 
943
  "Specify the indentation to use in the current logical block if STREAM
 
944
   (which defaults to *STANDARD-OUTPUT*) is it is a pretty-printing stream
 
945
   and do nothing if not.  (See PPRINT-LOGICAL-BLOCK.)  N is the indention
 
946
   to use (in ems, the width of an ``m'') and RELATIVE-TO can be either:
 
947
     :BLOCK - Indent relative to the column the current logical block
 
948
        started on.
 
949
     :CURRENT - Indent relative to the current column.
 
950
   The new indention value does not take effect until the following line
 
951
   break."
 
952
  (declare (type (member :block :current) relative-to)
 
953
           (type real n)
 
954
           (type (or stream (member t nil)) stream)
 
955
           (values null))
 
956
  #+ecl
 
957
  (unless (member relative-to '(:block :current))
 
958
    (error 'simple-type-error
 
959
           :format-control "~A is not a valid argument to PPRINT-INDENT"
 
960
           :format-arguments (list kind)
 
961
           :datum kind
 
962
           :expected-type '(member :block :current)))
 
963
  (let ((stream (case stream
 
964
                  ((t) *terminal-io*)
 
965
                  ((nil) *standard-output*)
 
966
                  (t stream))))
 
967
    (when (and (pretty-stream-p stream) *print-pretty*)
 
968
      (enqueue-indent stream relative-to (round n))))
 
969
  nil)
 
970
 
 
971
(defun pprint-tab (kind colnum colinc &optional stream)
 
972
  "If STREAM (which defaults to *STANDARD-OUTPUT*) is a pretty-printing
 
973
   stream, perform tabbing based on KIND, otherwise do nothing.  KIND can
 
974
   be one of:
 
975
     :LINE - Tab to column COLNUM.  If already past COLNUM tab to the next
 
976
       multiple of COLINC.
 
977
     :SECTION - Same as :LINE, but count from the start of the current
 
978
       section, not the start of the line.
 
979
     :LINE-RELATIVE - Output COLNUM spaces, then tab to the next multiple of
 
980
       COLINC.
 
981
     :SECTION-RELATIVE - Same as :LINE-RELATIVE, but count from the start
 
982
       of the current section, not the start of the line."
 
983
  (declare (type (member :line :section :line-relative :section-relative) kind)
 
984
           (type unsigned-byte colnum colinc)
 
985
           (type (or stream (member t nil)) stream)
 
986
           (values null))
 
987
  #+ecl
 
988
  (unless (member kind '(:line :section :line-relative :section-relative))
 
989
    (error 'simple-type-error
 
990
           :format-control "~A is not a valid argument to PPRINT-TAB"
 
991
           :format-arguments (list kind)
 
992
           :datum kind
 
993
           :expected-type '(member :line :section :line-relative :section-relative)))
 
994
  (let ((stream (case stream
 
995
                  ((t) *terminal-io*)
 
996
                  ((nil) *standard-output*)
 
997
                  (t stream))))
 
998
    (when (and (pretty-stream-p stream) *print-pretty*)
 
999
      (enqueue-tab stream kind colnum colinc)))
 
1000
  nil)
 
1001
 
 
1002
(defun pprint-fill (stream list &optional (colon? t) atsign?)
 
1003
  "Output LIST to STREAM putting :FILL conditional newlines between each
 
1004
   element.  If COLON? is NIL (defaults to T), then no parens are printed
 
1005
   around the output.  ATSIGN? is ignored (but allowed so that PPRINT-FILL
 
1006
   can be used with the ~/.../ format directive."
 
1007
  (declare (ignore atsign?))
 
1008
  (pprint-logical-block (stream list
 
1009
                                :prefix (if colon? "(" "")
 
1010
                                :suffix (if colon? ")" ""))
 
1011
    (pprint-exit-if-list-exhausted)
 
1012
    (loop
 
1013
      (write-object (pprint-pop) stream)
 
1014
      (pprint-exit-if-list-exhausted)
 
1015
      (write-char #\space stream)
 
1016
      (pprint-newline :fill stream))))
 
1017
 
 
1018
(defun pprint-linear (stream list &optional (colon? t) atsign?)
 
1019
  "Output LIST to STREAM putting :LINEAR conditional newlines between each
 
1020
   element.  If COLON? is NIL (defaults to T), then no parens are printed
 
1021
   around the output.  ATSIGN? is ignored (but allowed so that PPRINT-LINEAR
 
1022
   can be used with the ~/.../ format directive."
 
1023
  (declare (ignore atsign?))
 
1024
  (pprint-logical-block (stream list
 
1025
                                :prefix (if colon? "(" "")
 
1026
                                :suffix (if colon? ")" ""))
 
1027
    (pprint-exit-if-list-exhausted)
 
1028
    (loop
 
1029
      (write-object (pprint-pop) stream)
 
1030
      (pprint-exit-if-list-exhausted)
 
1031
      (write-char #\space stream)
 
1032
      (pprint-newline :linear stream))))
 
1033
 
 
1034
(defun pprint-tabular (stream list &optional (colon? t) atsign? tabsize)
 
1035
  "Output LIST to STREAM tabbing to the next column that is an even multiple
 
1036
   of TABSIZE (which defaults to 16) between each element.  :FILL style
 
1037
   conditional newlines are also output between each element.  If COLON? is
 
1038
   NIL (defaults to T), then no parens are printed around the output.
 
1039
   ATSIGN? is ignored (but allowed so that PPRINT-TABULAR can be used with
 
1040
   the ~/.../ format directive."
 
1041
  (declare (ignore atsign?))
 
1042
  (pprint-logical-block (stream list
 
1043
                                :prefix (if colon? "(" "")
 
1044
                                :suffix (if colon? ")" ""))
 
1045
    (pprint-exit-if-list-exhausted)
 
1046
    (loop
 
1047
      (write-object (pprint-pop) stream)
 
1048
      (pprint-exit-if-list-exhausted)
 
1049
      (write-char #\space stream)
 
1050
      (pprint-tab :section-relative 0 (or tabsize 16) stream)
 
1051
      (pprint-newline :fill stream))))
 
1052
 
 
1053
 
 
1054
;;;; Pprint-dispatch tables.
 
1055
 
 
1056
(defvar *initial-pprint-dispatch*)
 
1057
 
 
1058
(defstruct (pprint-dispatch-entry
 
1059
            (:print-function %print-pprint-dispatch-entry))
 
1060
  ;;
 
1061
  ;; The type specifier for this entry.
 
1062
  (type (required-argument) :type t)
 
1063
  ;;
 
1064
  ;; The priority for this guy.
 
1065
  (priority 0 :type real)
 
1066
  ;;
 
1067
  ;; T iff one of the original entries.
 
1068
  (initial-p (not (boundp '*initial-pprint-dispatch*)) :type (member t nil))
 
1069
  ;;
 
1070
  ;; And the associated function.
 
1071
  (function (required-argument) :type (or function symbol)))
 
1072
 
 
1073
(defun %print-pprint-dispatch-entry (entry stream depth)
 
1074
  (declare (ignore depth))
 
1075
  (print-unreadable-object (entry stream :type t)
 
1076
    (format stream "Type=~S, priority=~S~@[ [Initial]~]"
 
1077
            (pprint-dispatch-entry-type entry)
 
1078
            (pprint-dispatch-entry-priority entry)
 
1079
            (pprint-dispatch-entry-initial-p entry))))
 
1080
 
 
1081
(defstruct (pprint-dispatch-table
 
1082
            (:print-function %print-pprint-dispatch-table))
 
1083
  ;;
 
1084
  ;; A list of all the entries (except for CONS entries below) in highest
 
1085
  ;; to lowest priority.
 
1086
  (entries nil :type list)
 
1087
  ;;
 
1088
  ;; A hash table mapping things to entries for type specifiers of the
 
1089
  ;; form (CONS (MEMBER <thing>)).  If the type specifier is of this form,
 
1090
  ;; we put it in this hash table instead of the regular entries table.
 
1091
  (cons-entries (make-hash-table :test #'eql)))
 
1092
 
 
1093
(defun %print-pprint-dispatch-table (table stream depth)
 
1094
  (declare (ignore depth))
 
1095
  (print-unreadable-object (table stream :type t :identity t)))
 
1096
 
 
1097
(defun cons-type-specifier-p (spec)
 
1098
  (declare (si::c-local))
 
1099
  (and (consp spec)
 
1100
       (eq (car spec) 'cons)
 
1101
       (cdr spec)
 
1102
       (null (cddr spec))
 
1103
       (let ((car (cadr spec)))
 
1104
         (and (consp car)
 
1105
              (let ((carcar (car car)))
 
1106
                (or (eq carcar 'member)
 
1107
                    (eq carcar 'eql)))
 
1108
              (cdr car)
 
1109
              (null (cddr car))))))
 
1110
 
 
1111
(defun entry< (e1 e2)
 
1112
  (declare (type pprint-dispatch-entry e1 e2)
 
1113
           (si::c-local))
 
1114
  (if (pprint-dispatch-entry-initial-p e1)
 
1115
      (if (pprint-dispatch-entry-initial-p e2)
 
1116
          (< (pprint-dispatch-entry-priority e1)
 
1117
             (pprint-dispatch-entry-priority e2))
 
1118
          t)
 
1119
      (if (pprint-dispatch-entry-initial-p e2)
 
1120
          nil
 
1121
          (< (pprint-dispatch-entry-priority e1)
 
1122
             (pprint-dispatch-entry-priority e2)))))
 
1123
 
 
1124
 
 
1125
(defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*))
 
1126
  (declare (type (or pprint-dispatch-table null) table))
 
1127
  (let* ((orig (or table *initial-pprint-dispatch*))
 
1128
         (new (make-pprint-dispatch-table
 
1129
               :entries (copy-list (pprint-dispatch-table-entries orig))))
 
1130
         (new-cons-entries (pprint-dispatch-table-cons-entries new)))
 
1131
    (maphash #'(lambda (key value)
 
1132
                 (setf (gethash key new-cons-entries) value))
 
1133
             (pprint-dispatch-table-cons-entries orig))
 
1134
    new))
 
1135
 
 
1136
(defun pprint-dispatch (object &optional (table *print-pprint-dispatch*))
 
1137
  (declare (type (or pprint-dispatch-table null) table))
 
1138
  (let* ((table (or table *initial-pprint-dispatch*))
 
1139
         (cons-entry
 
1140
          (and (consp object)
 
1141
               (gethash (car object)
 
1142
                        (pprint-dispatch-table-cons-entries table))))
 
1143
         (entry
 
1144
          (dolist (entry (pprint-dispatch-table-entries table) cons-entry)
 
1145
            (when (and cons-entry
 
1146
                       (entry< entry cons-entry))
 
1147
              (return cons-entry))
 
1148
            (when (typep object (pprint-dispatch-entry-type entry))
 
1149
              (return entry)))))
 
1150
    (if entry
 
1151
        (values (pprint-dispatch-entry-function entry) t)
 
1152
        (values #'(lambda (stream object)
 
1153
                    (write-ugly-object object stream))
 
1154
                nil))))
 
1155
 
 
1156
(defun set-pprint-dispatch (type function &optional
 
1157
                            (priority 0) (table *print-pprint-dispatch*))
 
1158
  (declare (type (or null function) function)
 
1159
           (type real priority)
 
1160
           (type pprint-dispatch-table table))
 
1161
  ;; FIXME! This check should be automatically generated when compiling
 
1162
  ;; with high enough safety mode.
 
1163
  (unless (typep priority 'real)
 
1164
    (error 'simple-type-error
 
1165
           :format-control "Not a valid priority for set-pprint-dispatch: ~A"
 
1166
           :format-arguments (list priority)
 
1167
           :expected-type 'real
 
1168
           :datum priority))
 
1169
  (if function
 
1170
      (if (cons-type-specifier-p type)
 
1171
          (setf (gethash (second (second type))
 
1172
                         (pprint-dispatch-table-cons-entries table))
 
1173
                (make-pprint-dispatch-entry :type type :priority priority
 
1174
                                            :function function))
 
1175
          (let ((list (delete type (pprint-dispatch-table-entries table)
 
1176
                              :key #'pprint-dispatch-entry-type
 
1177
                              :test #'equal))
 
1178
                (entry (make-pprint-dispatch-entry
 
1179
                        :type type
 
1180
                        :priority priority :function function)))
 
1181
            (do ((prev nil next)
 
1182
                 (next list (cdr next)))
 
1183
                ((null next)
 
1184
                 (if prev
 
1185
                     (setf (cdr prev) (list entry))
 
1186
                     (setf list (list entry))))
 
1187
              (when (entry< (car next) entry)
 
1188
                (if prev
 
1189
                    (setf (cdr prev) (cons entry next))
 
1190
                    (setf list (cons entry next)))
 
1191
                (return)))
 
1192
            (setf (pprint-dispatch-table-entries table) list)))
 
1193
      (if (cons-type-specifier-p type)
 
1194
          (remhash (second (second type))
 
1195
                   (pprint-dispatch-table-cons-entries table))
 
1196
          (setf (pprint-dispatch-table-entries table)
 
1197
                (delete type (pprint-dispatch-table-entries table)
 
1198
                        :key #'pprint-dispatch-entry-type
 
1199
                        :test #'equal))))
 
1200
  nil)
 
1201
 
 
1202
 
 
1203
;;;; Standard pretty-printing routines.
 
1204
 
 
1205
(defun pprint-array (stream array)
 
1206
  (cond ((or (and (null *print-array*) (null *print-readably*))
 
1207
             (stringp array)
 
1208
             (bit-vector-p array))
 
1209
         (write-ugly-object array stream))
 
1210
        (*print-readably*
 
1211
         (pprint-raw-array stream array))
 
1212
        ((vectorp array)
 
1213
         (pprint-vector stream array))
 
1214
        (t
 
1215
         (pprint-multi-dim-array stream array))))
 
1216
 
 
1217
(defun pprint-vector (stream vector)
 
1218
  (pprint-logical-block (stream nil :prefix "#(" :suffix ")")
 
1219
    (dotimes (i (length vector))
 
1220
      (unless (zerop i)
 
1221
        (write-char #\space stream)
 
1222
        (pprint-newline :fill stream))
 
1223
      (pprint-pop)
 
1224
      (write-object (aref vector i) stream))))
 
1225
 
 
1226
(defun pprint-array-contents (stream array)
 
1227
  (declare (si::c-local)
 
1228
           (array array))
 
1229
  (labels ((output-guts (stream index dimensions)
 
1230
               (if (null dimensions)
 
1231
                   (write-object (row-major-aref array index) stream)
 
1232
                   (pprint-logical-block
 
1233
                    (stream nil :prefix "(" :suffix ")")
 
1234
                    (let ((dim (car dimensions)))
 
1235
                      (unless (zerop dim)
 
1236
                        (let* ((dims (cdr dimensions))
 
1237
                               (index index)
 
1238
                               (step (reduce #'* dims))
 
1239
                               (count 0))
 
1240
                          (loop                         
 
1241
                           (pprint-pop)
 
1242
                           (output-guts stream index dims)
 
1243
                           (when (= (incf count) dim)
 
1244
                             (return))
 
1245
                           (write-char #\space stream)
 
1246
                           (pprint-newline (if dims :linear :fill)
 
1247
                                           stream)
 
1248
                           (incf index step)))))))))
 
1249
    (output-guts stream 0 (array-dimensions array))))
 
1250
 
 
1251
(defun pprint-multi-dim-array (stream array)
 
1252
  (declare (si::c-local))
 
1253
  (funcall (formatter "#~DA") stream (array-rank array))
 
1254
  (pprint-array-contents stream array))
 
1255
 
 
1256
(defun pprint-raw-array (stream array)
 
1257
  (declare (si::c-local))
 
1258
  (write-string "#A" stream)
 
1259
  (pprint-logical-block (stream nil :prefix "(" :suffix ")")
 
1260
    (write-object (array-element-type array) stream)
 
1261
    (write-char #\Space stream)
 
1262
    (pprint-newline :fill stream)
 
1263
    (write-object (array-dimensions array) stream)
 
1264
    (write-char #\Space stream)
 
1265
    (pprint-newline :fill stream)
 
1266
    (pprint-array-contents stream array)))
 
1267
 
 
1268
(defun pprint-lambda-list (stream lambda-list &rest noise)
 
1269
  (declare (ignore noise))
 
1270
  (pprint-logical-block (stream lambda-list :prefix "(" :suffix ")")
 
1271
    (let ((state :required)
 
1272
          (first t))
 
1273
      (loop
 
1274
        (pprint-exit-if-list-exhausted)
 
1275
        (unless first
 
1276
          (write-char #\space stream))
 
1277
        (let ((arg (pprint-pop)))
 
1278
          (unless first
 
1279
            (case arg
 
1280
              (&optional
 
1281
               (setf state :optional)
 
1282
               (pprint-newline :linear stream))
 
1283
              ((&rest &body)
 
1284
               (setf state :required)
 
1285
               (pprint-newline :linear stream))
 
1286
              (&key
 
1287
               (setf state :key)
 
1288
               (pprint-newline :linear stream))
 
1289
              (&aux
 
1290
               (setf state :optional)
 
1291
               (pprint-newline :linear stream))
 
1292
              (t
 
1293
               (pprint-newline :fill stream))))
 
1294
          (ecase state
 
1295
            (:required
 
1296
             (pprint-lambda-list stream arg))
 
1297
            ((:optional :key)
 
1298
             (pprint-logical-block
 
1299
                 (stream arg :prefix "(" :suffix ")")
 
1300
               (pprint-exit-if-list-exhausted)
 
1301
               (if (eq state :key)
 
1302
                   (pprint-logical-block
 
1303
                       (stream (pprint-pop) :prefix "(" :suffix ")")
 
1304
                     (pprint-exit-if-list-exhausted)
 
1305
                     (write-object (pprint-pop) stream)
 
1306
                     (pprint-exit-if-list-exhausted)
 
1307
                     (write-char #\space stream)
 
1308
                     (pprint-newline :fill stream)
 
1309
                     (pprint-lambda-list stream (pprint-pop))
 
1310
                     (loop
 
1311
                       (pprint-exit-if-list-exhausted)
 
1312
                       (write-char #\space stream)
 
1313
                       (pprint-newline :fill stream)
 
1314
                       (write-object (pprint-pop) stream)))
 
1315
                   (pprint-lambda-list stream (pprint-pop)))
 
1316
               (loop
 
1317
                 (pprint-exit-if-list-exhausted)
 
1318
                 (write-char #\space stream)
 
1319
                 (pprint-newline :linear stream)
 
1320
                 (write-object (pprint-pop) stream))))))
 
1321
        (setf first nil)))))
 
1322
 
 
1323
(defun pprint-lambda (stream list &rest noise)
 
1324
  (declare (ignore noise))
 
1325
  (funcall (formatter
 
1326
            "~:<~^~W~^~3I ~:_~/SI:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
 
1327
           stream list))
 
1328
 
 
1329
(defun pprint-block (stream list &rest noise)
 
1330
  (declare (ignore noise))
 
1331
  (funcall (formatter "~:<~^~W~^~3I ~:_~W~1I~@{ ~_~W~}~:>") stream list))
 
1332
 
 
1333
(defun pprint-flet (stream list &rest noise)
 
1334
  (declare (ignore noise))
 
1335
  (funcall (formatter
 
1336
            "~:<~^~W~^ ~@_~:<~@{~:<~^~W~^~3I ~:_~/SI:PPRINT-LAMBDA-LIST/~1I~:@_~@{~W~^ ~_~}~:>~^ ~_~}~:>~1I~@:_~@{~W~^ ~_~}~:>")
 
1337
           stream
 
1338
           list))
 
1339
 
 
1340
(defun pprint-let (stream list &rest noise)
 
1341
  (declare (ignore noise))
 
1342
  (funcall (formatter "~:<~^~W~^ ~@_~:<~@{~:<~^~W~@{ ~_~W~}~:>~^ ~_~}~:>~1I~:@_~@{~W~^ ~_~}~:>")
 
1343
           stream
 
1344
           list))
 
1345
 
 
1346
(defun pprint-progn (stream list &rest noise)
 
1347
  (declare (ignore noise))
 
1348
  (funcall (formatter "~:<~^~W~@{ ~_~W~}~:>") stream list))
 
1349
 
 
1350
(defun pprint-progv (stream list &rest noise)
 
1351
  (declare (ignore noise))
 
1352
  (funcall (formatter "~:<~^~W~^~3I ~_~W~^ ~_~W~^~1I~@{ ~_~W~}~:>")
 
1353
           stream list))
 
1354
 
 
1355
(defun pprint-quote (stream list &rest noise)
 
1356
  (declare (ignore noise))
 
1357
  (if (and (consp list)
 
1358
           (consp (cdr list))
 
1359
           (null (cddr list)))
 
1360
      (case (car list)
 
1361
        (function
 
1362
         (write-string "#'" stream)
 
1363
         (write-object (cadr list) stream))
 
1364
        (quote
 
1365
         (write-char #\' stream)
 
1366
         (write-object (cadr list) stream))
 
1367
        (t
 
1368
         (pprint-fill stream list)))
 
1369
      (pprint-fill stream list)))
 
1370
 
 
1371
(defun pprint-setq (stream list &rest noise)
 
1372
  (declare (ignore noise))
 
1373
  (pprint-logical-block (stream list :prefix "(" :suffix ")")
 
1374
    (pprint-exit-if-list-exhausted)
 
1375
    (write-object (pprint-pop) stream)
 
1376
    (pprint-exit-if-list-exhausted)
 
1377
    (write-char #\space stream)
 
1378
    (pprint-newline :miser stream)
 
1379
    (if (and (consp (cdr list)) (consp (cddr list)))
 
1380
        (loop
 
1381
          (pprint-indent :current 2 stream)
 
1382
          (write-object (pprint-pop) stream)
 
1383
          (pprint-exit-if-list-exhausted)
 
1384
          (write-char #\space stream)
 
1385
          (pprint-newline :linear stream)
 
1386
          (pprint-indent :current -2 stream)
 
1387
          (write-object (pprint-pop) stream)
 
1388
          (pprint-exit-if-list-exhausted)
 
1389
          (write-char #\space stream)
 
1390
          (pprint-newline :linear stream))
 
1391
        (progn
 
1392
          (pprint-indent :current 0 stream)
 
1393
          (write-object (pprint-pop) stream)
 
1394
          (pprint-exit-if-list-exhausted)
 
1395
          (write-char #\space stream)
 
1396
          (pprint-newline :linear stream)
 
1397
          (write-object (pprint-pop) stream)))))
 
1398
 
 
1399
#+ecl-min  
 
1400
(defmacro pprint-tagbody-guts (stream)
 
1401
  `(loop
 
1402
     (pprint-exit-if-list-exhausted)
 
1403
     (write-char #\space ,stream)
 
1404
     (let ((form-or-tag (pprint-pop)))
 
1405
       (pprint-indent :block 
 
1406
                      (if (atom form-or-tag) 0 1)
 
1407
                      ,stream)
 
1408
       (pprint-newline :linear ,stream)
 
1409
       (write-object form-or-tag ,stream))))
 
1410
 
 
1411
(defun pprint-tagbody (stream list &rest noise)
 
1412
  (declare (ignore noise))
 
1413
  (pprint-logical-block (stream list :prefix "(" :suffix ")")
 
1414
    (pprint-exit-if-list-exhausted)
 
1415
    (write-object (pprint-pop) stream)
 
1416
    (pprint-tagbody-guts stream)))
 
1417
 
 
1418
(defun pprint-case (stream list &rest noise)
 
1419
  (declare (ignore noise))
 
1420
  (funcall (formatter
 
1421
            "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~:/SI:PPRINT-FILL/~^~@{ ~_~W~}~:>~}~:>")
 
1422
           stream
 
1423
           list))
 
1424
 
 
1425
(defun pprint-defun (stream list &rest noise)
 
1426
  (declare (ignore noise))
 
1427
  (funcall (formatter
 
1428
            "~:<~^~W~^ ~@_~:I~W~^ ~:_~/SI:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
 
1429
           stream
 
1430
           list))
 
1431
 
 
1432
(defun pprint-destructuring-bind (stream list &rest noise)
 
1433
  (declare (ignore noise))
 
1434
  (funcall (formatter
 
1435
            "~:<~^~W~^~3I ~_~:/SI:PPRINT-LAMBDA-LIST/~^ ~_~W~^~1I~@{ ~_~W~}~:>")
 
1436
           stream list))
 
1437
 
 
1438
(defun pprint-do (stream list &rest noise)
 
1439
  (declare (ignore noise))
 
1440
  (pprint-logical-block (stream list :prefix "(" :suffix ")")
 
1441
    (pprint-exit-if-list-exhausted)
 
1442
    (write-object (pprint-pop) stream)
 
1443
    (pprint-exit-if-list-exhausted)
 
1444
    (write-char #\space stream)
 
1445
    (pprint-indent :current 0 stream)
 
1446
    (funcall (formatter "~:<~@{~:<~^~W~^ ~@_~:I~W~@{ ~_~W~}~:>~^~:@_~}~:>")
 
1447
             stream
 
1448
             (pprint-pop))
 
1449
    (pprint-exit-if-list-exhausted)
 
1450
    (write-char #\space stream)
 
1451
    (pprint-newline :linear stream)
 
1452
    (pprint-linear stream (pprint-pop))
 
1453
    (pprint-tagbody-guts stream)))
 
1454
 
 
1455
(defun pprint-dolist (stream list &rest noise)
 
1456
  (declare (ignore noise))
 
1457
  (pprint-logical-block (stream list :prefix "(" :suffix ")")
 
1458
    (pprint-exit-if-list-exhausted)
 
1459
    (write-object (pprint-pop) stream)
 
1460
    (pprint-exit-if-list-exhausted)
 
1461
    (pprint-indent :block 3 stream)
 
1462
    (write-char #\space stream)
 
1463
    (pprint-newline :fill stream)
 
1464
    (funcall (formatter "~:<~^~W~^ ~:_~:I~W~@{ ~_~W~}~:>")
 
1465
             stream
 
1466
             (pprint-pop))
 
1467
    (pprint-tagbody-guts stream)))
 
1468
 
 
1469
(defun pprint-typecase (stream list &rest noise)
 
1470
  (declare (ignore noise))
 
1471
  (funcall (formatter
 
1472
            "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~W~^~@{ ~_~W~}~:>~}~:>")
 
1473
           stream
 
1474
           list))
 
1475
 
 
1476
(defun pprint-prog (stream list &rest noise)
 
1477
  (declare (ignore noise))
 
1478
  (pprint-logical-block (stream list :prefix "(" :suffix ")")
 
1479
    (pprint-exit-if-list-exhausted)
 
1480
    (write-object (pprint-pop) stream)
 
1481
    (pprint-exit-if-list-exhausted)
 
1482
    (write-char #\space stream)
 
1483
    (pprint-newline :miser stream)
 
1484
    (pprint-fill stream (pprint-pop))
 
1485
    (pprint-tagbody-guts stream)))
 
1486
 
 
1487
(defun pprint-function-call (stream list &rest noise)
 
1488
  (declare (ignore noise))
 
1489
  (funcall (formatter "~:<~^~W~^ ~:_~:I~@{~W~^ ~_~}~:>")
 
1490
           stream
 
1491
           list))
 
1492
 
 
1493
 
 
1494
;;;; Interface seen by regular (ugly) printer and initialization routines.
 
1495
 
 
1496
(eval-when (:compile-toplevel :execute)
 
1497
(defconstant +magic-forms+
 
1498
  '((lambda pprint-lambda)
 
1499
    ;; Special forms.
 
1500
    (block pprint-block)
 
1501
    (catch pprint-block)
 
1502
    (compiler-let pprint-let)
 
1503
    (eval-when pprint-block)
 
1504
    (flet pprint-flet)
 
1505
    (function pprint-quote)
 
1506
    (labels pprint-flet)
 
1507
    (let pprint-let)
 
1508
    (let* pprint-let)
 
1509
    (locally pprint-progn)
 
1510
    (macrolet pprint-flet)
 
1511
    (multiple-value-call pprint-block)
 
1512
    (multiple-value-prog1 pprint-block)
 
1513
    (progn pprint-progn)
 
1514
    (progv pprint-progv)
 
1515
    (quote pprint-quote)
 
1516
    (return-from pprint-block)
 
1517
    (setq pprint-setq)
 
1518
    (symbol-macrolet pprint-let)
 
1519
    (tagbody pprint-tagbody)
 
1520
    (throw pprint-block)
 
1521
    (unwind-protect pprint-block)
 
1522
    
 
1523
    ;; Macros.
 
1524
    (case pprint-case)
 
1525
    (ccase pprint-case)
 
1526
    (ctypecase pprint-typecase)
 
1527
    (defconstant pprint-block)
 
1528
    (define-modify-macro pprint-defun)
 
1529
    (define-setf-expander pprint-defun)
 
1530
    (defmacro pprint-defun)
 
1531
    (defparameter pprint-block)
 
1532
    (defsetf pprint-defun)
 
1533
    (defstruct pprint-block)
 
1534
    (deftype pprint-defun)
 
1535
    (defun pprint-defun)
 
1536
    (defvar pprint-block)
 
1537
    (destructuring-bind pprint-destructuring-bind)
 
1538
    (do pprint-do)
 
1539
    (do* pprint-do)
 
1540
    (do-all-symbols pprint-dolist)
 
1541
    (do-external-symbols pprint-dolist)
 
1542
    (do-symbols pprint-dolist)
 
1543
    (dolist pprint-dolist)
 
1544
    (dotimes pprint-dolist)
 
1545
    (ecase pprint-case)
 
1546
    (etypecase pprint-typecase)
 
1547
    #+nil (handler-bind ...)
 
1548
    #+nil (handler-case ...)
 
1549
    #+nil (loop ...)
 
1550
    (multiple-value-bind pprint-progv)
 
1551
    (multiple-value-setq pprint-block)
 
1552
    (pprint-logical-block pprint-block)
 
1553
    (print-unreadable-object pprint-block)
 
1554
    (prog pprint-prog)
 
1555
    (prog* pprint-prog)
 
1556
    (prog1 pprint-block)
 
1557
    (prog2 pprint-progv)
 
1558
    (psetf pprint-setq)
 
1559
    (psetq pprint-setq)
 
1560
    #+nil (restart-bind ...)
 
1561
    #+nil (restart-case ...)
 
1562
    (setf pprint-setq)
 
1563
    (step pprint-progn)
 
1564
    (time pprint-progn)
 
1565
    (typecase pprint-typecase)
 
1566
    (unless pprint-block)
 
1567
    (when pprint-block)
 
1568
    (with-compilation-unit pprint-block)
 
1569
    #+nil (with-condition-restarts ...)
 
1570
    (with-hash-table-iterator pprint-block)
 
1571
    (with-input-from-string pprint-block)
 
1572
    (with-open-file pprint-block)
 
1573
    (with-open-stream pprint-block)
 
1574
    (with-output-to-string pprint-block)
 
1575
    (with-package-iterator pprint-block)
 
1576
    (with-simple-restart pprint-block)
 
1577
    (with-standard-io-syntax pprint-progn))))
 
1578
 
 
1579
(progn
 
1580
  (let ((*print-pprint-dispatch* (make-pprint-dispatch-table)))
 
1581
    ;; Printers for regular types.
 
1582
    (set-pprint-dispatch 'array #'pprint-array)
 
1583
    (set-pprint-dispatch '(cons (and symbol (satisfies fboundp)))
 
1584
                         #'pprint-function-call -1)
 
1585
    (set-pprint-dispatch 'cons #'pprint-fill -2)
 
1586
    ;; Cons cells with interesting things for the car.
 
1587
    (dolist (magic-form '#.+magic-forms+)
 
1588
      (set-pprint-dispatch `(cons (eql ,(first magic-form)))
 
1589
                           (symbol-function (second magic-form))))
 
1590
    (setf *initial-pprint-dispatch* *print-pprint-dispatch*)
 
1591
    )
 
1592
  (setf *print-pprint-dispatch* (copy-pprint-dispatch nil))
 
1593
  #-ecl-min
 
1594
  (setf *print-pretty* t))