This file is indexed.

/usr/share/scheme48-1.9/big/pp.scm is in scheme48 1.9-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
; Part of Scheme 48 1.9.  See file COPYING for notices and license.

; Authors: John Ramsdell, Richard Kelsey, Jonathan Rees

;;;; A pretty-printer

; This isn't exactly in the spirit of the rest of the Scheme 48
; system.  It's too hairy, and it has unexploited internal generality.
; It really ought to be rewritten.  In addition, it seems to be buggy
; -- it sometimes prints unnecessarily wide lines.  Usually it's
; better than no pretty printer at all, so we tolerate it.

; From: ramsdell@linus.mitre.org
; Date:  Wed, 12 Sep 1990 05:14:49 PDT
;
; As you noted in your comments, pp.scm is not a straight forward
; program.  You could add some comments that would greatly ease the task
; of figuring out what his going on.  In particular, you should describe
; the interface of various objects---most importantly the interface of a
; formatter.  You might also add some description as to what protocol
; they are to follow.

; Other things to implement some day:
;  - LET, LET*, LETREC binding lists should be printed vertically if longer
;    than about 30 characters
;  - COND clauses should all be printed vertically if the COND is vertical
;  - Add an option to lowercase or uppercase symbols and named characters.
;  - Parameters controlling behavior of printer should be passed around
;  - Do something about choosing between #f and ()
;  - Insert line breaks intelligently following head of symbol-headed list,
;    when necessary
;  - Some equivalents of *print-level*, *print-length*, *print-circle*.

; Possible strategies:
;   (foo x y z)     Horizontal = infinity sticky 
;   (foo x y        One sticky + one + body (e.g. named LET)
;     z
;     w)
;   (foo x          One + body
;     y
;     z)
;   (foo x          Two + body
;        y
;     z)
;   (foo x          Big ell = infinity + body (combination)
;	 y
;	 z)
;   (foo            Little ell, zero + body (combination)
;     x
;     y)
;   (foo            Vertical
;    x
;    y)
;
; Available height/width tradeoffs:
;   Combination:
;     Horizontal, big ell, or little ell.
;   Special form:
;     Horizontal, or M sticky + N + body.
;   Random (e.g. vector, improper list, non-symbol-headed list):
;     Horizontal, or vertical.  (Never zero plus body.)

(define (p x . port-option)
  (let ((port (if (pair? port-option) (car port-option)
		  (current-output-port))))
    (pretty-print x port 0)
    (newline port)))

(define *line-width* 80)

(define *single-line-special-form-limit* 30)

; Stream primitives

(define head car)
(define (tail s) (force (cdr s)))

(define (map-stream proc stream)
  (cons (proc (head stream))
	(delay (map-stream proc (tail stream)))))

(define (stream-ref stream n)
  (if (= n 0)
      (head stream)
      (stream-ref (tail stream) (- n 1))))

; Printer

(define (pretty-print obj port pos)
  (let ((node (pp-prescan obj 0)))
;    (if (> (column-of (node-dimensions node)) *line-width*)
;        ;; Eventually add a pass to change format of selected combinations
;        ;; from big-ell to little-ell.
;        (begin (display ";** too wide - ")
;               (write (node-dimensions node))
;               (newline)))
    (print-node node port pos)))

(define make-node list)

(define (node-dimensions node)
  ((car node)))

(define (node-pass-2 node pos)
  ((cadr node) pos))

(define (print-node node port pos)
  ((caddr node) port pos))

