<* PRAGMA LL *> MODULEA snapshot is an S-expression, written out by hand but normally read in using the Sx package. Restore methods take an Rd.T as an argument. A snapshot method writes its own data, then calls the snapshot method of its supertype. A restore method reads its own data from the reader, then calls its supertype's restore method on the remaining list. Snapshot and restore methods must be exact inverses.; ZeusSnapshot
Some restore methods may find it convenient to read the input from the Rd.T into a List.T using Sx.Read. This technique is used extensively below.
IMPORT Algorithm, AlgorithmClass, Atom, Classes, Env, Fmt, File, FileRd, FileWr, FormsVBT, FS, RefList, OSConfig, OSError, Pathname, Point, Rd, Rect, RefListUtils, RegularFile, StableVBT, Sx, Text, TextRd, TextWr, Thread, Trestle, TrestleComm, VBT, View, ViewClass, Wr, Zeus, ZeusClass, ZeusPanel, ZeusPanelFriends, ZeusPanelPrivate, ZeusPrivate, ZeusUtil; IMPORT Process, Stdio; <*FATAL FormsVBT.Error, FormsVBT.Unimplemented, TrestleComm.Failure, Thread.Alerted, Wr.Failure *>Convenience procedures for ZeusPanel init and exit.
PROCEDURE************ Session Snapshot / Restore ************FinalSnapshot (panel : ZeusPanelPrivate.T) RAISES {} = <* LL = VBT.mu *> (* Snapshot to default file at Zeus exit. *) BEGIN Snapshot(panel, StateDirFile(FinalState), FALSE); END FinalSnapshot; PROCEDUREInitialRestore (panel : ZeusPanelPrivate.T) RAISES {} = <* LL = VBT.mu *> (* Restore from default file at Zeus startup. *) BEGIN Restore(panel, StateDirFile(FinalState), FALSE); END InitialRestore;
Snapshot and restore sessions to the StateDir directory
PROCEDURE**************** Snapshot / Restore ****************SessionToStateDir (sess : ZeusPanelPrivate.Session; report: BOOLEAN := TRUE) RAISES {} = VAR twr := TextWr.New(); fname := StateDirFile(sess.name); wr : Wr.T; BEGIN (* LL = VBT.mu *) TRY SessionToWr(sess, twr); wr := FileWr.Open(fname); Sx.Print(wr, Sx.Read(TextRd.New(TextWr.ToText(twr)))); Wr.PutText(wr, "\n"); Wr.Close(wr); EXCEPT | Rd.EndOfFile, Sx.ReadError, Sx.PrintError => ZeusPanel.ReportErrorC(report, "Trouble with Sx in snapshot"); | Wr.Failure, OSError.E => ZeusPanel.ReportErrorC(report, "Cannot open file: " & fname); | FormsVBT.Error (msg) => ZeusPanel.ReportErrorC(report, msg); | ZeusClass.Error (msg) => ZeusPanel.ReportErrorC(report, msg); | Thread.Alerted => ZeusPanel.ReportErrorC( report, "Snapshort alerted; incompletely recorded"); END; END SessionToStateDir; PROCEDURESessionFromStateDir (panel : ZeusPanelPrivate.T; name : TEXT; report: BOOLEAN := TRUE): BOOLEAN RAISES {} = (* Return TRUE if successful *) VAR fname := StateDirFile(name); rd : Rd.T; list : RefList.T; msg : TEXT; BEGIN (* LL = VBT.mu *) TRY rd := FileRd.Open(fname); list := Sx.Read(rd); EXCEPT | OSError.E => (* no such file or directory *) RETURN FALSE; | Rd.EndOfFile => ZeusPanel.ReportErrorC( report, "Unexpected end of file in " & fname); RETURN FALSE; | Sx.ReadError (msg) => ZeusPanel.ReportErrorC( report, "Syntax error in " & fname & ": " & msg); RETURN FALSE; | Thread.Alerted => ZeusPanel.ReportErrorC(report, "Alerted while reading " & fname); RETURN FALSE; END; TRY RestoreSession(panel, list, FALSE); RETURN TRUE; EXCEPT | BadSnapshot (err) => msg := err; | FormsVBT.Error (err) => msg := err; | ZeusClass.Error (err) => msg := err; | Thread.Alerted => msg := "interrupted"; END; ZeusPanel.ReportErrorC( report, "Problems restoring file: " & fname & " - " & msg); RETURN FALSE; END SessionFromStateDir;
PROCEDURE**************** Data-only Snapshot / Restore ****************Snapshot (panel: ZeusPanelPrivate.T; file: TEXT; report: BOOLEAN := TRUE) RAISES {} = (* LL = VBT.mu *) VAR wr : Wr.T; BEGIN TRY wr := FileWr.Open(file); SnapshotToWr(panel, wr, report); Wr.Close(wr); FormsVBT.PopDown(panel.fv, "SnapshotDialog"); EXCEPT | Wr.Failure, OSError.E (*(ec)*) => ZeusPanel.ReportErrorC(report, "Cannot open file: " & file (* & " (" & OS.errMessage[ec] & ")"*)); END; END Snapshot; PROCEDURESnapshotToWr (panel: ZeusPanelPrivate.T; wr: Wr.T; report: BOOLEAN := TRUE) RAISES {} = (* LL = VBT.mu *) VAR twr := TextWr.New(); BEGIN TRY ZeusPanelPrivate.PrepForSnapshot(panel); SnapshotWr(panel, twr); Sx.Print(wr, Sx.Read(TextRd.New(TextWr.ToText(twr)))); Wr.PutText(wr, "\n"); EXCEPT | Rd.EndOfFile, Sx.ReadError, Sx.PrintError => ZeusPanel.ReportErrorC(report, "Trouble with Sx in snapshot"); | FormsVBT.Error (msg) => ZeusPanel.ReportErrorC(report, msg); | ZeusClass.Error (msg) => ZeusPanel.ReportErrorC(report, msg); | Thread.Alerted => ZeusPanel.ReportErrorC( report, "Snapshort alerted; incompletely recorded"); END; END SnapshotToWr; PROCEDURESnapshotWr (panel: ZeusPanelPrivate.T; wr: Wr.T) RAISES {FormsVBT.Error, Thread.Alerted, ZeusClass.Error} = (* LL = VBT.mu *) VAR l := RefList.Reverse(panel.sessions); (* reverse so order is same after restoration *) BEGIN Wr.PutText(wr, "("); panel.fv.snapshot(wr); WHILE l # NIL DO SessionToWr(RefListUtils.Pop(l), wr); END; Wr.PutText(wr, ")\n"); END SnapshotWr; PROCEDURESessionToWr (sess: ZeusPanelPrivate.Session; wr: Wr.T) RAISES {FormsVBT.Error, Thread.Alerted, ZeusClass.Error} = (* LL = VBT.mu *) VAR dom := VBT.Domain(sess.fv); nw := Trestle.ScreenOf(sess.fv, Rect.NorthWest(dom)); se := Trestle.ScreenOf(sess.fv, Rect.SouthEast(dom)); vlist, addlist: RefList.T; BEGIN Wr.PutText(wr, "("); Wr.PutText( wr, "(InTrestle " & Fmt.Bool(sess.inTrestle) & ")\n"); Wr.PutText(wr, "(Session \"" & sess.name & "\")\n"); Wr.PutText( wr, "(ScreenPos " & Fmt.Int(nw.id) & " " & Fmt.Int(nw.q.h) & " " & Fmt.Int(nw.q.v) & " " & Fmt.Int(se.q.h) & " " & Fmt.Int(se.q.v) & ")\n"); Wr.PutText(wr, "(FV "); sess.fv.snapshot(wr); Wr.PutText(wr, ")\n"); AlgToWr(wr, sess.alg); Wr.PutText(wr, "("); Zeus.Acquire(sess); vlist := sess.views; addlist := sess.viewsToAdd; WHILE addlist # NIL DO WITH v = RefListUtils.Pop(addlist) DO IF NOT RefList.Member(vlist, v) THEN RefListUtils.Push(vlist, v); END; END; END; ViewsToWr(wr, sess, vlist); Zeus.Release(sess); Wr.PutText(wr, ")"); Wr.PutText(wr, ")\n"); END SessionToWr; PROCEDUREAlgToWr (wr: Wr.T; alg: Algorithm.T) RAISES {Thread.Alerted, ZeusClass.Error} = (* LL = VBT.mu *) BEGIN Wr.PutText(wr, "("); IF (alg # NIL) AND NOT Text.Equal(alg.name, "") THEN Wr.PutText(wr, "(Alg \"" & alg.name & "\")\n"); alg.snapshot(wr); ELSE Wr.PutText(wr, "(Alg \"NIL\")\n"); END; Wr.PutText(wr, ")\n"); END AlgToWr; PROCEDUREViewsToWr ( wr : Wr.T; <*UNUSED*> sess : ZeusPanelPrivate.Session; views: RefList.T (* of View.T *)) RAISES {ZeusClass.Error} = (* LL = VBT.mu *) VAR rest: RefList.T; view: View.T; scr : Trestle.ScreenOfRec; BEGIN rest := views; WHILE rest # NIL DO view := NARROW(rest.head, View.T); scr := Trestle.ScreenOf(view, Point.Origin); (* this test wouldn't be needed if deleting views got rid of them: *) IF scr.id # Trestle.NoScreen THEN Wr.PutText(wr, "("); Wr.PutText(wr, "(View \"" & view.name & "\")\n"); view.snapshot(wr); Wr.PutText(wr, ")\n"); END; rest := rest.tail; END; END ViewsToWr; EXCEPTION BadSnapshot( TEXT ); PROCEDURERestore (panel : ZeusPanelPrivate.T; file : TEXT; report: BOOLEAN := TRUE) RAISES {} = (* LL = VBT.mu *) VAR rd: Rd.T; BEGIN TRY rd := FileRd.Open(file); EXCEPT | OSError.E => ZeusPanel.ReportErrorC(report, "Cannot open file: " & file); RETURN; END; RestoreFromRd(panel, rd, report, file); FormsVBT.PopDown(panel.fv, "RestoreDialog"); END Restore; PROCEDURERestoreFromRd (panel : ZeusPanelPrivate.T; rd : Rd.T; report: BOOLEAN := TRUE; file : TEXT := NIL ) RAISES {} = <* LL = VBT.mu *> (* Restore(p, file) == RestoreFromRd(p, FileRd.Open(file)) *) VAR list: RefList.T; ra : REFANY; BEGIN TRY ra := Sx.Read(rd); IF ISTYPE(ra, RefList.T) THEN list := ra ELSE RAISE Sx.ReadError("File does not contain a RefList.T") END; EXCEPT | Rd.EndOfFile => ZeusPanel.ReportErrorC(report, "Unexpected end of file in " & file); RETURN; | Sx.ReadError (msg) => ZeusPanel.ReportErrorC( report, "Syntax error in " & file & ": " & msg); RETURN; | Thread.Alerted => ZeusPanel.ReportErrorC(report, "Alerted while reading " & file); RETURN; END; RestoreFromList(panel, list, report); END RestoreFromRd; PROCEDURERestoreFromList (panel: ZeusPanelPrivate.T; list: RefList.T; report: BOOLEAN := TRUE) RAISES {} = VAR msg: TEXT; BEGIN ZeusPanelPrivate.DestroyAllSessions(panel); TRY PrivateRestoreFromList(panel, list); ZeusPanelPrivate.OverrideRestore(panel); RETURN; EXCEPT | BadSnapshot (err) => msg := err; | FormsVBT.Error (err) => msg := err; | ZeusClass.Error (err) => msg := err; | Thread.Alerted => msg := "interrupted"; END; ZeusPanel.ReportErrorC( report, "Problems restoring from snapshot: " & msg); ZeusPanelPrivate.DestroyAllSessions(panel); END RestoreFromList; PROCEDUREPrivateRestoreFromList (panel: ZeusPanelPrivate.T; list: RefList.T) RAISES {BadSnapshot, FormsVBT.Error, Thread.Alerted, ZeusClass.Error} = (* LL = VBT.mu *) VAR l : RefList.T; wr: TextWr.T; BEGIN IF list = NIL THEN RAISE BadSnapshot("Snapshot list is empty") END; l := RefListUtils.Pop(list); (* Snapshot brackets w/ parens *) TRY wr := TextWr.New(); Sx.Print(wr, l); panel.fv.restore(TextRd.New(TextWr.ToText(wr))); EXCEPT Sx.PrintError, FormsVBT.Mismatch => END; ZeusPanelPrivate.LoadFromPanel(panel); WHILE (list # NIL) DO IF (NOT ISTYPE(list.head, RefList.T)) OR (list.head = NIL) THEN RAISE BadSnapshot("Not a valid snapshot"); END; l := RefListUtils.Pop(list); TYPECASE l.head OF | RefList.T => RestoreSession(panel, l, TRUE); ELSE RAISE BadSnapshot("Not a valid snapshot"); END; END; END PrivateRestoreFromList; PROCEDURERestoreSession (panel : ZeusPanelPrivate.T; list : RefList.T; restoreIT : BOOLEAN) RAISES {BadSnapshot, FormsVBT.Error, Thread.Alerted, ZeusClass.Error} = (* LL = VBT.mu *) (* If restoreIT, put the session where it wants to be; o/w, put it in Trestle or not as dictated by the panel. *) VAR sess : ZeusPanelPrivate.Session; bool : BOOLEAN; l : RefList.T; keyword: TEXT; BEGIN bool := FormsVBT.GetBoolean(panel.fv, "inTrestle"); TRY WHILE (list # NIL) DO IF NOT ISTYPE(list.head, RefList.T) THEN RAISE BadSnapshot("Invalid session snapshot"); END; l := RefListUtils.Pop(list); IF l # NIL THEN TYPECASE l.head OF | Atom.T (sxs) => keyword := Atom.ToText(sxs); IF Text.Equal(keyword, "InTrestle") THEN IF restoreIT THEN bool := GetSessInTrestle(l) END; ELSIF Text.Equal(keyword, "Session") THEN sess := GetSession(panel, l, bool); ELSIF Text.Equal(keyword, "ScreenPos") THEN IF (sess # NIL) AND sess.inTrestle THEN GetSessPosition(panel, sess, l); END; ELSIF Text.Equal(keyword, "FV") THEN IF sess # NIL THEN GetSessFV(sess, l) END; ELSE RAISE BadSnapshot("Unknown keyword"); END; | RefList.T (lfirst) => IF sess # NIL THEN TYPECASE lfirst.head OF | Atom.T => GetAlg(sess, l); | RefList.T => GetViews(sess, l); ELSE RAISE BadSnapshot("Invalid session snapshot"); END; END; ELSE RAISE BadSnapshot("Invalid session snapshot"); END; END; END; EXCEPT | BadSnapshot (msg) => IF sess # NIL THEN ZeusPanelPrivate.DestroySession(sess); END; RAISE BadSnapshot(msg); END; END RestoreSession; PROCEDUREGetSession (panel: ZeusPanelPrivate.T; arg: REFANY; inTrestle: BOOLEAN): ZeusPanelPrivate.Session RAISES {BadSnapshot} = (* LL = VBT.mu *) VAR sess: ZeusPanelPrivate.Session; BEGIN KeywordCheck(arg, "Session"); IF ISTYPE(arg, RefList.T) AND (RefList.Length(arg) = 2) AND ISTYPE(RefList.Nth(arg, 1), TEXT) AND ZeusPanelPrivate.GroupInfoExists(RefList.Nth(arg, 1)) THEN ZeusPanelPrivate.NewSession(RefList.Nth(arg, 1), panel, inTrestle, FALSE); sess := panel.sessions.head; ELSE RAISE BadSnapshot("Garbled session name"); END; RETURN sess; END GetSession; PROCEDUREGetSessInTrestle (arg: REFANY): BOOLEAN RAISES {BadSnapshot} = (* LL = VBT.mu *) BEGIN KeywordCheck(arg, "InTrestle"); IF ISTYPE(arg, RefList.T) AND (RefList.Length(arg) = 2) AND ISTYPE(RefList.Nth(arg, 1), Atom.T) THEN IF RefList.Nth(arg, 1) = Sx.True THEN RETURN TRUE ELSIF RefList.Nth(arg, 1) = Sx.False THEN RETURN FALSE ELSE RAISE BadSnapshot("Garbled inTrestle parameter"); END; ELSE RAISE BadSnapshot("Garbled inTrestle parameter"); END; END GetSessInTrestle; PROCEDUREGetSessPosition (panel: ZeusPanelPrivate.T; sess: ZeusPanelPrivate.Session; arg: REFANY) RAISES {BadSnapshot} = (* LL = VBT.mu *) VAR l: RefList.T; PROCEDURE NarrowToInt (r: REFANY): INTEGER RAISES {BadSnapshot} = BEGIN TYPECASE r OF | REF INTEGER (rint) => RETURN rint^; ELSE RAISE BadSnapshot("Integer arg expected in position"); END; END NarrowToInt; BEGIN IF ISTYPE(arg, RefList.T) AND (RefList.Length(arg) = 6) THEN l := arg; KeywordCheck(l, "ScreenPos"); SetSessPosition( panel, sess, NarrowToInt(RefList.Nth(l, 1)), NarrowToInt(RefList.Nth(l, 2)), NarrowToInt(RefList.Nth(l, 3)), NarrowToInt(RefList.Nth(l, 4)), NarrowToInt(RefList.Nth(l, 5))); ELSE RAISE BadSnapshot("Error in session position"); END; END GetSessPosition; PROCEDURESetSessPosition (<*UNUSED*> panel: ZeusPanelPrivate.T; sess : ZeusPanelPrivate.Session; id : INTEGER; nwh, nwv, seh, sev: INTEGER) = (* LL = VBT.mu *) VAR nw := Point.FromCoords(nwh, nwv); se := Point.FromCoords(seh, sev); v := sess.fv; BEGIN DEC(nw.h, ZeusPanelFriends.XDRIFT); DEC(nw.v, ZeusPanelFriends.YDRIFT); DEC(se.h, ZeusPanelFriends.XDRIFT); DEC(se.v, ZeusPanelFriends.YDRIFT); IF ZeusUtil.ScreenPosOK(id, nw) THEN StableVBT.SetShape(v, ABS(se.h - nw.h), ABS(se.v - nw.v)); Trestle.Overlap(v, id, nw); ELSE (* leave alone; already installed *) END END SetSessPosition; PROCEDUREGetSessFV (sess: ZeusPanelPrivate.Session; arg: REFANY) RAISES {BadSnapshot} = (* LL = VBT.mu *) VAR wr: TextWr.T; BEGIN KeywordCheck(arg, "FV"); IF ISTYPE(arg, RefList.T) AND (RefList.Length(arg) = 2) AND ISTYPE(RefList.Nth(arg, 1), RefList.T) THEN TRY wr := TextWr.New(); Sx.Print(wr, RefList.Nth(arg, 1)); sess.fv.restore(TextRd.New(TextWr.ToText(wr))); EXCEPT | FormsVBT.Mismatch => | Sx.PrintError, FormsVBT.Error => RAISE BadSnapshot("Bad session FV snapshot"); END; ELSE RAISE BadSnapshot("Bad session FV snapshot"); END; END GetSessFV; PROCEDUREGetAlg (sess: ZeusPanelPrivate.Session; arg: REFANY; new := TRUE) RAISES {BadSnapshot, Thread.Alerted, ZeusClass.Error} = (* LL = VBT.mu *) (* IF new THEN create a new alg object, ELSE re-use the old one. *) VAR list, l: RefList.T; wr: TextWr.T; BEGIN IF (arg # NIL) AND ISTYPE(arg, RefList.T) THEN list := arg; ELSE RAISE BadSnapshot("Bad alg snapshot"); END; l := RefListUtils.Pop(list); IF (NOT ISTYPE(l, RefList.T)) OR (RefList.Length(l) # 2) THEN RAISE BadSnapshot("Bad alg snapshot"); END; KeywordCheck(l, "Alg"); TYPECASE l.tail.head OF | TEXT (text) => TRY EVAL Classes.FindAlg(text); EXCEPT Classes.NotFound => IF Text.Equal(text, "NIL") THEN RETURN ELSE RAISE BadSnapshot("Invalid alg name"); END; END; IF new THEN ZeusPanelPrivate.PickedAlg(sess, text); END; TRY wr := TextWr.New(); Sx.Print(wr, list.head); sess.alg.restore(TextRd.New(TextWr.ToText(wr))); EXCEPT Sx.PrintError => RAISE BadSnapshot("GetAlg error") END; ELSE RAISE BadSnapshot("Alg named not a string"); END; END GetAlg; PROCEDUREGetViews (sess: ZeusPanelPrivate.Session; arg: REFANY) RAISES {BadSnapshot, ZeusClass.Error} = (* LL = VBT.mu *) VAR list: RefList.T; BEGIN IF NOT ISTYPE(arg, RefList.T) THEN RAISE BadSnapshot("Bad views") END; list := arg; WHILE list # NIL DO GetView(sess, RefListUtils.Pop(list)); END; END GetViews; PROCEDUREGetView (sess: ZeusPanelPrivate.Session; arg: REFANY) RAISES {BadSnapshot, ZeusClass.Error} = (* LL = VBT.mu *) VAR list, l: RefList.T; view : View.T; discard: TEXT; wr: TextWr.T; BEGIN IF (arg = NIL) OR (NOT ISTYPE(arg, RefList.T)) THEN RAISE BadSnapshot("Bad view snapshot") END; list := arg; l := RefListUtils.Pop(list); IF (NOT ISTYPE(l, RefList.T)) OR (RefList.Length(l) # 2) THEN RAISE BadSnapshot("Bad view snapshot"); END; KeywordCheck(l, "View"); TYPECASE l.tail.head OF | TEXT (text) => TRY EVAL Classes.FindView(text); EXCEPT Classes.NotFound => IF NOT ZeusPanelPrivate.IsCodeView(text, sess, discard) THEN RETURN; (* Be more forgiving; ignore invalid view names, to allow code views that don't belong to the current algorithm. *) (* RAISE BadSnapshot("Invalid view name");*) END; END; view := ZeusPanelPrivate.PickedView(sess, text); TRY wr := TextWr.New(); Sx.Print(wr, list.head); view.restore(TextRd.New(TextWr.ToText(wr))); EXCEPT Sx.PrintError => RAISE BadSnapshot("GetView error") END; ELSE RAISE BadSnapshot("View named not a string"); END; END GetView;
Procedures to save and restore panel and algorithm data, ignoring views completely, under the assumption that the sessions at the time of snapshot can be mapped to those in panel.sessions at the time of restoration, in the same order.
PROCEDURE********** Utilities **********GrabDataList (panel: ZeusPanelPrivate.T): REFANY = <* LL = VBT.mu *> VAR l := panel.sessions; BEGIN TRY WITH twr = TextWr.New() DO Wr.PutText(twr, "("); panel.fv.snapshot(twr); WHILE l # NIL DO WITH sess = NARROW(RefListUtils.Pop(l), ZeusPanelPrivate.Session) DO Wr.PutText(twr, "("); Wr.PutText(twr, "(Session \"" & sess.name & "\")\n"); Wr.PutText(twr, "(FV "); sess.fv.snapshot(twr); Wr.PutText(twr, ")\n"); AlgToWr(twr, sess.alg); Wr.PutText(twr, ")\n"); END; END; Wr.PutText(twr, ")\n"); RETURN Sx.Read(TextRd.New(TextWr.ToText(twr))); END; EXCEPT | ZeusClass.Error, Rd.EndOfFile, Sx.ReadError => ZeusPanel.ReportError("Trouble writing data snapshot"); RETURN NIL; END; END GrabDataList; PROCEDURERestoreData (panel: ZeusPanelPrivate.T; list: RefList.T) = <* LL = VBT.mu *> VAR l, sesslist: RefList.T; sess: ZeusPanelPrivate.Session; wr: TextWr.T; BEGIN TRY IF (list # NIL) AND ISTYPE(list.head, RefList.T) THEN l := RefListUtils.Pop(list); ELSE RAISE BadSnapshot("Bad format (1)"); END; TRY wr := TextWr.New(); Sx.Print(wr, l); panel.fv.restore(TextRd.New(TextWr.ToText(wr))); EXCEPT Sx.PrintError, FormsVBT.Mismatch => RAISE BadSnapshot("Bad format (2)"); END; ZeusPanelPrivate.LoadFromPanel(panel); sesslist := panel.sessions; WHILE (list # NIL) AND (sesslist # NIL) DO sess := RefListUtils.Pop(sesslist); l := RefListUtils.Pop(list); IF ISTYPE(l, RefList.T) THEN WHILE l # NIL DO WITH lfirst = RefListUtils.Pop(l) DO IF (lfirst # NIL) AND ISTYPE(lfirst, RefList.T) THEN TYPECASE NARROW(lfirst, RefList.T).head OF | Atom.T (sxs) => IF Text.Equal(Atom.ToText(sxs), "Session") THEN IF NOT Text.Equal(RefList.Nth(lfirst, 1), sess.name) THEN RAISE BadSnapshot("Session name mismatch"); END; ELSIF Text.Equal(Atom.ToText(sxs), "FV") THEN GetSessFV(sess, lfirst); ELSE RAISE BadSnapshot("Unknown keyword"); END; | RefList.T (ll) => IF ISTYPE(ll.head, Atom.T) THEN GetAlg(sess, lfirst, FALSE); ELSE RAISE BadSnapshot("Bad format (3)"); END; ELSE RAISE BadSnapshot("Bad format (4)"); END (* TYPECASE *); ELSE RAISE BadSnapshot("Bad format (5)"); END; END (* WITH *); END (* WHILE *); (* for each session sublist *) ELSE RAISE BadSnapshot("Bad format (6)"); END; END (* WHILE *); (* for each session *) IF (list # NIL) OR (sesslist # NIL) THEN RAISE BadSnapshot("Wrong number of sessions"); END; EXCEPT BadSnapshot(msg) => ZeusPanel.ReportError("Data snapshot error: " & msg); ELSE ZeusPanel.ReportError("Data snapshot error"); END (* TRY *); END RestoreData;
PROCEDURE**************** Mainline ****************KeywordCheck (arg: REFANY; t: TEXT) RAISES {BadSnapshot} = (* LL = arbitrary *) BEGIN TRY ZeusUtil.KeywordCheck(arg, t); EXCEPT ZeusUtil.BadSnapshot (msg) => RAISE BadSnapshot(msg); END; END KeywordCheck; PROCEDUREStateDirFile (file: TEXT): Pathname.T = <* LL = arbitrary *> <* FATAL Pathname.Invalid *> VAR home := Env.Get (HomeDir); BEGIN IF home = NIL THEN home := OSConfig.UserHome(); IF home = NIL THEN Wr.PutText (Stdio.stderr, "Error: the HOME environment variable is undefined.\n"); Wr.PutText (Stdio.stderr, "Please set it to the path of your home directory and try again.\n"); Process.Exit (0); END; END; WITH path = Pathname.Decompose (home) DO path.addhi(StateDir); MakeStateDir(Pathname.Compose(path)); path.addhi(file); RETURN Pathname.Compose(path) END; END StateDirFile; PROCEDUREMakeStateDir (path: Pathname.T) = <* LL = arbitrary *> VAR status: File.Status; exists: BOOLEAN := TRUE; BEGIN TRY TRY status := FS.Status(path) EXCEPT OSError.E => exists := FALSE; END; IF NOT exists OR NOT status.type = FS.DirectoryFileType THEN IF exists AND status.type = RegularFile.FileType THEN FS.DeleteFile(path) END; FS.CreateDirectory(path); END; EXCEPT | OSError.E => ZeusPanel.ReportError("Can't create " & path); END; END MakeStateDir;
BEGIN END ZeusSnapshot.