[comp.lang.lisp] KCL bug reading/writing circular structures

andrewt@watnext.waterloo.edu (Andrew Thomas) (10/21/88)

I am using KCL on a microvax,  version KCL May 20, 1986.  I am trying
to use the write and read functions to save data.  I define several
structures, in which instances may contain pointers to other
structures in their fields.  In return, these pointed-to instances of
other structures may point back to the original structure instance.
By setting the *print-circle* variable, (write x) will produce output
using the #n= and #n# forms.  The problem is, (read) will not read
these back in.  I have tried to recreate this problem using very messy
circular lists, but (read) always gets it right, so the problem is
limited to structures.  Here is some simple sample code.  Run this
file and then perform the function (dobug):
---------- bug.l ---------------------------------------------------
(defstruct a val)
(defstruct b val)
(setf *print-circle* t)
(defun dobug ()
  (prog (a b c)
	(setf a (make-a))
	(setf b (make-b :val a))
	(setf (a-val a) b)

	(setf stream (open (pathname "bug")
			   :direction :output :if-exists :rename-and-delete))
	(write a :stream stream)
	(close stream)
	(setf stream (open (pathname "bug")))
	(setf c (read stream))
	(close stream))
)
----------------------------------------------------------------
The output in the file ./bug is correct, but the reader won't read it:
------- ./bug ----------------------------------
#0=#S(a val #S(b val #0#))
------------------------------------------------
Output to the screen is:

>(dobug)

Error: #0# is undefined.
Error signalled by SYSTEM:SHARP-S-READER.

Broken at READ.  Type :H for Help.
>>
-----------------------------------------------
Any suggestions as to how to fix this problem (patches, existence of a
later version, programming techniques to avoid this) would be most
gratefully accepted.

Andrew Thomas	Dept. of Systems Design		University of Waterloo

harrisr@rpics (Richard Harris) (10/25/88)

It is not hard to make KCL handle #n= and #n# with structures.

In the (c) function patch_sharp in the file c/read.d, add the lines
	case t_structure:
	{
	       int i;

	       for (i = 0; i < x->str.str_length; i++)
	               x->str.str_self[i] = patch_sharp(x->str.str_self[i]);
	       break;
        }

Also, in the (lisp) function sharp-s-reader in the file lsp/defstruct.lsp,
change the call to read from (read stream) into (read stream t nil t).

Rick Harris