BSD 4_3_Net_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 15 Aug 1983 15:28:21 +0000 (07:28 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 15 Aug 1983 15:28:21 +0000 (07:28 -0800)
Work on file usr/src/usr.bin/lisp/lisplib/pp.l

Synthesized-from: CSRG/cd2/net.2

usr/src/usr.bin/lisp/lisplib/pp.l [new file with mode: 0644]

diff --git a/usr/src/usr.bin/lisp/lisplib/pp.l b/usr/src/usr.bin/lisp/lisplib/pp.l
new file mode 100644 (file)
index 0000000..56c61d2
--- /dev/null
@@ -0,0 +1,417 @@
+(setq rcs-pp-
+   "$Header: /usr/lib/lisp/RCS/pp.l,v 1.2 83/08/15 22:27:54 jkf Exp $")
+
+;;
+;; pp.l                                        -[Mon Aug 15 10:52:13 1983 by jkf]-
+;;
+;; pretty printer for franz lisp
+;;
+
+(declare (macros t))
+
+(declare (special poport pparm1 pparm2 lpar rpar form linel))
+; (declare (localf $patom1 $prd1 $prdf charcnt condclosefile))
+
+; =======================================
+; pretty printer top level routine pp
+;
+;
+; calling form- (pp arg1 arg2 ... argn)
+; the args may be names of functions, atoms with associated values
+; or output descriptors.
+; if argi is:
+;    an atom - it is assumed to be a function name, if there is no
+;             function property associated with it,then it is assumed
+;              to be an atom with a value
+;    (P port)-  port is the output port where the results of the
+;              pretty printing will be sent.
+;              poport is the default if no (P port) is given.
+;    (F fname)- fname is  a file name to write the results in
+;    (A atmname) - means, treat this as an atom with a value, dont
+;              check if it is the name of a function.
+;    (E exp)-   evaluate exp without printing anything
+;    other -   pretty-print the expression as is - no longer an error
+;
+;    Also, rather than printing only a function defn or only a value, we will
+;    let prettyprops decide which props to print.  Finally, prettyprops will
+;    follow the CMULisp format where each element is either a property
+;    or a dotted pair of the form (prop . fn) where in order to print the
+;    given property we call (fn id val prop).  The special properties
+;    function and value are used to denote those "properties" which
+;    do not actually appear on the plist.
+;
+; [history of this code: originally came from Harvard Lisp, hacked to
+; work under franz at ucb, hacked to work at cmu and finally rehacked
+; to work without special cmu macros]
+
+(declare (special $outport$ $fileopen$ prettyprops))
+
+(setq prettyprops '((comment . pp-comment)
+                   (function . pp-function)
+                   (value . pp-value)))
+
+; printret is like print yet it returns the value printed, this is used
+; by pp                
+(def printret
+  (macro ($l$)
+        `(progn (print ,@(cdr $l$)) ,(cadr $l$))))
+
+(def pp
+  (nlambda ($xlist$)
+       (prog ($gcprint $outport$ $cur$ $fileopen$ $prl$ $atm$)
+
+             (setq $gcprint nil)                       ; don't print
+                                                       ; gc messages in pp.
+
+             (setq $outport$ poport)                   ; default port
+             ; check if more to do, if not close output file if it is
+             ; open and leave
+
+
+   toploop    (cond ((null (setq $cur$ (car $xlist$)))
+                    (condclosefile)
+                    (terpr)
+                    (return t)))
+
+             (cond ((dtpr $cur$)
+                    (cond ((equal 'P (car $cur$))      ; specifying a port
+                           (condclosefile)             ; close file if open
+                           (setq $outport$ (eval (cadr $cur$))))
+
+                          ((equal 'F (car $cur$))      ; specifying a file
+                           (condclosefile)             ; close file if open
+                           (setq $outport$ (outfile (cadr $cur$))
+                                 $fileopen$ t))
+
+                                               
+                          ((equal 'E (car $cur$))
+                           (eval (cadr $cur$)))
+
+                          (t (pp-form $cur$ $outport$)))       ;-DNC inserted
+                    (go botloop)))
+
+
+      (mapc (function
+            (lambda (prop)
+                    (prog (printer)
+                          (cond ((dtpr prop)
+                                 (setq printer (cdr prop))
+                                 (setq prop (car prop)))
+                                (t (setq printer 'pp-prop)))
+                          (cond ((eq 'value prop)
+                                 (and (boundp $cur$)
+                                      (apply printer
+                                             (list $cur$
+                                                   (eval $cur$)
+                                                   'value))
+                                      (terpr $outport$)))
+                                ((eq 'function prop)
+                                 (and (getd $cur$)
+                                      (cond ((not (bcdp (getd $cur$)))
+                                             (apply printer
+                                                    (list $cur$
+                                                          (getd $cur$)
+                                                          'function)))
+                                            ; restore message about
+                                            ; bcd since otherwise you
+                                            ; just get nothing and
+                                            ; people were complaining.
+                                            ; - dhl.
+                                            #-cmu
+                                            (t
+                                             (msg N 
+                                                  "pp: function " 
+                                                  (or $cur$)
+                                                  " is machine coded (bcd) "))
+                                            )
+                                      (terpri $outport$)))
+                                ((get $cur$ prop)
+                                 (apply printer
+                                        (list $cur$
+                                              (get $cur$ prop)
+                                              prop))
+                                 (terpri $outport$))))))
+           prettyprops)
+
+
+ botloop      (setq $xlist$ (cdr $xlist$))
+
+             (go toploop))))
+
+(setq pparm1 50 pparm2 100)
+
+;   -DNC These "prettyprinter parameters" are used to decide when we should
+;      quit printing down the right margin and move back to the left -
+;      Do it when the leftmargin > pparm1 and there are more than pparm2
+;      more chars to print in the expression
+
+; cmu prefers dv instead of setq
+
+#+cmu
+(def pp-value (lambda (i v p)
+                     (terpri $outport$)
+                     (pp-form (list 'dv i v) $outport$)))
+
+#-cmu
+(def pp-value (lambda (i v p)
+                     ;;(terpr $outport$) ;; pp-form does an initial terpr.
+                     ;;                        we don't need two.
+                     (pp-form `(setq ,i ',v) $outport$)))
+
+(def pp-function (lambda (i v p)
+                        #+cmu (terpri $outport$)
+                        ;;
+                        ;; add test for traced functions and don't
+                        ;; print the trace mess, just the original
+                        ;; function.  - dhl.
+                        ;;
+                        ;; this test might belong in the main pp
+                        ;; loop but fits in easily here. - dhl
+                        ;;
+                        (cond ((and (dtpr v)
+                                    (dtpr (cadr v))
+                                    (memq (caadr v)
+                                          '(T-nargs T-arglist))
+                                    (cond ((bcdp (get i 'trace-orig-fcn))
+                                           #-cmu
+                                           (msg N 
+                                                "pp: function " 
+                                                (or i) 
+                                                " is machine coded (bcd) ")
+                                           t)
+                                          (t (pp-form 
+                                              (list 'def i 
+                                                    (get i 'trace-orig-fcn))
+                                              $outport$)
+                                             t))))
+                              ; this function need to return t, but
+                              ; pp-form returns nil sometimes.
+                              (t (pp-form (list 'def i v) $outport$)
+                                 t))))
+
+(def pp-prop (lambda (i v p)
+                    #+cmu (terpri $outport$)
+                    (pp-form (list 'defprop i v p) $outport$)))
+
+(def condclosefile 
+  (lambda nil
+         (cond ($fileopen$
+                (terpr $outport$)
+                (close $outport$)
+                (setq $fileopen$ nil)))))
+\f
+;
+; these routines are meant to be used by pp but since
+; some people insist on using them we will set $outport$ to nil
+; as the default
+(setq $outport$ nil)
+
+
+
+(defun pp-form (value &optional ($outport$ poport oport-p) (lmar 0))
+ ($prdf value lmar 0))
+
+; this is for compatability with old code, will remove soon -- jkf
+(def $prpr (lambda (x) (pp-form x $outport$)))
+
+
+\f
+(declare (special rmar))       ; -DNC this used to be m - I've tried to
+                               ; to fix up the pretty printer a bit.  It
+                               ; used to mess up regularly on (a b .c) types
+                               ; of lists.  Also printmacros have been added.
+
+(def $prdf
+  (lambda (l lmar rmar)
+    (prog nil
+;
+;                      - DNC - Here we try to fix the tendency to print a
+;                        thin column down the right margin by allowing it
+;                        to move back to the left if necessary.
+;
+         (cond ((and (>& lmar pparm1) (>& (flatc l (1+ pparm2)) pparm2))
+                (terpri $outport$)
+                (patom "; <<<<< start back on the left <<<<<" $outport$)
+                ($prdf l 5 0)
+                (terpri $outport$)
+                (patom "; >>>>> continue on the right >>>>>" $outport$)
+                (terpri $outport$)
+                (return nil)))
+          (tab lmar $outport$)
+     a    (cond ((and (dtpr l)
+                     (atom (car l))
+                     (or (and (get (car l) 'printmacro)
+                              (funcall (get (car l) 'printmacro)
+                                       l lmar rmar))
+                         (and (get (car l) 'printmacrochar)
+                              (printmacrochar (get (car l) 'printmacrochar)
+                                              l lmar rmar))))
+                (return nil))
+;
+;                              -DNC - a printmacro is a lambda (l lmar rmar)
+;                              attached to the atom.  If it returns nil then
+;                              we assume it did not apply and we continue.
+;                              Otherwise we assume it did the job.
+;
+                ((or (not (dtpr l))
+;                    (*** at the moment we just punt hunks etc)
+                     (and (atom (car l)) (atom (cdr l))))
+                 (return (printret l $outport$)))
+                ((<& (+ rmar (flatc l (charcnt $outport$)))
+                   (charcnt $outport$))
+                ;
+                ;      This is just a heuristic - if print can fit it in then figure that
+;      the printmacros won't hurt.  Note that despite the pretentions there
+;      is no guarantee that everything will fit in before rmar - for example
+;      atoms (and now even hunks) are just blindly printed.    - DNC
+;
+                 (printaccross l lmar rmar))
+                ((and ($patom1 lpar)
+                      (atom (car l))
+                      (not (atom (cdr l)))
+                      (not (atom (cddr l))))
+                 (prog (c)
+                       (printret (car l) $outport$)
+                       ($patom1 '" ")
+                       (setq c (nwritn $outport$))
+                  a    ($prd1 (cdr l) c)
+                       (cond
+                        ((not (atom (cdr (setq l (cdr l)))))
+                         (terpr $outport$)
+                         (go a)))))
+                (t
+                 (prog (c)
+                       (setq c (nwritn $outport$))
+                  a    ($prd1 l c)
+                       (cond
+                        ((not (atom (setq l (cdr l))))
+                         (terpr $outport$)
+                         (go a))))))
+     b    ($patom1 rpar))))
+
+(def $prd1
+  (lambda (l n)
+    (prog nil
+          ($prdf (car l)
+                 n
+                 (cond ((null (setq l (cdr l))) (|1+| rmar))
+                       ((atom l) (setq n nil) (plus 4 rmar (pntlen l)))
+                       (t rmar)))
+          (cond
+           ((null n) ($patom1 '" . ") (return (printret l $outport$))))
+;         (*** setting n is pretty disgusting)
+;         (*** the last arg to $prdf is the space needed for the suffix)
+;              ;Note that this is still not really right - if the prefix
+;              takes several lines one would like to use the old rmar 
+;              until the last line where the " . mumble)" goes.
+       )))
+
+; -DNC here's the printmacro for progs - it replaces some hackery that
+; used to be in the guts of $prdf.
+
+(def printprog
+  (lambda (l lmar rmar)
+    (prog (col)
+          (cond ((cdr (last l)) (return nil)))
+          (setq col (add1 lmar))
+          (princ '|(| $outport$)
+          (princ (car l) $outport$)
+          (princ '| | $outport$)
+          (print (cadr l) $outport$)
+          (mapc '(lambda (x)
+                        (cond ((atom x)
+                               (tab col $outport$)
+                               (print x $outport$))
+                          (t ($prdf x (+ lmar 6) rmar))))
+               (cddr l))
+          (princ '|)| $outport$)
+          (return t))))
+
+(putprop 'prog 'printprog 'printmacro)
+
+;;
+;;     simpler version which
+;;     should look nice for lambda's also.(inside mapcar's) -dhl
+;;
+(defun print-lambda (l lmar rmar)
+  (prog (col)
+       (cond ((cdr (last l)) (return nil)))
+       (setq col (add1 lmar))
+       (princ '|(| $outport$)
+              (princ (car l) $outport$)
+              (princ '| | $outport$)
+              (print (cadr l) $outport$)
+              (let ((c (cond ((eq (car l) 'lambda)
+                              8)
+                             (t 9))))
+                   (mapc '(lambda (x)
+                                  ($prdf x (+ lmar c) rmar))
+                         (cddr l)))
+              (princ '|)| $outport$)
+       (terpr $outport$)
+       (tab lmar $outport$)
+       (return t)))
+
+(putprop 'lambda 'print-lambda 'printmacro)
+(putprop 'nlambda 'print-lambda 'printmacro)
+
+; Here's the printmacro for def.  The original $prdf had some special code
+; for lambda and nlambda.
+
+(def printdef
+  (lambda (l lmar rmar)
+    (cond ((and (zerop lmar)           ; only if we're really printing a defn
+                (zerop rmar)
+                (cadr l)
+                (atom (cadr l))
+                (dtpr (caddr l))
+                (null (cdddr l))
+                (memq (caaddr l) '(lambda nlambda macro lexpr))
+                (null (cdr (last (caddr l)))))
+           (princ '|(| $outport$)
+           (princ 'def $outport$)
+           (princ '| | $outport$)
+           (princ (cadr l) $outport$)
+           (terpri $outport$)
+           (princ '|  (| $outport$)
+           (princ (caaddr l) $outport$)
+           (princ '| | $outport$)
+           (princ (cadaddr l) $outport$)
+           (terpri $outport$)
+           (mapc  '(lambda (x) ($prdf x 4 0)) (cddaddr l))
+           (princ '|))| $outport$)
+           t))))
+
+(putprop 'def 'printdef 'printmacro)
+
+; There's a version of this hacked into the printer (where it don't belong!)
+; Note that it must NOT apply to things like (quote a b).
+
+;
+; adding printmacrochar so that it can be used by other read macros
+; which create things of the form (tag lisp-expr) like quote does,
+; I know this is restrictive but it is helpful in the frl source. - dhl.
+;
+;
+
+(def printmacrochar
+  (lambda (macrochar l lmar rmar)
+    (cond ((or (null (cdr l)) (cddr l)) nil)
+          (t (princ macrochar $outport$) 
+             ($prdf (cadr l) (add1 lmar) rmar)
+             t))))
+
+(putprop 'quote '|'| 'printmacrochar)
+
+(def printaccross
+  (lambda (l lmar rmar)
+    (prog nil
+;         (*** this is needed to make sure the printmacros are executed)
+          (princ '|(| $outport$)
+     l:   (cond ((null l))
+                ((atom l) (princ '|. | $outport$) (princ l $outport$))
+                (t ($prdf (car l) (nwritn $outport$) rmar)
+                   (setq l (cdr l))
+                   (cond (l (princ '| | $outport$)))
+                   (go l:))))))
+