~
BEGIN
OPEN SoftcardFSAccess;
QUIT: CARD32 ← SoftcardDataExch.QUIT; -- 0 is the type which stops the watch procedure of the SPARC
Log: We are going unmonitored for now, we'll fix that if it causes too many problems.
logActive: BOOLEAN ← FALSE;
log: IO.STREAM ← NIL;
Log on file
logName: Rope.ROPE;
StartLog:
PROC [fName: Rope.
ROPE ←
NIL] ~ {
IF logActive THEN StopLog[];
logName ← IF fName#NIL THEN fName ELSE "///Temp/Softcard/SoftcardFSAccess.log";
log ← FS.StreamOpen[fileName: logName, accessOptions: create, keep: 3];
logActive ← TRUE;
};
StopLog:
PROC ~ {
-- do not use on viewer log
logActive ← FALSE;
IO.Close[log];
};
FlushLog:
PROC ~ {
StopLog[];
StartLog[logName];
};
Log on console viewer
StartViewerLog:
PROC ~ {
IF logActive THEN StopLog[];
log ← GetStream[1];
logActive ← TRUE;
};
StopViewerLog:
PROC ~ {
logActive ← FALSE;
};
LogC:
PROC [what:
CARD32] ~ {
IO.PutF[log, "%08x\t", IO.card[what]];
};
LogR:
PROC [what: Rope.
ROPE] ~ {
IO.PutRope[log, what];
IO.PutChar[log, '\n];
};
maxMsgSize: NAT = 80; --limited on the Sparc side
SendFSError:
PROC [error:
FS.ErrorDesc] ~ {
DoPutError: SoftcardDataExch.PutProc ~
TRUSTED {
s: IO.STREAM ← IO.TIS[text: r];
nBytes ← IO.UnsafeGetBlock[self: s, block: ub];
};
groupVal: CARD32;
codeName: Rope.ROPE ← Atom.GetPName[error.code];
r: REF TEXT ← RefText.ObtainScratch[Rope.Length[codeName]+Rope.Length[error.explanation]+3];
groupVal ←
SELECT error.group
FROM
ok => 1,
bug => 2,
environment=> 3,
lock => 4,
client => 5,
user => 6,
ENDCASE => 7; -- will never happen, right ?
r ← RefText.AppendRope[r, IO.PutFR["%g %d %g", [rope[codeName]], [cardinal[groupVal]], [rope[error.explanation]] ]];
IF r.length>maxMsgSize
THEN {
r.length ← maxMsgSize;
r[maxMsgSize-1] ← '.;
r[maxMsgSize-2] ← '.;
r[maxMsgSize-3] ← '.;
};
SoftcardDataExch.PutPacket[SOPEN, groupVal, 0, r.length, DoPutError];
RefText.ReleaseScratch[r];
SoftcardDataExch.PutPacket[QUIT];
IF logActive THEN LogR[error.explanation];
};
blkSize: NAT ← 8*1024;
ReadIt:
PROC [s:
IO.
STREAM, data1, len:
CARD32] ~ {
stillToDo: NAT ← MAX[len, MIN[blkSize, IO.CharsAvail[s]]]; -- get at least a buffer
index: CARD32 ← 0;
UNTIL
IO.EndOf[s]
DO
DoPutBlock: SoftcardDataExch.PutProc ~
TRUSTED {
nBytes ← IO.UnsafeGetBlock[self: s, block: ub];
n ← n+nBytes;
};
n: NAT ← 0;
count: NAT ← MIN[blkSize, stillToDo];
SoftcardDataExch.PutPacket[SREAD, data1, index, count, DoPutBlock];
stillToDo ← stillToDo-n;
index ← index+n;
IF stillToDo=0 THEN EXIT;
ENDLOOP;
SoftcardDataExch.PutPacket[QUIT];
IF logActive AND data1>0ffh THEN {LogC[data1]; LogC[len]; LogC[index]; LogC[IO.GetIndex[s ! IO.Error => CONTINUE]]; LogR["Read Block"];}
};
UnknownStream: PUBLIC SIGNAL ~ CODE;
GetStream:
PROC [streamNo:
CARD32]
RETURNS [s:
IO.
STREAM] ~ {
s ← NARROW[CardTab.Fetch[streams, streamNo].val];
IF s=NIL THEN SIGNAL UnknownStream;
};
RegisterConsoleStreams:
PUBLIC
PROC [in, out, err:
IO.
STREAM] ~ {
[] ← CardTab.Store[streams, STDIN, in];
[] ← CardTab.Store[streams, STDOUT, out];
[] ← CardTab.Store[streams, STDERR, out]; --err
};
ActionClose: SoftcardDataExch.ActionProc ~ {
IF data1>specialStreams
THEN {
--do not close the console
stream: IO.STREAM ← GetStream[data1];
IO.Close[stream];
[] ← CardTab.Delete[streams, data1];
};
IF logActive THEN {LogC[data1]; LogR["Close"];}
};
ActionWrite: SoftcardDataExch.ActionProc ~ {
stream: IO.STREAM ← GetStream[data1];
IO.UnsafePutBlock[self: stream, block: ub];
IF logActive AND data1>0ffh THEN {LogC[data1]; LogC[ub.count]; LogR["Write"];}
};
ActionRead: SoftcardDataExch.ActionProc ~ {
stream: IO.STREAM ← GetStream[data1];
TRUSTED { Process.Detach[ FORK ReadIt[stream, data1, data2]];}
ReadIt[stream, data1, data2];
};
ActionSetIndex: SoftcardDataExch.ActionProc ~ {
stream: IO.STREAM ← GetStream[data1];
IO.SetIndex[stream, data2];
IF logActive THEN {LogC[data1]; LogC[data2]; LogR["SetIndex"];}
};
ActionGetIndex: SoftcardDataExch.ActionProc ~ {
if data2=0 means get & send index info, else means get index and correct it by -data2 (cache thrown away in the softcard);
stream: IO.STREAM ← GetStream[data1];
index:
INT ←
IO.GetIndex[stream !
IO.Error => IF ec=NotImplementedForThisStream THEN GOTO Exit]; --do not ask the console
IF data2=0
THEN {
SoftcardDataExch.PutPacket[SGETINDEX, data1, index];
SoftcardDataExch.PutPacket[QUIT];
}
ELSE IO.SetIndex[stream, index-data2];
IF logActive THEN {LogC[data1]; LogC[data2]; LogR["GetIndex"];}
};
ActionSetLength: SoftcardDataExch.ActionProc ~ {
stream: IO.STREAM ← GetStream[data1];
IO.SetLength[stream, data2];
IF logActive THEN {LogC[data1]; LogC[data2]; LogR["SetLength"];}
};
ActionGetLength: SoftcardDataExch.ActionProc ~ {
stream: IO.STREAM ← GetStream[data1];
index: INT ← IO.GetLength[stream];
SoftcardDataExch.PutPacket[SGETLENGTH, data1, index];
SoftcardDataExch.PutPacket[QUIT];
IF logActive THEN {LogC[data1]; LogC[data2]; LogR["GetLength"];}
};
ActionOpen: SoftcardDataExch.ActionProc ~ {
fsError: FS.ErrorDesc;
{
name: Rope.ROPE;
accessOptions: FS.AccessOptions;
stream: IO.STREAM;
IF data1<=specialStreams THEN RETURN; -- do not perturbate console streams
IF ub.count=0
THEN name ← "NoFileNameSpecified.data"
ELSE {
ros: IO.STREAM ← IO.ROS[];
IO.UnsafePutBlock[ros, ub];
name ← IO.RopeFromROS[ros];
};
IF data2=
TSCREATE
THEN {
in, out, err: IO.STREAM;
[in, out, err] ← SoftcardTool.CreateCmdStreams[name]; -- to hide viewers from this
[] ← CardTab.Store[streams, data1, in];
[] ← CardTab.Store[streams, data1+1, out];
[] ← CardTab.Store[streams, data1+2, err];
}
ELSE {
accessOptions ←
SELECT data2
FROM
FSCREATE => create,
FSAPPEND => append,
FSWRITE => write,
ENDCASE => read;
stream ←
FS.StreamOpen[
fileName: name,
accessOptions: accessOptions,
streamBufferParms: [vmPagesPerBuffer: blkSize/PrincOps.bytesPerPage, nBuffers: 4],
wDir: defaultDir
! FS.Error => {fsError ← error; GOTO NoSuchFile}];
IF stream#NIL THEN [] ← CardTab.Store[streams, data1, stream];
};
SoftcardDataExch.PutPacket[QUIT];
IF logActive THEN {LogC[data1]; LogC[data2]; LogR[name];}
EXITS
NoSuchFile => TRUSTED {Process.Detach[FORK SendFSError[fsError]]};
};
};
Reset:
PUBLIC
PROC[fileInput:
IO.
STREAM] ~ {
GetRidOfOne: CardTab.EachPairAction ~ {
s: IO.STREAM ← NARROW[val];
IF key>2 AND s#NIL THEN IO.Close[s ! FS.Error => CONTINUE];
};
s0: IO.STREAM ← GetStream[0];
s1: IO.STREAM ← GetStream[1];
s2: IO.STREAM ← GetStream[2];
[] ← CardTab.Pairs[x: streams, action: GetRidOfOne];
streams ← CardTab.Create[];
IO.Reset[s0];
[] ← CardTab.Store[streams, 0, s0];
IO.Reset[s1];
[] ← CardTab.Store[streams, 1, s1];
IO.Reset[s2];
[] ← CardTab.Store[streams, 2, s2];
SoftcardDataExch.Restart[];
};
streams: CardTab.Ref ← CardTab.Create[];
defaultDir: Rope.ROPE ← FSExtras.GetWDir[];
SoftcardDataExch.Register[SCLOSE, ActionClose];
SoftcardDataExch.Register[SWRITE, ActionWrite];
SoftcardDataExch.Register[SREAD, ActionRead];
SoftcardDataExch.Register[SSETINDEX, ActionSetIndex];
SoftcardDataExch.Register[SGETINDEX, ActionGetIndex];
SoftcardDataExch.Register[SSETLENGTH, ActionSetLength];
SoftcardDataExch.Register[SGETLENGTH, ActionGetLength];
SoftcardDataExch.Register[SOPEN, ActionOpen];
SparcSoftcardLoaderOps.RegisterStartProc[$SparcFSAccess, Reset];