(FILECREATED "30-MAY-79 00:25:14" <LISPUSERS>CIRCLPRINT.;3   19722

     changes to:  CIRCLPRINTCOMS

     previous date: " 5-JUL-78 19:49:27" <LISPUSERS>CIRCLPRINT.;2)


(PRETTYCOMPRINT CIRCLPRINTCOMS)

(RPAQQ CIRCLPRINTCOMS [(FNS CIRCLMAKER CIRCLMAKER1 CIRCLPRINT CIRCLMARK RLPRIN1 RLRESTORE CSEARCH 
			    PLACEPRINT C2PRINT ROOMLEFT RLPRIN2 CPRINT CLPRINT CIRCLNC)
	(VARS CIRCLMARKER)
	(BLOCKS (CIRCLBLOCK CIRCLMAKER CIRCLMAKER1 CIRCLPRINT CIRCLMARK RLPRIN1 RLRESTORE CSEARCH 
			    PLACEPRINT C2PRINT ROOMLEFT RLPRIN2 CPRINT CLPRINT CIRCLNC
			    (ENTRIES CIRCLPRINT CIRCLMARK RLPRIN1 RLPRIN2 RLRESTORE CIRCLMAKER 
				     CIRCLMAKER1)
			    (SPECVARS RLKNT LABELIST REFLIST)
			    (LOCALFREEVARS PLACELIST LL)
			    (NOLINKFNS . T)
			    (GLOBALVARS #UNDOSAVES RESETVARSLST])
(DEFINEQ

(CIRCLMAKER
  [LAMBDA (L)                                   (* lmm: 19 MAY 75 232)
    (PROG (LABELIST REFLIST)
          (CIRCLMAKER1 L)

          (* An error is generated if REFLIST is non-NIL, 
	  because this means that some nodes are referenced in
	  L without being labeled (i.e. defined) and indicates
	  that the user may have omitted some code.
	  See the comments in CIRCLMAKER1 for additional 
	  information.)


          (COND
	    (REFLIST (ERROR (QUOTE "LABEL NOT FOUND FOR REFERENCE")))
	    (T (RETURN L])

(CIRCLMAKER1
  [LAMBDA (L)

          (* This function makes use of two free variables, 
	  REFLIST and LABELIST, which are alist-like 
	  structures that provide information about nodes that
	  have been defined (labeled) and where they have been
	  referenced. LABELIST is a list of lists.
	  Each list in labelist is of the form 
	  (n . L), where n is the number that is being used to
	  label the node L. REFLIST is also a list of lists.
	  Each list in REFLIST is of the form 
	  (n (L1 L2 ...) (L1' L2' ...)), where n is the number
	  of the node that is being referred to, and L1, 
	  L2,... are those nodes for which car is a reference 
	  to {n}, and L1', L2',... are those nodes for which 
	  cdr is a reference to {n}.)


    (PROG (CARL CDRL CARLN CDRLN NODECODE)
          [COND
	    ((LISTP L)
	      (SETQ CARL (CAR L))
	      (SETQ CDRL (CDR L]
          (COND
	    [(AND CARL (ATOM CARL))
	      (COND
		[[AND (NEQ CARL (QUOTE {}))
		      (EQ (NTHCHAR CARL 1)
			  (QUOTE {))
		      (EQ (NTHCHAR CARL -1)
			  (QUOTE }))
		      (FIXP (SETQ CARLN (MKATOM (SUBSTRING CARL 2 -2]

          (* This part of the conditional checks to see 
	  whether CARL is a reference to a node, i.e. an atom 
	  of the form {n}, where n is a number.
	  If so, then we check to see whether the node has yet
	  been labeled (this is the assoc on labelist), 
	  whether it has been previously referred to, but not 
	  labelled (this is the assoc on reflist), or else 
	  assume that it has neither been referred to nor 
	  labelled previously. In the first case, we replace 
	  (/rplaca) CARL with a pointer to the node that is 
	  labelled n (as explained above, this would be cdr of
	  nodecode). In the second case, we add a pointer to L
	  to (cadr nodecode) which is that part of REFLIST 
	  which contains pointers to those nodes for which car
	  is the atom {n}. In the final case, we add a new 
	  sublist to REFLIST, to record that a reference has 
	  been made to a node numbered n.
	  It should be noted that, throughout this program, 
	  all such manipulations are undoable, so that the 
	  user can (for example) control-D and undo circlmaker
	  to regain his original expression.)


		  (COND
		    ((SETQ NODECODE (ASSOC CARLN LABELIST))
		      (/RPLACA L (CDR NODECODE)))
		    ((SETQ NODECODE (ASSOC CARLN REFLIST))
		      (/NCONC1 (CADR NODECODE)
			       L))
		    (T (SETQ REFLIST (/NCONC1 REFLIST
					      (LIST CARLN (LIST L)
						    NIL]
		([AND (NEQ CARL (QUOTE *))
		      (NEQ CARL (QUOTE **))
		      (EQ (NTHCHAR CARL 1)
			  (QUOTE *))
		      (EQ (NTHCHAR CARL -1)
			  (QUOTE *))
		      (FIXP (SETQ CARLN (MKATOM (SUBSTRING CARL 2 -2]

          (* This part of the conditional checks to see 
	  whether CARL is a label for a node, i.e. an atom of 
	  the form *n*, where n is a number.
	  If so, then we check to see whether a node has 
	  already been labelled by the same number, in which 
	  case an error is generated 
	  (*n* is ambiguous, multiply used label). Otherwise, 
	  we check to see that cdr of l is a list, in which 
	  case we physically (but undoably) remove the label 
	  from L , add a new sublist to LABELIST, and check to
	  see whether there is a sublist on REFLIST that 
	  indicates that references to L have already been 
	  made. If so, then we make the appropriate changes to
	  car and cdr of the nodes wwich referenced L, and 
	  undoably remove the sublist 
	  (NODECODE) from REFLIST, because the only purpose of
	  this sublist was to preserve a record of those nodes
	  which referenced L, before the label for L was found
	  and the actual pointers from those nodes to L could 
	  be established-- now that the pointers have been 
	  established, we can decrement REFLIST-- if all nodes
	  that are referenced are in fact labeled somewhere in
	  the structure, then REFLIST should eventually in 
	  this way be decremented to NIL-- otherwise the 
	  monitoring function CIRCLMAKER will generate an 
	  error, if it was the top level function that called 
	  CIRCLMAKER1. Finally, we call circlmaker1 
	  recursively on L, and return the resultant value of 
	  L. If the original cdr of l were not a list, then we
	  would generate the CARL "IS MISPLACED LABEL" error--
	  this is intended to handle expressions like 
	  (*1* . {1}), which are anomalous because the label 
	  does not really point to a node, and there is a 
	  likelihood that the user has inadvertently omitted 
	  some code.)


		  (COND
		    ((ASSOC CARLN LABELIST)
		      (ERROR CARL (QUOTE 
				"IS AMBIGUOUS, MULTIPLY USED LABEL")))
		    ((LISTP (CDR L))
		      (/RPLACA L (CADR L))
		      (/RPLACD L (CDDR L))
		      (SETQ LABELIST (/NCONC1 LABELIST
					      (CONS CARLN L)))
		      [COND
			((SETQ NODECODE (ASSOC CARLN REFLIST))
			  (SETQ REFLIST (/DREMOVE NODECODE REFLIST))
			  [MAPC (CADR NODECODE)
				(FUNCTION (LAMBDA (X)
				    (/RPLACA X L]
			  (MAPC (CADDR NODECODE)
				(FUNCTION (LAMBDA (X)
				    (/RPLACD X L]
		      (CIRCLMAKER1 L)
		      (RETURN L))
		    (T (ERROR CARL (QUOTE "IS MISPLACED LABEL"]
	    ((LISTP CARL)
	      (CIRCLMAKER1 CARL)))
          (COND
	    [(AND CDRL (ATOM CDRL))
	      (COND
		[[AND (NEQ CDRL (QUOTE {}))
		      (EQ (NTHCHAR CDRL 1)
			  (QUOTE {))
		      (EQ (NTHCHAR CDRL -1)
			  (QUOTE }))
		      (FIXP (SETQ CDRLN (MKATOM (SUBSTRING CDRL 2 -2]

          (* This branch of the conditional checks to see 
	  whether CDRL is a reference to a node, i.e. an atom 
	  of the form {n} where n is a number.
	  If so, then the steps followed are analogous to 
	  those described above for the case in which CARL is 
	  a reference to a node. A similar check is made below
	  to see whether CDRL is a label for a node.
	  An error is generated in this case, because such a 
	  label has no meaning (the label does not point to a 
	  node), and there is a likelihood that the user has 
	  inadvertently omitted some code.
	  The error message reads "*n* IS MISPLACED LABEL".)


		  (COND
		    ((SETQ NODECODE (ASSOC CDRLN LABELIST))
		      (/RPLACD L (CDR NODECODE)))
		    ((SETQ NODECODE (ASSOC CDRLN REFLIST))
		      (/NCONC1 (CADDR NODECODE)
			       L))
		    (T (SETQ REFLIST (/NCONC1 REFLIST
					      (LIST CDRLN NIL
						    (LIST L]
		([AND (EQ (NTHCHAR CDRL 1)
			  (QUOTE *))
		      (NEQ CDRL (QUOTE *))
		      (NEQ CDRL (QUOTE **))
		      (EQ (NTHCHAR CDRL -1)
			  (QUOTE *))
		      (FIXP (MKATOM (SUBSTRING CDRL 2 -2]
		  (ERROR CDRL (QUOTE "IS MISPLACED LABEL"]
	    ((LISTP CDRL)
	      (CIRCLMAKER1 CDRL)))
          (RETURN L])

(CIRCLPRINT
  [LAMBDA (L PRINTFLG RLKNT)            (* lmm: 24-JAN-76 1 22)
    [RESETLST (RESETSAVE (RADIX 10))
	      (RESETVARS (#UNDOSAVES)
			 (PROG NIL
			       (CIRCLMARK L RLKNT)
			       (COND
				 (PRINTFLG (RLPRIN1 L))
				 (T (RLPRIN2 L)))
			       (RLRESTORE L]
    L])

(CIRCLMARK
  [LAMBDA (L RLKNT)                             (* lmm: 19 MAY 75 233)
    (PROG NIL
          (COND
	    ((NULL RLKNT)
	      (SETQ RLKNT 0)))
          (RETURN (CSEARCH L])

(RLPRIN1
  [LAMBDA (L)
    (PROG (PLACELIST LL)
          (SETQ PLACELIST NIL)
          (SETQ LL (LINELENGTH))
          (CLPRINT L (QUOTE CAR))
          (TERPRI])

(RLRESTORE
  [LAMBDA (L)                                   (* lmm: 19 MAY 75 234)
    (PROG NIL
          (COND
	    ((AND (LISTP L)
		  (EQ (CAAR L)
		      CIRCLMARKER))
	      (RPLACA L (CADAR L))
	      (RLRESTORE (CAR L))
	      (RLRESTORE (CDR L])

(CSEARCH
  [LAMBDA (L)                                   (* lmm: 19 MAY 75 234)
    (PROG (NXPOINT)
          (COND
	    ((LISTP L)
	      (SETQ NXPOINT (CAR L))
	      [COND
		[(LISTP NXPOINT)
		  (COND
		    ((EQ (CAR NXPOINT)
			 CIRCLMARKER)
		      [COND
			((NULL (CDDR NXPOINT))
			  (NCONC1 NXPOINT (SETQ RLKNT (ADD1 RLKNT]
		      (RETURN NIL))
		    (T (/RPLACA L (LIST CIRCLMARKER NXPOINT))
		       (CSEARCH NXPOINT]
		(T (/RPLACA L (LIST CIRCLMARKER NXPOINT]
	      (RETURN (CSEARCH (CDR L])

(PLACEPRINT
  [LAMBDA (P)
    (COND
      (P (COND
	   ((IGREATERP (CDAR P)
		       -1)
	     (SPACES (IDIFFERENCE (CDAR P)
				  (POSITION)))
	     (PRIN1 (CAAR P))
	     (RPLACD (CAR P)
		     -1)))
	 (PLACEPRINT (CDR P])

(C2PRINT
  [LAMBDA (L CAMEFROM)                          (* lmm: 19 MAY 75 234)
    (PROG NIL
          (TERPRI)
          (PLACEPRINT PLACELIST)
          (TERPRI)
          (TERPRI)
          (RETURN (CPRINT L CAMEFROM])

(ROOMLEFT
  [LAMBDA NIL
    (IDIFFERENCE LL (POSITION])

(RLPRIN2
  [LAMBDA (L)
    (RESETLST (PROG (PLACELIST LL)

          (* Rather than checking NCHARS of every atom before 
	  printing it just to make sure that lines don't go 
	  over the boundary (causing LISP to put in TERPRI's 
	  where we don't want them) LINELENGTH is just changed
	  to be something huge and we are conservative about 
	  how much we think will fit on a line...
	  If a structure has atoms with more than 8 
	  characters, and appears on the end of a line, it 
	  might overflow, though)


		    (SETQ LL (IDIFFERENCE (LINELENGTH)
					  8))
		    (RESETSAVE (LINELENGTH (IPLUS LL 80)))
		    (CPRINT L (QUOTE CAR))
		    (TERPRI)
		    (PLACEPRINT PLACELIST)
		    (TERPRI])

(CPRINT
  [LAMBDA (L CAMEFROM)

          (* This function does most of the work involved in 
	  circlprinting in the double line format.
	  IN this format, a node is labeled by the appearance 
	  of its number on the line below where the node 
	  begins. If the node is car of the node we came from 
	  (i.e. if CAMEFRON = 'CAR) then the node begins with 
	  a left parens, and the node's number should begin 
	  immediately below that left parens.
	  If the node is cdr of the node we came from 
	  (i.e. if CAMEFROM = 'CDR) then the node is a tail of
	  a list, and the number identifying it should appear 
	  on the line below the beginning of that tail.
	  Thus, when labeeling a node we have to save the 
	  position where the node begins.
	  Also, we have to alternate printing nodes and 
	  printing their labels below them.
	  The function that prints labels below nodes is 
	  PLACEPRINT. CPRINT saves the information necessary 
	  to print labels in the correct position by adding 
	  sublists to an alist called PLACELIST.
	  When CPRINT adds a sublist to PLACELIST, this 
	  sublist is of the form (N . P), where N is the 
	  number of the ndoe being labeled, and P is the 
	  position where printing of the label should begin.
	  When PLACEPRINT prints a line of labels, it merely 
	  cdr's thru PLACELIST checking to see if there are 
	  any sublists of the form (N . P), where P is greater
	  than -1.0 For each such sublist, N is printed and 
	  then the sublist is physically altered to be of the 
	  form (N . -1). Thus PLACELIST can also be used as a 
	  list of all labels that have been printed 
	  (or will be printed, when PLACEPRINT is called next), 
	  and CPRINT can merely do an assoc on placelist to 
	  see if a given node has been previously labeled.)


    (PROG (LN N CARL CARLN CDRL CDRLN LABELEDCDRL? LABELEDCARL? 
	      EXSPACES ROOM)
          (COND
	    ((ILESSP (SETQ ROOM (ROOMLEFT))
		     3)
	      (C2PRINT L CAMEFROM))
	    ((OR (NLISTP L)
		 (NLISTP (CAR L))
		 (NEQ (CAAR L)
		      CIRCLMARKER))
	      (ERROR (QUOTE "UNCIRCLMARKED LIST STRUCTURE")))
	    ((AND (SETQ LN (CDDAR L))
		  (SETQ N (CAR LN))
		  (FASSOC N PLACELIST))
					(* L has already been printed;
					print a back reference)
	      [COND
		((ILESSP ROOM (IPLUS 2 (CIRCLNC N)))
		  (RETURN (C2PRINT L CAMEFROM]
	      (PRIN1 (QUOTE {))
	      (PRIN1 N)
	      (PRIN1 (QUOTE })))
	    ([AND LN (ILESSP ROOM (IPLUS 3 (SETQ EXSPACES (CIRCLNC
					     N]
	      (C2PRINT L CAMEFROM))
	    (T [COND
		 (LN (SETQ PLACELIST (NCONC1 PLACELIST
					     (CONS (CAR LN)
						   (POSITION]
					(* If LN is not NIL, the 
					structure needs to be labeled)
	       [COND
		 ((EQ CAMEFROM (QUOTE CAR))
		   (PRIN1 (QUOTE %(]
	       [COND
		 (LN (COND
		       ((OR (NEQ EXSPACES 1)
			    (NEQ CAMEFROM (QUOTE CAR)))
					(* Make sure there is enough 
					space to clearly label L)
			 (SPACES EXSPACES]
	       [COND
		 ((NLISTP (SETQ CARL (CADAR L)))
		   (PRIN2 CARL))
		 ((EQ L CARL)
		   (COND
		     ((ILESSP (ROOMLEFT)
			      (IPLUS 2 EXSPACES))
		       (TERPRI)
		       (PLACEPRINT PLACELIST)
		       (TERPRI)
		       (TERPRI)))
		   (PRIN1 (QUOTE {))
		   (PRIN1 (CAR LN))
		   (PRIN1 (QUOTE })))
		 (T (CPRINT CARL (QUOTE CAR]
	       (COND
		 ((NULL (CDR L))
		   (PRIN1 (QUOTE %))))
		 ((NLISTP (CDR L))
		   (PRIN1 (QUOTE " ."))
		   (SPACES 1)
		   (PRIN2 (CDR L))
		   (PRIN1 (QUOTE %))))
		 ((AND (SETQ CDRLN (CDDADR L))
		       (FASSOC (CAR CDRLN)
			       PLACELIST))
					(* If (CDR L) has been labeled, 
					then print a reference.)
		   (COND
		     ([ILESSP (ROOMLEFT)
			      (IPLUS 6 (CIRCLNC (CAR CDRLN]
		       (TERPRI)
		       (PLACEPRINT PLACELIST)
		       (TERPRI)
		       (TERPRI)))
		   (PRIN1 (QUOTE " ."))
		   (SPACES 1)
		   (PRIN1 (QUOTE {))
		   (PRIN1 (CAR CDRLN))
		   (PRIN1 (QUOTE }))
		   (PRIN1 (QUOTE %))))
		 (T (SPACES 1)
		    (CPRINT (CDR L)
			    (QUOTE CDR])

(CLPRINT
  [LAMBDA (L CAMEFROM)

          (* This function does most of the work involved in 
	  cirlcprinting in the single line format.
	  The problems encountered with the double line format
	  (see CPRINT) do not occur here.
	  In particular the alist PLACELIST is used by CLPRINT
	  only to store the numbers of the reentrant nodes 
	  that have already been labeled, not the positions 
	  where they were labeled. CLPRINT prints a 
	  description of each node (i.e. a label, a reference,
	  or car and cdr) as it encounters it.)


    (PROG (LN N LABELIT CARL CDRL CDRLN LISTPCDRL? LABELEDCDRL? 
	      EXSPACES)
          (COND
	    ((ILESSP (ROOMLEFT)
		     2)
	      (TERPRI)))
          (COND
	    ((LISTP L)
	      (COND
		((NOT (EQ (CAAR L)
			  CIRCLMARKER))
		  (ERROR (QUOTE "UNCIRCLMARKED LIST STRUCTURE")))
		((AND (SETQ LN (CDDAR L))
		      (SETQ N (CAR LN))
		      (SETQ EXSPACES (CIRCLNC N))
		      (FMEMB N PLACELIST))

          (* If L is a reentrant node and has already been 
	  labeled then we simply print a reference to L.
	  CIRCLNC computes the number of digits in N which is 
	  2 less than the number of characters needed to label
	  or reference L, and makes it the value of EXSPACES.
	  If N is greater than or equal to 10000, then an 
	  error is generated. Otherwise, the FMEMB on 
	  placelist checks to see if L has already been 
	  labeled, in which case we print a reference to L, in
	  the code below this comment.)


		  (COND
		    ((ILESSP (ROOMLEFT)
			     (IPLUS 2 EXSPACES))
		      (TERPRI)))
		  (PRIN1 (QUOTE {))
		  (PRIN1 N)
		  (PRIN1 (QUOTE })))
		(T (COND
		     (LN                (* Checks to see if L has to be 
					labeled.)
			 (COND
			   ((ILESSP (ROOMLEFT)
				    (IPLUS 3 EXSPACES))
			     (TERPRI)))
			 (SETQ LABELIT T)))
		   [COND
		     (LABELIT           (* If L is to be labeled, then 
					add N to placelist.)
			      (SETQ PLACELIST (NCONC PLACELIST LN]
		   [COND
		     ((EQ CAMEFROM (QUOTE CAR))
		       (PRIN1 (QUOTE %(]
		   (COND
		     (LABELIT           (* If L is to be labeled, then 
					print a label.)
			      (PRIN1 (QUOTE *))
			      (PRIN1 (CAR LN))
			      (PRIN1 (QUOTE *))
			      (SPACES 1)))
		   (COND
		     [(LISTP (SETQ CARL (CADAR L)))

          (* If CARL is a list then if L = CARL then print a 
	  reference to CARL automatically, else CPRINT CARL.)


		       (COND
			 ((EQ L CARL)
			   (COND
			     ((ILESSP (ROOMLEFT)
				      (IPLUS 2 EXSPACES))
			       (TERPRI)))
			   (PRIN1 (QUOTE {))
			   (PRIN1 (CAR LN))
			   (PRIN1 (QUOTE })))
			 (T (CLPRINT CARL (QUOTE CAR]
		     (T (PRIN2 CARL)))
		   (COND
		     ((LISTP (SETQ CDRL (CDR L)))
					(* Check whether CDRL needs to 
					be labeled.)
		       (COND
			 ((AND (SETQ CDRLN (CDDADR L))
			       (FMEMB (CAR CDRLN)
				      PLACELIST))
			   (SETQ LABELEDCDRL? T))
			 (T (SETQ LABELEDCDRL? NIL)))
		       (SETQ LISTPCDRL? T))
		     (T (SETQ LISTPCDRL? NIL)))
		   (COND
		     (CDRL              (* make sure there will be a 
					space between carl and cdrl.)
			   (SPACES 1)))
		   (COND
		     [LISTPCDRL?

          (* If CDRL has been labeled and is reentrant, then 
	  print a reference. Else if CDRL is a list the 
	  CLPRINT CDRL, else just prin1 it.)


		       (COND
			 (LABELEDCDRL? (SETQ N (CAR CDRLN))
				       (COND
					 ((ILESSP (ROOMLEFT)
						  (IPLUS 5
							 (CIRCLNC
							   N)))
					   (TERPRI)))
				       (PRIN1 (QUOTE %.))
				       (SPACES 1)
				       (PRIN1 (QUOTE {))
				       (PRIN1 (CAR CDRLN))
				       (PRIN1 (QUOTE }))
				       (PRIN1 (QUOTE %))))
			 (T (CLPRINT CDRL (QUOTE CDR]
		     ((NULL CDRL)
		       (PRIN1 (QUOTE %))))
		     (T (PRIN1 (QUOTE %.))
			(SPACES 1)
			(PRIN2 CDRL)
			(PRIN1 (QUOTE %)])

(CIRCLNC
  [LAMBDA (N)
    (COND
      ((ILESSP N 10)
	1)
      ((ILESSP N 100)
	2)
      ((ILESSP N 1000)
	3)
      ((ILESSP N 10000)
	4)
      (T (ERROR (QUOTE "REENTRANT NODE HAS BEEN NUMBERD OVER 10000"])
)

(RPAQQ CIRCLMARKER "BEENHERE")
[DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY
(BLOCK: CIRCLBLOCK CIRCLMAKER CIRCLMAKER1 CIRCLPRINT CIRCLMARK RLPRIN1 RLRESTORE CSEARCH PLACEPRINT 
	C2PRINT ROOMLEFT RLPRIN2 CPRINT CLPRINT CIRCLNC (ENTRIES CIRCLPRINT CIRCLMARK RLPRIN1 RLPRIN2 
								 RLRESTORE CIRCLMAKER CIRCLMAKER1)
	(SPECVARS RLKNT LABELIST REFLIST)
	(LOCALFREEVARS PLACELIST LL)
	(NOLINKFNS . T)
	(GLOBALVARS #UNDOSAVES RESETVARSLST))
]
(DECLARE: DONTCOPY
  (FILEMAP (NIL (798 19253 (CIRCLMAKER 808 . 1331) (CIRCLMAKER1 1335 . 8241) (CIRCLPRINT 8245 . 8552) (
CIRCLMARK 8554 . 8739) (RLPRIN1 8743 . 8914) (RLRESTORE 8916 . 9169) (CSEARCH 9171 . 9675) (PLACEPRINT
 9679 . 9909) (C2PRINT 9911 . 10133) (ROOMLEFT 10137 . 10194) (RLPRIN2 10198 . 10942) (CPRINT 10946 . 
15100) (CLPRINT 15104 . 19037) (CIRCLNC 19041 . 19251)))))
STOP
P
