    (put-string port "        " 0 (min 8 n))
      (when (< 8 n)
        (spaces (- n 8)))))

  (define (indent to)
    (let ((col (port-column port)))
      (cond
       ((< to col)
        (put-string port "\n")
        (put-string port per-line-prefix)
        (spaces (- to (string-length per-line-prefix))))
       (else
        (spaces (- to col))))))

  (define (pr obj pp-pair)
    (match obj
      ((? vector?)
       (put-string port "#")
       (pr (vector->list obj) pp-pair))
      ((not (? pair?))
       (wr obj port))
      (('quote x)            (put-string port "'") (pr x pp-pair))
      (('quasiquote x)       (put-string port "`") (pr x pp-pair))
      (('unquote x)          (put-string port ",") (pr x pp-pair))
      (('unquote-splicing x) (put-string port ",@") (pr x pp-pair))
      (_
       ;; A pair (and possibly a list).  May have to split on multiple
       ;; lines.
       (call-with-truncating-output-string
        (lambda (port) (wr obj port))
        (lambda (full-str) (put-string port full-str))
        (lambda (partial-str) (pp-pair obj))
        #:initial-column (port-column port)
        #:max-column (- width (string-length per-line-prefix))
        #:allow-newline? #f))))

  (define (pp-expr expr)
    (match expr
      (((or 'quote 'quasiquote 'unquote 'unquote-splicing) _)
       (pp-quote expr))
      (('lambda _ _ . _)         (pp-lambda expr))
      (('lambda* _ _ . _)        (pp-lambda expr))
      (('let (? symbol?) _ _ . _) (pp-named-let expr))
      (('let _ _ . _)            (pp-let expr))
      (('let* _ _ . _)           (pp-let expr))
      (('letrec _ _ . _)         (pp-let expr))
      (('letrec* _ _ . _)        (pp-let expr))
      (('let-syntax _ _ . _)     (pp-let expr))
      (('letrec-syntax _ _ . _)  (pp-let expr))
      (('define _ _ . _)         (pp-define expr))
      (('define* _ _ . _)        (pp-define expr))
      (('define-public _ _ . _)  (pp-define expr))
      (('define-syntax _ _ . _)  (pp-define expr))
      (('if _ _ . (or () (_)))   (pp-if expr))
      (('cond . _)               (pp-cond expr))
      (('case _ . _)             (pp-case expr))
      (('begin . _)              (pp-begin expr))
      (('do _ _ . _)             (pp-do expr))
      (('syntax-rules _ . _)     (pp-syntax-rules expr))
      (('syntax-case _ _ . _)    (pp-syntax-case expr))
      (((? symbol? head) . _)
       (if (< max-call-head-width (string-length (symbol->string head)))
           (pp-list expr pp-expr)
           (pp-call expr pp-expr)))
      (_ (pp-list expr pp-expr))))

  (define (pp0 head body)
    (let ((body-col (+ (port-column port) indent-general)))
      (put-string port "(")
      (wr head port)
      (pp-down body body-col pp-expr)))

  (define (pp1 head param0 body pp-param0)
    (let ((body-col (+ (port-column port) indent-general)))
      (put-string port "(")
      (wr head port)
      (put-string port " ")
      (pr param0 pp-param0)
      (pp-down body body-col pp-expr)))

  (define (pp2 head param0 param1 body pp-param0 pp-param1)
    (let ((body-col (+ (port-column port) indent-general)))
      (put-string port "(")
      (wr head port)
      (put-string port " ")
      (pr param0 pp-param0)
      (put-string port " ")
      (pr param1 pp-param1)
      (pp-down body body-col pp-expr)))

  (define (pp-quote expr)
    (match obj
      ((head x)
       (put-string port
                   (match x
                     ('quote "'")
                     ('quasiquote "`")
                     ('unquote ",")
                     ('unquote-splicing ",@")))
       (pr x pp-expr))))

  (define (pp-lambda expr)
    (match expr
      ((head args . body)
       (pp1 head args body pp-expr-list))))

  (define (pp-let expr)
    (match expr
      ((head bindings . body)
       (pp1 head bindings body pp-expr-list))))

  (define (pp-named-let expr)
    (match expr
      ((head name bindings . body)
       (pp2 head name bindings body pp-expr pp-expr-list))))

  (define (pp-define expr)
    (match expr
      ((head args . body)
       (pp1 head args body pp-expr-list))))

  (define (pp-if expr)
    (match expr
      ((head test . body)
       ;; "if" indent is 4.
       (put-string port "(")
       (wr head port)
       (put-string port " ")
       (let ((body-col (port-column port)))
         (pr test pp-expr)
         (pp-down body body-col pp-expr)))))

  (define (pp-cond expr)
    (match expr
      ((head . clauses)
       (pp0 head clauses))))

  (define (pp-case expr)
    (match expr
      ((head x . clauses)
       (pp1 head x clauses pp-expr))))

  (define (pp-begin expr)
    (match expr
      ((head . body) (pp0 head body))))

  (define (pp-do expr)
    (match expr
      ((head bindings exit . body)
       (pp2 head bindings exit body pp-expr-list pp-expr-list))))

  (define (pp-syntax-rules expr)
    (match expr
      ((head literals . clauses)
       (pp1 head literals clauses pp-expr-list))))

  (define (pp-syntax-case expr)
    (match expr
      ((head stx literals . clauses)
       (pp2 head stx literals clauses pp-expr pp-expr-list))))

                                        ; (head item1
                                        ;       item2
                                        ;       item3)
  (define (pp-call expr pp-item)
    (match expr
      ((head . tail)
       (put-string port "(")
       (wr head port)
       (pp-down tail (+ (port-column port) 1) pp-item))))

                                        ; (item1
                                        ;  item2
                                        ;  item3)
  (define (pp-list l pp-item)
    (put-string port "(")
    (pp-down l (port-column port) pp-item))

  (define (pp-down l item-indent pp-item)
    (let loop ((l l))
      (match l
        (() (put-string port ")"))
        ((head . tail)
         (indent item-indent)
         (pr head pp-item)
         (loop tail))
        (improper-tail
         (indent item-indent)
         (put-string port ".")
         (indent item-indent)
         (pr improper-tail pp-item)
         (put-string port ")")))))

  (define (pp-expr-list l)
    (pp-list l pp-expr))

  (put-string port per-line-prefix)
  (pr obj pp-expr)
  (newline port)
  ;; Return `unspecified'
  (if #f #f))


