-- GeorgeAlto.mesa Edited by HGM on November 18, 1980 1:32 PM DIRECTORY AltoFileDefs USING [FP], DirectoryDefs USING [EnumerateDirectory], Inline USING [HighByte, LowByte], SegmentDefs USING [ Append, DefaultAccess, DefaultVersion, DestroyFile, FileHandle, FileNameError, GetFileTimes, InsertFile, NewFile, OldFileOnly, Read, ReleaseFile, SetFileTimes, WriteAppend], StreamDefs USING [ CreateByteStream, DiskHandle, FileLength, GetPosition, IndexToPosition, ReadBlock, SetPosition, WriteBlock], File USING [Capability, nullCapability], Space USING [Handle], System USING [GreenwichMeanTime], George USING [BYTE, Handle]; GeorgeAlto: PROGRAM IMPORTS DirectoryDefs, Inline, SegmentDefs, StreamDefs EXPORTS George, Space = BEGIN OPEN George; -- S P A C E S: nullHandle: PUBLIC Space.Handle ← NIL; -- D I R E C T O R Y and F I L E S: CreateNewFile: PUBLIC PROCEDURE [name: STRING, pages: CARDINAL] RETURNS [fp: File.Capability] = BEGIN OPEN SegmentDefs; file: FileHandle ← NewFile[ name, WriteAppend ! FileNameError => GOTO NotFound]; fp ← [file.fp, DefaultAccess]; EXITS NotFound => RETURN[File.nullCapability]; END; EnumerateDirectory: PUBLIC PROCEDURE [ proc: PROCEDURE [File.Capability, STRING] RETURNS [BOOLEAN]] = BEGIN MyProc: PROCEDURE [fp: POINTER TO AltoFileDefs.FP, name: STRING] RETURNS [BOOLEAN] = BEGIN name.length ← name.length - 1; -- stupid trailing dot RETURN[proc[[fp↑, SegmentDefs.DefaultAccess], name]]; END; DirectoryDefs.EnumerateDirectory[MyProc]; END; LookupExistingFile: PUBLIC PROCEDURE [name: STRING] RETURNS [fp: File.Capability] = BEGIN OPEN SegmentDefs; file: FileHandle ← NewFile[ name, Read, OldFileOnly ! FileNameError => GOTO NotFound]; fp ← [file.fp, DefaultAccess]; IF file.segcount = 0 AND file.lock = 0 THEN ReleaseFile[file]; EXITS NotFound => RETURN[File.nullCapability]; END; NameToCapability: PUBLIC PROCEDURE [name: STRING, pages: CARDINAL] RETURNS [fp: File.Capability] = BEGIN OPEN SegmentDefs; file: FileHandle ← NewFile[ name, Read + WriteAppend, DefaultVersion ! FileNameError => GOTO NotFound]; fp ← [file.fp, DefaultAccess]; IF file.segcount = 0 AND file.lock = 0 THEN ReleaseFile[file]; EXITS NotFound => RETURN[File.nullCapability]; END; DeleteFileFromDisk: PUBLIC PROCEDURE [fp: File.Capability] = BEGIN SegmentDefs.DestroyFile[SegmentDefs.InsertFile[@fp.fID]]; END; -- S T R E A M S: CreateAppendStream: PUBLIC PROCEDURE [fp: File.Capability] RETURNS [h: Handle] = BEGIN file: SegmentDefs.FileHandle ← SegmentDefs.InsertFile[ @fp.fID, SegmentDefs.Append]; h ← StreamDefs.CreateByteStream[file, SegmentDefs.Append]; END; CreateInputStream: PUBLIC PROCEDURE [fp: File.Capability] RETURNS [h: Handle] = BEGIN file: SegmentDefs.FileHandle ← SegmentDefs.InsertFile[ @fp.fID, SegmentDefs.Read]; h ← StreamDefs.CreateByteStream[file, SegmentDefs.Read]; END; CreateOutputStream: PUBLIC PROCEDURE [fp: File.Capability] RETURNS [h: Handle] = BEGIN file: SegmentDefs.FileHandle ← SegmentDefs.InsertFile[ @fp.fID, SegmentDefs.WriteAppend]; h ← StreamDefs.CreateByteStream[file, SegmentDefs.WriteAppend]; END; Destroy: PUBLIC PROCEDURE [h: Handle] = BEGIN h.destroy[h]; END; GetCreateDate: PUBLIC PROCEDURE [h: Handle] RETURNS [System.GreenwichMeanTime] = BEGIN dh: StreamDefs.DiskHandle = LOOPHOLE[h]; RETURN[SegmentDefs.GetFileTimes[dh.file].create]; END; GetIndex: PUBLIC PROCEDURE [h: Handle] RETURNS [LONG CARDINAL] = BEGIN RETURN[StreamDefs.GetPosition[h]]; END; GetLength: PUBLIC PROCEDURE [h: Handle] RETURNS [LONG CARDINAL] = BEGIN RETURN[StreamDefs.IndexToPosition[StreamDefs.FileLength[h]]]; END; SetCreateDate: PUBLIC PROCEDURE [h: Handle, t: System.GreenwichMeanTime] = BEGIN dh: StreamDefs.DiskHandle = LOOPHOLE[h]; SegmentDefs.SetFileTimes[file: dh.file, create: t]; END; SetIndex: PUBLIC PROCEDURE [h: Handle, i: LONG CARDINAL] = BEGIN StreamDefs.SetPosition[h, i]; END; -- D A T A T R A N S F E R: GetWords: PUBLIC PROCEDURE [h: Handle, p: POINTER, words: CARDINAL] RETURNS [CARDINAL] = BEGIN RETURN[StreamDefs.ReadBlock[h, p, words]]; END; GetByte: PUBLIC PROCEDURE [h: Handle] RETURNS [BYTE] = BEGIN RETURN[h.get[h]]; END; GetWord: PUBLIC PROCEDURE [h: Handle] RETURNS [WORD] = BEGIN left: BYTE ← h.get[h]; right: BYTE ← h.get[h]; RETURN[left*400B + right]; END; PutWordsHitEOF: ERROR = CODE; PutWords: PUBLIC PROCEDURE [h: Handle, p: POINTER, words: CARDINAL] = BEGIN n: CARDINAL = StreamDefs.WriteBlock[h, p, words]; IF n # words THEN ERROR PutWordsHitEOF; END; PutChar: PUBLIC PROCEDURE [h: Handle, c: CHARACTER] = BEGIN h.put[h, c]; END; PutByte: PUBLIC PROCEDURE [h: Handle, b: BYTE] = BEGIN h.put[h, b]; END; PutWord: PUBLIC PROCEDURE [h: Handle, w: WORD] = BEGIN h.put[h, Inline.HighByte[w]]; h.put[h, Inline.LowByte[w]]; END; END.