DIRECTORY Feedback, FeedbackClasses, IO, MessageWindow, Rope, TEditDocument, TEditInput, TEditInputExtras, TEditInputOps, TEditSelection, TextEdit, TextLooks, TextNode, ThisMachine, Tioga, TiogaRopes, UnixErrno, UnixSysCallExtensions, UnixSysCalls, UXIO, UXStrings, ViewerClasses; TiogaUnixFilter: CEDAR MONITOR IMPORTS Feedback, FeedbackClasses, IO, MessageWindow, Rope, TEditInput, TEditInputExtras, TEditInputOps, TEditSelection, TextEdit, TextNode, ThisMachine, TiogaRopes, UnixErrno, UnixSysCallExtensions, UnixSysCalls, UXIO, UXStrings ={ ROPE: TYPE ~ Rope.ROPE; router: Feedback.MsgRouter ¬ Feedback.EnsureRouter[$TiogaUnixFilter]; routerStream: IO.STREAM ¬ FeedbackClasses.CreateStreamOnRouter[router, $stderr]; GrainFudge: ARRAY TEditDocument.SelectionGrain OF INT ~ [ point: 0, char: 1, word: 1, node: 0, branch: 0]; UnixFilter: PROC [data: REF ANY, viewer: ViewerClasses.Viewer ¬ NIL, param: REF ¬ NIL] RETURNS [recordAtom: BOOL ¬ TRUE, quit: BOOL ¬ FALSE] --TEditInputExtras.CommandClosureProc-- ~ { filterCmd: ROPE ¬ NIL; Doit: PROC [root: Tioga.Node, tSel: TEditInputOps.Selection] ~ { start: Tioga.Location ~ [tSel.start.pos.node, IF tSel.start.pos.where=Tioga.NodeItself THEN 0 ELSE MIN[tSel.start.pos.where, TextNode.EndPos[tSel.start.pos.node]]]; end: Tioga.Location ~ [tSel.end.pos.node, IF tSel.end.pos.where=Tioga.NodeItself THEN TextNode.EndPos[tSel.end.pos.node] ELSE MIN[tSel.end.pos.where, TextNode.EndPos[tSel.end.pos.node]]]; len: INT ~ TextNode.LocOffset[start, end, 1, TRUE] + GrainFudge[tSel.granularity]; orgR: ROPE ~ TiogaRopes.RopeFromTioga[node: start.node, start: start.where, length: len, skipCommentNode: FALSE]; orgFN: ROPE ~ NewName["old"]; newFN: ROPE ~ NewName["new"]; errFN: ROPE ~ NewName["err"]; fullCmd: ROPE ~ filterCmd; SetContents[orgFN, orgR ! UXIO.Error => { Feedback.PutFL[router, oneLiner, $Error, "UXIO.Error[%g, %g] writing old contents", LIST[ [atom[error.code]], [rope[error.explanation]] ]]; GOTO GiveUp}; IO.Error => { Feedback.PutFL[router, oneLiner, $Error, "IO.Error[%g, %g (%g)] writing old contents", LIST[ [atom[IO.AtomFromErrorCode[ec]]], [rope[msg]], [refAny[details]] ]]; GOTO GiveUp}; ]; {ENABLE UNWIND => Delete[orgFN]; Delete[newFN]; {res: INT ~ UnixSysCallExtensions.Spawn[ cmd: UXStrings.Create[fullCmd], stdin: UXStrings.Create[orgFN], stdout: UXStrings.Create[newFN], stderr: UXStrings.Create[errFN] ]; errno: UnixErrno.Errno ~ UnixErrno.GetErrno[]; {ENABLE UNWIND => {Delete[newFN]; Delete[errFN]}; errR: ROPE; IF res#0 THEN { Feedback.PutFL[router, oneLiner, $Error, "UnixFilter op (%g) failed, res=%g, errno=%g.", LIST[ [rope[fullCmd]], [integer[res]], [integer[errno.ORD]] ]]; } ELSE { errR: ROPE ~ GetContents[errFN]; newR: ROPE ~ GetContents[newFN]; p1, p2: Tioga.Location; looks: TextLooks.Looks; IF newR=NIL THEN { Feedback.Append[router, oneLiner, $Error, "no results written"]; GOTO GiveUp}; TEditInputOps.Delete[saveForPaste: FALSE]; p1 ¬ p2 ¬ TEditSelection.InsertionPoint[TEditSelection.pSel]; looks ¬ tSel.looks; TEditSelection.Deselect[primary]; p2.where ¬ p1.where + TextEdit.ReplaceByRope[root: root, dest: p1.node, start: p1.where, len: 0, rope: newR, looks: looks, charSet: 0, charProps: NIL, event: TEditInput.currentEvent].resultLen; IF p2.where#p1.where THEN { tSel.start.pos ¬ p1; tSel.end.pos ¬ [p2.node, p2.where-1]; tSel.granularity ¬ char; tSel.pendingDelete ¬ FALSE; TEditSelection.MakeSelection[tSel, primary]; Feedback.Append[router, oneLiner, $FYI, "Done"]; } ELSE Feedback.Append[router, oneLiner, $FYI, "Empty result"]; IF errR.Length[]>0 THEN routerStream.PutF1["error: \"%q\"", [rope[errR]] ]; }; }}}--enables--; Delete[orgFN]; Delete[newFN]; Delete[errFN]; RETURN; EXITS GiveUp => quit ¬ TRUE; }; IF param#NIL THEN WITH param SELECT FROM x: ROPE => filterCmd ¬ x; ENDCASE => NULL; IF filterCmd=NIL THEN { MessageWindow.Append["Bogus PARAM", TRUE]; MessageWindow.Blink[]; RETURN [quit: TRUE]}; TEditInputOps.CallWithLocks[Doit]; RETURN [quit: TRUE]}; UnixFileFilter: PROC [data: REF ANY, viewer: ViewerClasses.Viewer ¬ NIL, param: REF ¬ NIL] RETURNS [recordAtom: BOOL ¬ TRUE, quit: BOOL ¬ FALSE] --TEditInputExtras.CommandClosureProc-- ~ { filterCmd: ROPE ¬ NIL; Doit: PROC [root: Tioga.Node, tSel: TEditInputOps.Selection] ~ { start: Tioga.Location ~ [tSel.start.pos.node, IF tSel.start.pos.where=Tioga.NodeItself THEN 0 ELSE MIN[tSel.start.pos.where, TextNode.EndPos[tSel.start.pos.node]]]; end: Tioga.Location ~ [tSel.end.pos.node, IF tSel.end.pos.where=Tioga.NodeItself THEN TextNode.EndPos[tSel.end.pos.node] ELSE MIN[tSel.end.pos.where, TextNode.EndPos[tSel.end.pos.node]]]; len: INT ~ TextNode.LocOffset[start, end, 1, TRUE] + GrainFudge[tSel.granularity]; orgR: ROPE ~ TiogaRopes.RopeFromTioga[node: start.node, start: start.where, length: len, skipCommentNode: FALSE]; orgFN: ROPE ~ NewName["old"]; newFN: ROPE ~ NewName["new"]; outFN: ROPE ~ NewName["out"]; errFN: ROPE ~ NewName["err"]; fullCmd: ROPE ~ Replace[filterCmd, orgFN, newFN]; SetContents[orgFN, orgR ! UXIO.Error => { Feedback.PutFL[router, oneLiner, $Error, "UXIO.Error[%g, %g] writing old contents", LIST[ [atom[error.code]], [rope[error.explanation]] ]]; GOTO GiveUp}; IO.Error => { Feedback.PutFL[router, oneLiner, $Error, "IO.Error[%g, %g (%g)] writing old contents", LIST[ [atom[IO.AtomFromErrorCode[ec]]], [rope[msg]], [refAny[details]] ]]; GOTO GiveUp}; ]; {ENABLE UNWIND => Delete[orgFN]; Delete[newFN]; {res: INT ~ UnixSysCallExtensions.Spawn[ cmd: UXStrings.Create[fullCmd], stdin: UXStrings.Create["/dev/null"], stdout: UXStrings.Create[outFN], stderr: UXStrings.Create[errFN] ]; errno: UnixErrno.Errno ~ UnixErrno.GetErrno[]; {ENABLE UNWIND => {Delete[outFN]; Delete[errFN]}; errR: ROPE; IF res#0 THEN { Feedback.PutFL[router, oneLiner, $Error, "UnixFilter op (%g) failed, res=%g, errno=%g.", LIST[ [rope[fullCmd]], [integer[res]], [integer[errno.ORD]] ]]; } ELSE { errR: ROPE ~ GetContents[errFN]; outR: ROPE ~ GetContents[outFN]; newR: ROPE ~ GetContents[newFN]; p1, p2: Tioga.Location; looks: TextLooks.Looks; IF newR=NIL THEN { Feedback.Append[router, oneLiner, $Error, "no results written"]; GOTO GiveUp}; TEditInputOps.Delete[saveForPaste: FALSE]; p1 ¬ p2 ¬ TEditSelection.InsertionPoint[TEditSelection.pSel]; looks ¬ tSel.looks; TEditSelection.Deselect[primary]; p2.where ¬ p1.where + TextEdit.ReplaceByRope[root: root, dest: p1.node, start: p1.where, len: 0, rope: newR, looks: looks, charSet: 0, charProps: NIL, event: TEditInput.currentEvent].resultLen; IF p2.where#p1.where THEN { tSel.start.pos ¬ p1; tSel.end.pos ¬ [p2.node, p2.where-1]; tSel.granularity ¬ char; tSel.pendingDelete ¬ FALSE; TEditSelection.MakeSelection[tSel, primary]; Feedback.Append[router, oneLiner, $FYI, "Done"]; } ELSE Feedback.Append[router, oneLiner, $FYI, "Empty result"]; IF outR.Length[]>0 THEN routerStream.PutF1["output: \"%q\"", [rope[outR]] ]; IF errR.Length[]>0 THEN routerStream.PutF1["error: \"%q\"", [rope[errR]] ]; }; }}}--enables--; Delete[orgFN]; Delete[newFN]; Delete[outFN]; Delete[errFN]; RETURN; EXITS GiveUp => quit ¬ TRUE; }; IF param#NIL THEN WITH param SELECT FROM x: ROPE => filterCmd ¬ x; ENDCASE => NULL; IF filterCmd=NIL THEN { MessageWindow.Append["Bogus PARAM", TRUE]; MessageWindow.Blink[]; RETURN [quit: TRUE]}; TEditInputOps.CallWithLocks[Doit]; RETURN [quit: TRUE]}; processorID: ROPE ~ ThisMachine.ProcessorID[$Hex]; uid: INT ¬ 0; NewName: ENTRY PROC [var: ROPE] RETURNS [ROPE] ~ { ENABLE UNWIND => NULL; processID: INT ~ UnixSysCalls.GetPID[]; uid ¬ uid+1; RETURN IO.PutFLR[".unix-filter-temp-%g-%g-%g-%g", LIST[ [rope[var]], [rope[processorID]], [integer[processID]], [integer[uid]] ]]}; SetContents: PROC [fn, r: ROPE] ~ { s: IO.STREAM ~ UXIO.CreateFileStream[fn, write]; s.PutRope[r]; s.Close[]; RETURN}; GetContents: PROC [fn: ROPE] RETURNS [r: ROPE] ~ { s: IO.STREAM ¬ NIL; s ¬ UXIO.CreateFileStream[fn, read !UXIO.Error, IO.Error => CONTINUE]; IF s=NIL THEN RETURN [NIL]; r ¬ IO.GetRope[s]; IO.Close[s]; RETURN}; Delete: PROCEDURE [fn: ROPE] ~ { UXIO.Delete[fn !UXIO.Error => CONTINUE]; RETURN}; Replace: PROC [r, fn1, fn2: ROPE] RETURNS [ROPE] ~ { i: INT ¬ 0; l: INT ¬ r.Length[]; WHILE i {repl: ROPE ~ IF c='1 THEN fn1 ELSE fn2; r ¬ Rope.Replace[r, i, 2, repl]; i ¬ i+repl.Length[]; l ¬ r.Length[]}; '$ => l ¬ (r ¬ Rope.Replace[r, i, 1, NIL]).Length[]; ENDCASE => i ¬ i+1; ENDLOOP; RETURN [r]}; TEditInputExtras.RegisterClosure[[$UnixFilter, UnixFilter, NIL]]; TEditInputExtras.RegisterClosure[[$UnixFileFilter, UnixFileFilter, NIL]]; }. – TiogaUnixFilter.mesa Copyright Σ 1993 by Xerox Corporation. All rights reserved. Last tweaked by Mike Spreitzer February 1, 1993 1:15 pm PST ΚΜ•NewlineDelimiter ™code™Kšœ Οeœ1™˜€Kš œ*žœ%žœ$žœžœ:˜»Kšœžœ%žœ!˜RKšœžœ`žœ˜qKšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ ˜˜šžœ ˜KšœTžœ3˜‹Kšžœ ˜ —šžœ ˜ KšœWžœžœ<˜‘Kšžœ ˜ —K˜—Kšœžœžœ˜ K˜šœžœ˜(K˜K˜K˜ K˜"—K˜.Kšœžœžœ#˜1Kšœžœ˜ šžœžœ˜KšœYžœ2žœ˜˜K˜—šžœ˜Kšœžœ˜ Kšœžœ˜ K˜K˜šžœžœžœ˜K˜@Kšžœ ˜ —Kšœ#žœ˜*K˜=K˜K˜!Kšœ”žœ-˜Δšžœžœ˜K˜K˜%K˜Kšœžœ˜K˜,K˜0K˜—Kšžœ9˜=Kšžœžœ4˜KK˜—Kšœ  œ˜K˜K˜K˜Kšžœ˜Kšžœžœ˜K˜—š žœžœžœžœžœž˜(Kšœžœ˜Kšžœžœ˜—šžœ žœžœ˜Kšœ$žœ˜*K˜Kšžœžœ˜—K˜"Kšžœžœ˜—K˜šŸœžœžœžœ!žœ žœžœžœžœžœžœžœ 'œ˜ΌKšœ žœžœ˜šŸœžœ6˜@Kš œ.žœ'žœžœžœ>˜€Kš œ*žœ%žœ$žœžœ:˜»Kšœžœ%žœ!˜RKšœžœ`žœ˜qKšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ$˜1˜šžœ ˜KšœTžœ3˜‹Kšžœ ˜ —šžœ ˜ KšœWžœžœ<˜‘Kšžœ ˜ —K˜—Kšœžœžœ˜ K˜šœžœ˜(K˜K˜%K˜ K˜"—K˜.Kšœžœžœ#˜1Kšœžœ˜ šžœžœ˜KšœYžœ2žœ˜˜K˜—šžœ˜Kšœžœ˜ Kšœžœ˜ Kšœžœ˜ K˜K˜šžœžœžœ˜K˜@Kšžœ ˜ —Kšœ#žœ˜*K˜=K˜K˜!Kšœ”žœ-˜Δšžœžœ˜K˜K˜%K˜Kšœžœ˜K˜,K˜0K˜—Kšžœ9˜=Kšžœžœ5˜LKšžœžœ4˜KK˜—Kšœ  œ˜K˜K˜K˜K˜Kšžœ˜Kšžœžœ˜K˜—š žœžœžœžœžœž˜(Kšœžœ˜Kšžœžœ˜—šžœ žœžœ˜Kšœ$žœ˜*K˜Kšžœžœ˜—K˜"Kšžœžœ˜—K˜Kšœ žœ!˜2Kšœžœ˜ K˜š Ÿœž œžœžœžœ˜2Kšžœžœžœ˜Kšœ žœ˜'K˜ Kšžœžœ)žœM˜ƒ—K˜šŸ œžœ žœ˜#Kšœžœžœžœ˜0K˜ K˜ Kšžœ˜—K˜š Ÿ œžœžœžœžœ˜2Kšœžœžœžœ˜Kš œžœžœžœ žœ˜FKš žœžœžœžœžœ˜Kšœžœ ˜Kšžœ ˜ Kšžœ˜—K˜šŸœž œžœ˜ Kšžœ žœ žœ˜(Kšžœ˜—K˜š Ÿœžœžœžœžœ˜4Kšœžœ˜ Kšœžœ˜šžœž˜ Kšœžœ˜Kšžœžœžœ˜šžœžœž˜#š œžœžœžœžœ˜2K˜ K˜K˜—Kšœ%žœ ˜4Kšžœ ˜—Kšžœ˜—Kšžœ˜ —K˜Kšœ;žœ˜AKšœCžœ˜IK˜—…—!Š*μ