-- 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]; }; }.