1
0
mirror of https://github.com/PDP-10/its.git synced 2026-02-08 09:21:17 +00:00
Files
PDP-10.its/src/libdoc/#print.rcw3
2018-10-03 07:33:27 -07:00

4252 lines
218 KiB
Common Lisp
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;-*-LISP-*-
(comment a fast pretty printer)
;-----------------------------------------------------------;
; -- THIS FILE IS OBSOLETE -- USE GPRINT -- ;
;-----------------------------------------------------------;
;this file was written by Richard C. Waters Feb. 1978.
;all comments and bugs should go to DICK@AI
; --- AN ADVERTISMENT FOR THIS PRINTER ---
;the goal of this printing package is to produce a general purpose printer which
;combines the best features of PRINT and GRINDEF while correcting some of their
;deficiencies.
;GOOD FEATURES OF PRINT RETAINED
; PRINLEVEL and PRINLENGTH abbreviation,
; printing of HUNKs in a recognizable way,
; reasonable speed.
;GOOD FEATURES OF GRINDEF RETAINED
; nice formatting of output,
; grind-functions for specifying your own formatting.
;BAD FEATURES CORRECTED
; GRINDEF is too slow, this is improved by simplifying the look ahead and virtually
; eliminating consing.
; the old printers blow up on circular lists, this is fixed by putting in a module that
; checks for circularity. (this can be disabled if you don't like the overhead it
; creates).
; there isn't any way to stop the old printers, you can turn off seeing the output, but
; you still have to wait until it's done computing unless you type a ^g and wipe
; out the whole environment. this is fixed by providing an interrupt function
; which causes the printer to immediatly abort and return normally.
; structure, and printing nothing if the object passed to #print is a naked ||.
;NEW FEATURES ADDED
; a new abbreviation mode is introduced. special variables PRINSTARTLINE and PRINENDLINE
; can be used to specify how many lines to print out. for example you could
; specify that only the first 4 lines should be printed out. an interrupt
; function is provided so that you can see the rest of the output if you want to.
; this works if the output is at top level, or from inside a program.
; a new format for grinding is introduced. it prints out a block of data in a tabular
; format where the width of the columns is automatically generated. it is useful
; for increasing the readability of densely printed stuff.
; a new method of specifying a grinding format is introduced. It allows you to construct
; a template which controls the format of printing. it can be used to produce a
; wide variety of formats, and is considerably simpler than writing a grind
; function.
; The #printer doesn't print anything to the left of the column position that
; it starts printing in. This is very usefull when the #printer is
; being called as a subroutine by some other function which is pretty
; printing something (eg when it is being used like SPRINT).
; #prin1 prints out nothing for "||" if "||" is passed to it as a single atom,
; and prints "||" for it inside a structure. This is handy since you
; can have a function return '|| and not have to see anything printed out.
;IN DEPTH DOCUMENTATION OF HOW TO USE THE #PRINTER
;
;this documentation is arranged into a set of sections which describe more and more
;advanced levels of interaction with the printer. what you should read depends on
;what you want to do. if you just want to load it in and use it without
;creating any of your own formats for printing things, then just read sections
;0 and 1. In order to make your own templates, and/or functions for
;formatting, you need to read about #GRIND-TEMPLATEs and #GRIND-FNs. (you will
;have to read a good deal of the rest in order to realy understand them) In
;order to set up your own printing system you will have to read everything
;including the implementation notes.
;
;The code for the #print programs appears after this initial set of comments.
;It is written in terms of a bunch of macros which are in the file dick;util >.
;Since there is some difficulty in understanding these macros, if you are
;not familiar with them, the end of this file contains a completely macro
;expanded version of these same programs.
;
;(the functions and special variables in this file start with # so that they will
; not collide with any names in other program packages. (for added safety a lot
; of things which are considered internal to the package begin with #1))
;
;SECTION 0 (JUST LOAD IT IN AND USE IT AS THE TOP LEVEL TTY PRINTER)
;
;HOW TO LOAD #PRINT
; a. execute (fasload #print fasl dsk liblsp)
;
;HOW TO START UP #PRINT
; a. execute (#1set-up-printer) this sets '#prin1 as the value of prin1
; (thus making it the default printer) and sets up ^S and ^C (see below).
; (you can just do (setq prin1 '#prin1) if you don't want the control
; characters)
; b. DO NOT change the fsubr properties of prin1 or princ since #print uses
; them.
;
;HOW TO GET RID OF THE #PRINTER
; a. execute (#1rem-printer) this undoes all of the actions of
; #1SET-UP-PRINTER and gets rid of the functions in the #print package.
; The primary use is to save space before creating a dumped version,
; however, #print really doesn't take up much space.
;THE BASIC STRUCTURE OF THE #PRINTER
;
;the #printer is implemented as three sets of programs which communicate with
; each other through two narrow bottle necks.
; 1. top level print functions like #PRINT, PRINL, and GRINDEF (see section 1)
; these form an easy interface for getting something printed. there are
; also a set of special varibles which control the format of printout
; (see section 1)
; 1-2. all of these functions eventually call #1PRINTER. this function then
; communicates the critical information about what to print and how with
; (2.) below. this is done partly through argument passing and partly
; through a set of special variables.
; 2. this set of programs formats an object for output. in doing this it
; creates an intermediate structure which tells how to format each part
; of the object if that part will not fit on one line. these functions
; use a set of special variables to communicate with each other. in
; addition they use atom properties and a few special variables to get
; information directly from the user. Furthermore, these routines are
; specifically designed so that they can be modified by the user.
; (each of these mechanisms is described in detail below)
; 2-3. the net result of the formatting functions in (2.) above is a sequence
; of calls on the function #1ENTER-OBJ. this function forms the complete
; interface with (3.) below. #1ENTER-OBJ constructs an ellaborate intermediate
; structure which is represented in several special variables. this part
; and (3.) below are extreamly convoluted and are not intended to be
; modified by the user.
; 3. the function #1PRINTOUT actually decides what will go where and prints
; the object out. it uses a number of special variables to communicate
; with itself and #1ENTER-OBJ.
;
;the general high speed of the #PRINTer is due to two things:
; 1. the #PRINTer does very little look ahead, in particular, it calls
; FLAT(SIZE/C) only once on each atom in the structure to be printed, and
; never calls it with a non atomic argument.
; 2. the #PRINTer does almost no consing. rather it does its own storage
; management including keeping a queue in an array. this greatly reduces
; garbage collections. the only consing is the fixnum consing which is
; neccessary because some special variables have fixnum values.
; fortunately most of these values are relatively static and/or small.
;SECTION 1 THE BASIC USER FUNCTIONS AND ABBREVIATION CONTROL VARIABLES
;
;the functions #PRINT, #PRIN1, and #PRINC are analogous to the functions
; PRINT, PRIN1, and PRINC. they are LSUBRs and take two arguments. the first
; must be an object to print out. the second can be either: a file, a list
; of files, NIL, or missing (in the last two cases the default files
; specified by ^R, ^W, and OUTFILES are used as output destinations)
;
;there a several special variables which can be used to control the amount of
; abbreviation which is performed by the printer. in each case if the
; variable has the value NIL then there is no abbreviation corresponding to
; that variable. (The #printer requires that all of these variables be BOUND
; and makes sure that this is the case when it is loaded in. (this is done
; by the function #1SET-UP-GLOBALS which gives all of the controling
; variables which are unbound a default value of NIL (ie no abbreviation)))
; 1. PRINLEVEL: just like PRINT, #PRINT prints # for lists which are at a
; depth greater than PRINLEVEL. It extends the definition of elision used in
; PRINT in that it forces prinlength to 3 at the deapest level printed. This
; is so that you don't see a long string of #'s at that level.
; 2. PRINLENGTH: just like PRINT, #PRINT prints ... for the ends of lists
; which are longer than PRINLENGTH. It extends the definition of elision
; used in PRINT in that if only one element of a list is going to be omitted
; and that element is an atom, then it is not omitted.
; 3. PRINENDLINE: #PRINT counts the lines it prints out (starting with the
; first line as line 0) and stops printing after printing the
; PRINENDLINEth line. if truncation occures, --- is printed at the end
; of the last line (if there is room). the printer then immediatly stops
; executing and returns no matter how large the output object is.
; 4. PRINSTARTLINE: if PRINSTARTLINE is greater than zero, then #PRINT skips
; over the initial lines of output and does not start to print out untill
; the PRINSTARTLINEth line is reached. (note that if PRINSTARTLINE is
; greater then PRINENDLINE nothing is going to print out) (also note that
; like PRINLEVEL and PRINLENGTH, PRINENDLINE and PRINSTARTLINE must be
; non-negative.)
; 5. #CHECKRECURSION: if this variable is non null then, #PRINT checks for
; circular lists and prints ^# for circular references where # is the number of
; cars and cdrs separating the two references to the item. for example,
; t1=(1 2 ^2) implies that (eq (cdr t1) (caddr t1)).
;
;there is a special variable PRINMODE which specifies what format #PRINT
; will use to print things out. (this is discussed more fully below)
; PRINMODE can take on two basic values:
; 1. 'CRUSH gives you crushed together output similar to PRINT. atoms are
; not broken over line boundries.
; 2. 'GRIND (or NIL) gives you nicely formated output like GRINDEF. (there
; are a number of ways that you can control what this looks like
; (see below))
;
;Hunks are printed out in a format different from the way PRINT prints them. Each
; hunk is printed as "{" cxr1 cxr2 cxr3 ... cxr0 "}". Thus
; (hunk 1 2 (hunk 3 4 5) 6) prints as
; {1 2 {3 4 5} 6}.
;there are two functions which are intended to be put on interrupt characters.
; (calling #1SET-UP-PRINTER sets these up)
; 1. #PRINTABORT (^S) causes the printer to stop and return normally.
; 2. #CONTINUE (^C) will cause the printer to resume printing from where it left
; off printing the last object which was truncated by ^S or prinendline. Note
; that this may not be the last thing which was #printed. Also, it only works on a
; line by line basis so there may be some duplication if the object printout was
; truncated by ^S (#PRINTABORT). #CONTINUE uses CURSORPOS and is only intended
; to work on output devises which support CURSORPOS.
; A special endpage function (#1ENDPAGEFN) is
; provided because the system one does not correctly do MORE
; processing with the printout produced by #CONTINUE (I think that this has
; something to do with #CONTINUE being on an interrupt character). this new
; endpage function is installed by #1SET-UP-PRINTER.
;
;there are three functions (PRINL, PRINL1, and PRINLC) which are analogous to
; #PRINT, #PRIN1, and #PRINC except that they allow you to specify the
; control parameters PRINLEVEL, PRINLENGTH, PRINENDLINE,
; PRINSTARTLINE, and PRINMODE as arguments rather than by setting the
; global variables. useing PRINL as an example, the argument order is:
; (PRINL object level length endline startline mode file) as an added
; conveniance, any of these arguments (except the object) can be omitted
; and will take on a default value (of NIL which means no abbreviation)
; as long as there is no ambiguity. the only abiguity that can arize is
; with the four numeric parameters (level, length, endline, and
; startline). with these, you must specify an initial subset of them.
; the most common way to call PRINL is (PRINL object file) this prints
; out the entire object on file (much like SPRINT). other valid calls on
; PRINL are: (PRINL foo 3 4 'grind tyo) ;this sets level=3 and length=4
; (PRINL bar nil nil 4) ;this sets endline=4
;
;there is a redefinition of the function GRINDEF which calls #PRINT. it is an
; FSUBR and takes arguments just like the old grindef. IE the first argument
; (which may be omitted) is a list of properties to grind. this list of
; properties is used in conjunction with the list of properties in the variable
; GRINDPROPERTIES in order to decide what properties of the specified atoms to
; print out. the remaining arguments to GRINDEF are atoms.
;
;there are three functions #EXPLODE, #EXPLODEC, and #EXPLODEL which correspond
; to #PRIN1, #PRINC, and #PRINL. They don't actually print anything out,
; rather they return a list of the characters which would be printed out
; if the whole structure fit on one line. (note that this includes all
; abbreviation which would have been used. #EXPLODEL allows you to
; directly specify the abbreviation parameters.) For example,
; (#explode '(1 2 3)) => '(/( /1 / /2 / /3 /))
; but if PRINLENGTH = 2 then it returns:
; (#explode '(1 2 3)) => '(/( /1 / /2 / /. /. /. /))
; as long as PRINMODE is 'GRIND then all macro inversion etc. happens ie:
; (#explodel '(1 (quote 2)) 'grind) => '(/( /1 / /'/2/))
;IMPLEMENTATION NOTE ON SECTION 1 (THE FUNCTION #1PRINTER)
;
;the function #1PRINTER takes 3 arguments:
; (#1PRINTER code object parameters) The first is a code which specifies what
; type of printing to do. The second argument is the object to print, and the
; last indicates the files to print out on. The code is a number which is
; decoded bit by bit as follows:
; bit0 - if 1 then atoms are PRINCed instead of PRIN1ed.
; bit1 - if 1 then a TERPRI is done before starting to print, and a
; space is printed at the end (like PRINT)
; bit2 - if 1 then the third argument is taken to be, not just
; files, but also an explicit specification of the abbreviation
; parameters (prinlevel prinlength prinendline prinstartline
; prinmode) (the way these are pattern matched out of the string
; provided is discussed as part of the discusion of PRINL above).
; bit3 - if 1 then #1PRINTER does an explode instead of actually
; printing anything.
; The function #1PRINTER is used to implement the functions #PRINT etc.
;
;#1PRINTER performs several main tasks:
; 1. if it is reentered while another call on it has not yet completed, it
; rebinds all of the special varibles used by the #PRINT system so that
; the old invocation will be protected while the current call is completed
; (the special variable #1NOWPRINTING is used as a flag to tell whether or
; not the #printer is being reentered). this enables the #PRINTer to work
; perfectly when it is reentered, the only change in its actions is that
; it creates a certain amount of garbage when it reinitializes itself
; whereas in general it does almost no CONSing.
; 2. #1PRINTER takes care of outputing crlf before output of #PRINT and
; #PRINL and a space after (as controled by #1PRINT-LIKE).
; 3. it takes care of printing || differently if it is the object to be
; printed than if it is in the object to be printed.
; 4. before calling the formatting routines to print out the object, #1PRINTER
; sets up a CATCH which enables #1PRINTABORT (^S) to stop the printer.
; this is also used to implement stopping when prinendline is reached.
; 5. the special variable #1TRUNCATED is used to keep track of whether the
; output is truncated or not, and if so on what line. if non-null, it holds a
; list of all the information needed to resume printing in the right place.
; This is used by #1CONTINUE to decide where to start printing out.
; #1PRINTER sets up the value of #1TRUNCATED whenever #1PRINTABORT or
; PRINENDLINE triggers the truncation of output. #1TRUNCATED is a list
; of the following components:
; 1. the CURSORPOS (line . column) where printing stopped.
; 2. the indentation where printing started in the first place.
; 3. the primary output file (#1MAINFILE).
; 4. the CODE which should be used when calling #1printer in order to
; continue printing out the truncated object.
; 5. the MAKNUM of the object being printed. (the maknum is used so
; that this will not prevent the object from getting garbage
; collected)
; 6. the abbreviation parameter list which should be passed to
; #1printer in order to continue printing the object. it has the form:
; a. the current prinlevel
; b. the current prinlength
; c. a prinendline of NIL
; d. a prinstartline of the line where truncation occured.
; e. the current prinmode
; f. the files being printed on.
; 6. most importantly, #1PRINTER translates the format control information into the
; form that the formatting routines expect. (see the discussion below of
; the special variables used to communicate with the format funcions.) In addition, the
; function #1FORMAT-INIT is called to set up the special variables which
; are used during the formatting and printout processes.
;
;if you wish to dispence with #1PRINTER and write a program which directly
; calls the format functions, you must make sure that the above variables
; are at least bound, and you must call #1FORMAT-INIT before calling the
; format functions. also note that you will be loosing the features which
; are implemented directly by #1PRINTER unless you make provision for them.
;THE SPECIAL VARIABLES USED BY THE TOP LEVEL FUNCTIONS:
;
;Variables which are set by the user to control certain fucntions:
; #checkrecursion (t/nil) this controls checking for circularity.
; prinlevel (a non-negative number or nil) this controls # abbreviation if
; structures get too deep.
; prinlength (a non-negative number or nil) this controls ... abbreviation if
; structures are too long.
; prinmode (a keyword, or a template (see below)) this controls the format of
; output it is discussed fully in the section on templates below.
; prinendline (a non-negative number or nil) this controls the number of lines
; which are printed out.
; prinstartline (a non-negative number or nil) this controls which line is the
; first line actually printed out.
; ^r (t/nil) if T this implies that the variable OUTFILES will be used to
; decide what files to output onto. (this is the same convention as with PRINT).
; ^w (t/nil) if NIL this implies that output will be done to the file in the
; variable TYO. (This is completely orthoganal to ^R and is the same convention
; as with PRINT)
; outfiles (a list of files) this is a list of files to perform output to.
; tyo (a file) this is the file which is the default "tty" file.
; grindproperties (a list of properties) this controls what the default properties
; displayed by GRINDEF will be.
;
;Variables which are used for communication between top level functions:
; #1print-like (t/nil) if T then a space is put after, and a crlf before what
; is being printed. this is used by #1PRINTER.
; #1nowprinting (t/nil) if T this says that there is an unfinished call on
; #1PRINTER on the stack. In that case all the volitile special variables
; are rebound before starting up another call on #1PRINTER in order to
; protect the state of the old call. This is used by #1PRINTER.
; grindef (the last argument to GRINDEF) this is used to implement the fact
; that (GRINDEF) does what ever the last call on GRINDEF did. THis is used
; by GRINDEF.
; #1mainfile (a file) this is a file which has been selected as the primary
; output file. It is used to make formating decisions based on such things
; as line length. In addition #CONTINUE tries to make its output look
; perfect on #1MAINFILE while it ends up only OK on the other files, if any.
; it is either the first file specified (if literal files were specified to
; a printing function) or the first file in OUTFILES if ^R and ^W are both
; T, or otherwise it is the value of TYO. (if it should turn out that
; #1MAINFILE failed to end up as a valid file things wouldn't work out
; right even if you were only #EXPLODEing.)
; #1truncated (nil or a description of an object which was truncated) this is
; created by #1PRINTER in order to communicate with #CONTINUE. It holds
; all of the information which #CONTINUE needs to finish printing
; something. (It is discussed in detail above.)
;Variables which form the interface between the top level functions and the
; format functions:
; #1princ-atoms (t / nil) is t if atoms should be PRINCed instead of PRIN1ed.
; #1files (list of files) holds a list of the files to print onto. (it can be NIL which
; implies that ^R ^W and OUTFILES will be used to decide where output will go.
; #1checkrecursion (t/nil) holds the value of #CHECKRECURSION.
; #1prinlevel (positive number) holds the value of #PRINLEVEL except that it is always a
; number. instead of NIL, a very large number is used to inhibit abbreviation.
; #1prinlength (positive number) holds the value of #PRINLENGTH except that it is always a
; number. instead of NIL, a very large number is used to inhibit abbreviation.
; #1prinlendline (positive number) holds the value of #PRINENDLINE except that it is always a
; number. instead of NIL, a very large number is used to inhibit abbreviation.
; #1prinstartline (positive number) holds the value of #PRINSTARTLINE except
; that it is always a number. instead of NIL, a 0 is used to inhibit
; abbreviation.
; #1prinmode (positive number) holds the value of PRINMODE (see the discussion of templates
; below) except that if PRINMODE is a keyword (such as GRIND) then the
; keyword is translated into a template.
; #1exploding (t/nil) is t if the #printer should produce a list of characters
; rather than print anything out.
; #1explode-result (a list of characters) (initialized to nil) is used to pass
; the results of #exploding back up to #1PRINTER. it collects the
; nreverse of the result.
; 1st arg of #1format-dispatch is the template to use when formatting the
; object. this is taken from the variable #1PRINMODE.
; 2nd arg of #1format-dispatch is the object to be formated.
;SECTION 2 CALLS ON THE FUNCTION #1ENTER-OBJ
;
;In order to print something, a sequence of calls on the function #1ENTER-OBJ
; is created. In order to understand the capabilities of the #printer,
; it is important to look at what a sequence of calls on #1ENTER-OBJ is like.
;
;the functions #1ENTER-OBJ takes three arguments: (#1enter-obj obj pcode lcode)
; In addition it looks at two global variables: #1fcode and #1bcode (the MACRO
; #1ENTER-FORMAT (#1enter-format fcode bcode) is available for setting these two
; global variables. The MACRO #1ENTER-FORMAT&OBJ (#1enter-format&obj fcode
; bcode obj pcode lcode) sets these two variables and then calls (#1enter-obj
; obj pcode lcode).) The separation between the two sets of inputs is
; motivated by the fact that the function invocation which sets the
; format, is often different from the one which decides what object to
; print. Put another way, the format depends on the context the object
; is in, while how the object itself is printed depends on the object
; itself. This will be discussed more fully below.
;
;Logically, #1ENTER-OBJ takes five arguments:
; 1. obj -- an object to be printed. The formatting functions (see below)
; convert a thing to be #printed into a sequence of objects to be
; printed. this sequence includes list delimeters on an equal footing
; with atoms in the thing to be printed. for example when #printing
; "(list (cons var1 var2) var3 var4)" the following sequence of 10 objects is
; created "/( list /( cons var1 var2 /) var3 var4 /)". The standard
; #printer only calls #1enter-obj with atomic objects, but a list or
; hunk could be used; however, it will be treated just like an indivisable atom.
; 2. pcode -- the printing code is one of {princ, prin1, nil} and specifies
; whether to use PRIN1 and FLATSIZE, or PRINC and FLATC when working
; with the object. a pcode of nil indicates that the object has been
; omitted, and there is no object to be printed corresponding to this
; call on #1enter-obj.
; 3. lcode -- the list code is one of {start, end, nil}. It is used to
; encode the nested structure of the thing being printed. It is
; motivated by the nesting in lists, but need not correspond to any
; actual delimiters, nor be limited to lists. For example the cxrs of
; a hunk, which are printed out inside "{}"s, are a nested structure like
; any other from the point of view of the calls on #1enter-obj. The
; lcode of END means that this object is the last object in a
; substructure. The lcode NIL indicates that this is neither the first
; nor last object in a substructure.
; the lcode START indicates the start of a nested structure. In
; addition, it indicates that the obj parameter is not an object to be
; printed, but rather the amount of indentation to use when printing out
; the substructure which starts here. This requires that an extra call
; on #1ENTER-OBJ be made at the start of each substructure. This extra
; call on #1ENTER-OBJ (the one with lcode=start) is a "header cell" for
; a nested structure. One the one hand, it is not part of the nested
; structure, but rather just introduces it; it contains general
; information which applies to the whole substructure (like the
; indentation, and the fcode and bcode (see below) for the substructure
; as a whole. On the other hand, the header cell is often operated on
; as a unit, refering to the entire substructure.
; the example above "(list (cons var1 var2) var3 var4)" can now be seen
; to generate 12 calls on #1ENTER-OBJ:
(declare '| obj pcode lcode
(#1enter-obj 6 nil 'start)
(#1enter-obj '/( 'princ nil)
(#1enter-obj 'list 'prin1 nil)
(#1enter-obj 6 nil 'start)
(#1enter-obj '/( 'princ nil)
(#1enter-obj 'cons 'prin1 nil)
(#1enter-obj 'var1 'prin1 nil)
(#1enter-obj 'var2 'prin1 nil)
(#1enter-obj '/) 'princ 'end)
(#1enter-obj 'var3 'prin1 nil)
(#1enter-obj 'var4 'prin1 nil)
(#1enter-obj '/) 'princ 'end) |)
; the indentation is "6" in the two substructures because LIST and CONS
; are being printed in functional notation which calls for an
; indentation of (+ (the length of the open delimeter (here 1))
; (the length of the function name (here 4))
; (the amount of spacing over ie 1)) = 6.
; 4. fcode -- a keyword which must be one of {never, normal, tblock, block, always}
; It describes the circumstances under which a crlf will be printed
; before the object to be printed. (NOTE that if this fcode is
; associated with a call on #1ENTER-OBJ which starts a substructure, then
; the "object being printed" refered to below, is the entire
; substructure. also note that the "prior object printed" may also
; refer to an entire substructure.)
; ALWAYS -- a crlf is always put before this item.
; NEVER -- a crlf will never be put before this object, unless the
; object is too long to fit on the end of the current line. If the
; object is the start of a substructure then a crlf is never
; inserted no matter how long it is. (in general non-atomic
; structures are not given 'NEVER fcodes.)
; In order to make it more likely, that NEVER really means never, the
; printer works with a logical line length which is 5 characters
; shorter than the actual line length. However, when it comes to
; processing a NEVER, the #printer uses the actual line length.
; The 5 character cushion is available only for printing NEVER objects
; NORMAL -- a crlf is put before this object if and only if the substructure
; containing this object was to long to fit on the end of the line
; it started on. Note that this is not a function of the object
; itself, but rather a function of the containing substructure.
; This is used to generate standard list output format: either,
; every element of the list is on the same line, or each one is on
; a separate line.
; BLOCK -- a crlf is put before this object if and only if either,
; this object is a substructure which has somewhere in it an ALWAYS
; code, or the prior object at the same level did not fit on one line, or
; this object is too long to fit on the end of this line.
; This is used to generate "block" output where several list
; elements are put on each line.
; TBLOCK -- a crlf is put before this object in exactly the same
; situations as with the BLOCK code. the difference is that when
; the objects are printed out, tabing is done in order to line them
; up in columns. (this variant of BLOCK can be much more readable.)
; NOTE that the #printer NEVER inserts two crlfs in a row.
;
; The routine which does output goes inside a substructure, and breaks
; it up in only two cases. The first case is when the substructure is
; simply too long to fit on one line. (the outputer first does as much
; as possible given the fcodes of the containing stuctures to start the
; substructure as far to the left as possible. The second case occures
; if the substructure contains an ALWAYS fcode somewhere inside itself.
; If the outputer looks inside a substructure, then that substructure
; may be broken up over several lines in order to make it fit.
; Otherwise, the substructure will appear as a unit on one line.
; 5. bcode -- this specifies the number of blanks to print out AFTER
; printing this item (usually 1 or 0). Note, that the bcode associated
; with an lcode of START is actually printed out after the object
; associated with the corresponding END lcode. IE it appears after the
; entire logical object. The bcode (if any)
; associated directly with the END lcode is IGNORED. there are no
; blanks printed out in conjunction with processing the START lcode.
; Note further, that blanks are never printed as the last characters
; on a line. therefore the bcodes associated with those objects that
; happen to end up on the end of a line are effectively ignored.
;
;now we can look at a complete example of the sequence of calls generated by
; the example, assuming that it is being printed in standard grind format.
;
(declare '|"(list (cons var1 var2) var3 var4)" leads too:
fcode bcode obj pcode lcode
1 (#1enter-format&obj 'never 0 6 nil 'start)
2 (#1enter-format&obj 'never 0 '/( 'princ nil)
3 (#1enter-format&obj 'never 1 'list 'prin1 nil)
4 (#1enter-format&obj 'never 1 6 nil 'start)
5 (#1enter-format&obj 'never 0 '/( 'princ nil)
6 (#1enter-format&obj 'never 1 'cons 'prin1 nil)
7 (#1enter-format&obj 'never 1 'var1 'prin1 nil)
8 (#1enter-format&obj 'normal 0 'var2 'prin1 nil)
9 (#1enter-format&obj 'never _ '/) 'princ 'end)
10 (#1enter-format&obj 'normal 1 'var3 'prin1 nil)
11 (#1enter-format&obj 'normal 0 'var4 'prin1 nil)
12 (#1enter-format&obj 'never _ '/) 'princ 'end)
if the line length were 21 then this would print out as:
(list (cons var1
var2)
var3
var4) |)
;
;In order to get a deaper understanding of how this works, consider the
; following trace of how the output part of the #printer would interpret
; this in order to produce output. Suppose that the line length on the
; primary output device was 21. The output section processes the calls
; on #1ENTER-OBJ one at a time (it actually does this as a coroutine with
; the functions which produce the calls on #1ENTER-OBJ, but this is only an
; efficiency issue (it reduces the amount of temporory storage needed)).
; Note that one question which the outputer often asks is how long
; something is. For effeciency, this is computed incrementally, but
; this aspect will be ignored here.
; Suppose the printer started out in column 0. When presented with
; the 1st call on #1ENTER-OBJ it asks whether or not the corresponding
; object (in this case the whole expression) is too long to fit on one
; line. Here the object is 33 chars long and there is only space for
; 21. The output point is already at the start of a line, so the system
; looks inside the substructure in order to see how to break it up.
; The system then looks at the 2nd call. the fcode is NEVER, so no
; crlf is done. a /( is printed out. the bcode is 0 so no blanks are
; printed.
; The 3rd call also has a NEVER fcode, so no crlf is printed. a
; "list" is printed (prin1ed since that is specified). then 1 blank is
; printed as specified by the bcode.
; The 4th call is a substructure header cell (as was the 1st). It
; has an fcode of NEVER so no crlf is printed, However, the current
; output point is column 6 (the first column is 0), and the length of
; this substructure is 17. as a result, it is not going to fit on this
; line. as a result the system goes down inside it to see how it can
; get broken up. (if it had been shorter (say 10) then the system
; would have printed all of it out (calls 4-9) without looking at any of
; those calls in detail.
; Since the system is looking inside, it looks at calls 5,6, & 7.
; they all have NEVER fcodes so they just print things out (even though
; we are getting closer and closer to the end of the line). They print
; out |(cons var1 |.
; Call 8 has an fcode of NORMAL. this specifies that a crlf should
; be inserted if the containing substructure is being broken up (which
; it is). (note that effectively the output system only looks at the
; fcode if the superior is being broken up.) As a result a crlf is
; done. Note that if the fcode had been BLOCK or TBLOCK then the
; system would have done a crlf because there isn't room to print the
; object in call 8 in the space left on the line. Further if the fcode
; had been NEVER the system would still have done a crlf as an emergency
; measure since you just can't print "var2" in the space left.
; After doing a crlf for call 8 the system spaces over to the
; current indentation (which is 12 6+6 for the two substructures which
; have been broken up.) The system then prints |var2|.
; It then looks at call 9. This has a NEVER fcode and so the
; system prints out /). In addition, call 9 has an END lcode. As a result, the
; system prints out a blank because a bcode of 1 was specified in the call (call
; 4) which was the header for this substructure. The current indentation is
; popped back to 6 corresponding to the one substructure which the system is
; down in.
; Call 10 has a NORMAL fcode so the system does crlf, and indents
; to the 6th column. It then prints |var3 |
; call 11 also has a NORMAL fcode so the system again does crlf,
; indents to 6 and then prints |var3|. (Note here that if the fcode
; had been BLOCK then the system would not have done a crlf since the
; object actually would fit on the same line as call 10.)
; Finally call 12 causes the outputer to print /) and pop up out of
; the structure being printed.
;SECTION 3 TEMPLATES
;
;As stated above, everything in the printer eventually boils down to a
; sequence of calls on #1ENTER-OBJ. In order to make it easier to get
; the correct sequence of calls generated, there is a structure called a
; template. A template in conjunction with a few conventions specifies
; what the sequence of calls will be. The conventions specify what the
; open and close delimeters are, and what their fcodes are. In addition
; they specify what all of the bcodes are, and the order in which the
; internal items of each substructure will appear. The template
; specifies the indentation, and what the fcodes of the internal items
; of each substructure will be.
; 1. the fcode and bcode associated with the header cell for a
; substructure is inhereted from the fcode and bcode expected of it
; based on its position in the structure which contains it. (note
; the highest level call has an fcode of NEVER and a bcode of 0 in
; all situations.) The template specifies the indentation which
; goes in the header cell.
; 2. the second and last calls for a substructure are the open and
; close delimiters respectively. the second call (the open delimeter) is /(
; for a list and /{ for a hunk. Its fcode is NEVER (so that it will always
; appear on the line the thing printed out starts on) and its bcode is nil.
; The last call (the close delimiter) is /) for a list and /} for a hunk. Its
; fcode is never (so that it will always be on the same line as the last item
; in the list or hunk being printed) and as noted above its bcode is ignored
; by the system.
; 3. The substructure structure of the calls on #1ENTER-OBJ follow
; exactly the tree structure of the thing being printed.
; 4. for a list, the elements of the list make up the 3rd through
; next to last calls. They each have a pcode of PRIN1 (or PRINC
; if #1PRINC-ATOMS is non-null). They each have a bcode of 1
; except the last element of the list (the next to last call)
; which has a bcode of 0. The template specifies the fcodes of
; these calls.
; 5. Hunks are exactly analogous with the cxrs appearing in the
; order 1,2,3, ... ,0.
;a template has a nested structure corresponding exactly to the nested
; structure of the thing being printed, and therefore also corresponding to the
; nested structure of calls on #1ENTER-OBJ created. They are motivated by the
; observation that the sequence of fcodes desired, for the internal items of a
; substructure usually takes the form of some initial sequence followed by an
; unbounded repeating pattern . Templates simulate this by being recursive
; through their cdrs. Similarly, they are often circular through there cars.
;
;the following is a "grammer" for templates:
; template := explicit-temp v NIL
; explicit-temp := ( indent-count item-temp*n )
; indent-count := number v NIL
; item-temp := ( {NEVER v ALWAYS v NORMAL v BLOCK v TBLOCK} . template )
;
; A template of NIL indicates that the template mechanism is not being
; used, and the format functions (see below) use other means for
; deciding what sequene of calls on #1enter-obj to create.
; An indent-count of NIL indicates that the indent code to use is
; (+ (Flatsize (first of list)) 1 (flatsize open-delimeter)).; This is
; used in creating standard functional indentation.
;
; the template specifies the indent-count, and for each internal
; item in each substructure, the fcode to use for it, and a template to
; use when formatting its internal strucutre. for example, the following
; template (shown as #print would print it) could be used to make
; everything print out in lisp function format. (it could have been used
; to generate the example in the previous section.)
; '(nil (never . ^3) (never . ^4) (normal . ^5) . ^1)
; Note that it is heavily recursive. Each of the subtemplates is
; itself, and it ends in an endless sequence of NORMAL fcodes.
;
; The example above corresponds to this template in that each substructure has
; an open delimeter with a NEVER fcode, and then two NEVER fcodes followed by
; NORMAL fcodes, and finally a close delimeter with a NEVER fcode. The car
; recursiveness of the template causes every substructure to be treated just the
; same way as the top structure is.
;
;There is a function #MAKE-TEMPLATE (with an associated sub-function
; #MAKE-TEMPLATE1) which can be used to easily generate these circular
; structures. This function allows you to specify a circular structure
; by giving the function a list as an argument which contains ellements of the
; form "(^ . n)". the input is copied, and each of these special
; elements is replaced by its nth parent in the new structure. the copy
; is then returned. (note that this does not damage the input, and
; works even if the input is itself circular.) the template above could
; have been created by:
; (#make-template
; '(nil (never . (^ . 3)) (never . (^ . 4)) (normal . (^ . 5)) . (^ . 1)))
;Having discussed templates, we can now give a complete explanation of the
; special variable PRINMODE. This variable can either be one of the
; atoms {GRIND, CRUSH, BLOCK, TBLOCK, MISER}, or a template. The
; variable #1PRINMODE (which actually controls the #printing process)
; must always be a template. If PRINMODE is an atom, then the function
; #1printer translates this atom into a template as follows:
; GRIND => nil
; CRUSH => (-900 (never . ^3) . ^1)
; BLOCK => (1 (never . ^3) (block . ^4) . ^1)
; TBLOCK => (1 (never . ^3) (tblock . ^4) . ^1)
; MISER => (1 (never . ^3) (normal . ^4) . ^1)
; Looking at these we can see what these modes will do, and more about
; how the formatting works in the #printer. The CRUSH template causes
; things to get printed out without formatting except that atoms are not
; broken up accross lines. all of its fcodes are NEVER, so that a crlf
; is only inserted when the very next atom to be printed won't fit on the
; rest of the current line. further the large negative indentation,
; guarrentees that the total indentation will allways be negative. this
; cuases printing to always start out as far left as the intial
; indentation point (note that the #printer will never go left of the
; initial indentation point).
; The BLOCK, TBLOCK, and MISER templates are very similar.
; They all specify indentations of 1. Assuming that the only open
; delimiters #printed are /( and /{ then this means that substructure
; elements are indented just enough to line up after the open delimiter.
; They all have NEVER as the first fcode, which ensures that the first
; item will be on the same line as the open delimiter. They then give
; all of the rest of the elements the same fcode. For BLOCK, these fcode
; is BLOCK and the resulting output looks like GRINDEF's block format,
; crlfs are inserted before any substructure which will not fit on one
; line, however, if several will fit on one line then they are put
; there. TBLOCK is just the same except that the elements printed out
; are lined up in columns like in a table. MISER prints things out like
; GRINDEF's miser format. The elements of a substructure are either all
; printed on one line, or each is printed on a separate line.
;
(declare '| the following gives comparative examples of these four printing
modes. It is based on the assumption that the line length is 30.
(list f foo bar (list (list a CRUSH mode
b) zap) a b c)
(list MISER mode
f
foo
bar
(list (list a b) zap)
a
b
c)
(list f foo bar BLOCK mode
(list (list a b) zap)
a b c)
(list f foo bar TBLOCK mode (this example assumes that the
(list (list a b) zap) #printer only saw the first four
a b c) elements of the list when it decided
what the tab spacing should be. This
is typical of the system's limited
look ahead.)
BLOCK and TBLOCK modes are most usefull for working with data structures. the following is
a data structure #printed out in BLOCK format. this saves a great deal of space over MISER
format and is a great deal more readable than CRUSH format would be.
((EXAMP1 CONSTANT1) (CONSTANT1 _*I1) (_*I1 _+I1) (_+I1 _GT1)
((_GT1 CE1) CONSTANT2) ((_GT1 CE0) (JOIN1 CE6)) (JOIN1 EXAMP1) (CONSTANT2 (JOIN2 CE5))
(JOIN2 _AREF1) (_AREF1 _A=1) (_A=1 CONSTANT3) (CONSTANT3 _+I2) (_+I2 _-I1) (_-I1 _GT2)
((_GT2 CE0) (JOIN2 CE2)) ((_GT2 CE1) (JOIN1 CE2)))
However, it still isn't all that readable. TBLOCK format (as shown below) is a great
deal more readable. It makes it a lot easier to identify the individual items at the top
level.
((EXAMP1 CONSTANT1) (CONSTANT1 _*I1) (_*I1 _+I1)
(_+I1 _GT1) ((_GT1 CE1) CONSTANT2) ((_GT1 CE0) (JOIN1 CE6))
(JOIN1 EXAMP1) (CONSTANT2 (JOIN2 CE5)) (JOIN2 _AREF1)
(_AREF1 _A=1) (_A=1 CONSTANT3) (CONSTANT3 _+I2)
(_+I2 _-I1) (_-I1 _GT2) ((_GT2 CE0) (JOIN2 CE2))
((_GT2 CE1) (JOIN1 CE2))) |)
; The template for GRIND is NIL. This means that the #printer
; will look at the structure of the thing being printed in order to
; decide how to format it. (This is discussed fully in the next
; section.) However, this usually ends up with the system having
; selected a particular template to use. One of these is for printing
; out functional forms:
; (nil (never) (never) (normal) . ^1)
; Note that this is a great deal like an example given earlier except
; that it specifies NIL for the templates of the substructures. This
; is so that after formatting the given list in functional form, it
; will again end up with a template of NIL in order to trigger the
; system to figure out how to print the substructures. this is the
; general way in which grinding proceeds.
; There one level templates for doing MISER, BLOCK, and TBLOCK
; output. analogous to the one level functional form template above,
; they con be used to specify one level of formating, and then they give
; a template of NIL so that new templates will be chosen for the lower
; levels. (these are held in the special variables
; #11level-miser-template, #11level-block-template, and
; #11level-tblock-template.)
; Another interesting template is the one which is used for
; formatting CONDs:
; (nil (never) (never . (1 (never) (normal) . ^1))
; (always . (1 (never) (normal) . ^1))
; . ^1)
; There are two interesting features of this. First, there is an
; always code which is used to insure that if a COND has more than one
; clause, it will go on more than one line no matter how short it is.
; Second, this template is two level while the last one was one level.
; it specifies the format for the COND, and the top level format for
; the clauses before becoming NIL.
;
;There is a function #1SET-UP-TEMPLATES which sets up a bunch of templates
; which are used by the rest of the system. This function is executed
; when #print is read in. a number of special variables are used to
; hold the templates which are built up. These variables should not be
; modified by the user. (the variables are #1miser-template
; #1block-template #1crush-template #1fn-template #11level-block-template
; #1defun1-template #1defun2-template #11level-tblock-template #1apply-template
; #11level-miser-template #1tblock-template)
;SECTION 4 THE FORMATTING FUNCTIONS
;
;The formatting functions take in an object to print and a template, and produce a sequence of
; calls on the function #1enter-obj. They don't actually print
; anything, however, they decide exactly how a thing will look when it
; is printed. In particular they implement prinlevel and prinlength
; abbreviation, circular structure abbreviation, and fancy formatting for
; grinding.
;
;The function #1FORMAT-INIT sets up a bunch of internal variables used by the
; format functions, and by #1ENTER-OBJ. It MUST be executed before a
; thing is formated! It reinitializes the world. #1PRINTER calls it
; before calling the formatting functions, if you bypass #1PRINTER you
; must call #1FORMAT-INIT yourself.
;
;as discussed above the main interface into the formatting functions is formed
; by the variables: #1princ-atoms, #1files, #1checkrecursion, #1prinlevel,
; #1prinlength, #1prinstartline, #1prinendline, #1prinmode, and #1exploding.
; Actually, #1files, #1prinstartline, #1prinendline, and #1exploding are not
; used by the formaters, and are just passed on to the function #1PRINTOUT.
; Further, the variable #1prinmode is not currently looked at (it is redundent
; with the template argument to the formaters).
; These variables are discussed above. In addition to them, each format
; function takes two arguments: a thing to be formated, and a template which
; says how to format it. (only #1FORMAT-DISPATCH can take a NIL template).
;
;The function #1FORMAT-DISPATCH takes a template and an item and decides which
; specific format function to call and what specific template to pass to
; it. In order to decide what to do #1FORMAT-DISPATCH looks at several
; features:
; 1. The primary feature is the type of the thing to print. It checks
; whether it is a hunk, list, or atom and uses different formaters
; in the three cases.
; 2. Second if there is a NIL template then it figures out what
; template to use. The interesting case of this is with lists. If
; the template is NIL then #1FORMAT-DISPATCH looks at the property
; list of the car of the list looking for #GRIND-TEMPLATE, and
; #GRIND-FN properties (see below).
; In any event it eventually calls a formatting function with an object,
; and a non-nil template.
;there are a variety of ways to effect the actions of #1FORMAT-DISPATCH
; 1. the variables #1FORMAT-DISPATCH, #1FORMAT-LIST,
; #1FORMAT-HUNK, and #1FORMAT-ATOM, are hooks for attaching your
; own formatting functions. If you give any of them a value, then
; this value will be FUNCALLed whenever the corresponding system
; function would have been. (note that if you write a formatting
; function it must be compatable with all of the restrictions
; described below. #1FORMAT-DISPATCH is a special case.)
;when #1FORMAT-DISPATCH gets a template of NIL then it looks at several
; other things in order to figure out what template to really use.
; 2. if you give an atom a #GRIND-TEMPLATE property then that property
; will be used as a template to print out lists whos cars are the
; given atom. COND, SETQ, and LAMBDA are given #GRIND-TEMPLATE
; properties when #print is loaded in.
; 3. the variable #1FN-GRIND-PROPERTIES is a list of properties. If
; an atom has any of these properties, then lists which start
; with it will print out in functional form.
; 4. the variable #1DEFAULT-SYMBOL-CAR-GRIND-TEMPLATE holds a template
; which is used when neither 2 nor 3 above are applicable.
; This is initially set up so that functional form is
; the default in this case. (this is what the old GRINDEF did)
; If this variable is set to #11level-tblock-template after fasloading #print
; then tab blocking will be done instead by default. This takes a little
; getting used to, but saves a lot of space when printing out on the tty. I
; recommend it.
; 5. the variable #1DEFAULT-NON-SYMBOL-CAR-GRIND-TEMPLATE holds a template
; which is used for lists whose cars are not atomic. (except that
; literal applications of lambda expressions have a special
; template which is held in the variable #1apply-template.) This is initially
; set up so that miser format (all the sublists indented 1 space) is used in
; this case (this is what old GRINDEF did). If this variable is set to
; #11level-tblock-template after fasloading #print then tab blocking will be
; done instead by default. This takes a little getting used to, but saves a lot
; of space when printing out on the tty. I recommend it.
; 6. If you give an atom a #GRIND-FN property, then that property will
; be FUNCALLed as the format function to use when the atom is the
; first of a list. (again this only applies when the template
; argument to #1FORMAT-DISPATCH is nil). When writing a formatting
; function to use this way you must follow the conventions set
; forth below. QUOTE, DEFUN, PROG, and DO are given special
; formatting functions at load time.
;The functions #1FORMAT-LIST and #1FORMAT-HUNK do the formatting of lists and
; hunks respectively. They have certain tasks they (like any formatting
; function) must perform:
; 1. They take a template as an argument (they could ignore it if they
; wanted to) they car cdr down the template in
; order get the correct fcodes, and indent count.
; 2. they call #1FORMAT-DISPATCH in order to do the formatting of
; EVERY subelement of the structures they are formatting.
; 3. as part of this they observe the convention that the variable
; #1FORMAT-DISPATCH may contain a user redefinition of the dispatching function.
; 4. They handle prinlength abbreviation. (this can be omitted)
; This is done by seeing that they don't output more than
; #1PRINLENGTH things in a substructure. They print |...| to
; indicate that something is being left out.
; 5. they handle prinlevel abbreviation. this is done in conjunction
; with the special variable #1LEVEL. If #1LEVEL is 0 when the
; formater is entered, then this indicates that the prinlevel is
; being exceeded. In this case the formaters output |#|. (It doesn't have to do
; abbreviation, but it must take care of #1LEVEL or else no one
; will be able to do prinlevel abbreviation right.)
; 6. they maintain the value of #1LEVEL (by decrementing it when they
; are entered, and incrementing it when they are exited). #1LEVEL is a
; number which is the difference between #1PRINLEVEL and the depth of
; the current sub-ellement being formated. If a format function
; simply didn't touch #1LEVEL, then it would not act like a level
; of structure from the point of view of the other formatting functions.
; 7. They check for recursion by calling the function #1RCHECK on
; every cons cell they encounter. If #1RINDEX returns something
; which is not EQ to its argument, then this indicates that its
; argument was recursive. In this case the formater should
; output the thing returned and not recurse into the item.
; The recursion checking is done in conjunction with
; the variable #1RINDEX. (this can be omitted, but #1RINDEX must be
; maintained or else no one will be able to do recursion checking correctly)
; 8. They maintain the value of #1RINDEX. #1RINDEX is a number which
; is the number of parents on the path from the current cons cell
; to the root of the top level object being printed. It is used by
; #1RCHECK which maintains an array (#1PARENTS) which holds that
; set of parents. #1RINDEX is maintaned by the formaters by
; saving its value on entry, and restoring this value before exit. If
; a formater doesn't call #1RCHECK, then it doesn't have to do
; anything with #1RINDEX.
; 9. #1FORMAT-LIST has special code to deal with atomic cdrs.
; 10. any formatting function must assume that the fcode and bcode which
; correspond to the object which is passed to it HAVE ALREADY BEEN
; SPECIFIED by the functions that called it. thus it should not
; specify the fcode or bcode for the top level thing it puts out.
; this is related to the tacit assumption that each formater will
; either just put out one thing, or will group everything it puts
; out into one substructure. If it doesn't do that, then it must
; take special steps to be compatable with the fcode and bcode its
; caller specified.
; 11. In line with this, a formater must specify an fcode and bcode BEFORE
; calling #1FORMAT-DISPATCH to deal with some substructure it needs
; to have formated.
; 12. Any formater should be carful that it will not crash on circular
; input even when recursion is not being checked for. that is to
; say that it should never do anything which could cause it to go
; into a loop without making any calls on #1ENTER-OBJ. (such as
; doing a flatsize of a non-atomic object.)
;The user can influence the actions of the formatting functions.
; 1. the variables #1OPEN-DEL and #1CLOSE-DEL can be used to modify
; the delimiters to be used by the formaters. setting them
; non-null cuases them to be used as the delimiters by the next
; call on a format function which recognizes them. However, they
; ONLY effect ONE call on the format functions. They do not cause
; a perminant change. the feature is used by the macro
; #MAKE-INVERT-QUOTE-FN which generates special format functions
; which do read macro inversion. (see below)
;the function #1RCHECK is a utility which is called by the formatting
; functions in order to check for recursive structures. It takes one
; input, an item. it either returns that item, or if #1CHECRECURSION
; is non-null and if the item is a recursive reference, #1RCHECK
; returns an atom of the form #^ where # is the number of cars and
; cdrs in the path from the first instance of the item, to this
; recursive instance of the item.
; In order to do this, #1RCHECK maintains an array (#1PARENTS)
; which contains the cells which are the ancesters of the current cell
; being checked. if that cell turns out not to be recursive, then it
; is put in the end of this array. The variable #1RINDEX points to
; the first free slot in the array #1parents. #1RCHECK increments
; #1RINDEX whenever it puts a new item in #1PARENTS, but it never
; decrements it. It is up to the formatting functions which call
; #1RCHECK to decrement #1RINDEX.
; The combination of #1PARENTS and #1RINDEX act like a stack.
; This stack follows the stack like order in which the formatting
; functions move over a thing to be printed. each call to #1RCHECK
; pushes a new item onto this stack. The formatting functions must see
; to it that these items get popped off of the stack. In order to do
; this each one saves the value of #1RINDEX when it starts to work,
; and then restores that value of #1RINDEX before it returns. this
; reflects the fact that each formatting function works on a single
; subtree and thus the state of #1PARENTS should be the same before
; and after the formatter is called.
;
;WRITING YOUR OWN FORMAT FUNCTIONS
;
;The easiest way to specify a special output format is through a template
; installed as the #GRIND-TEMPLATE property of some atom.
; However this may not be flexable enough in some situations. You can
; get complete control over how something is formated by writing your
; own format function. The resulting format function can be installed
; as the #1GRIND-FN property of some atom, or can be SETQed as the value
; of one of the atoms #1format-dispatch, #1format-list, #1format-hunk,
; or #1format-atom. (#1format-dispatch is a somewhat special case.)
; Any format function must follow all of the requirements set forth
; above. There are several mechanisms for assisting you in writing
; format functions.
;
;In order to write your own format functions, you should study the format
; functions included in the #printer.
;
;The macro #MAKE-INVERT-QUOTE-FN constructs formatting functions which do
; simple read macro inversion. for example
; (#make-invert-quote-fn quote /')
; (which is part of the basic #print package) builds a formatting
; function which outputs "(quote foo)" as "'foo". In order to see how
; this works, consider a more complete example:
; (#make-invert-quote-fn list /[ /])
; this would cause "(list a b c)" to print out as "[a b c]". The macro
; produces the following formatting function:
;
(declare '| (defun (list #grind-fn) (temp item)
(setq #1open-del '/[ #1close-del '/])
(cond (#1format-list (funcall #1format-list temp (cdr item)))
((#1format-list temp (cdr item))))) |)
;
; This uses the variables #1OPEN-DEL and #1CLOSE-DEL in order to change
; the delimeters of the thing being formated and then formats the cdr of
; the thing. (if there is no close delimeter specified in the macro
; call (as in the QUOTE example), then a null close delimiter is
; assumed.) Note that the formatting function produced follows the
; convention that the variable #1FORAMT-LIST may contain a user
; redefinition of the default list formatting function.
;
;The function #MAKE-INVERT-QUOTE-FN2 is basically very similar except that it makes the basic
; assumption that the relavent value is the CDR instead of the CADR.
; as a result of this, there is no case corresponding to having both an open
; and a close delimiter. Rather you merely specify an atom which is printed
; before the CDR which is otherwise printed normally. for example:
; (#make-invert-quote-fn2 '|`-expander/|| '|`|) (which is part of the
; standard printer environment along with handling "," ",@" and ",.")
; causes (|`-expander/|| a b c) to print out as `(a b c)
;The lsubr #1FORMAT-LSUBR is available in order to asisst you in writing
; format functions. Templates allow you to specify the fcodes to use.
; #1FORMAT-LSUBR allows you to additionally specify what objects to
; print and what order to print them in. This could be done by consing
; up a list of the things you wanted printed and then calling
; #1FORMAT-LIST. #1FORMAT-LSUBR allows you to get this effect without
; actually consing up the list. As such it is essentially used for
; efficiency. #1FORMAT-LSUBR could have been defined as:
; (defun #1format-lsubr nargs (#1format-list (arg 1) (listify (- 1 nargs))))
; the following example shows how #1FORMAT-LSUBR could be used to help
; write a nonstandard formater for hunks:
;
(declare '| (defun special-format-hunk (temp hunk)
(cond ((eq (hunksize hunk) 4)
(setq #1open-del '/@ #1close-del '/@)
((lambda (#1prinlevel #1prinlength)
(#1format-lsubr
'(1 (never) (never)) (maknum hunk) (cxr 3 hunk)))
4 4))
(t (#1format-hunk temp hunk)))) |)
;
; If you did a (setq #1format-hunk 'special-format-hunk) then whenever a
; hunk was going to be formated, the function SPECIAL-FORMAT-HUNK would
; be called. This function checks to see whether the hunk is a hunk4.
; If it is, then it prints out the maknum of the hunk and the cxr-3 of
; the hunk surrounded by @s. For example,
; (hunk 1 2 '(list zap) '(car foo)) would print out as
; "@123456 (list zap)@" if 123456 was the maknum of the hunk.
; Note that special-format-hunk binds #1prinlevel and
; #1prinlength in order to control the amount of abbreviation which will
; apply. If it hadn't bound them, then the abbreviation would have been
; a function of the depth of the hunk in the structure being printed.
; as it is it is always the same. If the hunk is not a hunk4 then the
; standard hunk formater is called in order to format the hunk.
;Using #1FORMAT-LSUBR implies that the standard formatting conventions
; described above will be used. If you want to do something complete
; original, you can write a format function which directly calls
; #1ENTER-OBJ. An example of the is (PROG #GRIND-FN) which is defined
; in the standard #printer. It is basically like #1FORMAT-LIST except
; that it prints the tags properly. This is also used to print DOs.
; There is also a little #GRIND-FN for DEFUN which makes it print out
; right in both 2 and 3 argument form.
;
;consider the following more detailed example.
(declare '(defun foo #grind-fn (unused-temp list)
(#1enter-obj 1 nil 'start)
(#1enter-format&obj 'never 0 (cadr list) 'prin1 nil)
(cond ((not (null (caddr list)))
(#1enter-format&obj 'never 0 '/- 'princ nil)
(#1enter-format&obj 'never (caddr list) 'prin1 nil)))
(#1enter-format&obj 'never 1 '/: 'princ nil)
(#1enter-format 'normal 0)
(#1format-dispatch nil (cadddr list))
(#1enter-format&obj 'never 0 '|| nil 'end)) )
;this directly calls #1enter-obj for five reasons: it uses non standard
; delimiters (in fact no open and close delimiters at all), it uses non-standard
; bcodes, it inserts certain internal delimeters (: and -), it does
; different things based on what the structure of the item is (ie
; whether or not the 3rd list ellement is nil), and it doesn't print the
; first item of the list at all, that just exists in order to get to the
; correct printout formatter. In GRIND mode,
; '(foo 1 2 3) would print as:
; "1-2: 3"
; '(foo 1 nil 3) would print as:
; "1: 3"
;IMPLEMENTATION NOTE ON SECTION 4,
;SPECIAL ATOMS USED BY THE FORMATTING FUNCTIONS:
;
;there are a set of special variables and properties which are used by the
; formatting functions either internally, or for control from the
; outside. this list describes EVERY special variable which is
; referenced by a format function, or is considered available to be
; looked at by a format function. (variables which are not actually
; used by the standard formaters are preceeded by a *.) These variables
; are divided into catagories even though there is really some logical overlap.
;
;variables passed down from #1PRINTER which describe how a thing will be formated.
; #1checkrecursion - (t/nil) if NIL, this enhibits the function #1rcheck from checking
; for circularity in objects being formated.
;*-#1prinlevel - (a non-negative number) The depth in a structure at which the formaters should
; abbreviate non-atomic substructures by inserting |#| in place of the
; substructure. This is not acutally looked at because the same information is
; indirectly encoded in the variable #1level (see below).
; #1prinlength - (a non-negative number) The maximum number of things to
; print out at any one level. if there are more that this many things at a
; given level, the |...| is printed out in place of the remainder. (actually if
; there is only 1 to many things, and the extra one is an atom, then the
; structure prints out unabbreviated.)
;*-#1prinstartline - (a non-negative number) This is the line number of the
; first line to print out. This is actually not used by the formaters, but it
; is available. (#1printout implements this abbreviation facility.)
;*-#1prinendline - (a non-negative number) This is the line number of the last
; line to print out. This is actually not used by the formaters, but it is
; available. (#1printout implements this abbreviation facility.)
;*-#1prinmode - (a template) This is the top level template to use for formatting the
; current thing. This is not actually used because it is passed as the
; first argument to the top level call of the format functions.
; #1princ-atoms - (t/nil) if non-NIL then individual atoms in the object to be
; formated. are marked so that they will be PRINCed instead of PRIN1ed.
; 1st argument to #1format-dispatch (and all other formatting functions) - (a
; template) this is a template which is used to guide the formatting of
; the object. The top level call of #1format-dispatch is passed the
; value of #1prinmode. Only #1format-dispatch can take a null template.
; 2nd argument to #1format-dispatch (and all other formatting functions) - (an
; arbitrary object) the object to be formated. #1formt-dispatch takes an
; object of any type. the others take restricted types as their names imply.
;variables which are set by the external environment and control the actions
; of the formaters.
; #grind-template PROPERTY - (a template) if an atom has a #grind-template
; property, then whenever #1format-dispatch is given a null template and
; a list whose car is that atom, then that template will be used to
; format the list.
; #fn-grind-properties - (a list of property names) if an atom doesn't have a
; #grind-template property, but it does have one of the properties in
; this list, then whenever #1format-dispatch is given a null template
; and a list whose car is that atom, then a template which causes
; grinding in functional form will be used to format the list.
; #1default-symbol-car-grind-template - (a template) if #1format-dispatch is
; given a nil template and a list with an atomic car, and neither of the
; above two cases applies, then this template will be used to format the list.
; #1apply-template - (a template) this template is used in GRIND mode to
; format lists whose cars are lambda expressions.
; #1default-non-symbol-car-grind-template - (a template) if #1format-dispatch
; is given a nil template and a list with a non-atomic car which is not
; a lambda expression, then this template will be used to format the list
; #grind-fn PROPERTY - (a formatting function) if an atom has a #grind-fn
; property, then whenever #1format-dispatch is given a null template and
; a list whose car is that atom, then that formatting function will be used to
; format the list.
; #1format-dispatch - (a formatting function or nil) if non-nil this function
; is called whenever #1format-dispatch whould have been.
; #1format-list - (a formatting function or nil) if non-nil this function
; is called whenever #1format-list whould have been.
; #1format-hunk - (a formatting function or nil) if non-nil this function
; is called whenever #1format-hunk whould have been.
; #1format-atom - (a formatting function or nil) if non-nil this function
; is called whenever atoms are to be formated.
;variables which are used for internal communication between the formatting
; functions. All of these variables must be initialized before calling
; any format functions (this is done by #1format-init).
; #1parents - (a one dimensional array) This is used by #1rcheck in order to
; remember what cons cells have already been formated, so that it can
; detect circularity.
; #1rsize - (the length of the array in #1parents) This is used by #1rcheck
; in order to check that it is not overflowing the array #1parents. It
; automatically extends the array if it needs to.
; #1rindex - (a non-negative number less than #1rsize) This is the index of
; the first free slot in #parents. It is incremented by #1rcheck
; whenever it adds a new entry into #1parents. It is the responcibility
; of the formatting functions which call #1rcheck to decrement the value
; of #1rindex. The easiest way to do this is for each format function to
; remember the value of #1rindex on entry, and restore this value on exit.
; (this works as long as the pattern of calls and returns of the format
; functions mirrors the tree like strucutre of the object being printed.)
; (initialized to zero)
; #1level - (a non-negative number) This counts down from #1prinlevel to
; zero. When it reaches zero, the format functions do prinlevel
; abbreviation. Each format function which corresponds to a level on
; nexting, should decrement #1level on entry, and increment it on exit.
; (initialized to #1prinlevel)
; #1open-del - (nil or a thing to be PRINCed as an open delimeter) If this is
; non-nil then it causes just one substructure to use it as the open
; delimiter. The one which uses it is the one corresponding to the
; temporally first call of a substructure formater after #1open-del is
; set. The substrucutres of this structure will use the normal
; delimiters. (initialized to NIL)
; #1close-del - (nil or a thing to be PRINCed as a close delimeter) this is
; just the same as #1open-del but for the close delimiter.
;
;variables which are used for communication between the formaters and
; #1ENTER-OBJ
; #1fcode - (one of {never normal tblock block always}) this says when to put
; a crlf before the next thing to print. it is initialized to 'never at
; the top level.
; #1bcode - (a non-negative number) this is how many blanks to print out
; after the next thing to print. it is initialized to zero at the top
; level. (note that #1FCODE and #1BCODE can be conveniently set by
; #1ENTER-FORMAT and #1ENTER-FORMAT&OBJ.
; 1st arg of #1enter-obj - (an arbitrary object or if the 3rd arg is 'start
; then a number) this is the object to be printed at this point, it need
; not be an atom, though with the standard formaters it always is. if
; the second argument is NIL and the third argument is not 'start then
; the first argument is ignored, and there is no object to print.
; 2nd arg of #1enter-obj - (one of {prin1 princ nil}) the code that says how
; to print the object.
; 3rd arg of #1enter-obj - (one of {start end nil}) the code that indicates
; the beginning and end of substructures.
;SECTION 5, THE FUNCTIONS #1ENTER-OBJ AND #1PRINTOUT
;
;this is the nitty gritty which takes the formatting instructions produced by
; the formatting functions and dynamically decides how the output will
; actually look. It then does the actuall output. this is the part of
; the program which is somewhat convoluted and contorted in order to get
; efficiency. it embodies the basic ideas which make this printer so
; much faster than standard GRINDEF.
; It is not intended that the user modify these two functions.
; This is in contrast to the other parts of the system which are
; explicitly intended to be modifiable. This section is included to
; make the documentation complete, and to give a more complete
; understanding of how the #printer works.
;
;above, the actions of the formatting functions were described as creating a
; sequence of calls on #1ENTER-OBJ. (Note the macros #1ENTER-FORMAT and
; #1ENTER-FORMAT&OBJ which help in this.) #1ENTER-OBJ converts this sequence
; of calls into a static data structure which is used by #1printout in
; order to do the printing. The static data object is needed because
; #1ENTER-OBJ must do some look ahead in order to figure out some of the
; information it adds into the sequence of calls.
; The sequences of calls on #1enter-obj are designed to be easy to
; make, and to have little redundancy. The data structure is designed
; to have all of the information which #1printout needs made explicit.
; The data structure follows the same basic structure as the
; sequence of calls on #1enter-obj. It has one node of information for
; each call on #1enter-obj. at each node, it has all of the information
; passed to #1enter-obj plus several other pieces of information:
; 1. the length of the object (or entire substructure)
; 2. whether of not the substructure corresponding to a node contains
; an always code within it.
; 3. whether or not the object corresponding to this node is complete.
; I.E. in the case of substructures whether or not all of the calls
; on #1enter-obj corresponding to its interior have already been
; processed, and therefor whether the pieces of information described
; in 1, and 2 are really accurate yet. Until the item is complete these
; pieces of information are only partially true. (Note however, that
; they are monotonic. Ie they length can only increase as more is known,
; and 2 & 3 can only go from false to true.)
; Note that each of these additional pieces of information is summary
; information about a number of nodes which combine to form a
; substructure. A number of nodes must be saved up in order to complete
; the calculation associated with a given node. (in the limit this
; implies that the information (for example the length) associated with
; the very first node (which is a substructure starting node for the
; whole thing to be printed) cannot be complete until all of the nodes
; have been created.
; This would lead to a large use of storage if it weren't for one
; very important fact. The function #1PRINTOUT is often able to decide
; what it will do with a node before it has complete information about
; the node. This is due to the monitonic nature of these fields. For
; example, #1ENTER-OBJ continually updates the length fields as new
; nodes are created. #1PRINTOUT can decide that a given substructure is
; too long to fit on one line as soon as its length gets longer than the
; line length. It does not have to wait until it knows what the actual
; complete length is. this allows early nodes to be processed even
; before they are complete constructed. (It turns out that whether
; something is too long for a line is the basic thing which #1PRINTOUT
; needs to know, and as a result the system only needs to have at one time
; the nodes which correspond to roughly one line of output. This is
; true even if the thing printing out ends up taking up hundreds of lines)
;An important efficiency comes from the fact that #1PRINTOUT processes nodes
; in the data structure in a purely first in first out order. this
; allows them to be stored in a queue. as each node is created it is
; added into the queue, and #1ENTER-OBJ updates the information
; associated with the other nodes still in the queue. when one
; is processed it is dropped form the queue, and #1ENTER-OBJ no longer
; tries to compute updated information for it.
; A very big savings comes from the fact that this queue is
; implemented in arrays in such a way that no CONSing is done. This
; prevents the #printer from creating garbage collections. These arrays
; are managable in size beacuse the number of nodes that must be
; remembered at once is a function of the line length and NOT of the size
; of the thing being printed (as discussed above).
; (this queue is not implement as a ring buffer wrapping around in
; the array, but rather by just shifting things over in the array when
; the queue strikes one end. This at first appears time inefficient,
; however, since the queue never gets very long, the time lost in
; shifting is more than made up for by the time saved in testing whether
; the queue is empty, and poping ellements off of the queue.)
;
;For storage efficiency, the information associated with each node is crammed
; into three cells:
; 1. (referred to as LENGTH) holds a number which is the length of the
; object associated with the node.
; 2. (referred to as OBJECT) holds the object or indentation code
; associated with the node.
; 3. (referred to as FLAGS) holds the blank code and all of the binary
; flags packed together as bits. a set of macros are used to set and
; check these bits.
;
;The function #1SET-UP-MACROS if exicuted creates all of the macros needed for
; in compilation or running these functions uncompiled. Otherwise, the
; macros are not defined when you fasload in #print. A function DECODE
; is also defined by #1SET-UP-MACROS. This function is a debugging aid.
; It decodes the bits in FLAGS into a more readable form.
; There are two basic macros which get defined. FLAGS is a macro
; which builts up FLAGS entries. It takes numbers, things which
; evaluate to numbers and quoted keywords from the list
; {always normal block tblock never princ prin1 list-start list-end
; complete inner-always}.
; It creates code which builds a FLAGS entry. for example:
; (flags 1 'never 'list-start (foo))
; creates a FLAGS entry which has a blank code of 1, a format code of
; 'never, is the starting node for a substructure, and which also has
; all of the bits set corresponding to the FLAG returned by (foo).
; A set of macros is produced for querying these bits. the set
; {always? normal? block? tblock? never? princ? prin1? list-start? list-end?
; complete? inner-always?} test for the presence of the corresponding
; flags. The macro BCODE returns the number corresponding to the blank
; code of a FLAGS entry.
;#1enter-obj performs several tasks:
; 1. It combines the variables #1FCODE #1BCODE, and its second and third
; arguments into a FLAGS entry. (Note that these variables can be
; conveniently set by #1ENTER-FORMAT and #1ENTER-FORMAT&OBJ.)
; 2. As part of this it takes the bcode associated with a list-start node
; and puts it on the last node in the substructure. this is done
; because it is more logical to state the bcode when starting the
; structure, but more conventient for #1PRINTOUT to have it at the end
; (which is after all where the blanks get printed). In order to do
; this #1ENTER-OBJ uses a stack implemented in a vector #1BCODESTACK and
; using a pointer #1SUPPTR. The stack is needed in order to remember
; the bcode from the time it is first available until the time it is
; needed.
; 3. It computes the length of each atomic node (those which aren't
; list-start nodes) and puts that as the length of the node and adds it
; into the length of all of the list start nodes which are its superiors
; (except those which have already been taken off the queue). The
; list-start nodes start out with length zero. The length of an atomic
; node is the bcode plus the flatsize (or flatc) of the object to print
; (if there is one). The vector #1SUPSTACK is used to keep a stack of
; the superiors of the current node. the stack contains numbers which
; are the differences between the positions in the queue of succeeding
; superiors. differences are used because they remain correct when the
; queue is shifted over. the pointer #1SUPPTR is used as the stack
; pointer since #1SUPSTACK and #1BCODESTACK go up and down in synchrony.
; 4. If any node has an ALWAYS flag, then #1ENTER-OBJ sets the INNER-ALWAYS
; flag on in each superior.
; 5. #1ENTER-OBJ sets the COMPLETE flag on in each atomic node, and with
; each list-end node, it marks the corresponding list-start, complete.
; 6. Internally it maintains #1SUPSTACK and #1BCODESTACK for its own use.
; this amounts to pushing each list-start node and doing a pop for each
; list-end node. In addition #1ENTER-OBJ extends the vectors if they
; ever prove to be too short. #1SUPSIZE holds their length for easy
; reference.
; 7. it enters each of these objects into the queue. the queue is
; implemented by three vectors: #1OBJ, #1FLAG and #1LENGTH and two
; pointers: #1INPTR which points to the insertion point and #1PP which
; points to the removal point (the head of the queue). These vectors
; are extended if they prove too small. the variable #1SIZE holds the
; length of these vectors for easy reference.
; 8. if the variable #1EXPLODING is non-nil then instead of queueing up the
; nodes, #1ENTER-OBJ just NCONCs up the EXPLODEs of the objects in the
; atom nodes in the variable #1EXPLODE-RESULT. NRECONC is used, so that
; #1EXPLODE-RESULT can simply be NREVERSed in order to get the result.
; 9. if #1EXPLODING is nil then #1ENTER-OBJ calls #1PRINTOUT each time a
; new node is added in order to see whether it has enough information to
; do something.
;the following example shows the static data structure built up corresponding
; to the example from section 2:
(declare `|"(list (cons var1 var2) var3 var4)" leads too:
fcode bcode obj pcode lcode length inner-a complete
1 'never _ 6 nil 'start 33 nil t
2 'never 0 '/( 'princ nil 1 nil t
3 'never 1 'list 'prin1 nil 5 nil t
4 'never _ 6 nil 'start 17 nil t
5 'never 0 '/( 'princ nil 1 nil t
6 'never 1 'cons 'prin1 nil 5 nil t
7 'never 1 'var1 'prin1 nil 5 nil t
8 'normal 1 'var2 'prin1 nil 4 nil t
9 'never 1 '/) 'princ 'end 2 nil t
10 'normal 1 'var3 'prin1 nil 5 nil t
11 'normal 0 'var4 'prin1 nil 4 nil t
12 'never 0 '/) 'princ 'end 1 nil t |)
;this is as you would see it left in memory after printout was complete. all
; of the complete bits have been turned on, there are no inner-always,
; the lengths have been computed, the bcodes have been moved from the
; list-start nodes to the corresponding list-end nodes. The section
; above which discusses calls on #1ENTER-OBJ discusses how the above
; sequence would be interpreted in order to print the list out.
;The function #1PRINTOUT acts like an interpreter for the data structure built
; up by #1ENTER-OBJ. Each time it is called it looks at the first
; element in the queue and decides whether or not it can do something
; with it. If it can do something it loops back and calls itself
; again. If not it just exits.
; 1. it first checks to see if the queue is empty, if so, it just exits.
; 2. It then checks to see if it is possible that it might have to tab in
; front of the next node (ie if it has a TBLOCK fcode and is complete).
; If this is the case, and if it hasn't already figured out what the size of
; tabs will be (the variable #1TABSIZE is 1) then It figures out what the size
; of tabs will be. It does this by looking at the length of the current node
; and the following nodes at the same level. It takes the max of all their
; lengths. However, it realizes that it may not have seen all of the subnodes
; which are supposed to be printed in columns and therefor this maximum may not
; be long enough to insure that all of the nodes will line up nicely when
; printed out. In order to make a more conservative estimate of the spacing
; required, it first raises its estimate by 20%, and then rounds it
; up to the largest integer which divides the available line length the same
; number of times. To do this it uses the properties of integer arithmitic and
; the expression:
; x = (// linelength (// linelength x))
; For example if the maximum node in view is 11 and the available line
; length is 62 (for example, the line length is 95 and this substructure
; starts in column 33). first the max would be increased by 20% to 13 and then it
; would be increased to 15 since 13 goes into 62 4 times, and 15 is the
; largest integer which goes into 62 4 times.
; Having computed the tab size, #1PRINTOUT then computes an offset
; in the variable #1TABOFFSET. this is done because the space remaining
; on the line may not be a multiple of the tab size. (In the example
; above the offset is 2.) How far to tab in a given situation is
; computed by the expression:
; (\ (- space-remaining #1taboffset) #1tabsize)
; (there is a bug in this if the space remaining ever gets less than
; #1TABOFFSET. In this case, the remainder function has a negative first
; argument and doesn't do what you would like. To fix this the offset
; stored in #1TABOFFSET is actually (- offset #1TABSIZE) this is just
; the same from the point of view of modular arithmetic and has the
; virtue that it is always negative.)
; 3. next #1PRINTOUT checks to see whether it needs to insert a crlf at the
; current point. In doing this it checks whether the last thing is did
; was to put out a crlf. if so, then it never puts out another one.
; then if the next thing needs to be tabbed in front, it checks to see
; whether enough spaces have been put out. Finally it looks at the
; fcode and sees whether it implies that a crlf whould be inserted. (See
; above for a deiscussion for what the fcodes mean.)
; 4. if a crlf is needed, then it is put out and blanks are printed in
; order to space over to the correct indentation column. the
; indentation codes in the calls to #1ENTER-OBJ are used in order to
; know what column to tab too. the indentation columns are remembered in
; a stack implemented by a vector in #1INDSTACK and the pointer
; #1INDPTR. (See below for how the indentation points are calculated.)
; This section implements #1prinstartline-#1prinendline
; abbreviation. a variable #1printing? is used as a flag which controls
; whether any actual output is ever done. Each time a crlf is to be
; performed #1PRINTOUT checks to see whether the state of this flag
; should be changed. if #1prinendline is reached, then #1PRINTOUT does
; a throw in order to abort the #printing.
; 5. Now #1PRINTOUT knows that if a crlf is needed before the next thing,
; it has already been put out. it now looks at the next thing to be
; printed out. there are three cases:
; 6. the next item is a substructure whose length as currently computed is
; already too long to fit in the space remaining on this line. In this
; case, #1PRINTOUT looks inside this structure in order to print it on
; more than one line. to do this, it simply moves over the header node
; and computes the new indentation column. the new indentation is
; computed by adding the indentaion count in the header cell to the
; current column possition. if the resulting indentation is less than
; the initial starting column position (kept in the variable #1CP) then
; it is increased to that. this is waht prevents the #printer from ever
; printing to the left of where it starts. if it is greater than the value of
; #1MAXINDENTLEN (which is initialized to 80% of the available line length) then
; it is reduced by 60% of the available line length. this keeps output
; from getting so pushed up against the left margin that there isn't enough
; room to print the individual atoms in the structure. an abrubt
; change in indentation is produced which tends to be rather ugly, but
; which is clearly understandable and saves the #1printer from disaster.
; The new indentation level is pushed onto the stack #1INDSTACK.
; (#1PRINTOUT does not have to check for overflow in this vector,
; because #1ENTER-OBJ extends it to be as long as #1SUPSTACK. The
; latter is as long as the maximum number of levels in the structure
; being printed. as a result #1INDSTACK can't overflow even if
; #1PRINTOUT has to look inside the deapest structure in the thing being
; printed.)
; In addition #1TABSIZE is set to 1 which indicates that it is
; unitialized. It will be recaluclated for this new level if needed.
; 7. alternatively, the next node may not be too long to fit and may be
; complete. if this is the case then it is printed out. #1PRINTOUT
; counts header nodes and LIST-END nodes in order to see when it has
; printed out all of the things associated with the initial node. If
; the first node encountered by #1PRINTOUT is a LIST-END node then
; #1PRINTOUT prints it out and pops up a level in the structure being
; printed. when it does this, it sets #1TABSIZE to 64000. which has the
; effect of preventing continued tabbing at the level popped back to.
; Logically #1PRINTOUT should keep a stack of tab sizes, so that it
; could continue tabing when it pops back out of a substructure.
; However, it was decided that if one of the substructures in a
; structure being printed with tabbing takes more than one line, then
; tabbing should not continue at that level. This was done because
; experimentation showed that continued tabbing made it harder to
; understand what was being #printed.
; 8. often neither 6 or 7 is true, in that case, #1PRINTOUT just does
; nothing and returns to #1ENTER-OBJ in order to get more information.
; 9. if either 6 or 7 was true then #1PRINTOUT loops back to the top in
; order to see whether it can do anything more.
;IMPLEMENTATION NOTE ON LEVEL 5
;SPECIAL VARIABLES USED BY #1ENTER-OBJ AND #1PRINTOUT
;
;a large number of these variables (particularly the ones which are internal
; to theis part of the package) are initialized by the function #1FORMAT-INIT.
;
;variables which are used for communication between the formaters and
; #1ENTER-OBJ:
; #1fcode - (one of {never normal tblock block always}) this says when to put
; a crlf before the next thing to print. it is initialized to 'never at
; the top level.
; #1bcode - (a non-negative number) this is how many blanks to print out
; after the next thing to print. it is initialized to zero at the top
; level. (note that #1FCODE and #1BCODE can be conveniently set by
; #1ENTER-FORMAT and #1ENTER-FORMAT&OBJ.
; 1st arg of #1enter-obj - (an arbitrary object or if the 3rd arg is 'start
; then a number) this is the object to be printed at this point, it need
; not be an atom, though with the standard formaters it always is. if
; the second argument is NIL and the third argument is not 'start then
; the first argument is ignored, and there is no object to print.
; 2nd arg of #1enter-obj - (one of {prin1 princ nil}) the code that says how
; to print the object.
; 3rd arg of #1enter-obj - (one of {start end nil}) the code that indicates
; the beginning and end of substructures.
;
;Variables which are used to communicate between #1PRINTER and #1ENTER-OBJ:
; #1exploding (t/nil) if T then #1PRINTOUT is not actually called, and the
; EXPLODEs of the nodes is consed up and returned instead.
; #1explode-result (a list of characters) if #exploding, this is used to
; accumulate the nreverse of the result in.
;
;Variables which are used to communicate between #1PRINTER and #1PRINTOUT:
; #1prinendline (a non-negative number) this says what line to stop printing
; on. when this line is reached a throw is done to terminate #printing.
; #1prinstartline (a non-negative number) this says what line to start
; printing on. Until this line is reached, nothing is actually printed out.
; #1cp (a non-negative number) this is the column position where #printed was
; initiated. #RINTOUT takes pains not to print ot the left of this
; point. it is treated as the defacto zero point for the left margin.
; this is initialized by #1FORMAT-INIT to (CHARPOS #1MAINFILE).
; #1linelen (a non-negative number) this is (- (LINEL #1MAINFILE) 5) the -5 is
; done in order to make closing parentheses come out in the right place a
; higher percentage of the time. this is used to figure out how much
; space is left on the current line being printed on.
; #1maxindentlen (a non-negative number) this is point 80% of the way from
; #1CP to #1LINELEN and is used to limit the total amount of indentation allowed.
; #1files (a list of files) this is used as an argument to PRINC PRIN1 TERPRI
; and TYO in order ot control where the output goes to.
;
;Variables used by #1ENTER-OBJ to communicate with itself:
; #1bcodestack (a vector of fixnums) this holds the bcodes which are specified
; at the start of substructures until they are used at the end of the substructure.
; #1supstack (a vector of fixnums) this holds differences which can be used to
; find the nodes which are the superiors of the current node.
; #1supptr (a fixnum pointer into the above two vectors) this is used to make
; a stack out of the above.
; #1supsize (the size of the above two vectors) this holds the size of the
; above vectors and #1indstack below (which are automatically extended if need be).
;
;Variables used for communication between #1ENTER-OBJ and #1PRINTOUT:
; #1obj (a vector of objects) the object at a node
; #1flag (a vector of flag bits crushed into fixnums) the flag bits for a node.
; #1length (a vector of fixnums)the length of each node.
; as discussed at length above, these three vectors form a queue holding
; the information at each node of the intermediate structure built up by
; #1ENTER-OBJ.
; #1inptr (a pointer into the above three vectors) the insertion point in the
; above queues.
; #1pp (a pointer into the above three vectors) the removal point in the above
; queues.
; #1size (the size of the above three vectors) this holds the size of the
; above vectors (which are automatically extended if need be).
;
;Variables used by #1PRINTOUT to communicate with itself:
; #1cline (a non-negative number) this is the relative line number of the
; place where #1PRINTOUT is currently printing. this is what is compared
; with #1prinendline and #1prinstartline.
; #1freelen (a number) this is the amount of free space left at the end of the
; current line. the current charpos on that line is (- #1linelen #1freelen).
; #1pending (a non-negative number) this is the number of blanks which should
; be printed before the next thing. #1PRINTOUT never prints any blanks
; until it absolutely has to, rather it just increments #1PENDING. this
; allows it to simply avoid printing blanks at the end of a line.
; #1tabsize (a non-negative number) this is the current size for tabbing (see
; the discussion above). The value 1 indicates that the correct tab size
; has not yet been calculated.
; #1taboffset (a negative number) This is used in conjunction with #1TABSIZE
; (see the discussion above).
; #1atstart? (t/nil) this flag is used by #1PRINTOUT in order to quichly check
; whether or not it is at the start of a line. ie whether th e last
; thing it did was to do a crlf or not.
; #1wentup? (t/nil) this is T if the last thing #1PRINTOUT did was to pop up
; out of a lower structure. this is used in conjunction with BLOCK and
; TBLOCK modes.
; #1printing? (t/nil) this is nil when #1cline is less that #1prinstartline
; and therefor actual printout is being supressed.
; #1indstack (a vector of numbers) this is a stack which is used to keep the
; indentation points associated wiht the different levels in the
; structure being printed. each indentation is greater than or equal to
; #1cp and less than of equal to #1maxindentlen.
; #1indptr (a pointer into the above vector) this is used to implement a
; stack in #1indstack.
;these are all declarations and macro definitions
(declare (fasload util fasl dsk dick) (u1setupreader)
(fixnum i j k n length end rindex max default-bcode bcode space level flags)
;system special variables which are looked at, never bound, and never assigned to
;(except that some of them may be given initial values at load time if they are unbound)
;most of these are used in order for the user to comunicate with the printer.
(special #checkrecursion prinlevel prinlength prinmode prinendline
prinstartline ^r ^w outfiles grindef grindproperties #fn-grind-properties
#1default-symbol-car-grind-template #1default-non-symbol-car-grind-template
tyo #1format-dispatch #1format-list #1format-atom #1format-hunk grind-macroexpanded)
;special variables which are used by the system to communicate with itself. they
;are rebound in order to save a state of the system, and are set up by #1format-init
;these should not be changed by the user unless he really knows what he is doing.
(special #1prinlevel #1prinlength #1prinendline #1prinstartline
#1cp #1linelen #1maxindentlen #1cline #1freelen #1pending #1tabsize
#1taboffset #1inptr #1pp #1supptr #1indptr #1size #1supsize #1rsize
#1prinmode #1checkrecursion #1mainfile #1truncated #1files
#1atstart? #1wentup? #1printing? #1obj #1flag #1length #1supstack
#1indstack #1parents #1nowprinting #1fcode #1bcode #1bcodestack
#1level #1rindex #1open-del #1close-del #1princ-atoms #1print-like
#1exploding #1explode-result)
;special variables which are used to hold system constants (they should never be modified)
(special #1miser-template #1block-template #1crush-template #1fn-template
#11level-block-template #1defun1-template
#1defun2-template #11level-tblock-template
#1apply-template #11level-miser-template #1tblock-template)
(*lexpr #prin1 #print prinl prinl1))
(declare (@define deffn))
;this file makes heavy use of the macros in the file util > dsk dick. for those who
;do not like to read macros like these, a completely macro expanded version of #print
;is included at the end of the file. that version contains no macro calls,
;and is guarrenteed to be accurate (in fact, the fasl file is actually a compilation of the
;the macro expanded version). As long as I maintain this file I will work with the
;macro version and keep the expanded version correct.
;these macros are here in order to satisfy the compiler,
;they logically belong with #1enter-obj
(deffn #1enter-format macro keep displace [_ f b]
`(setq #1fcode ,f #1bcode ,b))
(deffn #1enter-format&obj macro keep displace [_ f b o p l]
`(progn (#1enter-format ,f ,b)
(#1enter-obj ,o ,p ,l)))
;this is used to construct a fn #1set-up-macros which can be run at any time
;in order to define all of the macros which are needed for any of the functions
;below can be run interpretively. This gives you access to the macros without
;having them always defined.
(decl
(deffn build-#1set-up-ms macro []
(let ((#encodings '((always 64.) ; 000 100
(normal 128.) ; 000 200
(block 256.) ; 000 400
(never 512.) ; 001 000
(tblock 1024.) ; 002 000
(princ 2048.) ; 004 000
(prin1 4096.) ; 010 000
(list-start 8192.) ; 020 000
(list-end 16384.) ; 040 000
(complete 32768.) ; 100 000
(inner-always 65536.)))) ; 200 000
['deffn '#1set-up-macros '[]
!(over '((#1obj nil) (#1flag fixnum) (#1length fixnum) (#1supstack fixnum)
(#1indstack fixnum) (#1parents nil) (#1bcodestack fixnum))
-> [atom type] nconc
`((deffn ,atom macro displace [!from]
`(arraycall ,',type ,.(copy from)))
(deffn ,atom u1<- [to]
`((store ,to u1f) nil))))
'(deffn call macro displace [_ fn ! args]
`(if ,fn (funcall ,fn ,.args)
el (,fn ,.args)))
'(deffn bcode macro displace [_ x]
`(boole 1. 63. ,x))
!(over #encodings -> [name code]
list `(deffn ,(catenate name '?) macro displace [_ x]
`(not (zerop (boole 1. ,',code ,x)))))
;there are three different kinds of arguments to FLAGS. literal numbers, something that
;evaluates to a number, and quoted atoms from the list of flag names in #encodings
(subst #encodings 'encodings
'(deffn flags macro displace [_ ! args]
(begin (sum <- 0
body <- (over args -> arg
nconc (if (numberp arg)
(<- sum (+ sum arg))
nil
ef (or (atom arg) (not (eq (car arg) 'quote)))
[arg]
el;(eq (car arg) 'quote)
(let ((val (cadr (assq (cadr arg) 'encodings))))
(if (null val) (error '|bad code to FLAGs| args))
(<- sum (+ sum val)))
nil)))
(if (not (zerop sum)) (<- body [sum ! body]))
(if (null body) ''0
ef (null (cdr body)) ['progn ! body]
el ['+ ! body]))))
(subst #encodings 'encodings
'(deffn decode [x]
[(bcode x)
!(over 'encodings -> [name code]
select (not (zerop (boole 1. code x)))
list name)]))])))
(decl-double (build-#1set-up-ms))
(decl (#1set-up-macros))
;the basic printer produces output under the control of a template.
;(yet another simple programming language)
;the template conforms to the following grammer:
;
; template := explicit-temp v NIL
; explicit-temp := ( indent-count item-temp*n )
; indent-count := number v NIL
; item-temp := ( {NEVER v ALWAYS v NORMAL v BLOCK v TBLOCK} . template )
;
;if a template is NIL then the printer looks at the item to be printed in order to figure
;out what the template should be. if an indent count is NIL then (+ 2 (flatsize of the head of
;the list being printed)) is used as the indentation (this is functional form indentation).
;
;the printer carcdrs down the template and the item being printed in order to decide
;what format codes and indentation codes to use at each point.
;It has internal conventions for what the other flag fields will be.
;
;the average template is a very circular structure so that it can work on structures of
;arbitrary depth and circularity. the following function is included in order to make it
;easier to construct these circular structures. the argument to #make-template is a list
;which may contain elements of the form (^ . n) (as cars or cdrs). each of these is RPLACed
;by its nth parent in the list structure. for example:
;(SETQ X (#MAKE-TEMPLATE '(FOO (^ . 2) BAR . (^ . 1))))
;would produce an x such that (eq x (cadr x)) and (eq (cddr x) (cdddr x))
;x has the form (foo (foo (foo ...) ...) bar bar bar ...)
;note that #print whould print x out as (foo ^2 bar ^1) if #checkrecursion was non-null.
;
;note that this does not destroy its argument, and works even if its argument is circular.
(deffn #make-template [pattern]
(#make-template1 pattern nil nil))
(deffn #make-template1 [pattern oldbacklist newbacklist]
(if (atom pattern) pattern
ef (memq pattern oldbacklist)
(over oldbacklist until nil -> old
over newbacklist until nil -> new
(if (eq old pattern) (return new)))
ef (eq (car pattern) '^)
(over newbacklist until nil -> new
over icount <- (1- (cdr pattern)) by (1- icount) until nil
(if (zerop icount) (return new)))
el (let ((newcons (ncons nil)))
(pushonto oldbacklist pattern)
(pushonto newbacklist newcons)
(rplaca newcons (#make-template1 (car pattern) oldbacklist newbacklist))
(rplacd newcons (#make-template1 (cdr pattern) oldbacklist newbacklist))
newcons)))
;these are the basic templates which are used to implement the five basic printing
;modes MISER, CRUSH, BLOCK, TBLOCK, and the functional and block forms of GRIND.
(deffn #1set-up-templates []
(<- #1miser-template
(#make-template '(1 (never . (^ . 3)) (normal . (^ . 4)) . (^ . 1)))
#1crush-template
(#make-template '(-900 (never . (^ . 3)) . (^ . 1)))
#1block-template
(#make-template '(1 (never . (^ . 3)) (block . (^ . 4)) . (^ . 1)))
#1tblock-template
(#make-template '(1 (never . (^ . 3)) (tblock . (^ . 4)) . (^ . 1)))
#1fn-template
(#make-template '(nil (never) (never) (normal) . (^ . 1)))
#11level-miser-template
(#make-template '(1 (never) (normal) . (^ . 1)))
#11level-block-template
(#make-template '(1 (block) . (^ . 1)))
#11level-tblock-template
(#make-template '(1 (tblock) . (^ . 1)))
#1default-symbol-car-grind-template #1fn-template
#1default-non-symbol-car-grind-template #11level-miser-template
(get 'lambda '#grind-template)
(#make-template '(2 (never) (never . (1 (block) . (^ . 1)))
(normal) . (^ . 1)))
#1apply-template
(#make-template '(1 (never) (block) . (^ . 1)))
(get 'setq '#grind-template)
(#make-template '(nil (never) (never) (block) (always) (block) . (^ . 2)))
(get 'cond '#grind-template)
(#make-template '(nil (never) (never . (1 (never) (normal) . (^ . 1)))
(always . (1 (never) (normal) . (^ . 1)))
. (^ . 1)))
#1defun1-template
(#make-template '(2 (never) (never) (never) (normal) . (^ . 1)))
#1defun2-template
(#make-template '(2 (never) (never) (never) (never) (normal) . (^ . 1)))))
(#1set-up-templates)
;this checks that the special variables which control formatting are bound
;(the rest of the system assumes that they are bound) It gives them default
;values if they were not bound
(deffn #1set-up-globals []
(<- #1truncated nil)
(over '((prinlevel nil)
(prinlength nil)
(prinmode grind)
(prinstartline nil)
(prinendline nil)
(#checkrecursion nil)
(#fn-grind-properties (expr fexpr macro subr lsubr fsubr array autoload))
(grindproperties (expr fexpr macro))
(grindef nil)
(#1format-dispatch nil)
(#1format-list nil)
(#1format-hunk nil)
(#1format-atom nil)
(#1nowprinting nil)
(#1size nil))
-> [atom val]
(if (not (boundp atom))
(set atom val))))
(#1set-up-globals)
;________________________________________________________________________________
;this is available for setting up the suggested printing environment. it MUST
;BE CALLED BY THE USER if you want it to happen
(deffn #1set-up-printer []
(sstatus ttyint 19. '#printabort) ;^S stops printing
(sstatus ttyint 3. '#continue) ;^C makes it continue on
(endpagefn tyo '#1endpagefn) ;needed by ^C
(setq prin1 '#prin1)) ;makes #prin1 default printer
;this is available to free up almost all of the space taken up by the #printer.
;this really isn't very much space (binary program or otherwise)
(deffn #1rem-printer []
(if (eq (status ttyint 19.) '#printabort) (sstatus ttyint 19. nil))
(if (eq (status ttyint 3.) '#continue) (sstatus ttyint 3. nil))
(if (eq (endpagefn tyo) '#1endpagefn) (endpagefn tyo '+internal-tty-endpagefn))
(setq prin1 nil)
(over '((#1enter-format macro)(#1enter-format&obj macro)
(#make-template subr)(#make-template1 subr)
(#1set-up-templates subr)(#1set-up-globals subr)
(#1set-up-printer subr)(#1rem-printer subr)
(#prin1 lsubr)(#princ lsubr)(#print lsubr)
(#prinl1 lsubr)(#prinlc lsubr)(#prinl lsubr)
(#explode subr)(#explodec subr)(#explodel lsubr)
(grindef fsubr)(#1printabort subr)(#continue subr)
(#1endpage-fn subr)(#1printer subr)(#1format-init subr)
(#1format-dispatch subr)(#1rcheck subr)(#1format-list subr)
(#1format-lsubr lsubr)(#1format-hunk subr)
(#make-invert-quote-fn macro)(#make-invert-quote-fn2 macro)
(quote #grind-fn) (defun #grind-fn)(prog #grind-fn)(do #grind-fn)
(macroexpanded #grind-fn)
(#1set-up-macros subr)(#1enter-obj subr)(#1printout subr))
(remprop (car _) (cdr _)))
(over '(#1obj #1flag #1length #1supstack #1bcodestack #1indstack #1parents #1pobj)
(makunbound _)))
;the following are the main user functions for calling the #printer
;they are all in the form of a call on #1printer and they are all lsubrs
(defun #prin1 nargs (#1printer 0. (arg 1) (listify (- 1 nargs))))
(defun #princ nargs (#1printer 1. (arg 1) (listify (- 1 nargs))))
(defun #print nargs (#1printer 2. (arg 1) (listify (- 1 nargs))))
(defun prinl1 nargs (#1printer 4. (arg 1) (listify (- 1 nargs))))
(defun prinlc nargs (#1printer 5. (arg 1) (listify (- 1 nargs))))
(defun prinl nargs (#1printer 6. (arg 1) (listify (- 1 nargs))))
(defun #explode (obj) (#1printer 8. obj nil))
(defun #explodec (obj) (#1printer 9. obj nil))
(defun #explodel nargs (#1printer 14. (arg 1) (listify (- 1 nargs))))
;________________________________________________________________________________
;this is a rewritten version of grindef which calls prinl. it is intended to be
;exactly compatable with the old grindef as far as arguments etc.
;the variable GRINDPROPERTIES holds the default properties which will be printed
;out. additional properties can be specyfied as the first arg of GRINDEF. the printout
;format is of course a bit different as is the way you specify grind functions.
(deffn grindef fexpr [!arg]
(begin ([_ (not (atom _)) = props :!_ !atoms]
<- (if arg (<- grindef arg) el grindef)
selectedprops <- [!! props ! grindproperties])
(over atoms -> atom
(and (status feature trace) (memq atom (trace))) -> traced
(over [ind prop ! rest] <- (plist atom) by rest until (null ind)
select (and (if (and traced (memq ind '(expr fexpr macro)))
(<- traced nil)
(if (memq ind selectedprops)
(terpri) (princ '|;traced|))
nil
el t)
(memq ind selectedprops))
(if (and (not (atom prop)) (eq (car prop) 'lambda))
(prinl ['defun
! (if (eq ind 'expr) [atom]
ef (memq ind '(fexpr macro)) [atom ind]
el [[atom ind]])
! (cdr prop)]
'grind)
el (prinl ['defprop atom prop ind] 'grind)))))
'||)
;this should be put on an interrupt character i.e. (sstatus ttyint 19. '#printabort)
;it enables you to stop printing in the middle of something.
(deffn #printabort [unused-f unused-ch]
(nointerrupt nil)
(tyi tyi)
(if #1nowprinting (errset (throw '|aborted| #1printabort))))
;this allows you to continue output which was truncated because
;it was too many lines long. it is only really intended to work with output to the tty.
;this should be put on an interrupt character ie (sstatus ttyint 3. '#continue)
(declare ((lambda (obarray) (remprop (intern 'cursorpos) (intern 'acs))) sobarray))
;due to changes in cursorpos fn code.
(deffn #continue [unused-f unused-ch]
(nointerrupt nil)
(tyi tyi)
(if #1truncated
(begin ([c1truncatepos c1cp c1mainfile c1code c1obj
[_ _ _ _ _ c1files] = c1params] <- #1truncated
on-same-line <- (= (car c1truncatepos) (car (cursorpos c1mainfile))))
(cursorpos (car c1truncatepos) (cdr c1truncatepos) c1mainfile)
(cursorpos 'l c1mainfile)
(if on-same-line (terpri c1files) el (terpri c1mainfile))
(over i <- c1cp by (1- i) until (zerop i) (tyo 32. c1mainfile))
(#1printer c1code
;this terrible cludge is in here to force c1obj into a register so that the
;call on MUNKAM will compile correctly!!!!!!
((lambda (foo) (munkam (+ foo 0))) c1obj)
c1params)
(if (not on-same-line) (terpri #1files))))
'||)
;________________________________________________________________________________
;this is a new endpage function which must be used if #continue is used because
;for some reason the system endpagefn will not do mores during the printout initiated by
;#continue.
(deffn #1endpagefn [tty]
(nointerrupt nil) (cursorpos 'z tty) (cursorpos 'l tty)
(princ '|##more##| tty)
(let ((echofiles nil)) (tyi))
(cursorpos 'z tty) (cursorpos 'l tty) (cursorpos 'top tty) (cursorpos 'l tty))
;this is the main entry function into the internals of the printer.
;it checks to see if the printer is being reenterd and if so rebinds all of the critical
;globals so that the old invocation will be protected. then it sets up the initial
;values of all of the globals and fires up the format functions.
(deffn #1printer [code obj inits]
;if reentering printer rebind everything and recurse.
(if #1nowprinting
(let (#1nowprinting #1obj #1flag #1length #1supstack #1indstack #1parents
#1size #1supsize #1rsize #1prinlevel #1prinlength #1prinendline
#1prinstartline #1cp #1linelen #1maxindentlen #1cline #1freelen
#1pending #1tabsize #1taboffset #1inptr #1pp #1supptr #1indptr #1prinmode
#1checkrecursion #1mainfile #1files #1atstart? #1wentup?
#1printing? #1fcode #1bcode #1bcodestack #1open-del #1close-del #1level
#1rindex #1princ-atoms #1print-like #1exploding #1explode-result)
(#1printer code obj inits))
;decode arguments and set up format control variables.
el (begin (#1nowprinting <- t)
(<- #1princ-atoms (not (zerop (boole 1. 1. code)))
#1print-like (not (zerop (boole 1. 2. code)))
#1exploding (not (zerop (boole 1. 8. code)))
#1checkrecursion #checkrecursion)
(if (zerop (boole 1. 4. code))
(<- #1prinlevel (or prinlevel 64000.)
#1prinlength (or prinlength 64000.)
#1prinendline (or prinendline 64000.)
#1prinstartline (or prinstartline 0.)
#1prinmode prinmode)
el (<- #1prinlevel 64000. #1prinlength 64000.
#1prinendline 64000. #1prinstartline 0.
#1prinmode nil)
(match inits
[_ (if (numberp _) (<- #1prinlevel _) el (null _)) :!_
_ (if (numberp _) (<- #1prinlength _) el (null _)) :!_
_ (if (numberp _) (<- #1prinendline _) el (null _)) :!_
_ (if (numberp _) (<- #1prinstartline _) el (null _)) :!_
_ (or (memq _ '(grind block tblock miser crush)) (null _)
(and (not (atom _)) (not (atom (cdr _))) (not (atom (cadr _)))))
= #1prinmode :!_
! inits]))
(<- #1prinmode (if (eq #1prinmode 'grind) nil
ef (eq #1prinmode 'crush) #1crush-template
ef (eq #1prinmode 'tblock) #1tblock-template
ef (eq #1prinmode 'block) #1block-template
ef (eq #1prinmode 'miser) #1miser-template
el #1prinmode)
#1files (if (or (not (atom (car inits))) (null (car inits))) (car inits)
el inits))
;having decoded the args, do the work.
(if (and (not #1exploding) #1print-like (not (> #1prinstartline 0)))
(terpri #1files))
(if (and (atom obj) (null #1format-dispatch) (null #1format-atom) (not #1exploding))
(if #1princ-atoms (princ obj #1files) ef (not (eq obj '||)) (prin1 obj #1files))
el (#1format-init)
(if (null (errset
(if (catch (call #1format-dispatch #1prinmode obj) #1printabort)
(if (not #1exploding)
(<- #1truncated [(cursorpos #1mainfile) #1cp #1mainfile
(boole 7. code 4.) (maknum obj)
[#1prinlevel #1prinlength nil #1cline
#1prinmode #1files]])
(if (and #1printing? (plusp #1freelen))
(princ '| ---| #1files))))))
(if (null (errset (let (prin1)
(print '|error while #PRINTing:|)
(print obj))))
(let (prin1)
(print '|error while PRINTing MUNKAM of |)
(princ (maknum obj))))))
(if (and (not #1exploding) #1print-like (null #1truncated) #1printing?)
(tyo 32. #1files))
(if #1exploding
(prog2 nil (nreverse #1explode-result) (<- #1explode-result nil))
el t))))
(deffn #1format-init []
(if (null #1size)
(<- #1obj (array nil nil 100.)
#1flag (array nil fixnum 100.)
#1length (array nil fixnum 100.)
#1supstack (array nil fixnum 50.)
#1bcodestack (array nil fixnum 50.)
#1indstack (array nil fixnum 50.)
#1parents (array nil nil 50.)
#1size 100.
#1supsize 50.
#1rsize 50.))
(<- #1mainfile (if #1files (car #1files)
ef (and ^r ^w (car outfiles))
el tyo)
#1cp (charpos #1mainfile)
#1linelen (- (linel #1mainfile) 5)
#1maxindentlen (+ #1cp (* 4 (// (- #1linelen #1cp) 5)))
#1cline 0
#1atstart? t
#1freelen (- #1linelen #1cp)
#1pending 0
#1wentup? nil
#1printing? (not (> #1prinstartline 0))
#1tabsize 1
#1taboffset 0
#1inptr -1
#1pp 0
#1supptr 0
(#1supstack 0) 0
#1indptr 0
(#1indstack 0) #1cp
#1open-del nil
#1close-del nil
#1fcode 'never
#1bcode 0
#1level #1prinlevel
#1rindex 0
#1explode-result nil))
(deffn #1format-dispatch [template item]
(if (hunkp item)
(call #1format-hunk (if template el #11level-block-template) item)
ef (eq (typep item) 'list)
(if template (call #1format-list template item)
el (begin (head <- (car item)
symbol? <- (eq (typep head) 'symbol)
grind-fn <- (if symbol? (get head '#grind-fn))
template <- (if symbol?
(if (get head '#grind-template)
ef (getl head #fn-grind-properties) #1fn-template
el #1default-symbol-car-grind-template)
ef (and (eq (typep head) 'list)
(eq (car head) 'lambda))
#1apply-template
el #1default-non-symbol-car-grind-template))
(if grind-fn (funcall grind-fn template item)
el (call #1format-list template item))))
el (if #1format-atom (funcall #1format-atom template item)
el (#1enter-obj item (if #1princ-atoms 'princ el 'prin1) nil)))
nil)
;________________________________________________________________________________
;this does recursion checking. it looks in the array #1parents to see if the
;item has already been encountered. if so, an atom of the form ^# is consed
;up to stand in its place. If not it is put in the array #1parents, and
;#1rindex is incremented. it is up to the format functions which call
;#1rcheck to see that the value of rindex is decremented correctly.
(deffn #1rcheck [item]
;if the item is an atom, or if we are not checking then return quick
(if (or (atom item) (not #1checkrecursion)) item
;if the array is not big enough to add this item extend the array
el (if (not (< #1rindex #1rsize))
(<- #1rsize (+ #1rindex 25.))
(*rearray #1parents (car (arraydims #1parents)) #1rsize))
;search #1parents for item if you don't find it add it at the end
(over i <- 0 by (1+ i) until nil
(if (= i #1rindex)
(<- (#1parents i) item)
(<- #1rindex (1+ #1rindex))
(return item))
;if you do find it cons up atom to return
(if (eq item (#1parents i))
(return (implode (append '(/^) (exploden (- #1rindex i)))))))))
(deffn #1format-list [[icode ! temp] list]
(let ((orindex #1rindex) (olevel #1level)
(close-del #1close-del) (open-del #1open-del))
(<- #1open-del nil #1close-del nil)
(if (zerop #1level) (#1enter-obj '# 'princ nil)
ef (atom (<- list (#1rcheck list))) (#1enter-obj list 'princ nil)
el (<- #1level (1- #1level))
(if (null icode)
(if (null open-del) (<- icode 1)
el (<- icode (flatc open-del)))
(if (atom (car list))
(if #1princ-atoms (<- icode (+ icode 1 (flatc (car list))))
el (<- icode (+ icode 1 (flatsize (car list)))))))
(#1enter-obj icode nil 'start)
(#1enter-format&obj 'never 0 (or open-del '|(|) 'princ nil)
(over i <- (if (zerop #1level) 2 el #1prinlength) by (1- i) until nil
over [head ! rest] <- list by rest until nil
over [[fcode ! subtemp] ! rtemp] <- temp by rtemp until nil
(if (or (minusp i) (and (zerop i) (or rest (not (atom head)))))
(#1enter-format&obj fcode 0 '|...| 'princ nil)
(exit))
(#1enter-format fcode (if (null rest) 0 el 1))
(call #1format-dispatch subtemp head)
(if (null rest) (exit))
(if (not (eq (typep (<- rest (#1rcheck rest))) 'list))
(#1enter-format&obj (caar rtemp) 1 '/. 'princ nil)
(#1enter-format 'never 0)
(call #1format-dispatch (cdar rtemp) rest)
(exit)))
(#1enter-format&obj 'never 0 (or close-del '|)|) 'princ 'end)
(<- #1rindex orindex #1level olevel))))
(defun #1format-lsubr nargs
(begin ([icode ! temp] <- (arg 1) olevel <- #1level
close-del <- #1close-del open-del <- #1open-del)
(<- #1open-del nil #1close-del nil)
(if (zerop #1level) (#1enter-obj '# 'princ nil)
el (<- #1level (1- #1level))
(if (null icode)
(if (null open-del) (<- icode 1)
el (<- icode (flatc open-del)))
(if (atom (arg 2))
(if #1princ-atoms (<- icode (+ icode 1 (flatc (arg 2))))
el (<- icode (+ icode 1 (flatsize (arg 2)))))))
(#1enter-obj icode nil 'start)
(#1enter-format&obj 'never 0 (or open-del '|(|) 'princ nil)
(over i <- (if (zerop #1level) 2 el #1prinlength) by (1- i) until nil
over J <- 2 by (1+ j) until (> j nargs) (arg j) -> head
over [[fcode ! subtemp] ! rtemp] <- temp by rtemp until nil
(if (or (minusp i) (and (zerop i) (or (< j nargs) (not (atom head)))))
(#1enter-format&obj fcode 0 '|...| 'princ nil)
(exit))
(#1enter-format fcode (if (= j nargs) 0 el 1))
(call #1format-dispatch subtemp head))
(#1enter-format&obj 'never 0 (or close-del '|)|) 'princ 'end)
(<- #1level olevel))))
;________________________________________________________________________________
(deffn #1format-hunk [[icode ! temp] hunk]
(begin (orindex <- #1rindex olevel <- #1level
close-del <- #1close-del open-del <- #1open-del
end <- (1- (hunksize hunk)))
(<- #1open-del nil #1close-del nil)
(if (zerop #1level) (#1enter-obj '# 'princ nil)
ef (atom (<- hunk (#1rcheck hunk))) (#1enter-obj hunk 'princ nil)
el (<- #1level (1- #1level))
(if (null icode)
(if (null open-del) (<- icode 1)
el (<- icode (flatc open-del)))
(if (atom (cxr 1 hunk))
(if #1princ-atoms (<- icode (+ icode 1 (flatc (cxr 1 hunk))))
el (<- icode (+ icode 1 (flatsize (cxr 1 hunk)))))))
(#1enter-obj icode nil 'start)
(#1enter-format&obj 'never 0 (or open-del '|{|) 'princ nil)
(over i <- (if (zerop #1level) 2 el #1prinlength) by (1- i) until nil
over j <- 1 by (1+ j) until (> j end) (cxr j hunk) -> head
over [[fcode ! subtemp] ! rtemp] <- temp by rtemp until nil
(<- temp rtemp)
(if (or (minusp i) (and (zerop i) (or (< j end) (not (atom head)))))
(#1enter-format&obj fcode 0 '|...| 'princ nil)
(exit))
(#1enter-format fcode 1)
(call #1format-dispatch subtemp head))
(#1enter-format (caar temp) 0)
(call #1format-dispatch (cdar temp) (cxr 0 hunk))
(#1enter-format&obj 'never 0 (or close-del '|}|) 'princ 'end)
(<- #1rindex orindex #1level olevel))))
;this section contains some special grind-fns. A grind-fn must be written when
;the template format is not powerfull enough to allow you to do what you want.
;this macro constructs grind functions which do read macro inversion of macros
;like quote (which expect that the relavent data is in the CADR), does inversion
;where the CDR is the data, and you are specifying both a new open and close delimeter.
;#make-inver-quote-fn2 makes inverts for macros like "`" which put the relavent data in
;the CDR. It sets up a sublist with the specified delimeters
;note that #1format-list bombs out if passed an atomic item, so this checks
;to see if the cdr of the item is atomic, and if so does not do the inversion.
;in order to improve readability, it also refuses to invert a list if it
;has only an open delimiter, and more than one element in the rest of the list.
(deffn #make-invert-quote-fn macro keep displace check
[_ atom open-del close-del :!_]
(if close-del
`(defun (,atom #grind-fn) (temp item)
(cond ((cdr item)
(setq #1open-del ',open-del #1close-del ',close-del)
(cond (#1format-list (funcall #1format-list temp (cdr item)))
((#1format-list temp (cdr item)))))
((cond (#1format-list (funcall #1format-list temp (cdr item)))
((#1format-list temp item))))))
el `(defun (,atom #grind-fn) (temp item)
(cond ((and (cdr item) (null (cddr item)))
(setq #1open-del ',open-del #1close-del '|| #1level (1+ #1level))
(cond (#1format-list (funcall #1format-list temp (cdr item)))
((#1format-list temp (cdr item))))
(setq #1level (1- #1level)))
((cond (#1format-list (funcall #1format-list temp (cdr item)))
((#1format-list temp item))))))))
;this causes (quote ...) to print as '...
(#make-invert-quote-fn quote /')
;________________________________________________________________________________
;this function works very similar to the above except it expects the goodies to be in the cdr
;and just prints them as a list if they are a list.
(deffn #make-invert-quote-fn2 macro keep displace check [_ internal-atom external-atom]
`(defun (,internal-atom #grind-fn) (temp item)
(#1enter-obj 0 nil 'start)
(#1enter-format&obj 'never 0 ',external-atom 'princ nil)
(#1enter-format 'never 0)
(cond (#1format-dispatch (funcall #1format-dispatch nil (cdr item)))
((#1format-dispatch nil (cdr item))))
(#1enter-obj '|| 'princ 'end)))
;these standard definitions make the `macro print nicely.
(#make-invert-quote-fn2 |`-expander/|| |`|)
(#make-invert-quote-fn2 |`,/|| |,|)
(#make-invert-quote-fn2 |`,@/|| |,@|)
(#make-invert-quote-fn2 |`,./|| |,.|)
;this makes defun print out right by checking whether it is of the one or two
;keyword form.
(deffn defun #grind-fn [temp item]
(<- temp (if (and (match item [_ _ _ ! _])
(or (memq (2nd item) '(expr fexpr macro))
(memq (3rd item) '(expr fexpr macro))))
#1defun2-template
el #1defun1-template))
(call #1format-list temp item))
;this makes the #printer obay the grind-macroexpanded flag from the
;file DEFMAX so that macro expansions created with
;macro-expansion-use=macroexpanded print pretty.
(defun (macroexpanded #grind-fn) (temp item)
(setq item (cond (grind-macroexpanded (cadddr (cdr item)))
(t (cadddr item))))
(setq #1level (1+ #1level))
(cond (#1format-dispatch (funcall #1format-dispatch temp item))
((#1format-dispatch temp item)))
(setq #1level (1- #1level)))
;this takes care of making the tags come out right in a prog or do. it looks
;complex but really it is exactly the same as #1format-list with a piece added in
;the middle that works with the tags. it works even if there are two or more
;tags in a row.
(deffn prog #grind-fn [unused-template list]
;if list is short and has no tags then print it like a list.
;otherwise we force things to be on separate lines even if there are no tags.
(if (over (cddr list) until (atom _)
over i <- 0 by (1+ i) until nil
fastand (if (> i 10) (return nil))
(not (atom _)))
(call #1format-list #1fn-template list)
el (begin (orindex <- #1rindex olevel <- #1level
default-bcode bcode
any-labs-yet? <- nil)
(if #1princ-atoms (<- default-bcode (1+ (flatc (car list))))
el (<- default-bcode (1+ (flatsize (car list)))))
(<- bcode default-bcode)
(if (zerop #1level) (#1enter-obj '# 'princ nil)
ef (atom (<- list (#1rcheck list))) (#1enter-obj list 'princ nil)
el (<- #1level (1- #1level))
(#1enter-obj 1 nil 'start)
(#1enter-format&obj 'never 0 '|(| 'princ nil)
(over i <- (if (zerop #1level) 2 el #1prinlength) by (1- i) until nil
over [head ! rest] <- list by rest until nil
over k <- 1 by (1- k) until nil
(if (or (minusp i) (and (zerop i) (or rest (not (atom head)))))
(#1enter-format&obj 'never 0 '|...| 'princ nil)
(exit))
;this is the new part which figures the undenting of the tags.
(if (minusp k)
(if (and (atom head) head)
(if #1princ-atoms
(<- bcode (- bcode 1 (flatc head)))
el (<- bcode (- bcode 1 (flatsize head))))
(#1enter-format&obj
(if any-labs-yet? 'never el 'always) 1
head (if #1princ-atoms 'princ el 'prin1) nil)
(<- any-labs-yet? t)
el (if (not any-labs-yet?)
(#1enter-format&obj 'always default-bcode '|| nil nil)
el (#1enter-format&obj 'never (max 0 bcode) '|| nil nil)
(<- bcode default-bcode any-labs-yet? nil))
(#1enter-format 'never (if (null rest) 0 el 1))
(call #1format-dispatch nil head))
el (#1enter-format 'never (if (null rest) 0 el 1))
(call #1format-dispatch #11level-block-template head))
;back to normal stuff from #1format-list
(if (null rest) (exit))
(if (not (eq (typep (<- rest (#1rcheck rest))) 'list))
(#1enter-format&obj 'never 1 '/. 'princ nil)
(#1enter-format 'never 0)
(call #1format-dispatch nil rest)
(exit)))
(#1enter-format&obj 'never 0 '|)| 'princ 'end)
(<- #1rindex orindex #1level olevel)))))
;do can be handled just like prog.
(putprop 'do (get 'prog '#grind-fn) '#grind-fn)
;#1enter makes things easier for the format functions by maintaining the
;consistency of the intermediate structure. In particular as sublists grow,
;it keeps the length, inner-always and complete fields accurate. in order to
;do this, it needs to know where the the superiors of the current element are.
;this is the function of #1supstack. it contains the offsets to the superiors.
;if the end of the arrays are reached, then it shifts things over. (this looks
;slow compared with using a queue rapping around in the arrays, but it saves
;enough overhead in other places that it wins in the long run. #1supstack
;contains offsets so that nothing special has to be done when things are
;shifted over.) (note that the arrays are expanded if they need to be.)
;special checks are made so the #1enter never bothers to update an elemetn
;which #1printout has already passed over. (this also avoids referenceing
;outside the arrays.) the zero position of #1supstack is left unused in order
;to solve a lot of fencepost problems. it gets written in now and then though
;it logically shouldn't.
(deffn #1enter-obj [obj pcode lcode]
(begin (flag <- (flags (if (eq pcode 'prin1) (flags 'prin1)
ef (eq pcode 'princ) (flags 'princ)
el 0)
(if (eq #1fcode 'never) (flags 'never)
ef (eq #1fcode 'normal) (flags 'normal)
ef (eq #1fcode 'tblock) (flags 'tblock)
ef (eq #1fcode 'block) (flags 'block)
el;(eq #1fcode 'always)
(flags 'always))
(if (eq lcode 'start) (flags 'list-start)
ef (eq lcode 'end)
(flags 'list-end 'complete (#1bcodestack #1supptr))
el;(eq lcode nil)
(flags 'complete #1bcode)))
length <- (if (list-start? flag) 0
ef (prin1? flag) (+ (bcode flag) (flatsize obj))
ef (princ? flag) (+ (bcode flag) (flatc obj))
el (bcode flag)))
(if #1exploding
(if (princ? flag)
(<- #1explode-result (nreconc (explodec obj) #1explode-result))
ef (prin1? flag)
(<- #1explode-result (nreconc (explode obj) #1explode-result)))
(over i <- (bcode flag) by (1- i) until (not (plusp i))
(pushonto #1explode-result '| |))
(if (list-start? flag)
(<- #1supptr (1+ #1supptr)
(#1bcodestack #1supptr) #1bcode)
ef (list-end? flag)
(<- #1supptr (1- #1supptr)))
;otherwise go to next queue element and queue the stuff up.
el (<- #1inptr (1+ #1inptr)
(#1supstack #1supptr) (1+ (#1supstack #1supptr)))
;check if we have gone passed the end of the queue, if we have shift things over, or
;(if we must) extend the size of the arrays.
(if (not (< #1inptr #1size))
(if (< #1pp 10.)
(<- #1size (+ #1size 10.))
(*rearray #1obj (car (arraydims #1obj)) #1size)
(*rearray #1flag (car (arraydims #1flag)) #1size)
(*rearray #1length (car (arraydims #1length)) #1size)
el (over j <- #1pp by (1+ j) until (= j #1size)
over i <- 0 by (1+ i) until nil
(<- (#1obj i) (#1obj j)
(#1flag i) (#1flag j)
(#1length i) (#1length j)))
(<- #1inptr (- #1inptr #1pp)
#1pp 0)))
;fill in the slots in the new queue element.
(<- (#1obj #1inptr) obj
(#1flag #1inptr) flag
(#1length #1inptr) length)
;update the lengths of the superiors of the new queue element.
(over i <- #1supptr by (1- i) until (zerop i)
over j <- (- #1inptr (#1supstack i)) by (- j (#1supstack i)) until (< j #1pp)
(<- (#1length j) (+ length (#1length j))))
;if this queue element has the always? bit on, put the inner-always bit on in its superiors
(if (always? flag)
(over i <- #1supptr by (1- i) until (zerop i)
over j <- (- #1inptr (#1supstack i)) by (- j (#1supstack i)) until (< j #1pp)
(<- (#1flag j) (flags (#1flag j) 'inner-always))))
;if this queue element is the start of a list push it onto the supstack. (extend if needed)
(if (list-start? flag)
(<- #1supptr (1+ #1supptr))
(if (not (< #1supptr #1supsize))
(<- #1supsize (+ #1supsize 10.))
(*rearray #1supstack (car (arraydims #1supstack)) #1supsize)
(*rearray #1indstack (car (arraydims #1indstack)) #1supsize)
(*rearray #1bcodestack (car (arraydims #1bcodestack)) #1supsize))
(<- (#1supstack #1supptr) 0
(#1bcodestack #1supptr) #1bcode)
;if this element is the end of a list mark the superior complete and pop it off the supstack.
ef (list-end? flag)
(let ((i (- #1inptr (#1supstack #1supptr))))
(if (not (> #1pp i))
(<- (#1flag i) (flags (#1flag i) 'complete))))
(<- #1supptr (1- #1supptr)
(#1supstack #1supptr) (+ (#1supstack #1supptr) (#1supstack (1+ #1supptr)))))
;call #1printout to see if anything can get printed out.
(#1printout)))
nil)
;this is the function that actually decides how things get printed out. it is
;essentially an interpreter for the intermediate structure looked at as a
;program. it implements all of the meanings of the codes. (comments near the
;beginning discuss the semantics of the various flags.) #1enter puts enough
;information at each node, that #1printout can make almost all of its
;decisions based solely on the information at one node and general information
;about where it is in printing. (tblocking is the only major exception, in
;that case it looks at a bunch of nodes in order to figure out what the tab
;size should be.)
(deffn #1printout []
;if there is no more intermediate structure exit
(loop (flag)
(if (> #1pp #1inptr) (exit))
(<- flag (#1flag #1pp))
;if it the next thing is ready to print, and we may have to tab before it, and
;we don't yet know the tabsize, find it out.
(if (and (tblock? flag) (complete? flag) (= #1tabsize 1))
(begin (n <- (max 2 (#1length #1pp))
i <- 0
max <- (over j <- #1pp by (1+ j) until (> j #1inptr)
(#1flag j) -> flag
return n
(if (= i 0) (<- n (max n (#1length j))))
(if (list-start? flag) (<- i (1+ i))
ef (list-end? flag) (<- i (1- i))))
space <- (- #1linelen (#1indstack #1indptr)))
(<- max (min space (+ max (// max 5)))
#1tabsize (// space (// space max))
#1taboffset (- (\ space #1tabsize) #1tabsize))))
;if we are not already at the start of a line see if we have to put a crlf
;before the next thing.
(if (not #1atstart?)
;if we have to tab before the next thing, then make sure we are in the right column
(if (and (tblock? flag) (complete? flag))
(let ((j (\ (- #1freelen #1taboffset) #1tabsize)))
(<- #1pending (+ #1pending j)
#1freelen (- #1freelen j))))
;check if the code implies doing a terpri
(if (or (always? flag)
(normal? flag)
(and (or (block? flag) (tblock? flag))
(or #1wentup? (inner-always? flag)
(and (> (#1length #1pp) #1freelen)
(< #1freelen (- #1linelen (#1indstack #1indptr))))))
(and (never? flag) (not (list-start? flag))
(> (#1length #1pp) (+ 4 #1freelen))))
;we do need a new line set it up
(<- #1atstart? t
#1wentup? nil
#1cline (1+ #1cline)
#1pending (#1indstack #1indptr)
#1freelen (- #1linelen #1pending))
;check if we have exceeded prinendline if so stop printing
(if (> #1cline #1prinendline)
(throw '|#1prinendline exceeded| #1printabort))
;do the terpri and set up for the correct indentation
(if #1printing? (terpri #1files)
ef (<- #1printing? (not (> #1prinstartline #1cline)))
(<- #1pending (- #1pending #1cp)))))
;if the current thing won't go on one line (because it is too long or has an
;inner-always) then go down into it calculating new indentation level
(if (and (list-start? flag) (or (inner-always? flag) (> (#1length #1pp) #1freelen)))
(<- #1indptr (1+ #1indptr)
(#1indstack #1indptr)
(let ((i (max #1cp (+ (#1obj #1pp) (- #1linelen #1freelen)))))
(if (> i #1maxindentlen) (+ #1cp
(// (- #1linelen #1cp) 5)
(- i #1maxindentlen))
el i))
#1pp (1+ #1pp)
#1tabsize 1)
;otherwise if this item is completed then it will fit on one line and we go
;ahead and print it out. (we count delemiters to know when we are done)
ef (complete? flag)
(<- #1freelen (- #1freelen (#1length #1pp))
#1atstart? nil)
(loop (i <- 0)
(if (list-start? flag) (<- i (1+ i))
el (if (list-end? flag) (<- i (1- i)))
(if #1printing?
(over j <- #1pending by (1- j) until (not (plusp j))
(tyo 32. #1files))
(if (princ? flag) (princ (#1obj #1pp) #1files)
ef (prin1? flag) (prin1 (#1obj #1pp) #1files)))
(<- #1pending (bcode flag)))
(<- #1pp (1+ #1pp))
(if (zerop i) (exit)
;if we have just gone over a list end, then pop up a level
ef (minusp i)
(<- #1indptr (1- #1indptr)
#1wentup? t
#1tabsize 64000.)
(exit))
(<- flag (#1flag #1pp)))
;if the current thing wasn't complete either, then we quit because we don't
;have enough information to decide what to do.
el (exit))))
;this is a macro expanded version if this file. the fasl version has actually been produced
;by compiling this version. it is included because it may be more readable to some, and
;in the hope that it will allow #print to be maintained after my macros and I have gone.
;all of the comments above apply to the expanded version.
(declare '(macro expanded version of code |two )) at end to match|
(DECLARE (FIXNUM I J K N LENGTH END RINDEX MAX DEFAULT-BCODE BCODE SPACE
LEVEL FLAGS)
(SPECIAL /#CHECKRECURSION PRINLEVEL
PRINLENGTH PRINMODE PRINENDLINE
PRINSTARTLINE ^R ^W
OUTFILES GRINDEF GRINDPROPERTIES
/#FN-GRIND-PROPERTIES
/#1DEFAULT-SYMBOL-CAR-GRIND-TEMPLATE
/#1DEFAULT-NON-SYMBOL-CAR-GRIND-TEMPLATE TYO
/#1FORMAT-DISPATCH /#1FORMAT-LIST /#1FORMAT-ATOM
/#1FORMAT-HUNK GRIND-MACROEXPANDED)
(SPECIAL /#1PRINLEVEL /#1PRINLENGTH
/#1PRINENDLINE /#1PRINSTARTLINE /#1CP
/#1LINELEN /#1MAXINDENTLEN /#1CLINE
/#1FREELEN /#1PENDING /#1TABSIZE
/#1TABOFFSET /#1INPTR /#1PP
/#1SUPPTR /#1INDPTR /#1SIZE
/#1SUPSIZE /#1RSIZE /#1PRINMODE
/#1CHECKRECURSION /#1MAINFILE /#1TRUNCATED
/#1FILES /#1ATSTART? /#1WENTUP?
/#1PRINTING? /#1OBJ /#1FLAG
/#1LENGTH /#1SUPSTACK /#1INDSTACK
/#1PARENTS /#1NOWPRINTING /#1FCODE
/#1BCODE /#1BCODESTACK /#1LEVEL
/#1RINDEX /#1OPEN-DEL /#1CLOSE-DEL
/#1PRINC-ATOMS /#1PRINT-LIKE /#1EXPLODING
/#1EXPLODE-RESULT)
(SPECIAL /#1MISER-TEMPLATE /#1BLOCK-TEMPLATE
/#1CRUSH-TEMPLATE /#1FN-TEMPLATE
/#11LEVEL-BLOCK-TEMPLATE /#1DEFUN1-TEMPLATE
/#1DEFUN2-TEMPLATE /#11LEVEL-TBLOCK-TEMPLATE
/#1APPLY-TEMPLATE /#11LEVEL-MISER-TEMPLATE
/#1TBLOCK-TEMPLATE)
(*LEXPR /#PRIN1 /#PRINT PRINL PRINL1))
(DEFUN /#MAKE-TEMPLATE (PATTERN) (/#MAKE-TEMPLATE1 PATTERN NIL NIL))
(DEFUN /#MAKE-TEMPLATE1 (PATTERN OLDBACKLIST NEWBACKLIST)
(COND ((ATOM PATTERN) PATTERN)
((MEMQ PATTERN OLDBACKLIST)
((LAMBDA (OVERVAROLD OLD OVERVARNEW NEW)
(PROGN (SETQ OVERVAROLD OLDBACKLIST)
(SETQ OVERVARNEW NEWBACKLIST))
(PROG NIL
U1_L (PROGN (SETQ OLD (CAR OVERVAROLD))
(SETQ NEW (CAR OVERVARNEW)))
(COND ((EQ OLD PATTERN) (RETURN NEW)))
(PROGN (SETQ OVERVAROLD (CDR OVERVAROLD))
(SETQ OVERVARNEW (CDR OVERVARNEW)))
(GO U1_L)))
NIL NIL NIL NIL))
((EQ (CAR PATTERN) '^)
((LAMBDA (OVERVARNEW NEW ICOUNT)
(PROGN (SETQ OVERVARNEW NEWBACKLIST)
(SETQ ICOUNT (1- (CDR PATTERN))))
(PROG NIL
U1_L (SETQ NEW (CAR OVERVARNEW))
(COND ((ZEROP ICOUNT) (RETURN NEW)))
(PROGN (SETQ OVERVARNEW (CDR OVERVARNEW))
(SETQ ICOUNT (1- ICOUNT)))
(GO U1_L)))
NIL NIL NIL))
(((LAMBDA (NEWCONS)
(SETQ OLDBACKLIST (CONS PATTERN OLDBACKLIST))
(SETQ NEWBACKLIST (CONS NEWCONS NEWBACKLIST))
(RPLACA NEWCONS
(/#MAKE-TEMPLATE1 (CAR PATTERN)
OLDBACKLIST
NEWBACKLIST))
(RPLACD NEWCONS
(/#MAKE-TEMPLATE1 (CDR PATTERN)
OLDBACKLIST
NEWBACKLIST))
NEWCONS)
(NCONS NIL)))))
(DEFUN /#1SET-UP-TEMPLATES NIL
(PROGN (SETQ /#1MISER-TEMPLATE
(/#MAKE-TEMPLATE '(1. (NEVER ^ . 3.)
(NORMAL ^ . 4.) ^
. 1.)))
(SETQ /#1CRUSH-TEMPLATE
(/#MAKE-TEMPLATE '(-900. (NEVER ^ . 3.) ^ . 1.)))
(SETQ /#1BLOCK-TEMPLATE
(/#MAKE-TEMPLATE '(1. (NEVER ^ . 3.)
(BLOCK ^ . 4.) ^
. 1.)))
(SETQ /#1TBLOCK-TEMPLATE
(/#MAKE-TEMPLATE '(1. (NEVER ^ . 3.)
(TBLOCK ^ . 4.) ^
. 1.)))
(SETQ /#1FN-TEMPLATE
(/#MAKE-TEMPLATE '(NIL (NEVER) (NEVER) (NORMAL) ^ . 1.)))
(SETQ /#11LEVEL-MISER-TEMPLATE
(/#MAKE-TEMPLATE '(1. (NEVER) (NORMAL) ^ . 1.)))
(SETQ /#11LEVEL-BLOCK-TEMPLATE
(/#MAKE-TEMPLATE '(1. (BLOCK) ^ . 1.)))
(SETQ /#11LEVEL-TBLOCK-TEMPLATE
(/#MAKE-TEMPLATE '(1. (TBLOCK) ^ . 1.)))
(SETQ /#1DEFAULT-SYMBOL-CAR-GRIND-TEMPLATE /#1FN-TEMPLATE)
(SETQ /#1DEFAULT-NON-SYMBOL-CAR-GRIND-TEMPLATE
/#11LEVEL-MISER-TEMPLATE)
(PUTPROP 'LAMBDA
(/#MAKE-TEMPLATE '(2.
(NEVER)
(NEVER 1. (BLOCK) ^ . 1.)
(NORMAL)
^
. 1.))
'/#GRIND-TEMPLATE)
(SETQ /#1APPLY-TEMPLATE
(/#MAKE-TEMPLATE '(1. (NEVER) (BLOCK) ^ . 1.)))
(PUTPROP 'SETQ
(/#MAKE-TEMPLATE '(NIL (NEVER) (NEVER)
(BLOCK) (ALWAYS) (BLOCK)
^ . 2.))
'/#GRIND-TEMPLATE)
(PUTPROP 'COND
(/#MAKE-TEMPLATE '(NIL
(NEVER)
(NEVER 1. (NEVER) (NORMAL) ^ . 1.)
(ALWAYS 1. (NEVER) (NORMAL) ^ . 1.)
^
. 1.))
'/#GRIND-TEMPLATE)
(SETQ /#1DEFUN1-TEMPLATE
(/#MAKE-TEMPLATE '(2. (NEVER) (NEVER)
(NEVER) (NORMAL) ^
. 1.)))
(SETQ /#1DEFUN2-TEMPLATE
(/#MAKE-TEMPLATE '(2. (NEVER) (NEVER) (NEVER)
(NEVER) (NORMAL) ^ . 1.)))))
(/#1SET-UP-TEMPLATES)
(DEFUN /#1SET-UP-GLOBALS NIL
(SETQ /#1TRUNCATED NIL)
((LAMBDA (|OVERVAR([ ATOM VAL)| VAL ATOM)
(SETQ |OVERVAR([ ATOM VAL)|
'((PRINLEVEL NIL)
(PRINLENGTH NIL)
(PRINMODE GRIND)
(PRINSTARTLINE NIL)
(PRINENDLINE NIL)
(/#CHECKRECURSION NIL)
(/#FN-GRIND-PROPERTIES (EXPR FEXPR
MACRO
SUBR
LSUBR
FSUBR
ARRAY
AUTOLOAD))
(GRINDPROPERTIES (EXPR FEXPR MACRO))
(GRINDEF NIL)
(/#1FORMAT-DISPATCH NIL)
(/#1FORMAT-LIST NIL)
(/#1FORMAT-HUNK NIL)
(/#1FORMAT-ATOM NIL)
(/#1NOWPRINTING NIL)
(/#1SIZE NIL)))
(PROG NIL
U1_L (COND ((NULL |OVERVAR([ ATOM VAL)|) (RETURN NIL)))
((LAMBDA (U1_ITEM)
(SETQ ATOM (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ VAL (CAR U1_ITEM)))
(CAR |OVERVAR([ ATOM VAL)|))
(COND ((NOT (BOUNDP ATOM)) (SET ATOM VAL)))
(SETQ |OVERVAR([ ATOM VAL)| (CDR |OVERVAR([ ATOM VAL)|))
(GO U1_L)))
NIL NIL NIL))
(/#1SET-UP-GLOBALS)
(DEFUN /#1SET-UP-PRINTER NIL
(SSTATUS TTYINT 19. '/#PRINTABORT)
(SSTATUS TTYINT 3. '/#CONTINUE)
(ENDPAGEFN TYO '/#1ENDPAGEFN)
(SETQ PRIN1 '/#PRIN1))
(DEFUN /#1REM-PRINTER NIL
(COND ((EQ (STATUS TTYINT 19.) '/#PRINTABORT) (SSTATUS TTYINT 19. NIL)))
(COND ((EQ (STATUS TTYINT 3.) '/#CONTINUE) (SSTATUS TTYINT 3. NIL)))
(COND ((EQ (ENDPAGEFN TYO) '/#1ENDPAGEFN)
(ENDPAGEFN TYO '+INTERNAL-TTY-ENDPAGEFN)))
(SETQ PRIN1 NIL)
((LAMBDA (OVERVAR_ _)
(SETQ OVERVAR_
'((/#1ENTER-FORMAT MACRO)
(/#1ENTER-FORMAT&OBJ MACRO)
(/#MAKE-TEMPLATE SUBR)
(/#MAKE-TEMPLATE1 SUBR)
(/#1SET-UP-TEMPLATES SUBR)
(/#1SET-UP-GLOBALS SUBR)
(/#1SET-UP-PRINTER SUBR)
(/#1REM-PRINTER SUBR)
(/#PRIN1 LSUBR)
(/#PRINC LSUBR)
(/#PRINT LSUBR)
(/#PRINL1 LSUBR)
(/#PRINLC LSUBR)
(/#PRINL LSUBR)
(/#EXPLODE SUBR)
(/#EXPLODEC SUBR)
(/#EXPLODEL LSUBR)
(GRINDEF FSUBR)
(/#1PRINTABORT SUBR)
(/#CONTINUE SUBR)
(/#1ENDPAGE-FN SUBR)
(/#1PRINTER SUBR)
(/#1FORMAT-INIT SUBR)
(/#1FORMAT-DISPATCH SUBR)
(/#1RCHECK SUBR)
(/#1FORMAT-LIST SUBR)
(/#1FORMAT-LSUBR LSUBR)
(/#1FORMAT-HUNK SUBR)
(/#MAKE-INVERT-QUOTE-FN MACRO)
(/#MAKE-INVERT-QUOTE-FN2 MACRO)
'/#GRIND-FN
(DEFUN /#GRIND-FN)
(PROG /#GRIND-FN)
(DO /#GRIND-FN)
NIL
(/#1SET-UP-MACROS SUBR)
(/#1ENTER-OBJ SUBR)
(/#1PRINTOUT SUBR)))
(PROG NIL
U1_L (COND ((NULL OVERVAR_) (RETURN NIL)))
(SETQ _ (CAR OVERVAR_))
(REMPROP (CAR _) (CDR _))
(SETQ OVERVAR_ (CDR OVERVAR_))
(GO U1_L)))
NIL NIL)
((LAMBDA (OVERVAR_ _)
(SETQ OVERVAR_
'(/#1OBJ /#1FLAG
/#1LENGTH
/#1SUPSTACK
/#1BCODESTACK
/#1INDSTACK
/#1PARENTS
/#1POBJ))
(PROG NIL
U1_L (COND ((NULL OVERVAR_) (RETURN NIL)))
(SETQ _ (CAR OVERVAR_))
(MAKUNBOUND _)
(SETQ OVERVAR_ (CDR OVERVAR_))
(GO U1_L)))
NIL NIL))
(DEFUN /#PRIN1 NARGS (/#1PRINTER 0. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN /#PRINC NARGS (/#1PRINTER 1. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN /#PRINT NARGS (/#1PRINTER 2. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN PRINL1 NARGS (/#1PRINTER 4. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN PRINLC NARGS (/#1PRINTER 5. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN PRINL NARGS (/#1PRINTER 6. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN /#EXPLODE (OBJ) (/#1PRINTER 8. OBJ NIL))
(DEFUN /#EXPLODEC (OBJ) (/#1PRINTER 9. OBJ NIL))
(DEFUN /#EXPLODEL NARGS (/#1PRINTER 14. (ARG 1.) (LISTIFY (- 1. NARGS))))
(DEFUN GRINDEF FEXPR (ARG)
((LAMBDA (ATOMS PROPS SELECTEDPROPS)
(PROGN ((LAMBDA (U1_ITEM)
(OR (AND (NOT (ATOM U1_ITEM))
(NOT (ATOM (CAR U1_ITEM)))
(PROGN (SETQ PROPS (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
T))
T)
(SETQ ATOMS U1_ITEM))
(COND (ARG (SETQ GRINDEF ARG))
(GRINDEF)))
(SETQ SELECTEDPROPS (APPEND PROPS GRINDPROPERTIES)))
((LAMBDA (OVERVARATOM ATOM TRACED)
(SETQ OVERVARATOM ATOMS)
(PROG NIL
U1_L (COND ((NULL OVERVARATOM) (RETURN NIL)))
(PROGN (SETQ ATOM (CAR OVERVARATOM))
(SETQ TRACED
(AND (STATUS FEATURE TRACE)
(MEMQ ATOM (TRACE)))))
((LAMBDA (REST PROP IND)
((LAMBDA (U1_ITEM)
(SETQ IND (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ PROP (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ REST U1_ITEM))
(PLIST ATOM))
(PROG NIL
U1_L (COND ((NULL IND) (RETURN NIL)))
(COND ((AND (COND ((AND TRACED
(MEMQ IND
'(EXPR FEXPR MACRO)))
(SETQ TRACED NIL)
(COND ((MEMQ IND
SELECTEDPROPS)
(TERPRI)
(PRINC '|;traced|)))
NIL)
(T))
(MEMQ IND SELECTEDPROPS))
(COND ((AND (NOT (ATOM PROP))
(EQ (CAR PROP) 'LAMBDA))
(PRINL (CONS 'DEFUN
(NCONC (COND ((EQ IND
'EXPR)
(LIST ATOM))
((MEMQ IND '(FEXPR MACRO)) (LIST ATOM IND))
((LIST (LIST ATOM IND))))
(CDR PROP)))
'GRIND))
((PRINL (LIST 'DEFPROP
ATOM
PROP
IND)
'GRIND)))))
((LAMBDA (U1_ITEM)
(SETQ IND (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ PROP (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ REST U1_ITEM))
REST)
(GO U1_L)))
NIL NIL NIL)
(SETQ OVERVARATOM (CDR OVERVARATOM))
(GO U1_L)))
NIL NIL NIL))
NIL NIL NIL)
'||)
(DEFUN /#PRINTABORT (UNUSED-F UNUSED-CH)
(NOINTERRUPT NIL)
(TYI TYI)
(COND (/#1NOWPRINTING (ERRSET (THROW '|aborted| /#1PRINTABORT)))))
(DECLARE ((LAMBDA (OBARRAY) (REMPROP (INTERN 'CURSORPOS) (INTERN 'ACS)))
SOBARRAY))
(DEFUN /#CONTINUE (UNUSED-F UNUSED-CH)
(NOINTERRUPT NIL)
(TYI TYI)
(COND (/#1TRUNCATED
((LAMBDA (C1PARAMS C1FILES C1OBJ C1CODE C1MAINFILE C1CP
C1TRUNCATEPOS ON-SAME-LINE)
(PROGN ((LAMBDA (U1_ITEM)
(SETQ C1TRUNCATEPOS (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ C1CP (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ C1MAINFILE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ C1CODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ C1OBJ (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
((LAMBDA (U1_ITEM)
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ C1FILES (CAR U1_ITEM)))
(CAR U1_ITEM))
(SETQ C1PARAMS (CAR U1_ITEM)))
/#1TRUNCATED)
(SETQ ON-SAME-LINE
(= (CAR C1TRUNCATEPOS)
(CAR (CURSORPOS C1MAINFILE)))))
(CURSORPOS (CAR C1TRUNCATEPOS)
(CDR C1TRUNCATEPOS)
C1MAINFILE)
(CURSORPOS 'L C1MAINFILE)
(COND (ON-SAME-LINE (TERPRI C1FILES))
((TERPRI C1MAINFILE)))
((LAMBDA (I)
(SETQ I C1CP)
(PROG NIL
U1_L (COND ((ZEROP I) (RETURN NIL)))
(TYO 32. C1MAINFILE)
(SETQ I (1- I))
(GO U1_L)))
NIL)
(/#1PRINTER C1CODE
((LAMBDA (FOO) (MUNKAM (+ FOO 0.))) C1OBJ)
C1PARAMS)
(COND ((NOT ON-SAME-LINE) (TERPRI /#1FILES))))
NIL NIL NIL NIL NIL NIL NIL NIL)))
'||)
(DEFUN /#1ENDPAGEFN (TTY)
(NOINTERRUPT NIL)
(CURSORPOS 'Z TTY)
(CURSORPOS 'L TTY)
(PRINC '|##more##| TTY)
((LAMBDA (ECHOFILES) (TYI)) NIL)
(CURSORPOS 'Z TTY)
(CURSORPOS 'L TTY)
(CURSORPOS 'TOP TTY)
(CURSORPOS 'L TTY))
(DEFUN /#1PRINTER (CODE OBJ INITS)
(COND (/#1NOWPRINTING
((LAMBDA (/#1NOWPRINTING /#1OBJ /#1FLAG /#1LENGTH /#1SUPSTACK
/#1INDSTACK /#1PARENTS /#1SIZE /#1SUPSIZE /#1RSIZE
/#1PRINLEVEL /#1PRINLENGTH /#1PRINENDLINE
/#1PRINSTARTLINE /#1CP /#1LINELEN /#1MAXINDENTLEN
/#1CLINE /#1FREELEN /#1PENDING /#1TABSIZE
/#1TABOFFSET /#1INPTR /#1PP /#1SUPPTR /#1INDPTR
/#1PRINMODE /#1CHECKRECURSION /#1MAINFILE /#1FILES
/#1ATSTART? /#1WENTUP? /#1PRINTING? /#1FCODE /#1BCODE
/#1BCODESTACK /#1OPEN-DEL /#1CLOSE-DEL /#1LEVEL
/#1RINDEX /#1PRINC-ATOMS /#1PRINT-LIKE /#1EXPLODING
/#1EXPLODE-RESULT)
(/#1PRINTER CODE OBJ INITS))
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL))
(((LAMBDA (/#1NOWPRINTING)
(SETQ /#1NOWPRINTING T)
(PROGN (SETQ /#1PRINC-ATOMS (NOT (ZEROP (BOOLE 1. 1. CODE))))
(SETQ /#1PRINT-LIKE (NOT (ZEROP (BOOLE 1. 2. CODE))))
(SETQ /#1EXPLODING (NOT (ZEROP (BOOLE 1. 8. CODE))))
(SETQ /#1CHECKRECURSION /#CHECKRECURSION))
(COND ((ZEROP (BOOLE 1. 4. CODE))
(PROGN (SETQ /#1PRINLEVEL (OR PRINLEVEL 64000.))
(SETQ /#1PRINLENGTH (OR PRINLENGTH 64000.))
(SETQ /#1PRINENDLINE (OR PRINENDLINE 64000.))
(SETQ /#1PRINSTARTLINE (OR PRINSTARTLINE 0.))
(SETQ /#1PRINMODE PRINMODE)))
(T
(PROGN (SETQ /#1PRINLEVEL 64000.)
(SETQ /#1PRINLENGTH 64000.)
(SETQ /#1PRINENDLINE 64000.)
(SETQ /#1PRINSTARTLINE 0.)
(SETQ /#1PRINMODE NIL))
((LAMBDA (U1_ITEM)
(AND (OR (AND (NOT (ATOM U1_ITEM))
(COND ((NUMBERP (CAR U1_ITEM))
(SETQ /#1PRINLEVEL
(CAR U1_ITEM)))
((NULL (CAR U1_ITEM))))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
T))
T)
(OR (AND (NOT (ATOM U1_ITEM))
(COND ((NUMBERP (CAR U1_ITEM))
(SETQ /#1PRINLENGTH
(CAR U1_ITEM)))
((NULL (CAR U1_ITEM))))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
T))
T)
(OR (AND (NOT (ATOM U1_ITEM))
(COND ((NUMBERP (CAR U1_ITEM))
(SETQ /#1PRINENDLINE
(CAR U1_ITEM)))
((NULL (CAR U1_ITEM))))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
T))
T)
(OR (AND (NOT (ATOM U1_ITEM))
(COND ((NUMBERP (CAR U1_ITEM))
(SETQ /#1PRINSTARTLINE
(CAR U1_ITEM)))
((NULL (CAR U1_ITEM))))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
T))
T)
(OR (AND (NOT (ATOM U1_ITEM))
(OR (MEMQ (CAR U1_ITEM)
'(GRIND BLOCK
TBLOCK
MISER
CRUSH))
(NULL (CAR U1_ITEM))
(AND (NOT (ATOM (CAR U1_ITEM)))
(NOT (ATOM (CDR (CAR U1_ITEM)))
)
(NOT (ATOM (CADR (CAR U1_ITEM)))
)))
(PROGN (SETQ /#1PRINMODE
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
T))
T)
(PROGN (SETQ INITS U1_ITEM) T)))
INITS)))
(PROGN (SETQ /#1PRINMODE
(COND ((EQ /#1PRINMODE 'GRIND) NIL)
((EQ /#1PRINMODE 'CRUSH)
/#1CRUSH-TEMPLATE)
((EQ /#1PRINMODE 'TBLOCK)
/#1TBLOCK-TEMPLATE)
((EQ /#1PRINMODE 'BLOCK)
/#1BLOCK-TEMPLATE)
((EQ /#1PRINMODE 'MISER)
/#1MISER-TEMPLATE)
(/#1PRINMODE)))
(SETQ /#1FILES
(COND ((OR (NOT (ATOM (CAR INITS)))
(NULL (CAR INITS)))
(CAR INITS))
(INITS))))
(COND ((AND (NOT /#1EXPLODING)
/#1PRINT-LIKE
(NOT (> /#1PRINSTARTLINE 0.)))
(TERPRI /#1FILES)))
(COND ((AND (ATOM OBJ)
(NULL /#1FORMAT-DISPATCH)
(NULL /#1FORMAT-ATOM)
(NOT /#1EXPLODING))
(COND (/#1PRINC-ATOMS (PRINC OBJ /#1FILES))
((NOT (EQ OBJ '||)) (PRIN1 OBJ /#1FILES))))
(T
(/#1FORMAT-INIT)
(COND ((NULL (ERRSET (COND ((CATCH (COND (
/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH /#1PRINMODE OBJ))
((/#1FORMAT-DISPATCH /#1PRINMODE OBJ)))
/#1PRINTABORT)
(COND ((NOT /#1EXPLODING)
(SETQ /#1TRUNCATED
(LIST (CURSORPOS /#1MAINFILE)
/#1CP
/#1MAINFILE
(BOOLE 7. CODE 4.)
(MAKNUM OBJ)
(LIST /#1PRINLEVEL
/#1PRINLENGTH
NIL
/#1CLINE
/#1PRINMODE
/#1FILES)))
(COND ((AND
/#1PRINTING?
(PLUSP /#1FREELEN))
(PRINC '| ---| /#1FILES)))))))))
(COND ((NULL (ERRSET ((LAMBDA (PRIN1)
(PRINT '
|error while #PRINTing:|)
(PRINT OBJ))
NIL)))
((LAMBDA (PRIN1)
(PRINT '|error while PRINTing MUNKAM of |
)
(PRINC (MAKNUM OBJ)))
NIL)))))))
(COND ((AND (NOT /#1EXPLODING)
/#1PRINT-LIKE
(NULL /#1TRUNCATED)
/#1PRINTING?)
(TYO 32. /#1FILES)))
(COND (/#1EXPLODING
(PROG2 NIL
(NREVERSE /#1EXPLODE-RESULT)
(SETQ /#1EXPLODE-RESULT NIL)))
(T)))
NIL))))
(DEFUN /#1FORMAT-INIT NIL
(COND ((NULL /#1SIZE)
(PROGN (SETQ /#1OBJ (ARRAY NIL NIL 100.))
(SETQ /#1FLAG (ARRAY NIL FIXNUM 100.))
(SETQ /#1LENGTH (ARRAY NIL FIXNUM 100.))
(SETQ /#1SUPSTACK (ARRAY NIL FIXNUM 50.))
(SETQ /#1BCODESTACK (ARRAY NIL FIXNUM 50.))
(SETQ /#1INDSTACK (ARRAY NIL FIXNUM 50.))
(SETQ /#1PARENTS (ARRAY NIL NIL 50.))
(SETQ /#1SIZE 100.)
(SETQ /#1SUPSIZE 50.)
(SETQ /#1RSIZE 50.))))
(PROGN (SETQ /#1MAINFILE
(COND (/#1FILES (CAR /#1FILES))
((AND ^R ^W (CAR OUTFILES)))
(TYO)))
(SETQ /#1CP (CHARPOS /#1MAINFILE))
(SETQ /#1LINELEN (- (LINEL /#1MAINFILE) 5.))
(SETQ /#1MAXINDENTLEN
(+ /#1CP (* 4. (// (- /#1LINELEN /#1CP) 5.))))
(SETQ /#1CLINE 0.)
(SETQ /#1ATSTART? T)
(SETQ /#1FREELEN (- /#1LINELEN /#1CP))
(SETQ /#1PENDING 0.)
(SETQ /#1WENTUP? NIL)
(SETQ /#1PRINTING? (NOT (> /#1PRINSTARTLINE 0.)))
(SETQ /#1TABSIZE 1.)
(SETQ /#1TABOFFSET 0.)
(SETQ /#1INPTR -1.)
(SETQ /#1PP 0.)
(SETQ /#1SUPPTR 0.)
(STORE (ARRAYCALL FIXNUM /#1SUPSTACK 0.) 0.)
(SETQ /#1INDPTR 0.)
(STORE (ARRAYCALL FIXNUM /#1INDSTACK 0.) /#1CP)
(SETQ /#1OPEN-DEL NIL)
(SETQ /#1CLOSE-DEL NIL)
(SETQ /#1FCODE 'NEVER)
(SETQ /#1BCODE 0.)
(SETQ /#1LEVEL /#1PRINLEVEL)
(SETQ /#1RINDEX 0.)
(SETQ /#1EXPLODE-RESULT NIL)))
(DEFUN /#1FORMAT-DISPATCH (TEMPLATE ITEM)
(COND ((HUNKP ITEM)
(COND (/#1FORMAT-HUNK
(FUNCALL /#1FORMAT-HUNK
(COND (TEMPLATE)
(/#11LEVEL-BLOCK-TEMPLATE))
ITEM))
((/#1FORMAT-HUNK (COND (TEMPLATE)
(/#11LEVEL-BLOCK-TEMPLATE))
ITEM))))
((EQ (TYPEP ITEM) 'LIST)
(COND (TEMPLATE
(COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST TEMPLATE ITEM))
((/#1FORMAT-LIST TEMPLATE ITEM))))
(((LAMBDA (HEAD SYMBOL? GRIND-FN TEMPLATE)
(PROGN (SETQ HEAD (CAR ITEM))
(SETQ SYMBOL? (EQ (TYPEP HEAD) 'SYMBOL))
(SETQ GRIND-FN
(COND (SYMBOL? (GET HEAD '/#GRIND-FN))))
(SETQ TEMPLATE
(COND (SYMBOL?
(COND ((GET HEAD
'/#GRIND-TEMPLATE))
((GETL HEAD
/#FN-GRIND-PROPERTIES)
/#1FN-TEMPLATE)
(
/#1DEFAULT-SYMBOL-CAR-GRIND-TEMPLATE
)))
((AND (EQ (TYPEP HEAD) 'LIST)
(EQ (CAR HEAD) 'LAMBDA))
/#1APPLY-TEMPLATE)
(
/#1DEFAULT-NON-SYMBOL-CAR-GRIND-TEMPLATE
))))
(COND (GRIND-FN (FUNCALL GRIND-FN TEMPLATE ITEM))
((COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST TEMPLATE ITEM))
((/#1FORMAT-LIST TEMPLATE ITEM))))))
NIL NIL NIL NIL))))
((COND (/#1FORMAT-ATOM (FUNCALL /#1FORMAT-ATOM TEMPLATE ITEM))
((/#1ENTER-OBJ ITEM
(COND (/#1PRINC-ATOMS 'PRINC)
('PRIN1))
NIL)))))
NIL)
(DEFUN /#1RCHECK (ITEM)
(COND ((OR (ATOM ITEM) (NOT /#1CHECKRECURSION)) ITEM)
(T
(COND ((NOT (< /#1RINDEX /#1RSIZE))
(SETQ /#1RSIZE (+ /#1RINDEX 25.))
(*REARRAY /#1PARENTS
(CAR (ARRAYDIMS /#1PARENTS))
/#1RSIZE)))
((LAMBDA (I)
(SETQ I 0.)
(PROG NIL
U1_L (PROGN (COND ((= I /#1RINDEX)
(STORE (ARRAYCALL NIL /#1PARENTS I)
ITEM)
(SETQ /#1RINDEX (1+ /#1RINDEX))
(RETURN ITEM)))
(COND ((EQ ITEM (ARRAYCALL NIL /#1PARENTS I))
(RETURN (IMPLODE (APPEND '(^)
(EXPLODEN (- /#1RINDEX I))))))))
(SETQ I (1+ I))
(GO U1_L)))
NIL))))
(DEFUN /#1FORMAT-LIST (|U1_ARG1.| LIST)
((LAMBDA (ICODE TEMP)
(COND ((NOT ((LAMBDA (U1_ITEM)
(AND (NOT (ATOM U1_ITEM))
(PROGN (SETQ ICODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ TEMP U1_ITEM)
T)))
|U1_ARG1.|))
(ERROR 'BAD-ARGS-TO-/#1FORMAT-LIST (LIST |U1_ARG1.| LIST))))
((LAMBDA (ORINDEX OLEVEL CLOSE-DEL OPEN-DEL)
(PROGN (SETQ /#1OPEN-DEL NIL) (SETQ /#1CLOSE-DEL NIL))
(COND ((ZEROP /#1LEVEL) (/#1ENTER-OBJ '/# 'PRINC NIL))
((ATOM (SETQ LIST (/#1RCHECK LIST)))
(/#1ENTER-OBJ LIST 'PRINC NIL))
(T
(SETQ /#1LEVEL (1- /#1LEVEL))
(COND ((NULL ICODE)
(COND ((NULL OPEN-DEL) (SETQ ICODE 1.))
((SETQ ICODE (FLATC OPEN-DEL))))
(COND ((ATOM (CAR LIST))
(COND (/#1PRINC-ATOMS
(SETQ ICODE
(+ ICODE 1. (FLATC (CAR LIST)))))
((SETQ ICODE
(+ ICODE
1.
(FLATSIZE (CAR LIST))))))))))
(/#1ENTER-OBJ ICODE NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ (OR OPEN-DEL '|(|) 'PRINC NIL))
((LAMBDA (I REST HEAD RTEMP SUBTEMP FCODE)
(PROGN (SETQ I
(COND ((ZEROP /#1LEVEL) 2.)
(/#1PRINLENGTH)))
((LAMBDA (U1_ITEM)
(SETQ HEAD (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ REST U1_ITEM))
LIST)
((LAMBDA (U1_ITEM)
((LAMBDA (U1_ITEM)
(SETQ FCODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ SUBTEMP U1_ITEM))
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ RTEMP U1_ITEM))
TEMP))
(PROG NIL
U1_L (PROGN (COND ((OR (MINUSP I)
(AND (ZEROP I)
(OR REST
(NOT (ATOM HEAD)))))
(PROGN (SETQ /#1FCODE FCODE
/#1BCODE 0.)
(/#1ENTER-OBJ '|...|
'PRINC
NIL))
(RETURN NIL)))
(SETQ /#1FCODE FCODE
/#1BCODE
(COND ((NULL REST) 0.)
(1.)))
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
SUBTEMP
HEAD))
((/#1FORMAT-DISPATCH SUBTEMP HEAD)))
(COND ((NULL REST) (RETURN NIL)))
(COND ((NOT (EQ (TYPEP (SETQ REST
(/#1RCHECK REST)))
'LIST))
(PROGN (SETQ /#1FCODE (CAAR RTEMP)
/#1BCODE 1.)
(/#1ENTER-OBJ '|.|
'PRINC
NIL))
(SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
(CDAR RTEMP)
REST))
((/#1FORMAT-DISPATCH (CDAR RTEMP
)
REST)))
(RETURN NIL))))
(PROGN (SETQ I (1- I))
((LAMBDA (U1_ITEM)
(SETQ HEAD (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ REST U1_ITEM))
REST)
((LAMBDA (U1_ITEM)
((LAMBDA (U1_ITEM)
(SETQ FCODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ SUBTEMP U1_ITEM))
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ RTEMP U1_ITEM))
RTEMP))
(GO U1_L)))
NIL NIL NIL NIL NIL NIL)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ (OR CLOSE-DEL '|)|) 'PRINC 'END))
(PROGN (SETQ /#1RINDEX ORINDEX) (SETQ /#1LEVEL OLEVEL)))))
/#1RINDEX /#1LEVEL /#1CLOSE-DEL /#1OPEN-DEL))
NIL NIL))
(DEFUN /#1FORMAT-LSUBR NARGS
((LAMBDA (TEMP ICODE OLEVEL CLOSE-DEL OPEN-DEL)
(PROGN ((LAMBDA (U1_ITEM)
(SETQ ICODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ TEMP U1_ITEM))
(ARG 1.))
(SETQ OLEVEL /#1LEVEL)
(SETQ CLOSE-DEL /#1CLOSE-DEL)
(SETQ OPEN-DEL /#1OPEN-DEL))
(PROGN (SETQ /#1OPEN-DEL NIL) (SETQ /#1CLOSE-DEL NIL))
(COND ((ZEROP /#1LEVEL) (/#1ENTER-OBJ '/# 'PRINC NIL))
(T
(SETQ /#1LEVEL (1- /#1LEVEL))
(COND ((NULL ICODE)
(COND ((NULL OPEN-DEL) (SETQ ICODE 1.))
((SETQ ICODE (FLATC OPEN-DEL))))
(COND ((ATOM (ARG 2.))
(COND (/#1PRINC-ATOMS
(SETQ ICODE
(+ ICODE 1. (FLATC (ARG 2.)))))
((SETQ ICODE
(+ ICODE 1. (FLATSIZE (ARG 2.)))))))))
)
(/#1ENTER-OBJ ICODE NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ (OR OPEN-DEL '|(|) 'PRINC NIL))
((LAMBDA (I J HEAD RTEMP SUBTEMP FCODE)
(PROGN (SETQ I
(COND ((ZEROP /#1LEVEL) 2.)
(/#1PRINLENGTH)))
(SETQ J 2.)
((LAMBDA (U1_ITEM)
((LAMBDA (U1_ITEM)
(SETQ FCODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ SUBTEMP U1_ITEM))
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ RTEMP U1_ITEM))
TEMP))
(PROG NIL
U1_L (COND ((> J NARGS) (RETURN NIL)))
(SETQ HEAD (ARG J))
(PROGN (COND ((OR (MINUSP I)
(AND (ZEROP I)
(OR (< J NARGS)
(NOT (ATOM HEAD)))))
(PROGN (SETQ /#1FCODE FCODE
/#1BCODE 0.)
(/#1ENTER-OBJ '|...|
'PRINC
NIL))
(RETURN NIL)))
(SETQ /#1FCODE FCODE
/#1BCODE
(COND ((= J NARGS) 0.)
(1.)))
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
SUBTEMP
HEAD))
((/#1FORMAT-DISPATCH SUBTEMP HEAD))))
(PROGN (SETQ I (1- I))
(SETQ J (1+ J))
((LAMBDA (U1_ITEM)
((LAMBDA (U1_ITEM)
(SETQ FCODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ SUBTEMP U1_ITEM))
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ RTEMP U1_ITEM))
RTEMP))
(GO U1_L)))
NIL NIL NIL NIL NIL NIL)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ (OR CLOSE-DEL '|)|) 'PRINC 'END))
(SETQ /#1LEVEL OLEVEL))))
NIL NIL NIL NIL NIL))
(DEFUN /#1FORMAT-HUNK (|U1_ARG1.| HUNK)
((LAMBDA (ICODE TEMP)
(COND ((NOT ((LAMBDA (U1_ITEM)
(AND (NOT (ATOM U1_ITEM))
(PROGN (SETQ ICODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ TEMP U1_ITEM)
T)))
|U1_ARG1.|))
(ERROR 'BAD-ARGS-TO-/#1FORMAT-HUNK (LIST |U1_ARG1.| HUNK))))
((LAMBDA (ORINDEX OLEVEL CLOSE-DEL OPEN-DEL END)
(PROGN (SETQ ORINDEX /#1RINDEX)
(SETQ OLEVEL /#1LEVEL)
(SETQ CLOSE-DEL /#1CLOSE-DEL)
(SETQ OPEN-DEL /#1OPEN-DEL)
(SETQ END (1- (HUNKSIZE HUNK))))
(PROGN (SETQ /#1OPEN-DEL NIL) (SETQ /#1CLOSE-DEL NIL))
(COND ((ZEROP /#1LEVEL) (/#1ENTER-OBJ '/# 'PRINC NIL))
((ATOM (SETQ HUNK (/#1RCHECK HUNK)))
(/#1ENTER-OBJ HUNK 'PRINC NIL))
(T
(SETQ /#1LEVEL (1- /#1LEVEL))
(COND ((NULL ICODE)
(COND ((NULL OPEN-DEL) (SETQ ICODE 1.))
((SETQ ICODE (FLATC OPEN-DEL))))
(COND ((ATOM (CXR 1. HUNK))
(COND (/#1PRINC-ATOMS
(SETQ ICODE
(+ ICODE
1.
(FLATC (CXR 1. HUNK)))))
((SETQ ICODE
(+ ICODE
1.
(FLATSIZE (CXR 1. HUNK)))))))))
)
(/#1ENTER-OBJ ICODE NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ (OR OPEN-DEL '{) 'PRINC NIL))
((LAMBDA (I J HEAD RTEMP SUBTEMP FCODE)
(PROGN (SETQ I
(COND ((ZEROP /#1LEVEL) 2.)
(/#1PRINLENGTH)))
(SETQ J 1.)
((LAMBDA (U1_ITEM)
((LAMBDA (U1_ITEM)
(SETQ FCODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ SUBTEMP U1_ITEM))
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ RTEMP U1_ITEM))
TEMP))
(PROG NIL
U1_L (COND ((> J END) (RETURN NIL)))
(SETQ HEAD (CXR J HUNK))
(PROGN (SETQ TEMP RTEMP)
(COND ((OR (MINUSP I)
(AND (ZEROP I)
(OR (< J END)
(NOT (ATOM HEAD)))))
(PROGN (SETQ /#1FCODE FCODE
/#1BCODE 0.)
(/#1ENTER-OBJ '|...|
'PRINC
NIL))
(RETURN NIL)))
(SETQ /#1FCODE FCODE
/#1BCODE 1.)
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
SUBTEMP
HEAD))
((/#1FORMAT-DISPATCH SUBTEMP HEAD))))
(PROGN (SETQ I (1- I))
(SETQ J (1+ J))
((LAMBDA (U1_ITEM)
((LAMBDA (U1_ITEM)
(SETQ FCODE (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ SUBTEMP U1_ITEM))
(CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ RTEMP U1_ITEM))
RTEMP))
(GO U1_L)))
NIL NIL NIL NIL NIL NIL)
(SETQ /#1FCODE (CAAR TEMP)
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
(CDAR TEMP)
(CXR 0. HUNK)))
((/#1FORMAT-DISPATCH (CDAR TEMP) (CXR 0. HUNK))))
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ (OR CLOSE-DEL '}) 'PRINC 'END))
(PROGN (SETQ /#1RINDEX ORINDEX) (SETQ /#1LEVEL OLEVEL)))))
NIL NIL NIL NIL NIL))
NIL NIL))
(DEFUN /#MAKE-INVERT-QUOTE-FN MACRO (U1_BODY)
((LAMBDA (ATOM OPEN-DEL CLOSE-DEL)
(COND ((NOT ((LAMBDA (U1_ITEM)
(AND (NOT (ATOM U1_ITEM))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
(NOT (ATOM U1_ITEM)))
(PROGN (SETQ ATOM (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(NOT (ATOM U1_ITEM)))
(PROGN (SETQ OPEN-DEL (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(OR (AND (NOT (ATOM U1_ITEM))
(PROGN (SETQ CLOSE-DEL
(CAR U1_ITEM))
(NULL (CDR U1_ITEM))))
T))))
U1_BODY))
(ERROR 'BAD-ARGS-TO-/#MAKE-INVERT-QUOTE-FN (LIST U1_BODY))))
((LAMBDA (X Y) (RPLACA X (CAR Y)) (RPLACD X (CDR Y))) U1_BODY
(COND (CLOSE-DEL
(LIST 'DEFUN
(LIST* ATOM '(/#GRIND-FN))
'(TEMP ITEM)
(LIST* 'COND
(LIST* '(CDR ITEM)
(LIST 'SETQ
'/#1OPEN-DEL
(LIST 'QUOTE OPEN-DEL)
'/#1CLOSE-DEL
(LIST 'QUOTE CLOSE-DEL))
'((COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST
TEMP
(CDR ITEM)))
((/#1FORMAT-LIST TEMP
(CDR ITEM))))))
'(((COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST
TEMP
(CDR ITEM)))
((/#1FORMAT-LIST TEMP ITEM))))))))
((LIST 'DEFUN
(LIST* ATOM '(/#GRIND-FN))
'(TEMP ITEM)
(LIST* 'COND
(LIST* '(AND (CDR ITEM) (NULL (CDDR ITEM)))
(LIST* 'SETQ
'/#1OPEN-DEL
(LIST 'QUOTE OPEN-DEL)
'(/#1CLOSE-DEL '||
/#1LEVEL
(1+ /#1LEVEL)))
'((COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST
TEMP
(CDR ITEM)))
((/#1FORMAT-LIST TEMP
(CDR ITEM))))
(SETQ /#1LEVEL (1- /#1LEVEL))))
'(((COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST
TEMP
(CDR ITEM)))
((/#1FORMAT-LIST TEMP ITEM)))))))))))
NIL NIL NIL))
(DEFUN '/#GRIND-FN (TEMP ITEM)
(COND ((AND (CDR ITEM) (NULL (CDDR ITEM)))
(SETQ /#1OPEN-DEL '/'
/#1CLOSE-DEL '||
/#1LEVEL (1+ /#1LEVEL))
(COND (/#1FORMAT-LIST (FUNCALL /#1FORMAT-LIST TEMP (CDR ITEM)))
((/#1FORMAT-LIST TEMP (CDR ITEM))))
(SETQ /#1LEVEL (1- /#1LEVEL)))
((COND (/#1FORMAT-LIST (FUNCALL /#1FORMAT-LIST TEMP (CDR ITEM)))
((/#1FORMAT-LIST TEMP ITEM))))))
(DEFUN /#MAKE-INVERT-QUOTE-FN2 MACRO (U1_BODY)
((LAMBDA (INTERNAL-ATOM EXTERNAL-ATOM)
(COND ((NOT ((LAMBDA (U1_ITEM)
(AND (NOT (ATOM U1_ITEM))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
(NOT (ATOM U1_ITEM)))
(PROGN (SETQ INTERNAL-ATOM (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(NOT (ATOM U1_ITEM)))
(PROGN (SETQ EXTERNAL-ATOM (CAR U1_ITEM))
(NULL (CDR U1_ITEM)))))
U1_BODY))
(ERROR 'BAD-ARGS-TO-/#MAKE-INVERT-QUOTE-FN2 (LIST U1_BODY))))
((LAMBDA (X Y) (RPLACA X (CAR Y)) (RPLACD X (CDR Y))) U1_BODY
(LIST* 'DEFUN
(LIST* INTERNAL-ATOM '(/#GRIND-FN))
'(TEMP ITEM)
'(/#1ENTER-OBJ 0. NIL 'START)
(LIST* '/#1ENTER-FORMAT&OBJ
''NEVER
'0.
(LIST 'QUOTE EXTERNAL-ATOM)
'('PRINC NIL))
'((/#1ENTER-FORMAT 'NEVER 0.)
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH NIL (CDR ITEM)))
((/#1FORMAT-DISPATCH NIL (CDR ITEM))))
(/#1ENTER-OBJ '|| 'PRINC 'END)))))
NIL NIL))
(DEFUN `(/#GRIND-FN) (TEMP ITEM)
(/#1ENTER-OBJ 0. NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '/` 'PRINC NIL))
(SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH (FUNCALL /#1FORMAT-DISPATCH NIL (CDR ITEM)))
((/#1FORMAT-DISPATCH NIL (CDR ITEM))))
(/#1ENTER-OBJ '|| 'PRINC 'END))
(DEFUN ,(/#GRIND-FN) (TEMP ITEM)
(/#1ENTER-OBJ 0. NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '/, 'PRINC NIL))
(SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH (FUNCALL /#1FORMAT-DISPATCH NIL (CDR ITEM)))
((/#1FORMAT-DISPATCH NIL (CDR ITEM))))
(/#1ENTER-OBJ '|| 'PRINC 'END))
(DEFUN ,@(/#GRIND-FN) (TEMP ITEM)
(/#1ENTER-OBJ 0. NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '/,@ 'PRINC NIL))
(SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH (FUNCALL /#1FORMAT-DISPATCH NIL (CDR ITEM)))
((/#1FORMAT-DISPATCH NIL (CDR ITEM))))
(/#1ENTER-OBJ '|| 'PRINC 'END))
(DEFUN ,.(/#GRIND-FN) (TEMP ITEM)
(/#1ENTER-OBJ 0. NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '|,.| 'PRINC NIL))
(SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH (FUNCALL /#1FORMAT-DISPATCH NIL (CDR ITEM)))
((/#1FORMAT-DISPATCH NIL (CDR ITEM))))
(/#1ENTER-OBJ '|| 'PRINC 'END))
(DEFUN (DEFUN /#GRIND-FN) (TEMP ITEM)
(SETQ TEMP
(COND ((AND ((LAMBDA (U1_ITEM)
(AND (NOT (ATOM U1_ITEM))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
(NOT (ATOM U1_ITEM)))
(PROGN (SETQ U1_ITEM (CDR U1_ITEM))
(NOT (ATOM U1_ITEM)))))
ITEM)
(OR (MEMQ (CADR ITEM) '(EXPR FEXPR MACRO))
(MEMQ (CADDR ITEM) '(EXPR FEXPR MACRO))))
/#1DEFUN2-TEMPLATE)
(/#1DEFUN1-TEMPLATE)))
(COND (/#1FORMAT-LIST (FUNCALL /#1FORMAT-LIST TEMP ITEM))
((/#1FORMAT-LIST TEMP ITEM))))
(DEFUN NIL (TEMP ITEM)
(SETQ ITEM
(COND (GRIND-MACROEXPANDED (CADDDR (CDR ITEM)))
(T (CADDDR ITEM))))
(SETQ /#1LEVEL (1+ /#1LEVEL))
(COND (/#1FORMAT-DISPATCH (FUNCALL /#1FORMAT-DISPATCH TEMP ITEM))
((/#1FORMAT-DISPATCH TEMP ITEM)))
(SETQ /#1LEVEL (1- /#1LEVEL)))
(DEFUN (PROG /#GRIND-FN) (UNUSED-TEMPLATE LIST)
(COND (((LAMBDA (OVERVAR_ _ I OVER-ACC)
(PROGN (SETQ OVERVAR_ (CDDR LIST))
(SETQ I 0.)
(SETQ OVER-ACC T))
(PROG NIL
U1_L (COND ((ATOM OVERVAR_) (RETURN OVER-ACC)))
(SETQ _ (CAR OVERVAR_))
(SETQ OVER-ACC
(OR (PROGN (COND ((> I 10.) (RETURN NIL)))
(NOT (ATOM _)))
(RETURN NIL)))
(PROGN (SETQ OVERVAR_ (CDR OVERVAR_)) (SETQ I (1+ I)))
(GO U1_L)))
NIL NIL NIL NIL)
(COND (/#1FORMAT-LIST
(FUNCALL /#1FORMAT-LIST /#1FN-TEMPLATE LIST))
((/#1FORMAT-LIST /#1FN-TEMPLATE LIST))))
(((LAMBDA (ORINDEX OLEVEL DEFAULT-BCODE BCODE ANY-LABS-YET?)
(PROGN (SETQ ORINDEX /#1RINDEX)
(SETQ OLEVEL /#1LEVEL)
(SETQ ANY-LABS-YET? NIL))
(COND (/#1PRINC-ATOMS
(SETQ DEFAULT-BCODE (1+ (FLATC (CAR LIST)))))
((SETQ DEFAULT-BCODE (1+ (FLATSIZE (CAR LIST))))))
(SETQ BCODE DEFAULT-BCODE)
(COND ((ZEROP /#1LEVEL) (/#1ENTER-OBJ '/# 'PRINC NIL))
((ATOM (SETQ LIST (/#1RCHECK LIST)))
(/#1ENTER-OBJ LIST 'PRINC NIL))
(T
(SETQ /#1LEVEL (1- /#1LEVEL))
(/#1ENTER-OBJ 1. NIL 'START)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '|(| 'PRINC NIL))
((LAMBDA (I REST HEAD K)
(PROGN (SETQ I
(COND ((ZEROP /#1LEVEL) 2.)
(/#1PRINLENGTH)))
((LAMBDA (U1_ITEM)
(SETQ HEAD (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ REST U1_ITEM))
LIST)
(SETQ K 1.))
(PROG NIL
U1_L (PROGN (COND ((OR (MINUSP I)
(AND (ZEROP I)
(OR REST
(NOT (ATOM HEAD)))))
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '|...|
'PRINC
NIL))
(RETURN NIL)))
(COND ((MINUSP K)
(COND ((AND (ATOM HEAD) HEAD)
(COND (/#1PRINC-ATOMS
(SETQ BCODE
(- BCODE 1. (FLATC HEAD))))
((SETQ BCODE
(- BCODE 1. (FLATSIZE HEAD)))))
(PROGN (SETQ /#1FCODE
(COND (ANY-LABS-YET? 'NEVER)
('ALWAYS))
/#1BCODE 1.)
(/#1ENTER-OBJ HEAD
(COND (/#1PRINC-ATOMS 'PRINC)
('PRIN1))
NIL))
(SETQ ANY-LABS-YET? T))
(T
(COND ((NOT ANY-LABS-YET?)
(PROGN (SETQ
/#1FCODE 'ALWAYS
/#1BCODE DEFAULT-BCODE)
(/#1ENTER-OBJ '|| NIL NIL)))
(T
(PROGN (SETQ
/#1FCODE 'NEVER
/#1BCODE (MAX 0. BCODE))
(/#1ENTER-OBJ '|| NIL NIL))
(PROGN (SETQ BCODE
DEFAULT-BCODE)
(SETQ ANY-LABS-YET? NIL))))
(SETQ /#1FCODE 'NEVER
/#1BCODE
(COND ((NULL REST)
0.)
(1.)))
(COND (/#1FORMAT-DISPATCH
(FUNCALL
/#1FORMAT-DISPATCH
NIL
HEAD))
((/#1FORMAT-DISPATCH
NIL
HEAD))))))
(T
(SETQ /#1FCODE 'NEVER
/#1BCODE
(COND ((NULL REST) 0.)
(1.)))
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
/#11LEVEL-BLOCK-TEMPLATE
HEAD))
((/#1FORMAT-DISPATCH
/#11LEVEL-BLOCK-TEMPLATE
HEAD)))))
(COND ((NULL REST) (RETURN NIL)))
(COND ((NOT (EQ (TYPEP (SETQ REST
(/#1RCHECK REST)))
'LIST))
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 1.)
(/#1ENTER-OBJ '|.|
'PRINC
NIL))
(SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(COND (/#1FORMAT-DISPATCH
(FUNCALL /#1FORMAT-DISPATCH
NIL
REST))
((/#1FORMAT-DISPATCH NIL
REST)))
(RETURN NIL))))
(PROGN (SETQ I (1- I))
((LAMBDA (U1_ITEM)
(SETQ HEAD (CAR U1_ITEM))
(SETQ U1_ITEM (CDR U1_ITEM))
(SETQ REST U1_ITEM))
REST)
(SETQ K (1- K)))
(GO U1_L)))
NIL NIL NIL NIL)
(PROGN (SETQ /#1FCODE 'NEVER
/#1BCODE 0.)
(/#1ENTER-OBJ '|)| 'PRINC 'END))
(PROGN (SETQ /#1RINDEX ORINDEX)
(SETQ /#1LEVEL OLEVEL)))))
NIL NIL NIL NIL NIL))))
(PUTPROP 'DO (GET 'PROG '/#GRIND-FN) '/#GRIND-FN)
(DEFUN /#1ENTER-OBJ (OBJ PCODE LCODE)
((LAMBDA (FLAG LENGTH)
(PROGN (SETQ FLAG
(+ (COND ((EQ PCODE 'PRIN1) (PROGN 4096.))
((EQ PCODE 'PRINC) (PROGN 2048.))
(0.))
(COND ((EQ /#1FCODE 'NEVER) (PROGN 512.))
((EQ /#1FCODE 'NORMAL) (PROGN 128.))
((EQ /#1FCODE 'TBLOCK) (PROGN 1024.))
((EQ /#1FCODE 'BLOCK) (PROGN 256.))
((PROGN 64.)))
(COND ((EQ LCODE 'START) (PROGN 8192.))
((EQ LCODE 'END)
(+ 49152.
(ARRAYCALL FIXNUM /#1BCODESTACK /#1SUPPTR)))
((+ 32768. /#1BCODE)))))
(SETQ LENGTH
(COND ((NOT (ZEROP (BOOLE 1. 8192. FLAG))) 0.)
((NOT (ZEROP (BOOLE 1. 4096. FLAG)))
(+ (BOOLE 1. 63. FLAG) (FLATSIZE OBJ)))
((NOT (ZEROP (BOOLE 1. 2048. FLAG)))
(+ (BOOLE 1. 63. FLAG) (FLATC OBJ)))
((BOOLE 1. 63. FLAG)))))
(COND (/#1EXPLODING
(COND ((NOT (ZEROP (BOOLE 1. 2048. FLAG)))
(SETQ /#1EXPLODE-RESULT
(NRECONC (EXPLODEC OBJ) /#1EXPLODE-RESULT)))
((NOT (ZEROP (BOOLE 1. 4096. FLAG)))
(SETQ /#1EXPLODE-RESULT
(NRECONC (EXPLODE OBJ) /#1EXPLODE-RESULT))))
((LAMBDA (I)
(SETQ I (BOOLE 1. 63. FLAG))
(PROG NIL
U1_L (COND ((NOT (PLUSP I)) (RETURN NIL)))
(SETQ /#1EXPLODE-RESULT
(CONS '| | /#1EXPLODE-RESULT))
(SETQ I (1- I))
(GO U1_L)))
NIL)
(COND ((NOT (ZEROP (BOOLE 1. 8192. FLAG)))
(PROGN (SETQ /#1SUPPTR (1+ /#1SUPPTR))
(STORE (ARRAYCALL FIXNUM
/#1BCODESTACK
/#1SUPPTR)
/#1BCODE)))
((NOT (ZEROP (BOOLE 1. 16384. FLAG)))
(SETQ /#1SUPPTR (1- /#1SUPPTR)))))
(T
(PROGN (SETQ /#1INPTR (1+ /#1INPTR))
(STORE (ARRAYCALL FIXNUM /#1SUPSTACK /#1SUPPTR)
(1+ (ARRAYCALL FIXNUM /#1SUPSTACK /#1SUPPTR))))
(COND ((NOT (< /#1INPTR /#1SIZE))
(COND ((< /#1PP 10.)
(SETQ /#1SIZE (+ /#1SIZE 10.))
(*REARRAY /#1OBJ
(CAR (ARRAYDIMS /#1OBJ))
/#1SIZE)
(*REARRAY /#1FLAG
(CAR (ARRAYDIMS /#1FLAG))
/#1SIZE)
(*REARRAY /#1LENGTH
(CAR (ARRAYDIMS /#1LENGTH))
/#1SIZE))
(T
((LAMBDA (J I)
(PROGN (SETQ J /#1PP) (SETQ I 0.))
(PROG NIL
U1_L (COND ((= J /#1SIZE) (RETURN NIL)))
(PROGN (STORE (ARRAYCALL NIL
/#1OBJ
I)
(ARRAYCALL NIL /#1OBJ J))
(STORE (ARRAYCALL FIXNUM
/#1FLAG
I)
(ARRAYCALL FIXNUM
/#1FLAG
J))
(STORE (ARRAYCALL FIXNUM
/#1LENGTH
I)
(ARRAYCALL FIXNUM
/#1LENGTH
J)))
(PROGN (SETQ J (1+ J))
(SETQ I (1+ I)))
(GO U1_L)))
NIL NIL)
(PROGN (SETQ /#1INPTR (- /#1INPTR /#1PP))
(SETQ /#1PP 0.))))))
(PROGN (STORE (ARRAYCALL NIL /#1OBJ /#1INPTR) OBJ)
(STORE (ARRAYCALL FIXNUM /#1FLAG /#1INPTR) FLAG)
(STORE (ARRAYCALL FIXNUM /#1LENGTH /#1INPTR) LENGTH))
((LAMBDA (I J)
(PROGN (SETQ I /#1SUPPTR)
(SETQ J
(- /#1INPTR (ARRAYCALL FIXNUM /#1SUPSTACK I))))
(PROG NIL
U1_L (COND ((OR (ZEROP I) (< J /#1PP)) (RETURN NIL)))
(STORE (ARRAYCALL FIXNUM /#1LENGTH J)
(+ LENGTH (ARRAYCALL FIXNUM /#1LENGTH J)))
(PROGN (SETQ I (1- I))
(SETQ J
(- J (ARRAYCALL FIXNUM /#1SUPSTACK I))))
(GO U1_L)))
NIL NIL)
(COND ((NOT (ZEROP (BOOLE 1. 64. FLAG)))
((LAMBDA (I J)
(PROGN (SETQ I /#1SUPPTR)
(SETQ J
(- /#1INPTR
(ARRAYCALL FIXNUM /#1SUPSTACK I))))
(PROG NIL
U1_L (COND ((OR (ZEROP I) (< J /#1PP))
(RETURN NIL)))
(STORE (ARRAYCALL FIXNUM /#1FLAG J)
(+ 65536.
(ARRAYCALL FIXNUM /#1FLAG J)))
(PROGN (SETQ I (1- I))
(SETQ J
(- J
(ARRAYCALL FIXNUM
/#1SUPSTACK
I))))
(GO U1_L)))
NIL NIL)))
(COND ((NOT (ZEROP (BOOLE 1. 8192. FLAG)))
(SETQ /#1SUPPTR (1+ /#1SUPPTR))
(COND ((NOT (< /#1SUPPTR /#1SUPSIZE))
(SETQ /#1SUPSIZE (+ /#1SUPSIZE 10.))
(*REARRAY /#1SUPSTACK
(CAR (ARRAYDIMS /#1SUPSTACK))
/#1SUPSIZE)
(*REARRAY /#1INDSTACK
(CAR (ARRAYDIMS /#1INDSTACK))
/#1SUPSIZE)
(*REARRAY /#1BCODESTACK
(CAR (ARRAYDIMS /#1BCODESTACK))
/#1SUPSIZE)))
(PROGN (STORE (ARRAYCALL FIXNUM
/#1SUPSTACK
/#1SUPPTR)
0.)
(STORE (ARRAYCALL FIXNUM
/#1BCODESTACK
/#1SUPPTR)
/#1BCODE)))
((NOT (ZEROP (BOOLE 1. 16384. FLAG)))
((LAMBDA (I)
(COND ((NOT (> /#1PP I))
(STORE (ARRAYCALL FIXNUM /#1FLAG I)
(+ 32768.
(ARRAYCALL FIXNUM /#1FLAG I))))))
(- /#1INPTR (ARRAYCALL FIXNUM /#1SUPSTACK /#1SUPPTR)))
(PROGN (SETQ /#1SUPPTR (1- /#1SUPPTR))
(STORE (ARRAYCALL FIXNUM
/#1SUPSTACK
/#1SUPPTR)
(+ (ARRAYCALL FIXNUM
/#1SUPSTACK
/#1SUPPTR)
(ARRAYCALL FIXNUM
/#1SUPSTACK
(1+ /#1SUPPTR)))))))
(/#1PRINTOUT))))
NIL NIL)
NIL)
(DEFUN /#1PRINTOUT NIL
((LAMBDA (FLAG)
(PROG NIL
U1_L (COND ((> /#1PP /#1INPTR) (RETURN NIL)))
(SETQ FLAG (ARRAYCALL FIXNUM /#1FLAG /#1PP))
(COND ((AND (NOT (ZEROP (BOOLE 1. 1024. FLAG)))
(NOT (ZEROP (BOOLE 1. 32768. FLAG)))
(= /#1TABSIZE 1.))
((LAMBDA (N I MAX SPACE)
(PROGN (SETQ N
(MAX 2.
(ARRAYCALL FIXNUM /#1LENGTH /#1PP)))
(SETQ I 0.)
(SETQ MAX
((LAMBDA (J FLAG)
(SETQ J /#1PP)
(PROG NIL
U1_L (COND ((> J /#1INPTR)
(RETURN N)))
(SETQ FLAG
(ARRAYCALL FIXNUM
/#1FLAG
J))
(PROGN (COND ((= I 0.)
(SETQ N (MAX N (ARRAYCALL FIXNUM /#1LENGTH J)))))
(COND ((NOT (ZEROP (BOOLE
1.
8192.
FLAG)))
(SETQ I (1+ I)))
((NOT (ZEROP (BOOLE
1.
16384.
FLAG)))
(SETQ I (1- I)))))
(SETQ J (1+ J))
(GO U1_L)))
NIL NIL))
(SETQ SPACE
(- /#1LINELEN
(ARRAYCALL FIXNUM
/#1INDSTACK
/#1INDPTR))))
(PROGN (SETQ MAX (MIN SPACE (+ MAX (// MAX 5.))))
(SETQ /#1TABSIZE (// SPACE (// SPACE MAX)))
(SETQ /#1TABOFFSET
(- (\ SPACE /#1TABSIZE) /#1TABSIZE))))
NIL NIL NIL NIL)))
(COND ((NOT /#1ATSTART?)
(COND ((AND (NOT (ZEROP (BOOLE 1. 1024. FLAG)))
(NOT (ZEROP (BOOLE 1. 32768. FLAG))))
((LAMBDA (J)
(PROGN (SETQ /#1PENDING (+ /#1PENDING J))
(SETQ /#1FREELEN (- /#1FREELEN J))))
(\ (- /#1FREELEN /#1TABOFFSET) /#1TABSIZE))))
(COND ((OR (NOT (ZEROP (BOOLE 1. 64. FLAG)))
(NOT (ZEROP (BOOLE 1. 128. FLAG)))
(AND (OR (NOT (ZEROP (BOOLE 1. 256. FLAG)))
(NOT (ZEROP (BOOLE 1. 1024. FLAG))))
(OR /#1WENTUP?
(NOT (ZEROP (BOOLE 1. 65536. FLAG)))
(AND (> (ARRAYCALL FIXNUM
/#1LENGTH
/#1PP)
/#1FREELEN)
(< /#1FREELEN
(- /#1LINELEN
(ARRAYCALL FIXNUM
/#1INDSTACK
/#1INDPTR))))))
(AND (NOT (ZEROP (BOOLE 1. 512. FLAG)))
(NOT (NOT (ZEROP (BOOLE 1. 8192. FLAG))))
(> (ARRAYCALL FIXNUM /#1LENGTH /#1PP)
(+ 4. /#1FREELEN))))
(PROGN (SETQ /#1ATSTART? T)
(SETQ /#1WENTUP? NIL)
(SETQ /#1CLINE (1+ /#1CLINE))
(SETQ /#1PENDING
(ARRAYCALL FIXNUM
/#1INDSTACK
/#1INDPTR))
(SETQ /#1FREELEN
(- /#1LINELEN /#1PENDING)))
(COND ((> /#1CLINE /#1PRINENDLINE)
(THROW '|#1prinendline exceeded|
/#1PRINTABORT)))
(COND (/#1PRINTING? (TERPRI /#1FILES))
((SETQ /#1PRINTING?
(NOT (> /#1PRINSTARTLINE /#1CLINE)))
(SETQ /#1PENDING (- /#1PENDING /#1CP))))))))
(COND ((AND (NOT (ZEROP (BOOLE 1. 8192. FLAG)))
(OR (NOT (ZEROP (BOOLE 1. 65536. FLAG)))
(> (ARRAYCALL FIXNUM /#1LENGTH /#1PP)
/#1FREELEN)))
(PROGN (SETQ /#1INDPTR (1+ /#1INDPTR))
(STORE (ARRAYCALL FIXNUM /#1INDSTACK /#1INDPTR)
((LAMBDA (I)
(COND ((> I /#1MAXINDENTLEN)
(+ /#1CP
(// (- /#1LINELEN /#1CP)
5.)
(- I /#1MAXINDENTLEN)))
(I)))
(MAX /#1CP
(+ (ARRAYCALL NIL /#1OBJ /#1PP)
(- /#1LINELEN /#1FREELEN)))))
(SETQ /#1PP (1+ /#1PP))
(SETQ /#1TABSIZE 1.)))
((NOT (ZEROP (BOOLE 1. 32768. FLAG)))
(PROGN (SETQ /#1FREELEN
(- /#1FREELEN
(ARRAYCALL FIXNUM /#1LENGTH /#1PP)))
(SETQ /#1ATSTART? NIL))
((LAMBDA (I)
(SETQ I 0.)
(PROG NIL
U1_L (COND ((NOT (ZEROP (BOOLE 1. 8192. FLAG)))
(SETQ I (1+ I)))
(T
(COND ((NOT (ZEROP (BOOLE 1.
16384.
FLAG)))
(SETQ I (1- I))))
(COND (/#1PRINTING?
((LAMBDA (J)
(SETQ J /#1PENDING)
(PROG NIL
U1_L (COND ((NOT (PLUSP J))
(RETURN NIL)))
(TYO 32. /#1FILES)
(SETQ J (1- J))
(GO U1_L)))
NIL)
(COND ((NOT (ZEROP (BOOLE 1.
2048.
FLAG)))
(PRINC (ARRAYCALL NIL
/#1OBJ
/#1PP)
/#1FILES))
((NOT (ZEROP (BOOLE 1.
4096.
FLAG)))
(PRIN1 (ARRAYCALL NIL
/#1OBJ
/#1PP)
/#1FILES)))))
(SETQ /#1PENDING (BOOLE 1. 63. FLAG))))
(SETQ /#1PP (1+ /#1PP))
(COND ((ZEROP I) (RETURN NIL))
((MINUSP I)
(PROGN (SETQ /#1INDPTR (1- /#1INDPTR))
(SETQ /#1WENTUP? T)
(SETQ /#1TABSIZE 64000.))
(RETURN NIL)))
(SETQ FLAG (ARRAYCALL FIXNUM /#1FLAG /#1PP))
(GO U1_L)))
NIL))
((RETURN NIL)))
(GO U1_L)))
NIL))
))