TSRemoteFormatImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bob Hagmann, November 22, 1985 7:49:20 am PST
Rick Beach, June 3, 1985 2:48:04 pm PDT
DIRECTORY
Commander USING [CommandObject, Handle],
CommandTool USING [CurrentWorkingDirectory, Run],
ComputeServerClient USING [RemoteSuccess, StartService],
ComputeServerServer USING [Lookup, RegisteredProcHandle],
Convert USING [Error, RealFromRope],
IO USING [CreateStream, CreateStreamProcs, EndOfStream, STREAM, StreamProcs],
PieViewers USING [Set],
Process USING [InitializeCondition, SecondsToTicks],
PseudoCursors USING [Set],
Rope USING [Cat, Concat, Fetch, FromChar, IsEmpty, Length, ROPE, Substr],
TSFormat USING [],
TSViewer USING [Tool],
ViewerTools USING [SetContents];
=
BEGIN
OPEN TSViewer;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
outBufStreamData: TYPE = REF outBufStreamDataObject;
ThirtyTwoChars: TYPE = PACKED ARRAY [0..32) OF CHAR;
outBufStreamDataObject:
TYPE =
RECORD [
token: ROPE ← NIL,
bits: REF ThirtyTwoChars ← NEW[ThirtyTwoChars],
bitsIndex: INT ← 0,
tool: Tool ← NIL,
errMsg: ROPE ← NIL,
eof: BOOL ← FALSE
];
inBufStreamData: TYPE = REF inBufStreamDataObject;
inBufStreamDataObject:
TYPE =
RECORD [
token: ROPE ← NIL,
charsAvail: CONDITION,
eof: BOOL ← FALSE
];
inStreamProcs:
REF
IO.StreamProcs ←
IO.CreateStreamProcs[
variety: $input,
class: $TSetterIn,
getChar: InBufGetChar,
charsAvail: InCharsAvail
];
outStreamProcs:
REF
IO.StreamProcs ←
IO.CreateStreamProcs[
variety: $output,
class: $TSetterOut,
putChar: OutBufPutChar
];
OutBufPutChar:
PROC [self:
STREAM, char:
CHAR] = {
data: outBufStreamData = NARROW[self.streamData];
IF data.token #
NIL
AND data.token.Fetch[0] = 'b
THEN {
data.bits[data.bitsIndex] ← char;
data.bitsIndex ← data.bitsIndex + 1;
IF data.bitsIndex = 32
THEN
TRUSTED {
PseudoCursors.Set[data.tool.miniDisplay, LOOPHOLE[data.bits]];
data.token ← NIL;
data.bitsIndex ← 0;
};
}
ELSE {
IF char # '$
THEN data.token ← data.token.Concat[Rope.FromChar[char]]
ELSE {
IF ~data.token.IsEmpty[]
THEN {
SELECT data.token.Fetch[0]
FROM
'c => {
PseudoCursors.Set[data.tool.miniDisplay, NIL];
};
'p => {
realRope: ROPE = data.token.Substr[1];
pieSize: REAL ← 0.0;
pieSize ← Convert.RealFromRope[realRope ! Convert.Error => CONTINUE;];
PieViewers.Set[data.tool.pie, 100.0-pieSize];
};
'm => {
msg: ROPE = data.token.Substr[1];
ShowMessage[data.tool, msg];
};
'e => {
data.errMsg ← data.token;
};
ENDCASE;
};
data.token ← NIL;
};
};
};
InCharsAvail:
PROC [self:
STREAM, wait:
BOOL]
RETURNS [
INT] = {
data: inBufStreamData = NARROW[self.streamData];
RETURN[data.token.Length[]];
};
InBufGetChar:
ENTRY
PROC [self:
STREAM]
RETURNS [ch:
CHAR] = {
ENABLE UNWIND => NULL;
data: inBufStreamData = NARROW[self.streamData];
WHILE data.token.Length[] <= 0 AND ~ data.eof DO WAIT data.charsAvail ENDLOOP;
IF data.eof THEN ERROR IO.EndOfStream[self];
ch ← data.token.Fetch[0];
data.token ← data.token.Substr[1];
};
BufferInChar:
INTERNAL PROC [data: inBufStreamData, ch:
CHAR] = {
ENABLE UNWIND => NULL;
data.token ← data.token.Concat[Rope.FromChar[ch]];
NOTIFY data.charsAvail;
};
ShowMessage:
PROCEDURE [tool: Tool, msg:
ROPE] = {
tool.messageLog ← msg ← tool.messageLog.Cat["\n", msg];
ViewerTools.SetContents[tool.messageBox, msg];
[] ← tool.messageBox.class.scroll[tool.messageBox, thumb, 100];
};
FormatOneOutputFile:
PUBLIC
PROCEDURE [tool: Tool, names:
LIST
OF
ROPE] = {
found: BOOL;
success: ComputeServerClient.RemoteSuccess;
remoteMsg: ROPE ← NIL;
msg: ROPE ← NIL;
nameList: ROPE ← NIL;
inStream: IO.STREAM ← NIL;
inData: inBufStreamData;
outData: outBufStreamData;
outStream: IO.STREAM ← NIL;
stopProcess: PROCESS;
tryRemote: BOOL ← tool.remoteState # localOnly;
finished: BOOL ← FALSE;
retries: INT ← 0;
FOR n:
LIST
OF
ROPE ← names, n.rest
UNTIL n =
NIL
DO
IF nameList = NIL THEN nameList ← n.first
ELSE nameList ← Rope.Cat[nameList, " ", n.first];
ENDLOOP;
IF tool.tempPress THEN nameList ← Rope.Concat["-t ", nameList];
inStream ← IO.CreateStream[streamProcs: inStreamProcs,
streamData: inData ← NEW[inBufStreamDataObject ← []]];
outStream ← IO.CreateStream[streamProcs: outStreamProcs,
streamData: outData ← NEW[outBufStreamDataObject ← [tool: tool]]];
stopProcess ← FORK StopProcess[inData, outData, tool];
WHILE tryRemote
AND ~finished
AND retries < 4
DO
retries ← retries + 1;
IF tool.stop THEN EXIT;
inStream ← IO.CreateStream[streamProcs: inStreamProcs,
streamData: inData ← NEW[inBufStreamDataObject ← []]];
outStream ← IO.CreateStream[streamProcs: outStreamProcs,
streamData: outData ← NEW[outBufStreamDataObject ← [tool: tool]]];
stopProcess ← FORK StopProcess[inData, outData, tool];
[found: found, success: success, remoteMsg: remoteMsg] ← ComputeServerClient.StartService[service: "RemoteTSetter", cmdLine: nameList, in: inStream, out: outStream];
SELECT
TRUE
FROM
~found
OR success = false
OR success = cantImportController
OR success = cantImportServer
OR success = communicationFailure
OR success = commandNotFound
OR success = clientNotRunning => {
tryRemote ← FALSE;
};
success = aborted => {
tool.stop ← TRUE;
finished ← TRUE;
};
success = timeOut
OR success = serverTooBusy => {
LOOP;
};
found
AND success = true => {
finished ← TRUE;
};
ENDCASE;
SetDone[inData, outData];
TRUSTED {JOIN stopProcess;};
ENDLOOP;
IF ~tryRemote
THEN {
lookupProcData: ComputeServerServer.RegisteredProcHandle;
errMsg: ROPE ← NIL;
runError: BOOL ← FALSE;
IF tool.remoteState = remoteOnly
THEN {
ShowMessage[tool," Failed to perform remote TSet and remoteOnly is requested"];
}
ELSE {
lookupProcData ← ComputeServerServer.Lookup["RemoteTSetter", NIL];
IF lookupProcData =
NIL
THEN {
[errMsg: errMsg, error: runError] ← CommandTool.Run[bcdName: runDir.Concat["RemoteTSetter.bcd"], runEvenIfAlreadyRun: FALSE, runEvenIfUnbound: FALSE];
lookupProcData ← ComputeServerServer.Lookup["RemoteTSetter", NIL];
};
IF lookupProcData =
NIL
THEN {
ShowMessage[tool," Failed to start up RemoteTSetter.bcd on the workstation"];
}
ELSE {
result: REF ANY;
myCmd: Commander.Handle;
inStream ← IO.CreateStream[streamProcs: inStreamProcs,
streamData: inData ← NEW[inBufStreamDataObject ← []]];
outStream ← IO.CreateStream[streamProcs: outStreamProcs,
streamData: outData ← NEW[outBufStreamDataObject ← [tool: tool]]];
stopProcess ← FORK StopProcess[inData, outData, tool];
myCmd ←
NEW[Commander.CommandObject ← [
in: inStream,
out: outStream,
err: outStream,
commandLine: nameList ,
command: "RemoteTSetter ",
propertyList: NIL,
procData: NIL
]];
[result: result, msg: remoteMsg] ← lookupProcData.commanderProcHandle.proc[myCmd ! ABORTED => CONTINUE;];
IF result = $Failure
AND remoteMsg.IsEmpty[]
THEN
remoteMsg ← "Failed to Run local TSetter";
SetDone[inData, outData];
TRUSTED {JOIN stopProcess;};
};
};
};
SetDone[inData, outData];
TRUSTED {JOIN stopProcess;};
IF remoteMsg # NIL THEN ShowMessage[tool, remoteMsg];
IF NOT tool.debug THEN msg ← tool.pressName ELSE msg ← NIL;
IF tool.stop THEN msg ← msg.Concat[" aborted"]
ELSE msg ← msg.Concat[" completed"];
ShowMessage[tool, msg];
};
SetDone:
ENTRY
PROC[ inData: inBufStreamData, outData: outBufStreamData] = {
ENABLE UNWIND => NULL;
inData.eof ← TRUE;
outData.eof ← TRUE;
NOTIFY inData.charsAvail;
};
StopProcess:
PROC [ inData: inBufStreamData, outData: outBufStreamData, tool: Tool] = {
TRUSTED {Process.InitializeCondition[@inData.charsAvail, Process.SecondsToTicks[1]];};
StopInner[inData, outData, tool];
};
StopInner:
ENTRY
PROC [ inData: inBufStreamData, outData: outBufStreamData, tool: Tool] = {
ENABLE UNWIND => NULL;
sentStop: BOOL ← FALSE;
WHILE ~inData.eof
DO
WAIT inData.charsAvail;
IF tool.stop
AND ~sentStop
THEN {
BufferInChar[inData, 's];
sentStop ← TRUE;
};
ENDLOOP;
};
runDir: ROPE ← CommandTool.CurrentWorkingDirectory[];
Bob Hagmann August 7, 1985 9:09:52 am PDT
modified the stop code: added enable unwinds, and self deadlocks
changes to: InBufGetChar, BufferInChar, SetDone, StopProcess, StopInner, FormatOneOutputFile