SoftcardFSAccessImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
written by Ch. Le Cocq, August 4, 1988
Christian Le Cocq January 19, 1989 11:18:05 am PST
Christophe Cuenod September 12, 1988 5:59:56 pm PDT
Description of what this module does.
DIRECTORY
Atom,
CardTab,
IO,
FS,
FSExtras,
PrincOps,
Process,
RefText,
Rope,
SoftcardDataExch,
SoftcardFSAccess,
SoftcardTool,
SparcSoftcardLoaderOps;
SoftcardFSAccessImpl: CEDAR PROGRAM
IMPORTS Atom, CardTab, IO, FS, FSExtras, Process, RefText, Rope, SoftcardDataExch, SoftcardTool, SparcSoftcardLoaderOps
EXPORTS SoftcardFSAccess
~ 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: BOOLEANFALSE;
log: IO.STREAMNIL;
Log on file
logName: Rope.ROPE;
StartLog: PROC [fName: Rope.ROPENIL] ~ {
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.STREAMIO.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: NATMAX[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: NATMIN[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 ! IO.EndOfStream => CONTINUE];
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: INTIO.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"];}
EXITS
Exit => NULL;
};
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: INTIO.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.STREAMIO.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.STREAMNARROW[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];
END.