DIRECTORY Ascii, Basics USING [BITAND], Commander USING [CommandProc, Lookup, Register], CommandExtras USING [MakeUninterpreted], CommandTool USING [ArgumentVector, Failed, Parse], EditedStream USING [SetEcho], FS USING [Error, StreamOpen], Graphics USING [Context, DrawBox, SetPaintMode], GraphicsBasic, IO, IOClasses USING [CreateDribbleOutputStream], List USING [Length, Remove], Loader USING [BCDBuildTime], Menus USING [AppendMenuEntry, CreateEntry, FindEntry, MenuEntry, MenuProc, ReplaceMenuEntry], Process USING [Detach, MsecToTicks, Pause, SecondsToTicks], PupDefs USING [PupAddress, PupPackageMake, PupPackageDestroy], PupStream USING [ConsumeMark, GetPupAddress, PupByteStreamCreate, PupNameTrouble, SecondsToTocks, SendMark, StreamClosing, TimeOut], PupTypes USING [telnetSoc], Rope USING [Cat, Fetch, Find, Length, Match, ROPE, Substr], TiogaOps USING [GetCaret, GetRope, Location], TIPUser USING [InstantiateNewTIPTable, RegisterTIPPredicate, TIPPredicate, TIPTable], TypeScript USING [BackSpace, ChangeLooks, Create, InsertCharAtFrontOfBuffer, TS], UserCredentials USING [Get], ViewerClasses, ViewerEvents USING [EventProc, EventRegistration, RegisterEventProc, UnRegisterEventProc], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AcquireContext, AddProp, DestroyViewer, FetchProp, PaintViewer, ReleaseContext, XYWH2Box], ViewerTools USING [GetSelectedViewer, GetSelectionContents, SetSelection]; VMEBug: CEDAR MONITOR LOCKS h.LOCK USING h: Handle IMPORTS Ascii, Basics, Commander, CommandExtras, CommandTool, EditedStream, FS, Graphics, IO, IOClasses, List, Loader, Menus, Process, PupDefs, PupStream, Rope, TiogaOps, TIPUser, TypeScript, UserCredentials, ViewerEvents, ViewerIO, ViewerOps, ViewerTools SHARES Menus, ViewerClasses, ViewerOps = BEGIN Handle: TYPE = REF VMEBugInstanceRecord; State: TYPE = {idle, starting, running, closing, destroy}; DisconnectChar: CHAR = 220C; AbortChar: CHAR = 221C; ConnectChar: CHAR = 222C; LoginChar: CHAR = 223C; RemoteCloseChar: CHAR = 224C; MarkByte: TYPE = [0..256); setLineWidth: MarkByte = 2; setPageLength: MarkByte = 3; timingMark: MarkByte = 5; timingMarkReply: MarkByte = 6; VMEBugInstanceRecord: TYPE = MONITORED RECORD [ ts: TypeScript.TS, -- the primary typescript state: State _ idle, lorc: CHAR _ 'c, logFileName: Rope.ROPE, logStream: IO.STREAM, keyFile: Rope.ROPE, argv: CommandTool.ArgumentVector, pleaseStop: BOOL _ FALSE, uToSStopped: BOOL _ FALSE, sToUStopped: BOOL _ FALSE, inDestroy: BOOL _ FALSE, serverToUserProcess: PROCESS, userToServerProcess: PROCESS, serverName: Rope.ROPE _ "LittleWonder", useOldHost: BOOL _ FALSE, keyStream: IO.STREAM, destroyOnClose: BOOL _ FALSE, synchronous: BOOL _ FALSE, in: IO.STREAM, origOut: IO.STREAM, out: IO.STREAM, tipTable: TIPUser.TIPTable, serverStream: IO.STREAM _ NIL, oldSplit: Menus.MenuEntry _ NIL ]; logFileNumber: INT _ 0; chatInstanceList: LIST OF REF ANY _ NIL; destroyEvent: ViewerEvents.EventRegistration _ NIL; closeEvent: ViewerEvents.EventRegistration _ NIL; chatTipTable: TIPUser.TIPTable; flushCount: NAT _ 10; ServerToUser: PROC [h: Handle] = { This procedure is FORKed by the UserToServer process via StartUp at the time a aborting: SIGNAL = CODE; c: CHAR; mySST: MarkByte; GetServerChar: PROC [h: Handle] RETURNS [c: CHAR] = { RETURN[LOOPHOLE[Basics.BITAND[LOOPHOLE[h.serverStream.GetChar[ ! PupStream.TimeOut => { IF h.pleaseStop OR h.state # running THEN SIGNAL aborting ELSE RESUME}; ], CARDINAL], 177B], CHAR]]; }; BugPrompt: PROC [h: Handle] RETURNS [isPrompt: BOOL _ TRUE] = { DO IF (c _ GetServerChar[h]) = 125C THEN { h.out.PutChar[c]; IF (c _ GetServerChar[h]) = 124C THEN { h.out.PutChar[c]; IF (c _ GetServerChar[h]) = 117C THEN { h.out.PutChar[c]; IF (c _ GetServerChar[h]) = 122C THEN { h.out.PutChar[c]; UNTIL (c _ GetServerChar[h]) = '> DO h.out.PutChar[c]; ENDLOOP; h.out.PutChar[c]; -- get trailing SP IF (c _ GetServerChar[h]) # Ascii.SP THEN { h.out.PutChar[c]; RETURN[isPrompt _ FALSE]; }; EXIT; } ELSE {isPrompt _ FALSE; EXIT} } ELSE {isPrompt _ FALSE; EXIT} } ELSE {isPrompt _ FALSE; EXIT} } ELSE {isPrompt _ FALSE; EXIT}; ENDLOOP; h.out.PutChar[c]; }; DO ENABLE { ABORTED => GOTO Cleanup; PupStream.StreamClosing => { IF NOT h.pleaseStop THEN TypeScript.InsertCharAtFrontOfBuffer[ts: h.ts, char: RemoteCloseChar]; GOTO Cleanup}; IO.Error => GOTO Cleanup }; IF h.serverStream.EndOf[] THEN { mySST _ PupStream.ConsumeMark[h.serverStream]; IF mySST = timingMark THEN PupStream.SendMark[h.serverStream, timingMarkReply]; }; IF h.pleaseStop OR h.state # running THEN GOTO Cleanup; c _ GetServerChar[h ! aborting => GOTO Cleanup]; SELECT c FROM '? => {h.out.PutChar[c]; GetLineScript[h]}; -- for assembly 'T => {h.out.PutChar[c]; IF BugPrompt[h] THEN GetLineScript[h]}; -- command Ascii.BEL , Ascii.ControlA, Ascii.BS => TypeScript.BackSpace[h.ts]; Ascii.TAB, Ascii.CR, IN[Ascii.SP..'>], IN['P..'S], IN['U..'~], IN['A..'O] => h.out.PutChar[c]; ENDCASE => NULL; ENDLOOP; EXITS Cleanup => h.sToUStopped _ TRUE; }; -- ServerToUser InitialSetUp: PROC [h: Handle] = TRUSTED { PupStream.SendMark[h.serverStream, setLineWidth]; h.serverStream.PutChar[0C]; IF h.lorc='l OR h.lorc='x THEN { name, password: Rope.ROPE; [name: name, password: password] _ UserCredentials.Get[]; h.serverStream.PutRope[" Login "]; h.serverStream.PutRope[name]; IF h.lorc='l AND Rope.Find[s1: name, s2: "."] = -1 THEN h.serverStream.PutRope[".PA"]; h.serverStream.PutRope[" "]; h.serverStream.PutRope[password]; h.serverStream.PutRope[" \n"]; h.serverStream.Flush[]; }; h.serverStream.PutRope["B"]; -- set baud rate h.serverStream.Flush[]; h.serverStream.PutRope["2400\n"]; h.serverStream.Flush[]; h.serverStream.PutRope["C"]; -- connect h.serverStream.PutRope["\n"]; h.serverStream.Flush[]; }; FinishStringWithErrorMsg: PROC [h: Handle, errorMsg: Rope.ROPE] = { IF errorMsg # NIL THEN h.out.PutF[": %s.\n", IO.rope[errorMsg]] ELSE h.out.PutF[".\n"]; }; GetLineScript: PROC [h: Handle] = TRUSTED { { Flush: PROC = TRUSTED { h.serverStream.Flush[]; Process.Pause[Process.MsecToTicks[100]]; -- propagate pups }; keyLine: Rope.ROPE; DO IF h.keyStream # NIL AND NOT h.keyStream.EndOf[] THEN { IF h.pleaseStop OR h.state # running THEN GOTO CloseKeyStream; keyLine _ h.keyStream.GetLineRope[]; -- strips CR IF Rope.Length[keyLine] = 0 THEN LOOP; IF Rope.Fetch[keyLine, 0] = '* THEN LOOP -- comment line ELSE { Process.Pause[Process.SecondsToTicks[1]]; -- hang on for a sec! h.serverStream.PutF["%s\n", IO.rope[keyLine]]; Flush[]; RETURN; } } ELSE GOTO CloseKeyStream; ENDLOOP; EXITS CloseKeyStream => { IF h.keyStream # NIL THEN{ h.keyStream.Close[]; h.keyStream _ NIL; }; }; };}; -- GetLineScript StartUp: PROC [h: Handle] = BEGIN ENABLE UNWIND => h.state _ idle; h.state _ starting; IF NOT h.useOldHost OR h.serverName.Length[] = 0 THEN h.serverName _ FindHostName[h]; h.useOldHost _ FALSE; h.pleaseStop _ FALSE; h.sToUStopped _ FALSE; h.uToSStopped _ FALSE; ViewerTools.SetSelection[h.ts, NIL]; TRUSTED { h.out.PutF["\nViewers VMEBug of %t.\n", IO.time[Loader.BCDBuildTime[FindHostName]]]; }; IF h.logStream # NIL THEN h.out.PutF["Log file: %g\n", IO.rope[h.logFileName]] ELSE h.out.PutF["No log file.\n"]; OpenConnection[h]; IF h.serverStream = NIL THEN { h.state _ idle; RETURN; }; SetName[h, Rope.Cat["VMEBug on: ", h.serverName]]; -- in viewer herald InitialSetUp[h]; -- does Login/ Baud rate/ Connect h.state _ running; h.serverToUserProcess _ FORK ServerToUser[h]; END; FindHostName: PROC [h: Handle] RETURNS [host: Rope.ROPE] = { caret: TiogaOps.Location; r: Rope.ROPE; i: INT; r _ ViewerTools.GetSelectionContents[]; IF r.Length[] > 1 THEN RETURN[r]; caret _ TiogaOps.GetCaret[]; r _ TiogaOps.GetRope[caret.node]; i _ caret.where; WHILE i > 0 DO char: CHARACTER = Rope.Fetch[r, i - 1]; IF -- char # '* AND -- NOT VMEBugTokenProc[char] = other THEN EXIT; i _ i-1; ENDLOOP; host _ Rope.Substr[base: r, start: i, len: caret.where - i]; }; VMEBugTokenProc: IO.BreakProc = TRUSTED { IF IO.TokenProc[char] = other THEN RETURN [other]; IF char = '+ THEN RETURN [other]; RETURN [sepr]; }; OpenConnection: PROC [h: Handle] = TRUSTED { addr: PupDefs.PupAddress; PupDefs.PupPackageMake[]; { h.out.PutF["Opening connection to %g ... ", IO.rope[h.serverName]]; SELECT TRUE FROM Rope.Match[pattern: "LittleWonder", object: h.serverName, case: FALSE], Rope.Match[pattern: "dls+100017", object: h.serverName, case: FALSE] => { addr _ PupStream.GetPupAddress[PupTypes.telnetSoc, "dls+100017" ! PupStream.PupNameTrouble => { h.out.PutF["PUP name error"]; FinishStringWithErrorMsg[h, e]; GOTO Return; }]; h.serverStream _ PupStream.PupByteStreamCreate [addr, PupStream.SecondsToTocks[1] ! PupStream.StreamClosing => { h.out.PutF["Can't connect"]; FinishStringWithErrorMsg[h, text]; GOTO Return; }]; h.out.PutF["open.\n"]; }; ENDCASE => h.out.PutF["\nUnknown dls address.\n"]; EXITS Return => NULL; }; }; CloseConnection: PROC [h: Handle, print: BOOL] = TRUSTED { h.pleaseStop _ TRUE; IF h.serverStream # NIL THEN { IF print THEN h.out.PutF["\nClosing connection to %s", IO.rope[h.serverName] ! IO.Error => CONTINUE]; h.serverStream.Close[]; h.serverStream _ NIL; -- could cause pointer faults! IF print THEN h.out.PutF[" ... Closed\n" ! IO.Error => CONTINUE]; PupDefs.PupPackageDestroy[]; }; IF h.keyStream # NIL THEN { h.keyStream.Close[]; h.keyStream _ NIL; }; IF h.state = running THEN {JOIN h.serverToUserProcess}; IF h.logStream # NIL THEN h.logStream.Flush[]; h.state _ idle; SetName[h, "VMEBug"]; }; SetName: PROC [h: Handle, r: Rope.ROPE] = { -- in Viewer herald InternalSetName: PROC [v: ViewerClasses.Viewer] = { v.name _ r; ViewerOps.PaintViewer[viewer: v, hint: caption]; }; EnumerateSplits[h.ts, InternalSetName ! ANY => CONTINUE]; }; VMEBugMain: Commander.CommandProc = TRUSTED { -- registered by Init h: Handle _ NEW[VMEBugInstanceRecord _ []]; execOut: IO.STREAM _ cmd.out; switchChar: CHAR; i: NAT _ 2; h.argv _ CommandTool.Parse[cmd ! CommandTool.Failed => {msg _ errorMsg; CONTINUE; }]; IF h.argv = NIL THEN RETURN; h.lorc _ 'l; -- default GV login WHILE i < h.argv.argc DO IF h.argv[i].Length[] > 1 THEN SELECT h.argv[i].Fetch[0] FROM '- => { switchChar _ h.argv[i].Fetch[1]; SELECT switchChar FROM 'd => h.destroyOnClose _ TRUE; 'k => { IF i+1 < h.argv.argc THEN { h.keyStream _ IO.RIS[h.argv[i+1]]; i _ i + 1; }; }; 's => h.synchronous _ TRUE; ENDCASE => h.lorc _ switchChar; }; '> => h.logFileName _ Rope.Substr[base: h.argv[i], start: 1]; '< => h.keyFile _ Rope.Substr[base: h.argv[i], start: 1]; ENDCASE => execOut.PutF["VMEBug: unknown command: %s.\n", IO.rope[h.argv[i]]]; i _ i + 1; ENDLOOP; IF h.logFileName.Length[] = 0 THEN { h.logFileName _ IO.PutFR["VMEBug%d.log", IO.int[logFileNumber]]; logFileNumber _ logFileNumber + 1; }; IF h.keyFile.Length[] > 0 THEN h.keyStream _ FS.StreamOpen[fileName: h.keyFile ! FS.Error => IF error.group = user THEN { execOut.PutF["VMEBug: Cannot open %s\n", IO.rope[h.keyFile]]; CONTINUE; }]; h.ts _ TypeScript.Create[info: [name: "VMEBug", iconic: h.argv.argc <= 1 OR h.lorc = 'i], paint: TRUE]; TypeScript.ChangeLooks[h.ts, 'f]; h.ts.file _ h.logFileName; h.ts.icon _ typescript; h.logStream _ FS.StreamOpen[fileName: h.logFileName, accessOptions: $create ! FS.Error => IF error.group = user THEN { execOut.PutF["VMEBug: Cannot open %s\n", IO.rope[h.logFileName]]; CONTINUE; }]; chatTipTable.link _ h.ts.tipTable; chatTipTable.opaque _ FALSE; h.tipTable _ h.ts.tipTable _ chatTipTable; [in: h.in, out: h.origOut] _ ViewerIO.CreateViewerStreams[name: "VMEBug.log", viewer: h.ts, editedStream: FALSE]; h.out _ h.origOut; IF h.logStream # NIL THEN h.out _ IOClasses.CreateDribbleOutputStream[output1: h.origOut, output2: h.logStream]; EditedStream.SetEcho[h.in, NIL]; IF h.argv.argc > 1 THEN { h.serverName _ h.argv[1]; h.useOldHost _ TRUE; IF h.lorc = 'i THEN h.lorc _ 'c ELSE TypeScript.InsertCharAtFrontOfBuffer[ts: h.ts, char: IF h.lorc = 'c THEN ConnectChar ELSE LoginChar]; }; IF List.Length[chatInstanceList] = 0 THEN { destroyEvent _ ViewerEvents.RegisterEventProc[proc: MyDestroy, event: destroy] }; chatInstanceList _ CONS[h, chatInstanceList]; Menus.AppendMenuEntry[menu: h.ts.menu, entry: Menus.CreateEntry[name: "Disconnect", proc: MyDisconnect, clientData: h, fork: TRUE, documentation: "Close Ethernet connection"]]; Menus.AppendMenuEntry[menu: h.ts.menu, entry: Menus.CreateEntry[name: "Login", proc: MyLogin, clientData: h, documentation: "Open Ethernet Connection to selected host and send Login sequence"]]; Menus.AppendMenuEntry[menu: h.ts.menu, entry: Menus.CreateEntry[name: "Connect", proc: MyConnect, clientData: h, documentation: "Open Ethernet Connection to selected host"]]; Menus.AppendMenuEntry[menu: h.ts.menu, entry: Menus.CreateEntry[name: "BreakKey", proc: MyBreakKey, clientData: h, documentation: "Transmit Ascii.NULL (DLS interprets as RS-232 Line Break)"]]; Menus.AppendMenuEntry[menu: h.ts.menu, entry: Menus.CreateEntry[name: "FlushLog", proc: MyFlushLog, clientData: h, documentation: "Flush log file to disk."]]; h.oldSplit _ Menus.FindEntry[menu: h.ts.menu, entryName: "Split"]; Menus.ReplaceMenuEntry[menu: h.ts.menu, oldEntry: h.oldSplit, newEntry: Menus.CreateEntry[name: "Split", proc: MySplit, fork: TRUE, clientData: h, documentation: "Split window"]]; ViewerOps.AddProp[h.ts, $VMEBugToolData, h]; ViewerOps.PaintViewer[viewer: h.ts, hint: all]; IF h.synchronous THEN UserToServer[h] ELSE { h.userToServerProcess _ FORK UserToServer[h]; Process.Detach[h.userToServerProcess]; }; }; -- VMEBugMain UserToServer: PROC [h: Handle] = TRUSTED {{ char: CHAR; count: NAT _ 0; DO ENABLE { ABORTED => ERROR; -- ever happen? IO.Error => { CloseConnection[h, FALSE]; GOTO Die; }; PupStream.StreamClosing => { IF h.serverStream # NIL THEN { h.out.PutF["\nConnection being closed by %s", IO.rope[h.serverName]]; FinishStringWithErrorMsg[h, text]; CloseConnection[h, FALSE]; IF h.destroyOnClose THEN { ViewerOps.DestroyViewer[h.ts]; GOTO Die; }; }; CONTINUE; }; }; char _ h.in.GetChar[]; IF h.inDestroy THEN { CloseConnection[h, FALSE]; GOTO Die; }; SELECT char FROM AbortChar => {IF h.state = running THEN CloseConnection[h, TRUE]}; DisconnectChar => {IF h.state = running THEN CloseConnection[h, TRUE]}; RemoteCloseChar => {ERROR PupStream.StreamClosing[why: remoteClose, text: NIL]}; ConnectChar => {IF h.state = idle THEN { h.lorc _ 'c; StartUp[h]; count _ 0}; }; LoginChar => { IF h.state = idle THEN { h.lorc _ 'l; StartUp[h]; count _ 0}; }; ENDCASE => { char _ Ascii.Upper[char]; SELECT h.state FROM running => { h.serverStream.PutChar[char]; IF count >= flushCount OR h.in.CharsAvail[] = 0 THEN { h.serverStream.Flush[]; count _ 0} ELSE count _ count + 1; }; ENDCASE => h.out.PutChar[char]; }; ENDLOOP; EXITS Die => {IF h.logStream # NIL THEN h.logStream.Close[]}; }; }; -- end of UserToServer MyDestroy: ViewerEvents.EventProc = { h: Handle _ NARROW[ViewerOps.FetchProp[viewer, $VMEBugToolData]]; IF h = NIL THEN RETURN; IF NumSplit[viewer] = 1 THEN { -- last one h.inDestroy _ TRUE; chatInstanceList _ List.Remove[h, chatInstanceList]; IF List.Length[chatInstanceList] = 0 THEN { ViewerEvents.UnRegisterEventProc[proc: destroyEvent, event: destroy]; }; } ELSE IF NumSplit[viewer] > 1 THEN { IF viewer = h.ts THEN { Another: PROC [v: ViewerClasses.Viewer] = { IF v # viewer THEN h.ts _ v; }; EnumerateSplits[viewer, Another]; }; }; }; MyClose: ViewerEvents.EventProc = { h: Handle _ NARROW[ViewerOps.FetchProp[viewer, $VMEBugToolData]]; IF h = NIL THEN RETURN; TypeScript.InsertCharAtFrontOfBuffer[ts: h.ts, char: DisconnectChar]; }; MyConnect: Menus.MenuProc = { viewer: TypeScript.TS _ NARROW[parent]; h: Handle _ NARROW[clientData]; h.ts _ viewer; -- "primary" copy h.useOldHost _ mouseButton # red; TypeScript.InsertCharAtFrontOfBuffer[ts: h.ts, char: ConnectChar]; }; MyLogin: Menus.MenuProc = { viewer: TypeScript.TS _ NARROW[parent]; h: Handle _ NARROW[clientData]; h.ts _ viewer; -- "primary" copy h.useOldHost _ mouseButton # red; TypeScript.InsertCharAtFrontOfBuffer[ts: h.ts, char: LoginChar]; }; MyDisconnect: Menus.MenuProc = { h: Handle _ NARROW[clientData]; TypeScript.InsertCharAtFrontOfBuffer[ts: h.ts, char: DisconnectChar]; }; MyBreakKey: Menus.MenuProc = TRUSTED { h: Handle _ NARROW[clientData]; IF h.state # running THEN RETURN; IF h.serverStream # NIL THEN { h.serverStream.PutChar['\000]; h.serverStream.Flush[]; }; }; MyFlushLog: Menus.MenuProc = { h: Handle _ NARROW[clientData]; IF h.logStream # NIL THEN h.logStream.Flush[]; }; MySplit: Menus.MenuProc = { h: Handle _ NARROW[clientData]; CheckVMEBugProperties: PROC [v: ViewerClasses.Viewer] = { IF ViewerOps.FetchProp[v, $VMEBugToolData] = NIL THEN ViewerOps.AddProp[v, $VMEBugToolData, h]; v.tipTable _ h.tipTable; }; h.oldSplit.proc[parent: parent, clientData: h.oldSplit.clientData, mouseButton: mouseButton, shift: shift, control: control]; EnumerateSplits[NARROW[parent, ViewerClasses.Viewer], CheckVMEBugProperties]; }; ConnectionOpen: TIPUser.TIPPredicate = { h: Handle; viewer: ViewerClasses.Viewer _ ViewerTools.GetSelectedViewer[]; IF viewer=NIL THEN RETURN [FALSE]; -- no primary selection h _ NARROW[ViewerOps.FetchProp[viewer, $VMEBugToolData]]; IF h=NIL THEN RETURN [FALSE]; -- not a chat-like tool RETURN [h.state = running]; -- connection open? }; EnumerateSplits: PROC [v: ViewerClasses.Viewer, p: PROC [v: ViewerClasses.Viewer]] = { v2: ViewerClasses.Viewer _ v; IF v = NIL THEN RETURN; DO p[v2]; IF v2.link = NIL OR v2.link = v THEN RETURN; v2 _ v2.link; ENDLOOP; }; NumSplit: PROC [v: ViewerClasses.Viewer] RETURNS [count: INT _ 0] = { Counter: PROC [v2: ViewerClasses.Viewer] = { count _ count + 1; }; EnumerateSplits[v, Counter]; }; Init: PROC = { Commander.Register[key: "VMEBug", proc: VMEBugMain, doc: "Pup User Telnet, see VMEBugDoc.tioga"]; CommandExtras.MakeUninterpreted[Commander.Lookup["VMEBug"]]; chatTipTable _ TIPUser.InstantiateNewTIPTable["VMEBug.TIP"]; TIPUser.RegisterTIPPredicate[$ConnectionOpen, ConnectionOpen]; }; Init[]; END... of VMEBug âVMEBug.mesa Created by: Neil Gunther on March 7, 1985 12:25:12 pm PST Last edited by Neil Gunther, March 28, 1985 7:52:45 pm PST connection is opened. It is JOINED whenever the connection is closed. It also goes away if the VMEBug viewer is destroyed. This PROC includes '+ ,to handle Pup names of the form dls+someOctalValue iconic unless command line not empty create log file plug in VMEBug TIP table. If -i then we are just initializing the host name, else really connect closeEvent _ ViewerEvents.RegisterEventProc[proc: MyClose, event: close]; Watches viewer buttons & keyboard last viewer destroyed ! Close connection and exit ViewerEvents.UnRegisterEventProc[proc: closeEvent, event: close]; M a i n l i n e C o d e Ê2˜Jšœ ™ Jšœv™vJ˜šÏk ˜ Jšœ˜Jšœœœ˜Jšœ œ!˜0Jšœœ˜(Jšœ œ!˜2Jšœ œ ˜Jšœœ˜Jšœ œ"˜0J˜Jšœ˜Jšœ œ˜,Jšœœ˜Jšœœ˜JšœœU˜`Jšœœ.˜;Jšœœ1˜>Jšœ œy˜ˆJšœ œ ˜Jšœœ#œ ˜;Jšœ œ˜-JšœœH˜UJšœ œ=œ˜QJšœœ˜J˜Jšœ œH˜ZJšœ œ˜%Jšœ œ\˜kšœ œ9˜JJ˜——Jš Ðbxœœœœœœ ˜2šœ;˜CJšœœ œ!˜@J˜6Jšœ˜J˜2—Jšœ%˜2J˜Jšœœœ˜(Jšœœ/˜:J˜Jšœœ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœ˜Jšœ œ ˜J˜J˜J˜J˜J˜šœœ œœ˜/JšœœÏc˜,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šœ0œ˜4Jšœ.œ˜2Jšœ7˜7J˜J˜JšÏn œœ˜#JšœN˜NJšœF™Fšœ4™4šœ œ˜Jšœœ˜—Jšœ(œ œœ œœœœ=œœœ œ˜ šGœœ œœ œ œœ œœœ,œœ4œœ;œœCœeœEÏiœTœKœ œ7œ*œ œœœ œœœ œœ œ œœ œ,˜· š˜šœœ+˜Išœœ˜ JšœI˜IJšœ ˜—Jšœ œ ˜ —šœ˜$Jšœ.˜.——šœœœ:˜ZJ˜Jšœœ œ ˜7Jšœ3˜3š œœ1¡ œœœ¡œ˜¡Jšœœœ˜CJšœœœ˜Jšœœœœœœœœœœ˜J——Jš œœ˜Jšœ˜ Jš˜Jšœœ˜ —Jšœ¡ ˜—J˜J˜š  œœœ˜*J˜2J˜šœ œ œ˜ Jšœœ˜J˜9J˜"J˜Jšœ œ#œ˜VJ˜J˜!J˜J˜—Jšœ)¡ œx¡œ8˜íJ˜J˜—š œœœ˜CJšœ œœœ˜?Jšœ˜J˜J˜—J™š   œœœ¡œ¡œœ˜HJšœS¡˜a—šœ¡œœ˜'š œœœœ˜>Jšœœœœ˜CJšœ+¡œœ œœœœ¡ œ œ6¡œIœ ˜Ì——šœœœœ˜+Jš˜˜šœœœ˜J˜Jšœœ˜J˜—J˜—Jšœ ¡ ˜J˜J˜—š œœ˜!Jšœœ˜ Jšœ˜Jšœœœœ ˜UJšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜$šœ˜ Jšœ(œ*˜TJ˜—Jšœœœœ˜NJšœ˜"J˜šœœœ˜J˜Jšœ˜J˜—Jšœ7¡˜G—šœ¡ œ¡œ ˜AJ˜—šœœ˜9Jšœ˜Jšœ˜—š  œœ œ œ˜œ œœ˜vJšœ)œ˜AJšœ˜ J˜J˜—Jšœ™J˜"Jšœœ˜J˜*Jšœjœ˜qJ˜JšœœœW˜pJšœœ˜ šœœ˜J˜Jšœœ˜JšœF™FJšœ œ ˜Jšœ6œ œ œ ˜jJ˜—šœ#œ˜+JšœI™IJ˜NJ˜—Jšœœ˜-Jšœ}œ/˜°J˜ÂJ˜®J˜ÀJ˜žJ˜J˜BJšœ~œ1˜³Jšœ,˜,J˜/Jšœœ˜%šœ˜Jšœœ˜-J˜&J˜—Jšœ¡ ˜J˜Jš  œœœ˜,Jšœ¡!™"˜Jšœœ˜ Jšœœ˜šœœ˜ JšœœŸ˜"šœ ˜ Jšœ™Jšœ™Jšœœ˜Jšœ˜ J˜—˜šœœœ˜Jšœ.œ˜EJ˜"Jšœœ˜šœœ˜J˜Jšœ˜ J˜—J˜—Jšœ˜ J˜—J˜J˜šœ œ˜Jšœœ˜Jšœ˜ J˜—šœ˜Jšœ œœœ˜BJšœœœœ˜GJšœœ1œ˜Pšœœœ˜(Jšœ'˜'J˜—˜šœœ˜J˜$———šœ˜šœ"˜)Jšœ ˜˜J˜šœœœ˜7J˜#—Jšœ˜J˜—Jšœ˜—J˜—Jšœ˜—Jš˜—Jšœ œœœ˜=J˜šœ¡œ¡ ˜J˜—˜%Jšœ œ/˜AJšœœœœ˜šœœŸ ˜*Jšœœ˜J˜4šœ#œ˜+J˜EJšœA™AJ˜—J˜—šœœœ˜#šœœ˜š œœ˜+Jšœ œ ˜J˜—J˜!J˜—J˜—J˜J˜—˜#Jšœ œ/˜AJšœœœœ˜J˜EJ˜J˜—˜Jšœœœ ˜'Jšœ œ ˜JšœŸ˜ J˜"J˜BJ˜J˜—˜Jšœœœ ˜'Jšœ œ ˜JšœŸ˜ J˜"J˜@J˜J˜—˜ Jšœ œ ˜J˜EJ˜J˜—šœœ˜&Jšœ œ ˜Jšœœœ˜!šœœœ˜J˜J˜J˜—J˜J˜—˜Jšœ œ ˜Jšœœœ˜.J˜J˜——š œ˜Jšœ œ ˜š œœ˜9Jšœ+œœ*˜_J˜J˜—J˜}Jšœœ7˜MJ˜J˜—š œ˜(J˜ J˜?Jš œœœœœŸ˜:Jšœœ/˜9Jš œœœœœŸ˜5JšœŸ˜/J˜J˜—š œœœ˜VJ˜Jšœœœœ˜š˜J˜Jš œ œœ œœ˜,J˜ Jšœ˜—J˜J˜—š œœœ œ ˜Eš œœ˜,J˜J˜—J˜J˜J˜—š œœ˜Jšœa˜aJšœ<˜J˜J˜—Jšœ™J˜J˜J˜Jšœ¡ ˜J˜J˜—…—I°_Ä