DEFINITION MODULE PS;

(*
    Title    :  Persistent Data Manager
    LastEdit :  Thu Feb 16 14:05:20 1984
    Author   :  Lee Smith
    Acorn Computers VLSI Design Aids Group
*)

FROM SYSTEM IMPORT WORD, ADDRESS;

FROM PSMCI  IMPORT PSCANPROC;

(*------------------------------------------------------------------------*)
(*  It is intended that MODULE PS should be IMPORTed whole and that all   *)
(*  EXPORTed names should be qualified.  Viz. PS.Failed, PS.Read, etc.    *)
(*------------------------------------------------------------------------*)

EXPORT QUALIFIED 

(* VAR *)       Failed,        (* BOOLEAN, set if an operation fails *)
                Marked,        (* BOOLEAN, set by Prelude if object marked *)

(* Procs *)     Close, Read, Write, Enter, Find, Destroy, Unblock,
                WeakenRefsTo, Prelude, Data, VData, Ptr, Postlude, Next;

VAR             Failed : BOOLEAN;
                Marked : BOOLEAN;

(*------------------------------------------------------------------------*)
(*  The following procedures implement the persistence operations.        *)
(*  Procedures called from user-written data-structure scanning code are  *)
(*  described at the end of this DEFINITION MODULE.                       *)
(*------------------------------------------------------------------------*)

PROCEDURE Close(HeapName : ARRAY OF CHAR);
  (* The named heap is closed: on output this commits the transaction. *)
  (* Space occupied by the heap's name table is reclaimed.             *)

PROCEDURE Read(HeapName, ObjectName : ARRAY OF CHAR;
                           ScanProc : PSCANPROC) : ADDRESS;
  (* The named object is loaded from the named heap and a pointer to   *)
  (* is returned.  If the named object cannot be found then NIL is     *)
  (* returned and PS.Failed is set.  If the named heap hasn't yet been *)
  (* opened for reading then it is so opened and its symtab is loaded. *)

PROCEDURE Write(HeapName, ObjectName : ARRAY OF CHAR;
                ScanProc : PSCANPROC;  Object : ADDRESS);
  (* The named object is written to the named heap.  If the named heap *)
  (* is not open for Write then it is Created together with a new      *)
  (* empty symbol table.  The specified ObjectName is not necessarily  *)
  (* the name by which Object is known in the in-memory heap.          *)

PROCEDURE Enter(Name : ARRAY OF CHAR;  Object : ADDRESS);
  (* Enter the <Name,Object> pair into the in-memory heap's name-table.*)
  (* A reference to any previously entered object of the same name is  *)
  (* lost.  If Object = NIL then the named object is deleted.          *)

PROCEDURE Find(Name : ARRAY OF CHAR) : ADDRESS;
  (* Look up the named object in the heap's in-memory name table.  If  *)
  (* the named object is not found then NIL is returned.  Failed is    *)
  (* NOT set: it is not an error for an object not to be in a table.   *)

PROCEDURE Destroy(ScanProc : PSCANPROC;  VAR Object : ADDRESS);
  (* Object is unbuilt using the DFS scanning procedure ScanProc.      *)
  (* Object is set to NIL.  The user-written scanning procedures MUST  *)
  (* call Tidy (see below) for this to be effective.  BEWARE: Destroy  *)
  (* destroys all objects reachable from Object.  This may not be what *)
  (* is intended (especially if everything is reachable from Object).  *)

PROCEDURE Unblock(ScanProc : PSCANPROC;  Object : ADDRESS);
  (* After being output an object is left 'blocked' so that it will not *)
  (* be output again unintentionally.  Use this procedure to Unblock it.*)
  (* Unblock also reverses the marking done by WeakenRefsTo (see below).*)

PROCEDURE WeakenRefsTo(ScanProc : PSCANPROC;  Object :ADDRESS);
  (* Object MUST be known in the in-memory heap's name-table.  If not,  *)
  (* Failed is set.  If known, every data-structure object reachable    *)
  (* Object is marked specially so that all references to them are      *)
  (* translated to NIL on output.  Use Unblock to do the unmarking.     *)

(*------------------------------------------------------------------------*)
(*  The following procedures are all called from user-written data-       *)
(*  structure scanning code.  By adjusting what these procedures do, the  *)
(*  persistence package can implement all of the operations described in  *)
(*  the above sections.  The scanning code implements a naive, recursive  *)
(*  Depth-First Search of the data-structue graph.                        *)
(*------------------------------------------------------------------------*)

PROCEDURE Prelude(A : ADDRESS;  Length : CARDINAL);
  (* This is a multi-purpose procedure, the exact function of which     *)
  (* depends on context.  It is used for marking data structures, out-  *)
  (* putting them, relocating them after input, and deleting them.      *)
  (* Marked is set if A = NIL or if A^ is appropriately marked.  Length *)
  (* is in terms of the units returned by TSIZE() and MUST be the total *)
  (* length of the object at address A.                                 *)

PROCEDURE Data(VAR D : ARRAY OF WORD);
  (* This procedure must be called from the user-written scanning code  *)
  (* for each fixed length data field of each object being scanned.     *)

PROCEDURE VData(VAR D : ARRAY OF WORD;  Length : CARDINAL);
  (* This procedure must be called from the user-written scanning code  *)
  (* for each variable length data field of each object being scanned.  *)

PROCEDURE Ptr(VAR P : ADDRESS);
  (* This procedure must be called from the user-written scanning code  *)
  (* for each pointer field of each object being scanned.  This is used *)
  (* to output pointer fields and to relocate them again after input.   *)

PROCEDURE Postlude(VAR A : ADDRESS;  Length : CARDINAL);
  (* Usually this acts as a no-op.  During a call to Destroy, however,  *)
  (* it is equivalent to a call to DEALLOCATE.  Length is in terms of   *)
  (* the units returned by TSIZE(); it MUST be the length of the whole  *)
  (* object at address A.                                               *)
  
PROCEDURE Next(VAR A : ADDRESS;  type : CARDINAL);
  (* set ScanGraph.next and ScanGraph.type for next level of DFS.       *)
  
END PS.
