<> <> <> <> <> <> <> <> <> DIRECTORY IO, Rope, Runtime, WalnutDB, WalnutDBLog, WalnutWindow; WalnutFileImpl: CEDAR PROGRAM IMPORTS IO, Rope, Runtime, WalnutDB, WalnutDBLog, WalnutWindow EXPORTS WalnutDBLog = BEGIN OPEN WalnutDBLog; ROPE: TYPE = Rope.ROPE; <<********************************************************>> ReadPrefixInfo: PUBLIC PROC[strm: IO.STREAM, headersPos: INT] RETURNS[msgID: ROPE, categories: ROPE, outOfSynch: BOOL] = BEGIN curPos: INT; outOfSynch_ FALSE; UNTIL (curPos_ strm.GetIndex[]) = headersPos DO tag, value: ROPE; IF curPos > headersPos THEN {outOfSynch_ TRUE; RETURN}; [tag, value]_ TagAndValue[h: strm, inc: 2]; IF Rope.Equal[tag, msgIDRope, FALSE] THEN msgID_ value ELSE IF Rope.Equal[tag, categoriesRope, FALSE] THEN categories_ value; ENDLOOP; END; TagAndValue: PUBLIC PROC[h: IO.Handle, inc: INT] RETURNS[tag, value: ROPE] = BEGIN line: ROPE_ GetLine[h]; pos: INT_ line.Find[":"]; IF pos < 0 THEN RETURN; tag_ line.Substr[0, pos]; value_ line.Substr[pos+inc, Rope.MaxLen ! Runtime.BoundsFault => {tag_ NIL; CONTINUE}]; END; ReadStartOfMsg: PUBLIC PROC[strm: IO.STREAM, doReport: BOOL] RETURNS[startPos, prefixLength, entryLength: INT, entryChar: CHAR] = BEGIN ENABLE IO.EndOfStream => GOTO eoS; line: ROPE; prefixLength_ entryLength_ 0; entryChar_ 'X; -- not a valid entryType char IF strm.EndOf[] THEN RETURN; startPos_ strm.GetIndex[]; line_ GetLine[strm]; IF NOT line.Equal["*start*"] THEN BEGIN foo: INT_ startPos; IF doReport THEN WalnutWindow.Report[ IO.PutFR["**start** not found at pos %g. Skipping to next entry.", IO.int[startPos]]]; UNTIL line.Equal["*start*"] DO IF strm.EndOf[] THEN RETURN; startPos_ strm.GetIndex[]; line_ GetLine[strm] ENDLOOP; END; <> entryLength_ strm.GetInt[]; prefixLength_ strm.GetInt[]; line_ GetLine[strm]; entryChar_ line.Fetch[line.Length[]-1]; EXITS eoS => {entryLength_ -1; RETURN}; END; RopeFromStream: PUBLIC PROC[strm: IO.STREAM, len: INT] RETURNS[ROPE] = <> BEGIN Get1: SAFE PROC RETURNS[CHAR] = CHECKED {RETURN[strm.GetChar[]]}; RETURN[Rope.FromProc[len, Get1]]; END; GetLine: PROC[h: IO.STREAM] RETURNS[r: ROPE] = BEGIN r_ h.GetSequence[]; []_ h.GetChar[ ! IO.EndOfStream => CONTINUE]; -- read the CR END; <<********************************************************>> MakeLogEntry: PUBLIC PROC [ entryType: LogEntryType, entryText: ROPE, strm: IO.STREAM, msgID: ROPE_ NIL] RETURNS [INT] = <> <> <<(1) messages: entryText is the header and body of the message>> <<(2) insertions: entryText is of form (insertion of new relship):>> <> <> <> <> <> <> <<(3) deletions: entryText same form as above, but represents deletion of that relship or entity>> <<(4) hasbeenread: entryText is the messageID>> <> BEGIN OPEN IO; typeChar: CHAR; length: INT_ entryText.Length[]; prefixLen: INT_ minPrefixLength + msgID.Length[]; -- magic number isMessage: BOOL_ (entryType=message) OR (entryType=newMessage); Put1: SAFE PROC[c: CHAR] RETURNS[stop: BOOL] = CHECKED { strm.PutChar[c]; RETURN[FALSE]}; SELECT entryType FROM message => typeChar_ ' ; newMessage => typeChar_ '?; insertion => typeChar_ '+; deletion => typeChar_ '-; hasbeenread => typeChar_ '_; ENDCASE; IF isMessage THEN { IF entryText.Fetch[length-1] # CR THEN { entryText_ Rope.Concat[entryText, "\n"]; length_ length + 1}; }; strm.SetIndex[strm.GetLength[]]; strm.PutF["**start**\n%05d %05d US%g\n", int[prefixLen+length], int[prefixLen], char[typeChar]]; < 77777B>> IF msgID.Length[]#0 THEN strm.PutRope[msgID]; IF entryText.Length[] < 77777B THEN strm.PutRope[entryText] ELSE []_ Rope.Map[base: entryText, action: Put1]; strm.Flush[]; -- flush after every write RETURN[strm.GetIndex[]] END; <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> <> OldMessageFile: PUBLIC PROC[strm: IO.STREAM, defaultPrefix: ROPE] RETURNS [ok: BOOL] = BEGIN ENABLE UNWIND => NULL; DO beginMsgPos, msgLength, entryLength, prefixLength: INT; msgID, msgText, prefix, categories: ROPE; outOfSynch: BOOL_ FALSE; [beginMsgPos, prefixLength, entryLength, ]_ ReadStartOfMsg[strm, TRUE]; IF entryLength = -1 THEN RETURN[FALSE]; IF (entryLength=0) OR (entryLength=prefixLength) THEN EXIT; -- Hardy's null message at end IF IO.PeekChar[strm] = '@ THEN strm.SetIndex[beginMsgPos + prefixLength] -- hardy file ELSE [msgID, categories, outOfSynch]_ ReadPrefixInfo[strm, beginMsgPos+prefixLength]; IF outOfSynch THEN { WalnutWindow.Report["Can't find prefix info; skipping to next entry"]; strm.SetIndex[beginMsgPos + entryLength]; LOOP }; prefix_ IF categories#NIL THEN Rope.Cat[categoriesRope, ": ", categories, "\n"] ELSE defaultPrefix; IF msgID # NIL THEN prefix_ Rope.Cat[msgIDRope, ": ", msgID, "\n", prefix]; msgLength_ entryLength-prefixLength; msgText_ RopeFromStream[strm, msgLength]; WalnutDB.AddMessageToLog[entryText: msgText, prefix: prefix]; WalnutWindow.ReportRope["."]; ENDLOOP; RETURN[TRUE]; END; END.