|
|
1.1 root 1: (setq rcs-pp-
2: "$Header: /usr/lib/lisp/RCS/pp.l,v 1.2 83/08/15 22:27:54 jkf Exp $")
3:
4: ;;
5: ;; pp.l -[Mon Aug 15 10:52:13 1983 by jkf]-
6: ;;
7: ;; pretty printer for franz lisp
8: ;;
9:
10: (declare (macros t))
11:
12: (declare (special poport pparm1 pparm2 lpar rpar form linel))
13: ; (declare (localf $patom1 $prd1 $prdf charcnt condclosefile))
14:
15: ; =======================================
16: ; pretty printer top level routine pp
17: ;
18: ;
19: ; calling form- (pp arg1 arg2 ... argn)
20: ; the args may be names of functions, atoms with associated values
21: ; or output descriptors.
22: ; if argi is:
23: ; an atom - it is assumed to be a function name, if there is no
24: ; function property associated with it,then it is assumed
25: ; to be an atom with a value
26: ; (P port)- port is the output port where the results of the
27: ; pretty printing will be sent.
28: ; poport is the default if no (P port) is given.
29: ; (F fname)- fname is a file name to write the results in
30: ; (A atmname) - means, treat this as an atom with a value, dont
31: ; check if it is the name of a function.
32: ; (E exp)- evaluate exp without printing anything
33: ; other - pretty-print the expression as is - no longer an error
34: ;
35: ; Also, rather than printing only a function defn or only a value, we will
36: ; let prettyprops decide which props to print. Finally, prettyprops will
37: ; follow the CMULisp format where each element is either a property
38: ; or a dotted pair of the form (prop . fn) where in order to print the
39: ; given property we call (fn id val prop). The special properties
40: ; function and value are used to denote those "properties" which
41: ; do not actually appear on the plist.
42: ;
43: ; [history of this code: originally came from Harvard Lisp, hacked to
44: ; work under franz at ucb, hacked to work at cmu and finally rehacked
45: ; to work without special cmu macros]
46:
47: (declare (special $outport$ $fileopen$ prettyprops))
48:
49: (setq prettyprops '((comment . pp-comment)
50: (function . pp-function)
51: (value . pp-value)))
52:
53: ; printret is like print yet it returns the value printed, this is used
54: ; by pp
55: (def printret
56: (macro ($l$)
57: `(progn (print ,@(cdr $l$)) ,(cadr $l$))))
58:
59: (def pp
60: (nlambda ($xlist$)
61: (prog ($gcprint $outport$ $cur$ $fileopen$ $prl$ $atm$)
62:
63: (setq $gcprint nil) ; don't print
64: ; gc messages in pp.
65:
66: (setq $outport$ poport) ; default port
67: ; check if more to do, if not close output file if it is
68: ; open and leave
69:
70:
71: toploop (cond ((null (setq $cur$ (car $xlist$)))
72: (condclosefile)
73: (terpr)
74: (return t)))
75:
76: (cond ((dtpr $cur$)
77: (cond ((equal 'P (car $cur$)) ; specifying a port
78: (condclosefile) ; close file if open
79: (setq $outport$ (eval (cadr $cur$))))
80:
81: ((equal 'F (car $cur$)) ; specifying a file
82: (condclosefile) ; close file if open
83: (setq $outport$ (outfile (cadr $cur$))
84: $fileopen$ t))
85:
86:
87: ((equal 'E (car $cur$))
88: (eval (cadr $cur$)))
89:
90: (t (pp-form $cur$ $outport$))) ;-DNC inserted
91: (go botloop)))
92:
93:
94: (mapc (function
95: (lambda (prop)
96: (prog (printer)
97: (cond ((dtpr prop)
98: (setq printer (cdr prop))
99: (setq prop (car prop)))
100: (t (setq printer 'pp-prop)))
101: (cond ((eq 'value prop)
102: (and (boundp $cur$)
103: (apply printer
104: (list $cur$
105: (eval $cur$)
106: 'value))
107: (terpr $outport$)))
108: ((eq 'function prop)
109: (and (getd $cur$)
110: (cond ((not (bcdp (getd $cur$)))
111: (apply printer
112: (list $cur$
113: (getd $cur$)
114: 'function)))
115: ; restore message about
116: ; bcd since otherwise you
117: ; just get nothing and
118: ; people were complaining.
119: ; - dhl.
120: #-cmu
121: (t
122: (msg N
123: "pp: function "
124: (or $cur$)
125: " is machine coded (bcd) "))
126: )
127: (terpri $outport$)))
128: ((get $cur$ prop)
129: (apply printer
130: (list $cur$
131: (get $cur$ prop)
132: prop))
133: (terpri $outport$))))))
134: prettyprops)
135:
136:
137: botloop (setq $xlist$ (cdr $xlist$))
138:
139: (go toploop))))
140:
141: (setq pparm1 50 pparm2 100)
142:
143: ; -DNC These "prettyprinter parameters" are used to decide when we should
144: ; quit printing down the right margin and move back to the left -
145: ; Do it when the leftmargin > pparm1 and there are more than pparm2
146: ; more chars to print in the expression
147:
148: ; cmu prefers dv instead of setq
149:
150: #+cmu
151: (def pp-value (lambda (i v p)
152: (terpri $outport$)
153: (pp-form (list 'dv i v) $outport$)))
154:
155: #-cmu
156: (def pp-value (lambda (i v p)
157: ;;(terpr $outport$) ;; pp-form does an initial terpr.
158: ;; we don't need two.
159: (pp-form `(setq ,i ',v) $outport$)))
160:
161: (def pp-function (lambda (i v p)
162: #+cmu (terpri $outport$)
163: ;;
164: ;; add test for traced functions and don't
165: ;; print the trace mess, just the original
166: ;; function. - dhl.
167: ;;
168: ;; this test might belong in the main pp
169: ;; loop but fits in easily here. - dhl
170: ;;
171: (cond ((and (dtpr v)
172: (dtpr (cadr v))
173: (memq (caadr v)
174: '(T-nargs T-arglist))
175: (cond ((bcdp (get i 'trace-orig-fcn))
176: #-cmu
177: (msg N
178: "pp: function "
179: (or i)
180: " is machine coded (bcd) ")
181: t)
182: (t (pp-form
183: (list 'def i
184: (get i 'trace-orig-fcn))
185: $outport$)
186: t))))
187: ; this function need to return t, but
188: ; pp-form returns nil sometimes.
189: (t (pp-form (list 'def i v) $outport$)
190: t))))
191:
192: (def pp-prop (lambda (i v p)
193: #+cmu (terpri $outport$)
194: (pp-form (list 'defprop i v p) $outport$)))
195:
196: (def condclosefile
197: (lambda nil
198: (cond ($fileopen$
199: (terpr $outport$)
200: (close $outport$)
201: (setq $fileopen$ nil)))))
202:
203: ;
204: ; these routines are meant to be used by pp but since
205: ; some people insist on using them we will set $outport$ to nil
206: ; as the default
207: (setq $outport$ nil)
208:
209:
210:
211: (defun pp-form (value &optional ($outport$ poport oport-p) (lmar 0))
212: ($prdf value lmar 0))
213:
214: ; this is for compatability with old code, will remove soon -- jkf
215: (def $prpr (lambda (x) (pp-form x $outport$)))
216:
217:
218:
219: (declare (special rmar)) ; -DNC this used to be m - I've tried to
220: ; to fix up the pretty printer a bit. It
221: ; used to mess up regularly on (a b .c) types
222: ; of lists. Also printmacros have been added.
223:
224: (def $prdf
225: (lambda (l lmar rmar)
226: (prog nil
227: ;
228: ; - DNC - Here we try to fix the tendency to print a
229: ; thin column down the right margin by allowing it
230: ; to move back to the left if necessary.
231: ;
232: (cond ((and (>& lmar pparm1) (>& (flatc l (1+ pparm2)) pparm2))
233: (terpri $outport$)
234: (patom "; <<<<< start back on the left <<<<<" $outport$)
235: ($prdf l 5 0)
236: (terpri $outport$)
237: (patom "; >>>>> continue on the right >>>>>" $outport$)
238: (terpri $outport$)
239: (return nil)))
240: (tab lmar $outport$)
241: a (cond ((and (dtpr l)
242: (atom (car l))
243: (or (and (get (car l) 'printmacro)
244: (funcall (get (car l) 'printmacro)
245: l lmar rmar))
246: (and (get (car l) 'printmacrochar)
247: (printmacrochar (get (car l) 'printmacrochar)
248: l lmar rmar))))
249: (return nil))
250: ;
251: ; -DNC - a printmacro is a lambda (l lmar rmar)
252: ; attached to the atom. If it returns nil then
253: ; we assume it did not apply and we continue.
254: ; Otherwise we assume it did the job.
255: ;
256: ((or (not (dtpr l))
257: ; (*** at the moment we just punt hunks etc)
258: (and (atom (car l)) (atom (cdr l))))
259: (return (printret l $outport$)))
260: ((<& (+ rmar (flatc l (charcnt $outport$)))
261: (charcnt $outport$))
262: ;
263: ; This is just a heuristic - if print can fit it in then figure that
264: ; the printmacros won't hurt. Note that despite the pretentions there
265: ; is no guarantee that everything will fit in before rmar - for example
266: ; atoms (and now even hunks) are just blindly printed. - DNC
267: ;
268: (printaccross l lmar rmar))
269: ((and ($patom1 lpar)
270: (atom (car l))
271: (not (atom (cdr l)))
272: (not (atom (cddr l))))
273: (prog (c)
274: (printret (car l) $outport$)
275: ($patom1 '" ")
276: (setq c (nwritn $outport$))
277: a ($prd1 (cdr l) c)
278: (cond
279: ((not (atom (cdr (setq l (cdr l)))))
280: (terpr $outport$)
281: (go a)))))
282: (t
283: (prog (c)
284: (setq c (nwritn $outport$))
285: a ($prd1 l c)
286: (cond
287: ((not (atom (setq l (cdr l))))
288: (terpr $outport$)
289: (go a))))))
290: b ($patom1 rpar))))
291:
292: (def $prd1
293: (lambda (l n)
294: (prog nil
295: ($prdf (car l)
296: n
297: (cond ((null (setq l (cdr l))) (|1+| rmar))
298: ((atom l) (setq n nil) (plus 4 rmar (pntlen l)))
299: (t rmar)))
300: (cond
301: ((null n) ($patom1 '" . ") (return (printret l $outport$))))
302: ; (*** setting n is pretty disgusting)
303: ; (*** the last arg to $prdf is the space needed for the suffix)
304: ; ;Note that this is still not really right - if the prefix
305: ; takes several lines one would like to use the old rmar
306: ; until the last line where the " . mumble)" goes.
307: )))
308:
309: ; -DNC here's the printmacro for progs - it replaces some hackery that
310: ; used to be in the guts of $prdf.
311:
312: (def printprog
313: (lambda (l lmar rmar)
314: (prog (col)
315: (cond ((cdr (last l)) (return nil)))
316: (setq col (add1 lmar))
317: (princ '|(| $outport$)
318: (princ (car l) $outport$)
319: (princ '| | $outport$)
320: (print (cadr l) $outport$)
321: (mapc '(lambda (x)
322: (cond ((atom x)
323: (tab col $outport$)
324: (print x $outport$))
325: (t ($prdf x (+ lmar 6) rmar))))
326: (cddr l))
327: (princ '|)| $outport$)
328: (return t))))
329:
330: (putprop 'prog 'printprog 'printmacro)
331:
332: ;;
333: ;; simpler version which
334: ;; should look nice for lambda's also.(inside mapcar's) -dhl
335: ;;
336: (defun print-lambda (l lmar rmar)
337: (prog (col)
338: (cond ((cdr (last l)) (return nil)))
339: (setq col (add1 lmar))
340: (princ '|(| $outport$)
341: (princ (car l) $outport$)
342: (princ '| | $outport$)
343: (print (cadr l) $outport$)
344: (let ((c (cond ((eq (car l) 'lambda)
345: 8)
346: (t 9))))
347: (mapc '(lambda (x)
348: ($prdf x (+ lmar c) rmar))
349: (cddr l)))
350: (princ '|)| $outport$)
351: (terpr $outport$)
352: (tab lmar $outport$)
353: (return t)))
354:
355: (putprop 'lambda 'print-lambda 'printmacro)
356: (putprop 'nlambda 'print-lambda 'printmacro)
357:
358: ; Here's the printmacro for def. The original $prdf had some special code
359: ; for lambda and nlambda.
360:
361: (def printdef
362: (lambda (l lmar rmar)
363: (cond ((and (zerop lmar) ; only if we're really printing a defn
364: (zerop rmar)
365: (cadr l)
366: (atom (cadr l))
367: (dtpr (caddr l))
368: (null (cdddr l))
369: (memq (caaddr l) '(lambda nlambda macro lexpr))
370: (null (cdr (last (caddr l)))))
371: (princ '|(| $outport$)
372: (princ 'def $outport$)
373: (princ '| | $outport$)
374: (princ (cadr l) $outport$)
375: (terpri $outport$)
376: (princ '| (| $outport$)
377: (princ (caaddr l) $outport$)
378: (princ '| | $outport$)
379: (princ (cadaddr l) $outport$)
380: (terpri $outport$)
381: (mapc '(lambda (x) ($prdf x 4 0)) (cddaddr l))
382: (princ '|))| $outport$)
383: t))))
384:
385: (putprop 'def 'printdef 'printmacro)
386:
387: ; There's a version of this hacked into the printer (where it don't belong!)
388: ; Note that it must NOT apply to things like (quote a b).
389:
390: ;
391: ; adding printmacrochar so that it can be used by other read macros
392: ; which create things of the form (tag lisp-expr) like quote does,
393: ; I know this is restrictive but it is helpful in the frl source. - dhl.
394: ;
395: ;
396:
397: (def printmacrochar
398: (lambda (macrochar l lmar rmar)
399: (cond ((or (null (cdr l)) (cddr l)) nil)
400: (t (princ macrochar $outport$)
401: ($prdf (cadr l) (add1 lmar) rmar)
402: t))))
403:
404: (putprop 'quote '|'| 'printmacrochar)
405:
406: (def printaccross
407: (lambda (l lmar rmar)
408: (prog nil
409: ; (*** this is needed to make sure the printmacros are executed)
410: (princ '|(| $outport$)
411: l: (cond ((null l))
412: ((atom l) (princ '|. | $outport$) (princ l $outport$))
413: (t ($prdf (car l) (nwritn $outport$) rmar)
414: (setq l (cdr l))
415: (cond (l (princ '| | $outport$)))
416: (go l:))))))
417:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.