Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / usr.bin / lisp / pearl / ucisubset.l
CommitLineData
7129096e
C
1;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ucisubset.l ;;;;;;;;;;;;;;;;;;;;;;;;;
2; Functions for a subset of UCI Lisp that are either used by PEARL
3; or were needed by PEARL users at Berkeley.
4; This was purposely designed to interfere as little as necessary
5; with Franz Lisp, so things like the standard UCI do macro
6; and the Charniak (et al) let macro are not provided.
7; Includes what used to be sprint.l (at the end).
8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9; Copyright (c) 1983 , The Regents of the University of California.
10; All rights reserved.
11; Authors: Joseph Faletti and Michael Deering.
12
13(eval-when (compile)
14 (declare (special defmacro-for-compiling *savedefs*))
15 (setq defmacro-for-compiling t)
16 (setq *savedefs* nil))
17
18(declare (macros t))
19
20(defvar poport)
21(defvar pparm1 50)
22(defvar pparm2 100)
23(defvar lpar)
24(defvar rpar)
25(defvar form)
26(defvar linel)
27(defvar *outport* nil)
28(defvar *fileopen*)
29(defvar prettyprops '((comment . pp-comment)
30 (function . pp-function)
31 (value . pp-value)))
32
33(declare (localf *patom1))
34
35(defvar *file* nil)
36(defvar *oldfunctiondefinition*)
37(defvar *savedefs* t)
38
39(defmacro funl (&rest rest)
40 `(function (lambda .,rest)))
41
42;
43; ucilisp (de df dm) declare function macros.
44;
45; (DE name args body) -> declare exprs and lexprs.
46; If *savedefs* is t and function has previous definition,
47; save it under the property OLDDEF, and return '(name Redefined).
48; Otherwise, just do a defun and return name (as with defun).
49;
50(defun de macro (l)
51 (cond (*savedefs*
52 `(progn 'compile
53 (setq *oldfunctiondefinition* (getd ',(cadr l)))
54 (defun .,(cdr l))
55 (and *file*
56 (putprop ',(cadr l) *file* 'sourcefile))
57 (cond (*oldfunctiondefinition*
58 (putprop ',(cadr l) *oldfunctiondefinition* 'olddef)
59 (list ',(cadr l) 'Redefined))
60 ( t ',(cadr l)))))
61 ( t `(defun .,(cdr l)))))
62
63;
64; (df name args body) -> declare fexprs.
65;
66(defun df macro (l)
67 (cond (*savedefs*
68 `(progn 'compile
69 (setq *oldfunctiondefinition* (getd ',(cadr l)))
70 (defun ,(cadr l) fexpr .,(cddr l))
71 (and *file*
72 (putprop ',(cadr l) *file* 'sourcefile))
73 (cond (*oldfunctiondefinition*
74 (putprop ',(cadr l) *oldfunctiondefinition* 'olddef)
75 (list ',(cadr l) 'Redefined))
76 ( t ',(cadr l)))))
77 ( t `(defun ,(cadr l) fexpr .,(cddr l)))))
78
79;
80; macro's are not compiled except under the same
81; conditions as in franz lisp.
82; (usually just do (declare (macros t))
83; to have macros also compiled).
84;
85;
86; (dm name args body) -> declare macros. same as (defun name 'macro body)
87;
88(defun dm macro (l)
89 (cond (*savedefs*
90 `(progn 'compile
91 (setq *oldfunctiondefinition* (getd ',(cadr l)))
92 (defun ,(cadr l) macro .,(cddr l))
93 (and *file*
94 (putprop ',(cadr l) *file* 'sourcefile))
95 (cond (*oldfunctiondefinition*
96 (putprop ',(cadr l) *oldfunctiondefinition* 'olddef)
97 (list ',(cadr l) 'Redefined))
98 ( t ',(cadr l)))))
99 ( t `(defun ,(cadr l) macro .,(cddr l)))))
100
101; UCI Lisp character macros are non-separating when occurring in
102; the middle of atoms.
103(eval-when (compile load eval)
104 (add-syntax-class 'vucisplicemacro
105 '(csplicing-macro escape-when-first))
106 (add-syntax-class 'vucireadmacro
107 '(cmacro escape-when-first)))
108
109;
110; ucilisp functions which declare character macros.
111;
112;
113; dsm - declare splicing read macro.
114;
115(defun dsm macro (l)
116 (cond (*savedefs*
117 `(progn 'compile
118 (setq *oldfunctiondefinition*
119 (and (memq (getsyntax ',(cadr l))
120 '(vucireadmacro vucisplicemacro
121 vsplicing-macro vmacro))
122 (get ',(cadr l) readtable)))
123 (eval-when (compile load eval)
124 (setsyntax ',(cadr l) 'vucisplicemacro ',(caddr l)))
125
126 (and *file*
127 (putprop ',(cadr l) *file* 'sourcefile))
128 (cond (*oldfunctiondefinition*
129 (putprop ',(cadr l) *oldfunctiondefinition* 'oldmacro)
130 (list ',(cadr l) 'Redefined))
131 ( t ',(cadr l)))))
132 ( t `(eval-when (compile load eval)
133 (setsyntax ',(cadr l) 'vucisplicemacro ',(caddr l))))))
134
135;
136; drm - declare read macro.
137;
138(defun drm macro (l)
139 (cond (*savedefs*
140 `(progn 'compile
141 (setq *oldfunctiondefinition*
142 (and (memq (getsyntax ',(cadr l))
143 '(vucireadmacro vucisplicemacro
144 vsplicing-macro vmacro))
145 (get ',(cadr l) readtable)))
146 (eval-when (compile load eval)
147 (setsyntax ',(cadr l) 'vucireadmacro ',(caddr l)))
148
149 (and *file*
150 (putprop ',(cadr l) *file* 'sourcefile))
151 (cond (*oldfunctiondefinition*
152 (putprop ',(cadr l) *oldfunctiondefinition* 'oldmacro)
153 (list ',(cadr l) 'Redefined))
154 ( t ',(cadr l)))))
155 ( t `(eval-when (compile load eval)
156 (setsyntax ',(cadr l) 'vucireadmacro ',(caddr l))))))
157
158;
159; ucilisp selectq function. (written by jkf)
160;
161(defun selectq* macro (form)
162 ((lambda (x)
163 `((lambda (,x)
164 (cond
165 ,@(maplist
166 (function
167 (lambda (ff)
168 (cond ((null (cdr ff))
169 `( t ,(car ff)))
170 ((atom (caar ff))
171 `((eq ,x ',(caar ff))
172 . ,(cdar ff)))
173 (t
174 `((memq ,x ',(caar ff))
175 . ,(cdar ff))))))
176 (cddr form))))
177 ,(cadr form)))
178 (gensym 'z)))
179
180(defun some macro (l)
181 `((lambda (f a)
182 (prog ()
183 loop
184 (cond ((null a) (return nil))
185 ((funcall f (car a))
186 (return a))
187 ( t (setq a (cdr a))
188 (go loop)))))
189 ,(cadr l)
190 ,(caddr l)))
191
192(defmacro subset (fun lis)
193 `(mapcan (function (lambda (ele)
194 (cond ((funcall ,fun ele) (ncons ele)))))
195 ,lis))
196
197(defun length (l)
198 (prog (n)
199 (setq n 0)
200 loop
201 (and (atom l)
202 (return n))
203 (setq l (cdr l))
204 (setq n (1+ n))
205 (go loop)))
206
207(defmacro apply* (fcn args)
208 `(prog (fcndef)
209 (return
210 (cond ((atom ,fcn)
211 (or (and (eq 'binary (type ,fcn))
212 (setq fcndef ,fcn))
213 (setq fcndef (getd ,fcn)))
214 (cond ((or (and (eq 'binary (type fcndef))
215 (eq 'macro (getdisc fcndef)))
216 (and (dtpr fcndef)
217 (eq 'macro (car fcndef))))
218 (funcall ,fcn (cons ,fcn ,args)))
219 ( t (apply ,fcn ,args))))
220 ( t (apply ,fcn ,args))))))
221
222(defmacro every (fcn args)
223 `(prog (kkkk)
224 (setq kkkk ,args)
225 loop
226 (cond ((null kkkk)
227 (return t))
228 ((apply* ,fcn (list (pop kkkk)))
229 (go loop)))
230 (return nil)))
231
232(defun timer fexpr (request)
233 (let ((timein (ptime)) timeout result cpu garbage)
234 (prog ()
235 loop
236 (setq result (eval (car request)))
237 (and (setq request (cdr request))
238 (go loop)))
239 (setq timeout (ptime))
240 (setq cpu (quotient (fix (times 1000
241 (quotient (difference (car timeout)
242 (car timein))
243 60.0)))
244 1000.0))
245 (setq garbage (quotient (fix (times 1000
246 (quotient (difference (cadr timeout)
247 (cadr timein))
248 60.0)))
249 1000.0))
250 (print (cons cpu garbage))
251 (terpri)
252 result))
253
254(putd 'consp (getd 'dtpr))
255
256(putd 'msgprintfn (getd 'patom))
257
258;
259; ucilisp msg function. (written by jkf)
260;
261(defmacro msg ( &rest body)
262 `(progn ,@(mapcar
263 (function
264 (lambda (form)
265 (cond ((eq form t) '(line-feed 1))
266 ((numberp form)
267 (cond ((>& form 0)
268 `(msg-space ,form))
269 ( t `(line-feed ,(minus form)))))
270 ((atom form) `(msgprintfn ,form))
271 ((eq (car form) t) '(msgprintfn '\ ))
272 ((eq (car form) 'e)
273 `(msgprintfn ,(cadr form)))
274 ( t `(msgprintfn ,form)))))
275 body)
276 nil)) ; return nil!
277
278;
279; this NEED NOT be fixed to not use do.
280;
281(defmacro msg-space (n)
282 (cond ((eq 1 n) '(patom '" "))
283 ( t `(do i ,n (1- i) (<& i 1) (patom '\ )))))
284
285(defmacro line-feed (n)
286 (cond ((eq 1 n) '(terpr))
287 ( t `(do i ,n (1- i) (<& i 1) (terpr)))))
288
289; compatability functions: functions required by uci lisp but not
290; present in franz
291;
292; union uses the franz do loop (not the ucilisp one).
293
294(defvar membfn 'member)
295
296(defun union n
297 (and (> n 0)
298 (do ((res (ncons nil))
299 (i 1 (1+ i)))
300 ((eq i (1+ n)) (car res))
301 (mapc (function
302 (lambda (arg)
303 (or (apply* membfn (list arg (car res)))
304 (tconc res arg))))
305 (arg i)))))
306
307(defun enter (v l)
308 (cond ((apply* membfn (list v l)) l)
309 ( t (cons v l))))
310
311(defun append2 (a b &aux (c (ncons nil)))
312 (do ((a a (cdr a)))
313 ((null a))
314 (tconc c (car a)))
315 (rplacd (cdr c) b)
316 (car c))
317
318(putd 'noduples (getd 'union))
319(putd 'append* (getd 'append))
320(putd '*append (getd 'append))
321(putd '*dif (getd 'diff))
322(putd '*eval (getd 'eval))
323(putd '*great (getd 'greaterp))
324(putd '*less (getd 'lessp))
325(putd '*max (getd 'max))
326(putd '*nconc (getd 'nconc))
327(putd '*plus (getd 'plus))
328(putd '*times (getd 'times))
329(putd 'expandmacro (getd 'macroexpand))
330(putd 'mapcl (getd 'mapcar))
331(putd 'memb (getd 'member))
332
333(dm clrbfi ()
334 '(drain piport))
335
336(defun save fexpr (l)
337 (let ((fcnname (car l)))
338 (putprop fcnname (getd fcnname) 'olddef)))
339
340(defun unsave fexpr (l)
341 (let* ((name (car l))
342 (old (get name 'olddef)))
343 (and old
344 (putprop name (getd name) 'olddef)
345 (putd name old))
346 old))
347
348(putd 'atcat (getd 'concat))
349
350(putd 'gt (getd '>))
351(putd 'lt (getd '<))
352
353(defun le macro (x)
354 `(not (> .,(cdr x))))
355
356(defun ge macro (x)
357 `(not (< .,(cdr x))))
358
359(defun litatom macro (x)
360 `(and (atom .,(cdr x))
361 (not (numberp .,(cdr x)))))
362
363(putd 'peekc (getd 'tyipeek))
364
365;
366; unbound - (setq x (unbound)) will unbind x.
367; "this [code] is sick" - jkf.
368;
369(defun unbound macro (l)
370 `(fake -4))
371
372(or (getd 'franzboundp)
373 (putd 'franzboundp (getd 'boundp)))
374
375(defun boundp (item)
376 (cond ((arrayp item))
377 ((franzboundp item))))
378
379(defvar *dskin* t)
380(defvar piport)
381
382;(eval-when (load eval compile)
383; (or (boundp '*dskin*)
384; (setq *dskin* t)))
385
386(eval-when (load eval)
387 (or (getd 'dskprintfn)
388 (putd 'dskprintfn (getd 'patom))))
389
390(defun dskin fexpr (l)
391 (mapc 'dskin1 l)
392 (terpri) t )
393
394(defun dskin1 (*file*)
395 (prog (port)
396 (terpri)
397 (patom '|>>>|)
398 (cond ((null (setq port (car (errset (infile *file*) nil))))
399 (patom '|couldn't open file |)
400 (patom *file*))
401 ( t (patom *file*)
402 (patom '| |)
403 (dskin2 port)
404 (close port)))))
405
406(defun dskin2 (port)
407 (prog (expr value)
408 loop
409 (cond ((null (setq expr (read port))) nil)
410 ( t (cond ((memq (car expr) '(de df defmacro dm drm
411 dsm setq def defun))
412 (cond ((memq *dskin* '(name both))
413 (patom (cadr expr))
414 (patom '|: |))))
415 ((eq (car expr) 'create)
416 (cond ((memq *dskin* '(name both))
417 (patom (caddr expr))
418 (patom '|: |)))))
419 (setq value (eval expr))
420 (and (memq *dskin* '(t both))
421 (or (eq value '*invisible*)
422 (progn (dskprintfn value)
423 (patom '| |))))
424 (go loop)))))
425
426(defun nequal (arg1 arg2)
427 (not (equal arg1 arg2)))
428
429(defun readl fexpr (l)
430 (cond ((null l) (readl1 nil))
431 ( t (readl1 (eval (car l))))))
432
433(putd 'lineread (getd 'readl))
434
435(defun readl1 (flag)
436 (cond ((not (and flag
437 (eq (tyipeek) 10)
438 (tyi)))
439 (prog (input)
440 (setq input (ncons nil)) ; initialize for tconc.
441 loop
442 (cond ((not (eq (tyipeek) 10))
443 (tconc input (read))
444 (go loop))
445 ( t ; the actual list is in the CAR.
446 (tyi)
447 (return (car input))))))))
448
449(defun defv fexpr (l)
450 (set (car l) (cadr l)))
451
452(defun remprops (item proplist)
453 (mapc (funl (prop)
454 (remprop item prop))
455 proplist)
456 nil)
457
458(defun addprop (id value prop)
459 (putprop id (enter value (get id prop)) prop))
460
461(defun nconc1 (l elmt)
462 (rplacd (last l) (cons elmt nil)))
463
464(defun dremove (elmt l)
465 (let (newl)
466 (cond ((dtpr l)
467 (cond ((eq elmt (car l))
468 (setq newl (delq elmt l))
469 (rplaca l (car newl))
470 (rplacd l (cdr newl)))
471 ( t (delq elmt l))))
472 ( t l))))
473
474(defun intersection (set1 set2)
475 (prog (inter)
476 (mapc (funl (elt) (putprop elt t '*inter*)) set1)
477 (mapc (funl (elt) (and (get elt '*inter*)
478 (setq inter (cons elt inter))))
479 set2)
480 (mapc (funl (elt) (remprop elt '*inter*)) set1)
481 (return inter)))
482
483(defun initsym1 expr (l)
484 (prog (num)
485 (cond ((dtpr l)
486 (setq num (cadr l))
487 (setq l (car l)))
488 ( t (setq num 0)))
489 (putprop l num 'symctr)
490 (return (concat l num))))
491
492(defun initsym fexpr (l)
493 (mapcar (function initsym1) l))
494
495(defun newsym fexpr (l)
496 (let ((name (car l)))
497 (concat name
498 (putprop name
499 (1+ (or (get name 'symctr)
500 -1))
501 'symctr))))
502
503(defun oldsym fexpr (l)
504 (let ((sym (car l)))
505 (concat sym (get sym 'symctr))))
506
507(defun allsym fexpr (l)
508 (prog (num symctr syms)
509 (cond ((dtpr (car l))
510 (setq num (cadar l))
511 (setq l (caar l)))
512 ( t (setq num 0)
513 (setq l (car l))))
514 (or (setq symctr (get l 'symctr))
515 (return))
516 loop
517 (and (>& num symctr)
518 (return syms))
519 (setq syms (cons (concat l symctr) syms))
520 (setq symctr (1- symctr))
521 (go loop)))
522
523(defun remsym1 expr (l)
524 (prog1 (funcall (function oldsym)
525 (cond ((dtpr (car l)) (car l))
526 ( t l)))
527 (mapc (function remob) (apply (function allsym) l))
528 (cond ((dtpr (car l)) (putprop (caar l) (1- (cadar l)) 'symctr))
529 ( t (remprop (car l) 'symctr)))))
530
531(defun remsym fexpr (l)
532 (maplist (function remsym1) l))
533
534(defun symstat fexpr (l)
535 (mapcar (funl (k)
536 (list k (get k 'symctr)))
537 l))
538
539(defun suflist (itemlist num)
540 (cond ((dtpr itemlist) (nth (1+ num) itemlist))))
541
542;;;;;;;;;;;;;;;;;;;;;;; (formerly sprint.l) ;;;;;;;;;;;;;;;;;;;;;;;;
543; A few additions to the library file ucbpp.l, mostly to add
544; a UCI Lisp-like "sprint" including some modifications for
545; more flexible printmacros.
546;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
547
548; Moved to front and converted to defvar.
549; (declare (special poport pparm1 pparm2 lpar rpar form linel))
550; (declare (localf *patom1))
551; (declare (special *outport* *fileopen* prettyprops))
552
553; =======================================
554; pretty printer top level routine pp
555;
556;
557; calling form- (pp arg1 arg2 ... argn)
558; the args may be names of functions, atoms with associated values
559; or output descriptors.
560; if argi is:
561; an atom - it is assumed to be a function name, if there is no
562; function property associated with it,then it is assumed
563; to be an atom with a value
564; (P port)- port is the output port where the results of the
565; pretty printing will be sent.
566; poport is the default if no (P port) is given.
567; (F fname)- fname is a file name to write the results in
568; (A atmname) - means, treat this as an atom with a value, dont
569; check if it is the name of a function.
570; (E exp)- evaluate exp without printing anything
571; other - pretty-print the expression as is - no longer an error
572;
573; Also, rather than printing only a function defn or only a value, we will
574; let prettyprops decide which props to print. Finally, prettyprops will
575; follow the CMULisp format where each element is either a property
576; or a dotted pair of the form (prop . fn) where in order to print the
577; given property we call (fn id val prop). The special properties
578; function and value are used to denote those "properties" which
579; do not actually appear on the plist.
580;
581; [history of this code: originally came from Harvard Lisp, hacked to
582; work under franz at ucb, hacked to work at cmu and finally rehacked
583; to work without special cmu macros]
584; THEN, hacked to use for PEARL.
585
586; moved to front.
587;(setq prettyprops '((comment . pp-comment)
588; (function . pp-function)
589; (value . pp-value)))
590
591; printret is like print yet it returns the value printed, this is used
592; by pp
593(def printret
594 (macro (*l*)
595 `(progn (print ,@(cdr *l*)) ,(cadr *l*))))
596
597(def pp
598 (nlambda (*xlist*)
599 (prog (*outport* *cur* *fileopen* *prl* *atm*)
600
601 (setq *outport* poport) ; default port
602 ; check if more to do, if not close output file if it is
603 ; open and leave
604
605
606 toploop (cond ((null (setq *cur* (car *xlist*)))
607 (condclosefile)
608 (terpr)
609 (return t)))
610
611 (cond ((dtpr *cur*)
612 (cond ((equal 'P (car *cur*)) ; specifying a port
613 (condclosefile) ; close file if open
614 (setq *outport* (eval (cadr *cur*))))
615
616 ((equal 'F (car *cur*)) ; specifying a file
617 (condclosefile) ; close file if open
618 (setq *outport* (outfile (cadr *cur*))
619 *fileopen* t))
620
621
622 ((equal 'E (car *cur*))
623 (eval (cadr *cur*)))
624
625 ( t (terpri *outport*)
626 (*prpr *cur*))) ;-DNC inserted
627 (go botloop)))
628
629
630 (mapc (function
631 (lambda (prop)
632 (prog (printer)
633 (cond ((dtpr prop)
634 (setq printer (cdr prop))
635 (setq prop (car prop)))
636 ( t (setq printer 'pp-prop)))
637 (cond ((eq 'value prop)
638 (cond ((boundp *cur*)
639 (apply printer
640 (list *cur*
641 (eval *cur*)
642 'value)))))
643 ((eq 'function prop)
644 (cond ((and (getd *cur*)
645 (not (bcdp (getd *cur*))))
646 (apply printer
647 (list *cur*
648 (getd *cur*)
649 'function)))))
650 ((get *cur* prop)
651 (apply printer
652 (list *cur*
653 (get *cur* prop)
654 prop)))))))
655 prettyprops)
656
657
658 botloop (setq *xlist* (cdr *xlist*))
659
660 (go toploop))))
661
662; moved to front.
663;(setq pparm1 50 pparm2 100)
664
665; -DNC These "prettyprinter parameters" are used to decide when we should
666; quit printing down the right margin and move back to the left -
667; Do it when the leftmargin > pparm1 and there are more than pparm2
668; more chars to print in the expression
669
670; cmu prefers dv instead of setq
671
672#+cmu
673(def pp-value (lambda (i v p)
674 (terpri *outport*) (*prpr (list 'dv i v))))
675
676#-cmu
677(def pp-value (lambda (i v p)
678 (terpr *outport*) (*prpr `(setq ,i ',v))))
679(def pp-function (lambda (i v p)
680 (terpri *outport*) (*prpr (list 'def i v))))
681(def pp-prop (lambda (i v p)
682 (terpri *outport*) (*prpr (list 'defprop i v p))))
683
684(def condclosefile
685 (lambda nil
686 (cond (*fileopen*
687 (terpr *outport*)
688 (close *outport*)
689 (setq *fileopen* nil)))))
690
691;
692; these routines are meant to be used by pp but since
693; some people insist on using them we will set *outport* to nil
694; as the default (moved to front).
695;(setq *outport* nil)
696
697
698(def *prpr
699 (lambda (x)
700 (cond ((not (boundp '*outport*)) (setq *outport* poport)))
701 (terpr *outport*)
702 (*prdf x 0 0)))
703
704; This is the principle addition for PEARL.
705; SPRINT simply calls *prdf after filling in any missing parameters.
706(defun sprint (value &optional (lmar 0) (rmar 0))
707 (cond ((not (boundp '*outport*)) (setq *outport* poport)))
708 (*prdf value lmar rmar))
709
710(defvar rmar) ; -DNC this used to be m - I've tried to
711 ; to fix up the pretty printer a bit. It
712 ; used to mess up regularly on (a b .c) types
713 ; of lists. Also printmacros have been added.
714
715
716
717; Used to be $prdf but added a bit and changed to * to avoid
718; PEARL's history read macro $.
719(def *prdf
720 (lambda (l lmar rmar)
721 (prog (pmac)
722;
723; - DNC - Here we try to fix the tendency to print a
724; thin column down the right margin by allowing it
725; to move back to the left if necessary.
726;
727 (cond ((and (>& lmar pparm1) (>& (flatc l (1+ pparm2)) pparm2))
728 (terpri *outport*)
729 (princ '"; <<<<< start back on the left <<<<<" *outport*)
730 (*prdf l 5 0)
731 (terpri *outport*)
732 (princ '"; >>>>> continue on the right >>>>>" *outport*)
733 (terpri *outport*)
734 (return nil)))
735 (tab lmar *outport*)
736 a (cond ((and (dtpr l)
737 (atom (car l))
738 (setq pmac (get (car l) 'printmacro))
739 (cond ((stringp pmac)
740 ; Added for PEARL (and UCI Lisp compatibility).
741 ; a string printmacro means print this
742 ; string and then the cadr of l if
743 ; it's not nil, and only if l is
744 ; a one- or two-element list.
745 (cond ((cddr l) ; more than two elements.
746 nil)
747 ((null (cdr l)) ; only one element.
748 (patom pmac)
749 t)
750 ( t (patom pmac) ; two elements.
751 (patom (cadr l))
752 t)))
753 ( t (apply pmac (list l lmar rmar)))))
754 (return nil))
755;
756; -DNC - a printmacro is a lambda (l lmar rmar)
757; attached to the atom. If it returns nil then
758; we assume it did not apply and we continue.
759; Otherwise we assume it did the job.
760;
761 ((or (not (dtpr l))
762; (*** at the moment we just punt hunks etc)
763 (and (atom (car l)) (atom (cdr l))))
764 (return (printret l *outport*)))
765 ((<& (+ rmar (flatc l (chrct *outport*)))
766 (chrct *outport*))
767;
768; This is just a heuristic - if print can fit it in then figure that
769; the printmacros won't hurt. Note that despite the pretentions there
770; is no guarantee that everything will fit in before rmar - for example
771; atoms (and now even hunks) are just blindly printed. - DNC
772;
773 (printaccross l lmar rmar))
774 ((and (*patom1 lpar)
775 (atom (car l))
776 (not (atom (cdr l)))
777 (not (atom (cddr l))))
778 (prog (c)
779 (printret (car l) *outport*)
780 (*patom1 '" ")
781 (setq c (nwritn *outport*))
782 a (*prd1 (cdr l) c)
783 (cond
784 ((not (atom (cdr (setq l (cdr l)))))
785 (terpr *outport*)
786 (go a)))))
787 (t
788 (prog (c)
789 (setq c (nwritn *outport*))
790 a (*prd1 l c)
791 (cond
792 ((not (atom (setq l (cdr l))))
793 (terpr *outport*)
794 (go a))))))
795 b (*patom1 rpar))))
796
797(def *prd1
798 (lambda (l n)
799 (prog nil
800 (*prdf (car l)
801 n
802 (cond ((null (setq l (cdr l))) (|1+| rmar))
803 ((atom l) (setq n nil) (+ 4 rmar (pntlen l)))
804 ( t rmar)))
805 (cond
806 ((null n) (*patom1 '" . ") (return (printret l *outport*))))
807; (*** setting n is pretty disgusting)
808; (*** the last arg to *prdf is the space needed for the suffix)
809; ;Note that this is still not really right - if the prefix
810; takes several lines one would like to use the old rmar
811;( until the last line where the " . mumble)" goes.
812 )))
813
814; -DNC here's the printmacro for progs - it replaces some hackery that
815; used to be in the guts of *prdf.
816
817(def printprog
818 (lambda (l lmar rmar)
819 (prog (col)
820 (cond ((cdr (last l)) (return nil)))
821 (setq col (1+ lmar))
822 (princ '|(| *outport*)
823 (princ (car l) *outport*)
824 (princ '| | *outport*)
825 (print (cadr l) *outport*)
826 (mapc '(lambda (x)
827 (cond ((atom x)
828 (tab col *outport*)
829 (print x *outport*))
830 ( t (*prdf x (+ lmar 6) rmar))))
831 (cddr l))
832 (princ '|)| *outport*)
833 (return t))))
834
835(putprop 'prog 'printprog 'printmacro)
836
837; Here's the printmacro for def. The original *prdf had some special code
838; for lambda and nlambda.
839
840(def printdef
841 (lambda (l lmar rmar)
842 (cond ((and (\=& 0 lmar) ; only if we're really printing a defn
843 (\=& 0 rmar)
844 (cadr l)
845 (atom (cadr l))
846 (caddr l)
847 (null (cdddr l))
848 (memq (caaddr l) '(lambda nlambda macro lexpr))
849 (null (cdr (last (caddr l)))))
850 (princ '|(| *outport*)
851 (princ 'def *outport*)
852 (princ '| | *outport*)
853 (princ (cadr l) *outport*)
854 (terpri *outport*)
855 (princ '| (| *outport*)
856 (princ (caaddr l) *outport*)
857 (princ '| | *outport*)
858 (princ (cadaddr l) *outport*)
859 (terpri *outport*)
860 (mapc '(lambda (x) (*prdf x 4 0)) (cddaddr l))
861 (princ '|))| *outport*)
862 t))))
863
864(putprop 'def 'printdef 'printmacro)
865
866; There's a version of this hacked into the printer (where it don't belong!)
867; Note that it must NOT apply to things like (quote a b).
868
869(def printquote
870 (lambda (l lmar rmar)
871 (cond ((or (null (cdr l)) (cddr l)) nil)
872 ( t (princ '|'| *outport*)
873 (*prdf (cadr l) (1+ lmar) rmar)
874 t))))
875
876(putprop 'quote 'printquote 'printmacro)
877
878
879
880
881(def printaccross
882 (lambda (l lmar rmar)
883 (prog nil
884; (*** this is needed to make sure the printmacros are executed)
885 (princ '|(| *outport*) ;)
886 l: (cond ((null l))
887 ((atom l) (princ '|. | *outport*) (princ l *outport*))
888 ( t (*prdf (car l) (nwritn *outport*) rmar)
889 (setq l (cdr l))
890 (cond (l (princ '| | *outport*)))
891 (go l:))))))
892
893
894
895(def tab (lexpr (n)
896 (prog (nn prt) (setq nn (arg 1))
897 (cond ((>& n 1) (setq prt (arg 2))))
898 (cond ((>& (nwritn prt) nn) (terpri prt)))
899 (printblanks (- nn (nwritn prt)) prt))))
900
901; ========================================
902;
903; (charcnt port)
904; returns the number of characters left on the current line
905; on the given port
906;
907; =======================================
908
909
910(def charcnt
911 (lambda (port) (- linel (nwritn port))))
912
913(putd 'chrct (getd 'charcnt))
914
915(def *patom1 (lambda (x) (patom x *outport*)))
916
917; vi: set lisp: