<> <> <> <> <<>> DIRECTORY Ascii, ComputeClientInternal, ComputeServerDebugger, ComputeServerDebuggerRpcControl, EditedStream, FileViewerOps, IO, MBQueue, Menus, Process, PupDefs, PupErrors, PupStream, Rope, RPC, UserCredentials, ViewerIO, ViewerOps, ViewerClasses, VM; ComputeClientDebuggingImpl: CEDAR MONITOR IMPORTS ComputeClientInternal, ComputeServerDebuggerRpcControl, EditedStream, FileViewerOps, IO, MBQueue, Menus, Process, PupErrors, PupStream, Rope, RPC, --TiogaOps,-- UserCredentials, ViewerIO, ViewerOps EXPORTS ComputeServerDebugger = BEGIN <> ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; debuggerStreamState: TYPE = {normal, sawCR, sawAmper, sawDigit, sawFirstSpace, sawBackArrow, stuffable}; debugItem: TYPE = REF debugObject; debugObject: TYPE = RECORD [ alive: BOOL _ TRUE, menuHitQueue: MBQueue.Queue _ MBQueue.Create[], viewer: ViewerClasses.Viewer _ NIL, state: debuggerStreamState _ normal, viewerInStream: STREAM, viewerOutStream: STREAM, inOutPupStream: STREAM ]; <> OpenDebugStream: PUBLIC PROC [listenerPupAddress: PupDefs.PupAddress, newListenerPupAddress: PupDefs.PupAddress, name: ROPE, serverMachine: ROPE] RETURNS [byteStreamOK: BOOL _ TRUE] = { inOutPupStream: STREAM _ NIL; found: BOOL; found _ ComputeClientInternal.MatchPupAddress[listenerPupAddress].found; IF found THEN { currentViewer: ViewerClasses.Viewer _ NIL; debugInfo: debugItem _ NIL; viewerInStream, viewerOutStream: STREAM; inOutPupStream _ PupStream.PupByteStreamCreate[remote: newListenerPupAddress, ticks: PupStream.SecondsToTocks[1] ! PupStream.StreamClosing => CONTINUE;] ; IF inOutPupStream # NIL THEN { title: ROPE _ NIL; IF serverMachine # NIL THEN title _ Rope.Cat["[", serverMachine, "] "]; currentViewer _ ViewerOps.CreateViewer[flavor: $Typescript, info: [iconic: FALSE, name: Rope.Cat["REMOTE ", title, name]]]; [viewerInStream, viewerOutStream] _ ViewerIO.CreateViewerStreams[name: NIL, viewer: currentViewer]; debugInfo _ NEW[debugObject _ [viewer: currentViewer, viewerInStream: viewerInStream, viewerOutStream: viewerOutStream, inOutPupStream: inOutPupStream]]; CreateInterpreterMenu[debugInfo]; TRUSTED { Process.Detach[FORK CopyPupToViewerStream[debugInfo]]; Process.Detach[FORK CopyViewerToPupStream[debugInfo]]; }; } ELSE byteStreamOK _ FALSE; } ELSE byteStreamOK _ FALSE; }; OpenSourceViewer: PUBLIC PROC [listenerPupAddress: PupDefs.PupAddress, name: ROPE, index: INT ] = { found: BOOL; found _ ComputeClientInternal.MatchPupAddress[listenerPupAddress].found; IF found THEN { FileViewerOps.OpenSource[fileName: name, index: index, feedBack: NIL]; }; }; CopyPupToViewerStream: PROC [debugInfo: debugItem] = { WHILE debugInfo.alive DO IF debugInfo.inOutPupStream.CharsAvail[] > 0 THEN{ char: CHAR; char _ debugInfo.inOutPupStream.GetChar[ ! IO.EndOfStream => {EXIT;}]; SELECT char FROM '\n => debugInfo.state _ sawCR; '& => debugInfo.state _ sawAmper ; IN ['0..'9] => IF debugInfo.state = sawAmper OR debugInfo.state = sawDigit THEN debugInfo.state _ sawDigit ELSE debugInfo.state _ normal; ' => IF debugInfo.state = sawDigit THEN debugInfo.state _ sawFirstSpace ELSE { IF debugInfo.state = sawBackArrow THEN debugInfo.state _ stuffable ELSE debugInfo.state _ normal; }; '_ => IF debugInfo.state = sawFirstSpace THEN debugInfo.state _ sawBackArrow ELSE debugInfo.state _ normal; ENDCASE => debugInfo.state _ normal; debugInfo.viewerOutStream.PutChar[char]; } ELSE Process.Pause[4]; ENDLOOP; debugInfo.alive _ FALSE; }; CopyViewerToPupStream: PROC [debugInfo: debugItem] = { stuffToFlush: BOOL _ FALSE; WHILE debugInfo.alive DO IF debugInfo.viewerInStream.CharsAvail[ ! IO.Error => EXIT ] > 0 THEN { char: CHAR; char _ debugInfo.viewerInStream.GetChar[ ! IO.EndOfStream => {EXIT;}; EditedStream.Rubout => { char _ Ascii.DEL; }; ]; debugInfo.inOutPupStream.PutChar[char]; stuffToFlush _ TRUE; } ELSE { IF stuffToFlush THEN debugInfo.inOutPupStream.Flush[] ELSE Process.Pause[4]; stuffToFlush _ FALSE; }; ENDLOOP; debugInfo.alive _ FALSE; PupStream.SendMark[debugInfo.inOutPupStream, 26B ! PupErrors.StreamClosing => CONTINUE;]; debugInfo.inOutPupStream.Close[! IO.Error => CONTINUE;] ; }; CreateInterpreterMenu: PROC[debugInfo: debugItem] = { menu: Menus.Menu _ debugInfo.viewer.menu; InsME: PROC[line: NAT, name: ROPE, proc: Menus.MenuProc] = { Menus.InsertMenuEntry [menu: menu, line: line, entry: MBQueue.CreateMenuEntry [q: debugInfo.menuHitQueue, name: name, proc: proc, clientData: debugInfo]]; }; <> <> <> <> <<>> InsME[line: 1, name: "WalkStack", proc: WalkStackHit]; InsME[line: 1, name: "ShowFrame", proc: ShowFrameHit]; <> InsME[line: 1, name: "Abort", proc: AbortHit]; InsME[line: 1, name: "Source", proc: SourceHit]; ChangeLines[debugInfo.viewer, 2]; }; ChangeLines: PROC[v: ViewerClasses.Viewer, nLines: NAT] = { Menus.ChangeNumberOfLines[v.menu, nLines]; ViewerOps.EstablishViewerPosition[v, v.wx, v.wy, v.ww, v.wh]; <> ViewerOps.PaintViewer[v, all]; }; WalkStackHit: Menus.MenuProc = TRUSTED { <<[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]>> debugInfo: debugItem = NARROW[clientData, debugItem]; StuffIt[debugInfo, Rope.Cat[" ---- &WalkStack[nFrames: ", SELECT mouseButton FROM red => "1", yellow => "-1000", blue => "-1" ENDCASE => ERROR, ", h: &H]\n"]]; }; ShowFrameHit: Menus.MenuProc = TRUSTED { <<[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]>> debugInfo: debugItem = NARROW[clientData, debugItem]; StuffIt[debugInfo, " ---- &ShowFrame[h: &H]\n"]; }; <> <<[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]>> <> <> <<};>> AbortHit: Menus.MenuProc = TRUSTED { <<[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]>> debugInfo: debugItem = NARROW[clientData, debugItem]; StuffIt[debugInfo, " ---- &ABORT[h: &H]\n"]; }; SourceHit: Menus.MenuProc = TRUSTED { <<[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]>> debugInfo: debugItem = NARROW[clientData, debugItem]; StuffIt[debugInfo, " ---- &Source[h: &H]\n"]; }; StuffIt: ENTRY PROC[debugInfo: debugItem, rope: ROPE] = { ENABLE UNWIND => NULL; <> IF Rope.IsEmpty[rope] THEN RETURN; UNTIL debugInfo.state = stuffable DO Process.Pause[5]; ENDLOOP; <> debugInfo.viewerOutStream.PutRope[rope]; debugInfo.inOutPupStream.PutRope[rope]; debugInfo.inOutPupStream.Flush[]; }; <> name, password: ROPE; [name, password] _ UserCredentials.Get[]; ComputeServerDebuggerRpcControl.ExportInterface[ interfaceName: [ type: "ComputeServerDebugger.summoner", instance: ComputeClientInternal.myNetAddressRope, version: [1,1]], user: name, password: RPC.MakeKey[password] ]; END. <> <> <<>>