-- File: OthelloLisp.mesa -- Created 9-Jul-84 15:06:38 Lichtenberg DIRECTORY CommonSoftwareFileTypes USING [tCarryVolumeDirectory], Environment USING [wordsPerPage, Byte], File USING [Type, Create, Delete, File, MakePermanent, nullFile, PageNumber, PageCount, GetSize, SetSize, Unknown ], FileTypes USING [tUntypedFile], Floppy USING [Open, Close, FileHandle, nullFileID,GetNextFile, ErrorType, Error, VolumeHandle, Read, PageCount, PageNumber], Inline USING [LongCOPY], OthelloDefs, OthelloOps USING [ BootFileType, MakeBootable, MakeUnbootable, GetPhysicalVolumeBootFile, VoidPhysicalVolumeBootFile, SetVolumeBootFile, GetVolumeBootFile, VoidVolumeBootFile ], PhysicalVolume USING [ID], System USING [GreenwichMeanTime, gmtEpoch], Space USING [Map, CopyIn, Unmap, Window], TemporaryBooting USING [InvalidParameters], Time USING [Unpacked,Unpack,Append], Volume USING [Close, ID, GetAttributes, nullID, InsufficientSpace, Open ]; -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= OthelloLisp: PROGRAM IMPORTS File, OthelloDefs, OthelloOps, Floppy, Space, TemporaryBooting, Time, Volume, Inline = BEGIN -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -- These definitions stolen from AccessFloppy -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Attributes: TYPE = LONG POINTER TO AttributesRecord; AttributesRecord: TYPE = MACHINE DEPENDENT RECORD[ -- used by directory or leader page. -- identity attributes seal: WORD ← sealValue, -- used to check consistency of a file. version: CARDINAL, -- version of attributes record type. type: File.Type, -- file type of containing file. -- activity attributes createDate: FloppyTime, -- the creation data of the disk file. lastWrittenDate: FloppyTime, -- the date the disk file was last modified prior to copying to the floppy. -- file attributes size: Floppy.PageCount ← 0, -- number of pages in the floppy file not including the leader page. offset: Floppy.PageNumber ← 0, -- page number in the disk file correspoinding to the first page in the floppy file piece. totalSize: Floppy.PageCount ← 0, -- number of pages in the disk file. totalSizeInBytes: LengthInBytes ← 0, -- the number of bytes in the disk file -- name attributes length: CARDINAL ← 0, maxLength: CARDINAL ← maxNameLength, -- so that @length is STRING. name: PACKED ARRAY [0..maxNameLength) OF Environment.Byte, -- client attributes clientDataLength: CARDINAL ← 0 ,-- number of component in client's private data. clientData: SEQUENCE maxlength: CARDINAL OF UNSPECIFIED ]; LengthInBytes: TYPE = LONG CARDINAL; FloppyTime: TYPE = System.GreenwichMeanTime; tFloppyLeaderPage: File.Type = CommonSoftwareFileTypes.tCarryVolumeDirectory; -- Constants leaderLength: CARDINAL = 1; -- leaderLength*Environment.wordsPerPage must be greater than SIZE[AttributesRecord] maxDataSize: CARDINAL = leaderLength*Environment.wordsPerPage - SIZE[AttributesRecord]; maxNameLength: CARDINAL = 100; -- includes words field. nullTime: FloppyTime = System.gmtEpoch; sealValue: WORD = 125252B; -- 1010101010101010 bits pattern -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= CopyVM: PROC = BEGIN fromVolume, toVolume: Volume.ID; fromFile, toFile: File.File; pvID: PhysicalVolume.ID; error: BOOLEAN ← FALSE; currentBase: File.PageNumber; nextCount: File.PageCount; fromWindow,toWindow: Space.Window; toPointer: LONG POINTER; fromFileSize: File.PageCount; tries: CARDINAL; toFileSize: File.PageCount; minFileSize: File.PageCount; OthelloDefs.MyNameIs[ myNameIs: "Copy Lisp From Another Volume"L, myHelpIs: "Copies lisp from one volume to another"L]; [pvID, fromVolume] ← OthelloDefs.GetLvIDFromUser[prompt:"Volume to copy from: "L]; IF fromVolume = Volume.nullID THEN OthelloDefs.AbortingCommand["Invalid volume."L]; toVolume ← OthelloDefs.GetLvIDFromUser[prompt:"Volume to copy to: "L].lvID; IF toVolume = Volume.nullID THEN OthelloDefs.AbortingCommand["Invalid volume."L]; -- Open up the volumes Volume.Open[fromVolume]; Volume.Open[toVolume]; -- Is there a source file? fromFile ← OthelloOps.GetVolumeBootFile[fromVolume,hardMicrocode].file; IF fromFile = File.nullFile THEN { Volume.Close[fromVolume]; Volume.Close[toVolume]; OthelloDefs.AbortingCommand["No Lisp sysout on source volume"L]; }; -- Is there a dest file? Delete it if yes. toFile ← OthelloOps.GetVolumeBootFile[toVolume,hardMicrocode].file; IF toFile # File.nullFile THEN { OthelloOps.VoidVolumeBootFile[toVolume,hardMicrocode]; File.Delete[toFile]; IF OthelloOps.GetPhysicalVolumeBootFile[pvID,hardMicrocode].file = toFile THEN OthelloOps.VoidPhysicalVolumeBootFile[pvID,hardMicrocode]; }; -- Create the dest file fromFileSize ← File.GetSize[fromFile]; toFileSize ← fromFileSize; tries ← 20; toFile ← File.Create[toVolume, toFileSize, FileTypes.tUntypedFile ! Volume.InsufficientSpace => { tries ← tries - 1; toFileSize ← toFileSize - 100; OthelloDefs.WriteString["."L]; IF tries = 0 OR toFileSize < 0 THEN {error ← TRUE; CONTINUE} ELSE RETRY;};]; IF error THEN {Volume.Close[fromVolume]; Volume.Close[toVolume]; OthelloDefs.AbortingCommand["Destination volume does not contain sufficient space!"L];}; File.MakePermanent[toFile]; -- Create windows onto the file OthelloDefs.WriteString["Copying..."L]; currentBase ← 0; nextCount ← 100; minFileSize ← fromFileSize; IF toFileSize < fromFileSize THEN minFileSize ← toFileSize; DO -- until file has been copied fromWindow ← [file: fromFile, base: currentBase, count: nextCount]; toWindow ← [file: toFile, base: currentBase, count: nextCount]; toPointer ← Space.Map[toWindow].pointer; nextCount ← Space.CopyIn[toPointer,fromWindow]; toPointer ← Space.Unmap[toPointer]; currentBase ← currentBase + nextCount; OthelloDefs.WriteString["."L]; IF currentBase >= minFileSize THEN EXIT; ENDLOOP; OthelloDefs.WriteString["Installing..."L]; OthelloOps.MakeBootable[toFile, hardMicrocode, OthelloDefs.leaderPages ! TemporaryBooting.InvalidParameters => { OthelloDefs.WriteLine["Warning, trouble making bootable"L]; CONTINUE}]; OthelloOps.SetVolumeBootFile[toFile,hardMicrocode,OthelloDefs.leaderPages]; OthelloDefs.WriteLine["done"L]; Volume.Close[fromVolume]; Volume.Close[toVolume]; END; -- UGH.. This kludge sets the file's size to be as big as Pilot will let it be, on 100 page increments. SetBootFileSize: PRIVATE PROC[file: File.File, lvID: Volume.ID] = BEGIN tries: CARDINAL; oldSize: File.PageCount ← File.GetSize[file]; newSize: File.PageCount ← oldSize + Volume.GetAttributes[lvID].freePageCount; tries ← 20; OthelloOps.MakeUnbootable[file, hardMicrocode, OthelloDefs.leaderPages]; File.SetSize[file, newSize ! File.Unknown => {OthelloDefs.WriteLine["Warning: Trouble making file fill volume - File.Unknown"L]; CONTINUE}; Volume.InsufficientSpace => {OthelloDefs.WriteString["."L]; newSize ← newSize - 100; tries ← tries - 1; IF tries = 0 OR newSize < oldSize THEN {OthelloDefs.WriteLine["Warning: Expanding volume failed!"]; CONTINUE;} ELSE RETRY};]; OthelloOps.MakeBootable[file,hardMicrocode, OthelloDefs.leaderPages]; END; ExpandVM: PROC = BEGIN pvID: PhysicalVolume.ID; exVolume: Volume.ID; exFile: File.File; OthelloDefs.MyNameIs[ myNameIs: "Expand Vmem File"L, myHelpIs: "Expand the lisp virtual mem file on a volume"L]; [pvID, exVolume] ← OthelloDefs.GetLvIDFromUser[prompt:"Volume to expand: "L]; IF exVolume = Volume.nullID THEN OthelloDefs.AbortingCommand["Invalid volume."L]; Volume.Open[exVolume]; exFile ← OthelloOps.GetVolumeBootFile[exVolume, hardMicrocode].file; IF exFile = File.nullFile THEN OthelloDefs.AbortingCommand["No sysout on volume."L]; OthelloDefs.WriteString["Expanding file..."L]; SetBootFileSize[exFile,exVolume]; OthelloDefs.WriteLine["Done."L]; Volume.Close[exVolume]; END; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- FLOPPY commands --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ListFloppyFiles: PROC = BEGIN floppyHandle: Floppy.VolumeHandle; attRec: AttributesRecord; floppyFileAttributes: Attributes ← @attRec; currentFloppyFile: Floppy.FileHandle ← [floppyHandle,Floppy.nullFileID]; i: CARDINAL; timeTemp: STRING; unpackedTime: Time.Unpacked; floppyFileAttributes ← @attRec; -- Open floppy OthelloDefs.MyNameIs[myNameIs: "List Floppy Files"L, myHelpIs: "List files on pilot floppy"L]; floppyHandle ← Floppy.Open[ ! Floppy.Error => {PrintNames: PROC [x: Floppy.ErrorType] = {ShowFloppyError[x]};};]; -- Enumerate files DO currentFloppyFile ← Floppy.GetNextFile[currentFloppyFile]; IF currentFloppyFile.file = Floppy.nullFileID THEN EXIT; ReadLeaderPage[currentFloppyFile, floppyFileAttributes]; FOR i IN [0..floppyFileAttributes.length) DO OthelloDefs.WriteChar[LOOPHOLE[floppyFileAttributes.name[i]]]; ENDLOOP; THROUGH [0..(60-floppyFileAttributes.length)) DO OthelloDefs.WriteChar[' ]; ENDLOOP; OthelloDefs.WriteLongNumber[floppyFileAttributes.size]; OthelloDefs.WriteString[" "L]; unpackedTime ← Time.Unpack[time: floppyFileAttributes.createDate]; timeTemp ← " "; Time.Append[timeTemp,unpackedTime]; OthelloDefs.WriteLine[timeTemp]; ENDLOOP; Floppy.Close[floppyHandle]; END; ShowFloppyError: PROC [error:Floppy.ErrorType] = { errString: ARRAY Floppy.ErrorType OF STRING = [ notReady: "Floppy drive not ready."L, noSuchDrive: "noSuchDrive"L, invalidFormat: "Floppy not in pilot format"L, needsScavenging: "Floppy needs scavenging"L, invalidVolumeHandle: "invalidVolumeHandle"L, volumeNotOpen: "volumeNotOpen"L, fileNotFound: "File Not Found"L, endOfFile: "End of File"L, writeInhibited: "Floppy is write-protected"L, hardwareError: "Floppy hardware error"L, incompatibleSizes: "incompatibleSizes"L, insufficientSpace: "Floppy volume is full."L, zeroSizeFile: "Floppy file is zero-size!"L, fileListFull: "Floppy file list is full."L, invalidPageNumber: "invalidPageNumber"L, badDisk: "badDisk"L, badSectors: "badSectors"L, onlyOneSide: "onlyOneSide"L, onlySingleDensity: "onlySingleDensity"L, initialMicrocodeSpaceNotAvailable: "initialMicrocodeSpaceNotAvailable"L, stringTooShort: "stringTooShort"L, fileListLengthTooShort: "fileListLengthTooShort"L, floppyImageInvalid: "floppyImageInvalid"L, floppySpaceTooSmall: "floppySpaceTooSmall"L]; OthelloDefs.WriteString["Unexpected floppy problem: "L]; OthelloDefs.WriteString[errString[error]]; OthelloDefs.AbortingCommand["Floppy command aborted."L]; }; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- The following procs were stolen (more or less) from AccessFloppyImpl --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ReadLeaderPage: PROC [ file: Floppy.FileHandle, attributes: Attributes] = BEGIN -- make the buffer for the AttributesRecord in full pages. buffer: ARRAY [1..maxDataSize + SIZE[AttributesRecord]] OF WORD ← ALL[0]; length: CARDINAL ← 0; localAttributes: Attributes ← LOOPHOLE[LONG[@buffer]]; Floppy.Read[file, 0, leaderLength, localAttributes]; IF localAttributes.clientDataLength > attributes.maxlength THEN localAttributes.clientDataLength ← 0; length ← SIZE[AttributesRecord] + localAttributes.clientDataLength; [] ← Inline.LongCOPY[to: attributes, nwords: length, from: localAttributes]; END; -- ReadLeaderPage. --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Central commands --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ commandProcessor: OthelloDefs.CommandProcessor ← [LispCommands]; LispCommands: PROC [index: CARDINAL] = { SELECT index FROM 0 => CopyVM[]; 1 => ExpandVM[]; 2 => ListFloppyFiles[]; ENDCASE => OthelloDefs.IndexTooLarge}; -- Initialize OthelloDefs.RegisterCommandProc[@commandProcessor]; END...