-- StreamDefsImpl.mesa
-- Updated for Pilot Martin Newell 23-Jul-81 14:02:05
-- Last changed by Doug Wyatt, 13-Oct-81 17:46:21
-- Last changed by Bill Paxton, 22-Jan-82 8:35:38
DIRECTORY
DCSFileTypes USING [tLeaderPage],
Directory USING [CreateFile, Error, Lookup],
File USING [Capability, grow, LimitPermissions, Permissions, read, shrink, write],
FileStream USING [Create, EndOf, SetIndex],
JaMStorage USING [Zone],
Inline USING [BITAND, BITOR],
Stream USING [Delete, GetChar, GetWord, Handle, PutChar, PutWord],
StreamDefs USING [AccessOptions, Append, Read, StreamErrorCode,
StreamHandle, StreamObject, Write];
StreamDefsImpl: PROGRAM
IMPORTS Directory, File, FileStream, JaMStorage, Inline, Stream
EXPORTS StreamDefs = {
OPEN StreamDefs;
zone: UNCOUNTED ZONE = JaMStorage.Zone[];
StreamError: PUBLIC SIGNAL[stream: StreamHandle, error: StreamErrorCode] = CODE;
FileNameError: PUBLIC SIGNAL[name: LONG STRING] = CODE;
IsSet: PROC[a,b: UNSPECIFIED] RETURNS[BOOLEAN] = INLINE {
RETURN[Inline.BITAND[a,b]#0] };
Set: PROC[p: POINTER TO UNSPECIFIED, b: UNSPECIFIED] = INLINE {
p↑ ← Inline.BITOR[p↑,b] };
NewByteStream: PUBLIC PROC[name: LONG STRING, access: AccessOptions]
RETURNS [StreamHandle] = { OPEN File;
data: Data ← NIL;
s: StreamHandle ← NIL;
permissions: Permissions ← 0;
IF IsSet[access,Read] THEN Set[@permissions,read];
IF IsSet[access,Write] THEN Set[@permissions,write+shrink];
IF IsSet[access,Append] THEN Set[@permissions,write+grow];
IF permissions=0 THEN permissions ← read;
data ← NewStream[name,permissions];
s ← zone.NEW[StreamObject ← [reset: FileReset, get: FileGetChar,
putback: FilePutback, put: FilePutChar, endof: FileEndof, destroy: FileDestroy,
data: data]];
RETURN[s];
};
NewWordStream: PUBLIC PROC[name: LONG STRING, access: AccessOptions]
RETURNS [StreamHandle] = {
s: StreamHandle ← NewByteStream[name,access];
s.get ← FileGetWord; s.put ← FilePutWord;
RETURN[s];
};
Data: TYPE = LONG POINTER TO FileStreamData;
FileStreamData: TYPE = RECORD[file: Stream.Handle];
NewStream: PROC[name: LONG STRING, access: File.Permissions]
RETURNS[Data] = {
cap: File.Capability;
new: BOOLEAN ← FALSE;
cap ← Directory.Lookup[fileName: name, permissions: access !
Directory.Error => SELECT type FROM
fileNotFound => { new ← TRUE; CONTINUE };
invalidFileName => GOTO NotFound;
ENDCASE];
IF new THEN {
IF IsSet[access,File.read] THEN GOTO NotFound;
cap ← Directory.CreateFile[fileName: name,
fileType: DCSFileTypes.tLeaderPage, size: 0];
cap ← File.LimitPermissions[cap,access];
};
RETURN[zone.NEW[FileStreamData ← [FileStream.Create[cap]]]];
EXITS NotFound => ERROR FileNameError[name];
};
-- File Stream Procedures
FileReset: PROC[s: StreamHandle] = {
data: Data ← s.data;
FileStream.SetIndex[data.file,0];
};
FileGetChar: PROC[s: StreamHandle] RETURNS [CHARACTER] = {
data: Data ← s.data;
RETURN[Stream.GetChar[data.file]];
};
FileGetWord: PROC[s: StreamHandle] RETURNS [WORD] = {
data: Data ← s.data;
RETURN[Stream.GetWord[data.file]];
};
FilePutback: PROC[s: StreamHandle, c: CHARACTER] = {
ERROR StreamError[s,StreamOperation];
};
FilePutChar: PROC[s: StreamHandle, c: CHARACTER] = {
data: Data ← s.data;
Stream.PutChar[data.file, c];
};
FilePutWord: PROC[s: StreamHandle, w: WORD] = {
data: Data ← s.data;
Stream.PutWord[data.file, w];
};
FileEndof: PROC[s: StreamHandle] RETURNS [BOOLEAN] = {
data: Data ← s.data;
RETURN[FileStream.EndOf[data.file]];
};
FileDestroy: PROC[s: StreamHandle] = {
data: Data ← s.data;
Stream.Delete[data.file];
zone.FREE[@data];
zone.FREE[@s];
};
}.