DIRECTORY Commander USING [CommandProc, Register], IO USING [int, Put, PutChar, PutRope, rope, STREAM], Rope USING [Cat, Concat, Equal, Fetch, Find, Index, ROPE, Size, SkipOver, SkipTo, Substr], RopeIO USING [FromFile], TiogaFileOps USING [CreateRoot, InsertAsLastChild, Ref, SetContents, SetFormat, SetStyle, Store], UserCredentials USING [GetUserCredentials]; WalnutToPeanut: CEDAR PROGRAM IMPORTS Commander, IO, Rope, RopeIO, TiogaFileOps, UserCredentials = BEGIN ROPE: TYPE = Rope.ROPE; Node: TYPE = TiogaFileOps.Ref; File: TYPE = REF FileRep; FileRep: TYPE = RECORD[ link: File, -- for fileList name: ROPE, -- category name ("Active") filename: ROPE, -- file name ("Active.mail") root: Node, -- root node last: Node -- last top-level node ]; Message: TYPE = REF MessageRep; MessageRep: TYPE = RECORD[ sender: ROPE, date: ROPE, categories: ROPE, contents: ROPE ]; simpleUserName, userRName: ROPE _ NIL; InitUserName: PROC = { uN: ROPE = UserCredentials.GetUserCredentials[].name; pos: INT = Rope.Find[uN, "."]; IF pos<0 THEN { simpleUserName _ uN; userRName _ Rope.Concat[uN, ".PA"] } ELSE { simpleUserName _ Rope.Substr[uN, 0, pos]; userRName _ uN }; }; fileList: File _ NIL; CreateFile: PROC[name: ROPE] RETURNS[File] = { file: File = NEW[FileRep]; file.name _ name; file.filename _ Rope.Concat[name, ".mail"]; file.root _ TiogaFileOps.CreateRoot[]; TiogaFileOps.SetStyle[file.root, "Mail"]; file.last _ TiogaFileOps.InsertAsLastChild[file.root]; TiogaFileOps.SetContents[file.last, file.filename]; file.link _ fileList; fileList _ file; RETURN[file]; }; GetFile: PROC[name: ROPE] RETURNS[File] = { FOR file: File _ fileList, file.link UNTIL file=NIL DO IF Rope.Equal[file.name, name, FALSE] THEN RETURN[file]; REPEAT FINISHED => RETURN[CreateFile[name]]; ENDLOOP; }; ParseFailed: ERROR = CODE; ParseMessage: PROC[m: ROPE] RETURNS[Message] = { message: Message = NEW[MessageRep]; index: INT _ 0; Require: PROC[x: ROPE] = { start: INT = index; IF Rope.Find[m, x, start]=start THEN index _ start+Rope.Size[x] ELSE ERROR ParseFailed; }; SkipTo: PROC[x: ROPE] = { start: INT = index; index _ Rope.Find[m, x, start]+Rope.Size[x]; }; ReadTo: PROC[x: ROPE] RETURNS[ROPE] = { start: INT = index; end: INT = Rope.Find[m, x, start]; index _ end+Rope.Size[x]; RETURN[Rope.Substr[m, start, end-start]]; }; ReadN: PROC[n: INT] RETURNS[ROPE] = { start: INT = index; index _ start+n; RETURN[Rope.Substr[m, start, index-start]]; }; Require["*start*\n"]; SkipTo["\n"]; Require["gvMsgID: "]; message.sender _ ReadTo[" $"]; SkipTo["@"]; message.date _ ReadN[9]; SkipTo["\n"]; Require["Categories: "]; message.categories _ ReadTo["\n"]; message.contents _ Rope.Substr[m, index]; RETURN[message]; }; DeleteLeadingSPs: PROC[m: ROPE] RETURNS[ROPE] = { start: INT _ 0; len: INT _ Rope.Size[m]; WHILE start maxLen THEN s _ Rope.Concat[Rope.Substr[s, 0, maxLen-3], "..."]; RETURN[s]; }; GetFieldContents: PROC[m, name: ROPE] RETURNS[contents: ROPE] = { start: INT _ Rope.Find[m, name]; IF start<0 THEN contents _ "?" ELSE { end: INT; start _ start + Rope.Size[name]; end _ Rope.Find[m, "\n", start]; IF end <= start THEN contents _ "?" ELSE contents _ Rope.Substr[m, start, end-start]; }; }; MakeHeader: PROC[message: Message] RETURNS[header: ROPE] = { date, name, subject: ROPE _ NIL; date _ message.date; IF Rope.Equal[message.sender, userRName, FALSE] OR Rope.Equal[message.sender, simpleUserName, FALSE] THEN name _ Rope.Concat["To: ", GetFieldContents[message.contents, "\nTo: "]] ELSE name _ message.sender; subject _ GetFieldContents[message.contents, "\nSubject: "]; header _ Rope.Cat["\t", date, "\t", Truncate[name, 16], "\t", Truncate[subject, 44]]; RETURN[header]; }; AppendMessage: PROC[file: File, message: Message] = { head: Node = TiogaFileOps.InsertAsLastChild[file.root, file.last]; body: Node = TiogaFileOps.InsertAsLastChild[head]; TiogaFileOps.SetContents[head, MakeHeader[message]]; TiogaFileOps.SetFormat[head, "header"]; TiogaFileOps.SetContents[body, DeleteTrailingCRs[message.contents]]; file.last _ head; }; StoreFile: PROC[file: File] = { TiogaFileOps.Store[file.root, file.filename]; file.root _ NIL; file.last _ NIL; }; EnumerateNames: PROC[rope: ROPE, action: PROC[ROPE]] = { length: INT = Rope.Size[rope]; index: INT _ 0; DO start: INT = Rope.SkipOver[rope, index, " "]; IF start CONTINUE]; IF log=NIL THEN { s.PutRope["unable to open file!\n"]; RETURN }; length _ Rope.Size[log]; s.Put[IO.int[length], IO.rope[" bytes\n"]]; start _ Rope.Find[log, "*start*\n"]; IF start<0 THEN { s.PutRope["No messages found!\n"]; RETURN }; s.PutRope["Reading...\n"]; WHILE start GOTO Abort]; count _ count+1; IF count MOD 10=0 THEN { s.PutChar[IF count MOD 100=0 THEN '! ELSE '~]; }; start _ end; ENDLOOP; s.Put[IO.rope["... "], IO.int[count], IO.rope[" messages\n"]]; UNTIL fileList=NIL DO file: File = fileList; fileList _ file.link; s.PutRope["Writing "]; s.PutRope[file.filename]; s.PutRope["..."]; StoreFile[file]; s.PutRope["ok\n"]; ENDLOOP; EXITS Abort => { s.PutRope["... failed!\n"]; s.PutRope["Do an Expunge with Walnut, then try running WalnutToPeanut again.\n"]; fileList _ NIL; }; }; WalnutToPeanutCommand: Commander.CommandProc = { ReadLog["Walnut.DBLog", cmd.out]; }; InitUserName[]; Commander.Register["WalnutToPeanut", WalnutToPeanutCommand, "Create Peanut mail files from a freshly-expunged Walnut log"]; END. WalnutToPeanut.mesa Last edited by Doug Wyatt, April 19, 1983 2:58 pm A message in Walnut.DBLog has the following form: *start* 02203 00112 US gvMsgID: Horning.pa $ 3#203@18-Feb-83 12:37:26 PST Categories: UserExec CedarDiscussion ... message contents ... Κm˜headšœ™Jšœ1™1J˜šΟk ˜ Jšœ œ˜(Jšœœ$œ˜4Jšœœ*œ"˜ZJšœœ ˜Jšœ œO˜aJšœœ˜+——šœœ˜Jšœ œ-˜BJšœ˜J˜Jšœœœ˜J˜Jšœœ˜J˜Jšœœœ ˜šœ œœ˜Jšœ Οc˜Jšœœž˜'Jšœ œž˜,Jšœ ž ˜Jšœ ž˜!J˜—J˜Jšœ œœ ˜šœ œœ˜Jšœœ˜ Jšœœ˜ Jšœ œ˜Jšœ ˜J˜—J˜Jšœœœ˜&J˜šΟn œœ˜Jšœœ-˜5Jšœœ˜Jšœœ<˜IJšœ>˜BJ˜—J˜Jšœœ˜J˜šŸ œœœœ ˜.Jšœ œ ˜J˜Jšœ+˜+J˜&J˜)J˜6J˜3J˜&Jšœ˜ J˜—J˜šŸœœœœ ˜+šœ"œœ˜6Jšœœœœ˜8Jšœœœ˜,Jšœ˜—J˜—J˜JšœΊ™ΊJ™Jšœ œœ˜J˜šŸ œœœœ ˜0Jšœœ ˜#Jšœœ˜šŸœœœ˜Jšœœ ˜Jšœœ˜?Jšœœ ˜J˜—šŸœœœ˜Jšœœ ˜Jšœ,˜,J˜—š Ÿœœœœœ˜'Jšœœ ˜Jšœœ˜"Jšœ˜Jšœ#˜)J˜—š Ÿœœœœœ˜%Jšœœ ˜Jšœ˜Jšœ%˜+J˜—J˜J˜ J˜J˜J˜ J˜J˜ J˜J˜"J˜)Jšœ ˜J˜—J˜š Ÿœœœœœ˜1Jšœœ˜Jšœœ˜Jšœ œœœ˜JJšœ œœ"˜8Jšœœ˜Jšœ˜—J˜š Ÿœœœœœ˜2Jšœœ˜Jšœ œœœ˜EJšœ˜Jšœ˜—J˜š Ÿœœœ œœœ˜9Jšœœ˜!Jšœœ5˜RJšœ˜ J˜—J˜š Ÿœœ œœ œ˜AJšœœ˜ Jšœ œ˜šœ˜Jšœœ˜ J˜ Jšœ ˜ Jšœœ˜#Jšœ-˜1Jšœ˜—Jšœ˜—J˜šŸ œœœ œ˜J˜šœ˜Jšœœ)˜1Jšœ œ&˜3Jšœ'œ˜3J˜šœœœ˜Jš œ œœœœ˜.J˜—J˜ Jšœ˜—Jšœœœ œ˜>šœ œ˜Jšœ˜J˜J˜BJ˜J˜Jšœ˜—šœ ˜Jšœ˜J˜QJšœ œ˜J˜—J˜—J˜šŸœ˜0Jšœ!˜!J˜—J˜J˜J˜šœ;˜;J˜?—J˜Jšœ˜——…—X"Ν