DIRECTORY EditedStream USING [DeliverWhenProc, IsACR, Rubout, SetDeliverWhen], IO USING [BreakProc, CharsAvail, Close, EndOf, EndOfStream, Error, Flush, GetChar, GetTokenRope, PutF, PutRope, Reset, STREAM], List USING [AList], MBQueue USING [Create, CreateMenuEntry, Queue], Menus USING [InsertMenuEntry, MenuProc], Process USING [Abort, Detach, GetCurrent, InvalidProcess], ProcessProps USING [PushPropList], ReadEvalPrint, Rope USING [ROPE, Concat, Length, Fetch], RuntimeError USING [UNCAUGHT], TypeScript USING [Create], ViewerClasses USING [Viewer, ViewerRec], ViewerEvents USING [EventProc, RegisterEventProc], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AddProp, ComputeColumn, FetchProp]; ReadEvalPrintImpl: CEDAR MONITOR IMPORTS EditedStream, IO, MBQueue, Menus, Process, ProcessProps, Rope, RuntimeError, TypeScript, ViewerEvents, ViewerIO, ViewerOps EXPORTS ReadEvalPrint = BEGIN Handle: TYPE = ReadEvalPrint.Handle; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; CreateViewerEvaluator: PUBLIC PROC [clientProc: ReadEvalPrint.ClientProc, prompt: ROPE _ NIL, info: ViewerClasses.ViewerRec _ [], edited: BOOL _ TRUE, deliverWhen: EditedStream.DeliverWhenProc _ NIL, clientData: REF _ NIL, topLevel: BOOL _ TRUE] RETURNS [h: Handle] = { h _ NEW[ReadEvalPrint.RObject _ []]; h.clientProc _ clientProc; IF deliverWhen = NIL THEN deliverWhen _ EditedStream.IsACR; h.deliverWhenProc _ deliverWhen; h.menuHitQueue _ MBQueue.Create[]; h.prompt _ prompt; h.viewer _ TypeScript.Create[info: info, paint: FALSE]; h.clientData _ clientData; h.topLevel _ topLevel; ViewerOps.AddProp[h.viewer, $ReadEvalPrint, h]; [in: h.in, out: h.out] _ ViewerIO.CreateViewerStreams[name: NIL, viewer: h.viewer, editedStream: edited]; IF edited THEN EditedStream.SetDeliverWhen[h.in, deliverWhen]; Menus.InsertMenuEntry[menu: h.viewer.menu, line: 0, entry: MBQueue.CreateMenuEntry[q: h.menuHitQueue, name: "STOP!", proc: StopHit, clientData: h]]; ViewerOps.ComputeColumn[column: info.column]; }; CreateStreamEvaluator: PUBLIC PROC [clientProc: ReadEvalPrint.ClientProc, prompt: ROPE _ NIL, in, out: STREAM, deliverWhen: EditedStream.DeliverWhenProc _ NIL, clientData: REF _ NIL, topLevel: BOOL _ FALSE] RETURNS [h: Handle] = { h _ NEW[ReadEvalPrint.RObject _ []]; h.clientProc _ clientProc; IF deliverWhen = NIL THEN deliverWhen _ EditedStream.IsACR; h.deliverWhenProc _ deliverWhen; h.prompt _ prompt; h.in _ in; h.out _ out; h.clientData _ clientData; h.topLevel _ topLevel; }; Stop: PUBLIC PROC [h: Handle] = { h.terminateRequested _ TRUE; }; MainLoop: PUBLIC PROC [h: Handle, forkAndDetach: BOOL _ TRUE, properties: List.AList] = { inner: PROC = { MainLoopInternal[h]; }; IF forkAndDetach THEN TRUSTED { Process.Detach[FORK MainLoop[h, FALSE, properties]]; RETURN; }; IF properties # NIL THEN ProcessProps.PushPropList[properties, inner] ELSE inner[]; }; MainLoopInternal: PROC [h: Handle] = { commandLine: ROPE _ NIL; result: ROPE _ NIL; rejectThisOne: BOOL _ FALSE; in: STREAM _ h.in; out: STREAM _ h.out; breakProc: IO.BreakProc = { IF h.deliverWhenProc[char, NIL, in, NIL].activate THEN RETURN[break] ELSE RETURN[other]; }; DoRead: PROC RETURNS [destroyed: BOOL _ FALSE] = { destroyed _ IO.EndOf[in ! RuntimeError.UNCAUGHT => {destroyed _ TRUE; CONTINUE}]; IF NOT destroyed THEN { IO.PutF[out, h.prompt, [rope["b"]], [rope["B"]] ]; IF h.promptProc # NIL THEN h.promptProc[h]; GetLine[ ! IO.EndOfStream => CONTINUE]; }; }; GetLine: PROC = { commandLine _ NIL; commandLine _ IO.GetTokenRope[in, breakProc].token; IF commandLine.Length[] # 0 THEN IF NOT h.deliverWhenProc[commandLine.Fetch[0], NIL, in, NIL].activate THEN commandLine _ Rope.Concat[commandLine, IO.GetTokenRope[in, breakProc].token]; }; TRUSTED {h.mainLoopProcess _ LOOPHOLE[Process.GetCurrent[], SAFE PROCESS]}; UNTIL h.terminateRequested DO aborted: BOOL _ FALSE; syntaxError: BOOL _ FALSE; rubout: BOOL _ FALSE; in _ h.in; out _ h.out; IF in = NIL OR out = NIL THEN RETURN; IF DoRead[ ! ABORTED => {aborted _ TRUE; CONTINUE}; IO.Error => { IF ec = StreamClosed THEN EXIT; IF h.viewer = NIL OR h.viewer.destroyed THEN EXIT; IF ec = SyntaxError THEN {syntaxError _ TRUE; CONTINUE}; }; IO.EndOfStream => { IF h.viewer = NIL OR h.viewer.destroyed THEN EXIT; IF stream = in THEN EXIT; }; EditedStream.Rubout => {rubout _ TRUE; CONTINUE}; ] THEN EXIT; { ENABLE ABORTED => {aborted _ TRUE; GO TO out}; SELECT TRUE FROM rubout => { ENABLE RuntimeError.UNCAUGHT => GO TO out; IF h.ruboutProc # NIL THEN h.ruboutProc[h] ELSE { msg: ROPE _ " -- \n"; IF h.readIOSignalRope # NIL THEN msg _ h.readIOSignalRope; EatIt[in]; IO.PutRope[out, msg]; }; }; syntaxError => { ENABLE RuntimeError.UNCAUGHT => GO TO out; EatIt[in]; IO.PutRope[out, " -- Syntax error!\n"]; }; commandLine # NIL AND NOT aborted => { result _ h.clientProc[h, commandLine]; IF result # NIL THEN { IO.PutF[out, result]; result _ NIL; IO.PutRope[out, "\n"]; }; }; ENDCASE => {}; EXITS out => {}; }; IF aborted THEN { msg: ROPE _ " -- Aborted.\n"; IF h.evalABORTEDRope # NIL THEN msg _ h.evalABORTEDRope; IO.PutRope[out, msg ! RuntimeError.UNCAUGHT => CONTINUE]; IO.Flush[out ! RuntimeError.UNCAUGHT => CONTINUE]; EatIt[in ! ABORTED => CONTINUE]; IF NOT h.topLevel THEN { IF in # NIL THEN IO.Close[in ! RuntimeError.UNCAUGHT => CONTINUE; IO.Error => CONTINUE]; EXIT; }; }; ENDLOOP; }; StopHit: Menus.MenuProc = TRUSTED { h: Handle _ NARROW[clientData, Handle]; Process.Abort[h.mainLoopProcess ! Process.InvalidProcess => CONTINUE]; }; EatIt: PROC [st: STREAM] = { IF st # NIL THEN { ENABLE { IO.Error => GO TO done; IO.EndOfStream => GO TO done; RuntimeError.UNCAUGHT => GO TO done}; IO.Reset[st]; WHILE IO.CharsAvail[st] > 0 DO [] _ IO.GetChar[st]; IO.Reset[st]; ENDLOOP; EXITS done => {}; }; }; ViewerEvent: ViewerEvents.EventProc = TRUSTED { SELECT event FROM destroy => { prop: REF _ ViewerOps.FetchProp[viewer, $ReadEvalPrint]; IF prop # NIL THEN { Stop[NARROW[prop, Handle]]; }; }; ENDCASE; }; Init: PROC = { [] _ ViewerEvents.RegisterEventProc[proc: ViewerEvent, event: destroy, filter: $Typescript]; }; Init[]; END. bReadEvalPrintImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Original version by P. Rovner March 30, 1983 3:34 pm Russ Atkinson (RRA) November 26, 1985 12:49:08 pm PST This eventually makes the process associated with the handle terminate. We can be recursive here, since at the next level we do not recurse. Stuff the given properties on the current process. Get a command line. NIL out the command line even if we get an error Just in case the user alters these with intent. Try to read a `line' for the user. We try very hard to protect against errors, and to report the non-fatal ones. It is always fatal for the input stream to not be readable, for example. It is fatal to be aborted if not at topLevel. Rubouts should never be fatal. Here we handle the actual work of the world, as well as rubout and syntaxError reporting. We try to guard against errors when dealing with rubout and syntaxError reporting, but the user must not be overly protected against anything except ABORTED. We use PutF to handle % codes registered by the client. Implementation private procedures [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] This little helper routine eats all characters from an input stream until there are no more available. If the stream is NIL or any IO error occurs, then we just exit. Initialization Κ Ÿ˜™Jšœ Οmœ1™Kšœ”˜”Kšœ-˜-K˜—J™šŸœžœžœ0žœžœ žœ.žœžœžœ žœžœžœ˜ζKšœžœ˜$Kšœ˜Kšžœžœžœ"˜;Kšœ ˜ K˜K˜ K˜ Kšœ˜K˜K˜—J˜šŸœžœžœ˜!KšœG™GKšœžœ˜K˜—J˜š Ÿœžœžœžœžœ˜YKšœžœ˜'šžœžœžœ˜KšœD™DKšœžœ žœ˜4Kšžœ˜Kšœ˜—Kšœ2™2Kšžœžœžœ-žœ ˜SK˜—J˜šŸœžœ˜&Kšœ žœžœ˜Kšœžœžœ˜Kšœžœžœ˜Kšœžœ˜Kšœžœ ˜K˜šœ žœ˜šžœžœžœ ˜1Kšžœžœžœžœ˜&—Kšœ˜K˜—š Ÿœžœžœ žœžœ˜2Kš œ žœžœžœžœ˜Qšžœžœ žœ˜Kšžœ0˜2Kšžœžœžœ˜+Kšœ žœžœ˜'K˜—K˜K˜—šŸœžœ˜Kšœ™šœžœ˜Kšœ0™0—Kšœžœ#˜3šžœž˜ š žœžœ)žœžœ ž˜JKšœ'žœ$˜M——K˜—K˜Kšžœžœžœžœ˜KK˜šžœž˜K˜Kšœ žœžœ˜Kšœ žœžœ˜Kšœžœžœ˜K˜Kšœ/™/Kšœ ˜ Kšœ ˜ Kš žœžœžœžœžœžœ˜%K˜KšœŠ™Ššžœ ˜ Kšžœžœžœ˜&šžœ ˜ Kšžœžœžœ˜Kš žœ žœžœžœžœ˜2Kšžœžœžœžœ˜8K˜—šžœ˜Kš žœ žœžœžœžœ˜2Kšžœ žœžœ˜K˜—Kšœ!žœžœ˜1Kšœžœžœ˜ K˜—˜Kšœπžœ™ψKš žœžœžœžœžœ˜.šžœžœž˜šœ ˜ Kšžœžœžœžœ˜*šžœž˜Kšžœ˜šžœ˜Kšœžœ˜Kšžœžœžœ˜;Kšœ ˜ Kšžœ˜K˜——K˜—šœ˜Kšžœžœžœžœ˜*Kšœ ˜ Kšžœ&˜(K˜—šœžœžœžœ ˜&Kšœ&˜&šžœ žœžœ˜šžœ˜Kšœ7™7—Kšœ žœ˜ Kšžœ˜K˜—K˜—Kšžœ˜—Kšžœ ˜K˜—K˜šžœ žœ˜Kšœžœ˜Kšžœžœžœ˜8Kšžœ!žœžœ˜9Kšžœžœžœ˜2Kšœ žœžœ˜ šžœžœ žœ˜šžœžœžœžœ ˜Kš œžœžœžœ žœ˜;—Kšžœ˜K˜—Kšœ˜—K˜Kšžœ˜—K˜Kšœ˜—K˜™!K™šΟbœžœ˜#KšœN™NKšœ žœ˜'Kšœ<žœ˜FKšœ˜—K˜šŸœžœžœ˜Kšœyžœžœ!™§šžœžœžœ˜šžœ˜Kšžœ žœžœ˜Kšžœžœžœ˜Kšœ žœžœžœ˜%—Kšžœ ˜ šžœžœž˜Kšœžœ ˜Kšžœ ˜ Kšžœ˜—Kšžœ ˜Kšœ˜—K˜K˜—š  œžœ˜/šžœž˜šœ ˜ Kšœžœ/˜8šžœžœžœ˜Kšœžœ˜K˜—Kšœ˜—Kšžœ˜—Kšœ˜—K™šŸœžœ˜Kšœ\˜\K˜J˜——™J˜—J˜Jšžœ˜—…—Ύ&Ώ