(define (pp-prescan obj hang)
  (cond ((symbol? obj)
         (make-leaf (string-length (symbol->string obj))
                    obj hang))
        ((number? obj)
         (make-leaf (string-length (number->string obj))
                    obj hang))
        ((boolean? obj)
         (make-leaf 2 obj hang))
        ((string? obj)
         ;;++ Should count number of backslashes and quotes
         (make-leaf (+ (string-length obj) 2) obj hang))
        ((char? obj)
         (make-leaf (case obj
                      ((#\space) 7)
                      ((#\newline) 9)
                      (else 3))
                    obj hang))
        ((pair? obj)
         (pp-prescan-pair obj hang))
        ((vector? obj)
         (pp-prescan-vector obj hang))
	(else
	 (pp-prescan-random obj hang))))

(define (make-leaf width obj hang)
  (let ((width (+ width hang)))
    (make-node (lambda () width)
	       (lambda (pos)
		 (+ pos width))
	       (lambda (port pos)
		 (write obj port)
		 (do ((i 0 (+ i 1)))
		     ((>= i hang) (+ pos width))
		   (write-char #\) port))))))

(define (make-prefix-node string node)
  (let ((len (string-length string)))
    (make-node (lambda ()
		 (+ (node-dimensions node) len))
	       (lambda (pos)
		 (node-pass-2 node (+ pos len)))
	       (lambda (port pos)
		 (display string port)
		 (print-node node port (+ pos len))))))

(define (pp-prescan-vector obj hang)
  (if (= (vector-length obj) 0)
      (make-leaf 3 obj hang)
      (make-prefix-node "#" (pp-prescan-list (vector->list obj) #t hang))))

; Improve later.

(define (pp-prescan-random obj hang)
  (let ((l (disclose obj)))
    (if (list? l)
	(make-prefix-node "#." (pp-prescan-list l #t hang))
	(make-leaf 25 obj hang))))  ;Very random number

(define (pp-prescan-pair obj hang)
  (cond ((read-macro-inverse obj)
         =>
         (lambda (inverse)
	   (make-prefix-node inverse (pp-prescan (cadr obj) hang))))
        (else
         (pp-prescan-list obj #f hang))))

(define (pp-prescan-list obj random? hang)
  (let loop ((l obj) (z '()))
    (if (pair? (cdr l))
	(loop (cdr l)
	      (cons (pp-prescan (car l) 0) z))
	(make-list-node
	  (reverse
	    (if (null? (cdr l))
		(cons (pp-prescan (car l) (+ hang 1)) z)
		(cons (make-prefix-node ". " (pp-prescan (cdr l) (+ hang 1)))
		      (cons (pp-prescan (car l) 0) z))))
	  obj
	  (or random? (not (null? (cdr l))))))))

; Is it sufficient to tell parent node:
;  At a cost of X line breaks, I can make myself narrower by Y columns. ?
; Then how do we decide whether we narrow ourselves or some of our children?

(define (make-list-node node-list obj random?)
  (let* ((random? (or random?
		      ;; Heuristic for things like do, cond, let, ...
		      (not (symbol? (car obj)))
		      (eq? (car obj) 'else)))
	 (probe (if (not random?)
		    (indentation-for (car obj))
		    #f))
	 (format horizontal-format)
	 (dimensions (compute-dimensions node-list format))
	 (go-non-horizontal
	  (lambda (col)
	    (set! format
		  (cond (random? vertical-format)
			(probe (probe obj))
			(else big-ell-format)))
	    (let* ((start-col (+ col 1))
		   (col (node-pass-2 (car node-list) start-col))
		   (final-col
		       (format (cdr node-list) 
			       (lambda (node col target-col)
				 (node-pass-2 node target-col))
			       start-col
			       (+ col 1)
			       col)))
	      (set! dimensions (compute-dimensions node-list format))
	      final-col))))
    (if (> dimensions
	   (if probe
	       *single-line-special-form-limit*
	       *line-width*))
	(go-non-horizontal 0))
    (make-node (lambda () dimensions)
	       (lambda (col) ;Pass 2: if necessary, go non-horizontal
		 (let ((defacto (+ col (column-of dimensions))))
		   (if (> defacto *line-width*)
		       (go-non-horizontal col)
		       defacto)))
	       (lambda (port pos)
		 (write-char #\( port)
		 (let* ((pos (+ pos 1))
			(start-col (column-of pos))
			(pos (print-node (car node-list) port pos)))
		   (format (cdr node-list) 
			   (lambda (node pos target-col)
			     (let ((pos (go-to-column target-col
						      port pos)))
			       (print-node node port pos)))
			   start-col
			   (+ (column-of pos) 1)
			   pos))))))

(define (compute-dimensions node-list format)
  (let* ((start-col 1)			;open paren
	 (pos (+ (make-position start-col 0)
		 (node-dimensions (car node-list)))))
    (format (cdr node-list)
	    (lambda (node pos target-col)
	      (let* ((dims (node-dimensions node))
		     (lines (+ (line-of pos) (line-of dims)))
		     (width (+ target-col (column-of dims))))
		(if (>= (column-of pos) target-col)
		    ;; Line break required
		    (make-position
		     (max (column-of pos) width)
		     (+ lines 1))
		    (make-position width lines))))
	    start-col
	    (+ (column-of pos) 1)	;first-col
	    pos)))

; Three positions are significant
;   (foo baz ...)
;    ^   ^  ^
;    |   |  +--- (column-of pos)
;    |   +------ first-col
;    +---------- start-col

; Separators

(define on-same-line
  (lambda (start-col first-col pos)
    start-col first-col ;ignored
    (+ (column-of pos) 1)))

(define indent-under-first
  (lambda (start-col first-col pos)
    start-col ;ignored
    first-col))

(define indent-for-body
  (lambda (start-col first-col pos)
    first-col ;ignored
    (+ start-col 1)))

(define indent-under-head
  (lambda (start-col first-col pos)
    first-col ;ignored
    start-col))

; Format constructors

(define (once separator format)
  (lambda (tail proc start-col first-col pos)
    (if (null? tail)
	pos
	(let ((target-col (separator start-col first-col pos)))
	  (format (cdr tail)
		  proc
		  start-col
		  first-col
		  (proc (car tail) pos target-col))))))

(define (indefinitely separator)
  (letrec ((self (once separator	;eta
		       (lambda (tail proc start-col first-col pos)
			 (self tail proc start-col first-col pos)))))
    self))

(define (repeatedly separator count format)
  (do ((i 0 (+ i 1))
       (format format
	       (once separator format)))
      ((>= i count) format)))

; Particular formats

(define vertical-format
  (indefinitely indent-under-head))

(define horizontal-format
  (indefinitely on-same-line))

(define big-ell-format
  (indefinitely indent-under-first))

(define little-ell-format
  (indefinitely indent-for-body))

(define format-for-named-let
  (repeatedly on-same-line 2 (indefinitely indent-for-body)))

(define hook-formats
  (letrec ((stream (cons little-ell-format
			 (delay (map-stream (lambda (format)
					      (once indent-under-first format))
					    stream)))))
    stream))

; Hooks for special forms.
; A hook maps an expression to a format.

(define (compute-let-indentation exp)
  (if (and (not (null? (cdr exp)))
	   (symbol? (cadr exp)))
      format-for-named-let
      (stream-ref hook-formats 1)))

(define hook
  (let ((hooks (map-stream (lambda (format)
			     (lambda (exp) exp ;ignored
			       format))
			   hook-formats)))
    (lambda (n)
      (stream-ref hooks n))))


; Table of indent hooks.

(define indentations (make-table))

(define (indentation-for name)
  (table-ref indentations name))

(define (define-indentation name n)
  (table-set! indentations
	      name
	      (if (integer? n) (hook n) n)))

; Indent hooks for Revised^n Scheme.

(for-each (lambda (name)
	    (define-indentation name 1))
	  '(lambda define define-syntax let* letrec let-syntax letrec-syntax
	    case call-with-values call-with-input-file
	    call-with-output-file with-input-from-file
	    with-output-to-file syntax-rules))

(define-indentation 'do            2)
(define-indentation 'call-with-current-continuation 0)

(define-indentation 'let           compute-let-indentation)

; Kludge to force vertical printing (do AND and OR as well?)
(define-indentation 'if            (lambda (exp) big-ell-format))
(define-indentation 'cond          (lambda (exp) big-ell-format))


; Other auxiliaries

(define (go-to-column target-col port pos) ;=> pos
  ;; Writes at least one space or newline
  (let* ((column (column-of pos))
	 (line (if (>= column target-col)
		   (+ (line-of pos) 1)
		   (line-of pos))))
    (do ((column (if (>= column target-col)
		     (begin (newline port) 0)
		     column)
		 (+ column 1)))
	((>= column target-col)
	 (make-position column line))
      (write-char #\space port))))

(define (make-position column line)
  (+ column (* line 1000)))

(define (column-of pos)
  (remainder pos 1000))

(define (line-of pos)
  (quotient pos 1000))

(define (read-macro-inverse x)
  (cond ((and (pair? x)
              (pair? (cdr x))
              (null? (cddr x)))
         (case (car x)
           ((quote)            "'")
           ((quasiquote)       "`")
           ((unquote)          ",")
           ((unquote-splicing) ",@")
           (else #f)))
        (else #f)))

; For the command processor:

;(define-command 'p "<exp>" "pretty-print" '(expression)
;  (p (eval expression (user-package)) (command-output)))