-- LTFloppyImpl.mesa
-- Created by
-- JFung.pasa 14-Dec-83 12:37:04
-- a modified version taken from FloppyStuff.mesa
-- last edited by
-- JFung.pasa 14-Sep-84 10:10:39
DIRECTORY
AccessFloppy,
AccessFloppyUtil,
Ascii,
Environment,
Exec,
File,
FileName,
FileTypes USING [tUntypedFile],
Floppy,
Format,
FormSW,
Heap USING [systemZone],
Inline,
LispToolOps,
MFile,
MStream,
NSString USING [StringFromMesaString],
OthelloDefs,
OthelloOps,
Process USING [Pause, SecondsToTicks],
Put,
Runtime,
Space,
SpecialMFile USING [GetCapaWithAccess, LeaderPages],
Storage,
Stream,
String,
StringLookUp,
Time,
Tool USING [
Create, Destroy, MakeFileSW, MakeFormSW, MakeMsgSW, MakeSWsProc,
UnusedLogName],
ToolDriver,
ToolWindow,
Token,
UserInput,
Version,
Volume,
Window;
LTFloppyImpl: PROGRAM
IMPORTS
AccessFloppy, File, FileName, Floppy, FormSW,
Heap, Inline, LispToolOps, MFile, NSString, OthelloDefs, OthelloOps,
Process, Put, SpecialMFile, Storage, String, Volume,
Time, Tool, ToolDriver, Token,
UserInput
EXPORTS LispToolOps =
BEGIN OPEN ILT: LispToolOps;
-- constant
nullNextFile: NextFile = [];
-- TYPEs
Indicator: TYPE = {off, left, right};
DataHandle: TYPE = LONG POINTER TO Data;
Data: TYPE = MACHINE DEPENDENT RECORD [
-- Message subwindow stuff
msgSW(0): Window.Handle ← NIL,
-- File subwindow stuff
fileSW(2): Window.Handle ← NIL,
-- Form subwindow stuff
-- Note: enumerateds and booleans must be word boundary
-- aligned as addresses for them must be generated
--formSW: Window.Handle ← NIL,
paramSW(4): Window.Handle ← NIL,
commandSW(6): Window.Handle ← NIL,
busy(8): BOOLEAN ← FALSE, -- command is running
volName(9): LONG STRING ← NIL,
pattern(11): LONG STRING ← NIL,
indicator(13): Indicator ← left,
floppyName(14): LONG STRING ← NIL,
stream(16): MStream.Handle ← NIL,
from(18): LONG STRING ← NIL,
to(20): LONG STRING ← NIL,
numberOfFiles(22): INTEGER ← 0,
current(23): LptNextFile ← NIL,
fileList(25): LptNextFile ← NIL];
EnumProc: TYPE = PROCEDURE [
attributes: AccessFloppy.Attributes, fH: Floppy.FileHandle,
name: LONG STRING] RETURNS [stop: BOOLEAN ← FALSE];
LptNextFile: TYPE = LONG POINTER TO NextFile;
NextFile: TYPE = RECORD [
file: LONG STRING ← NIL,
size: LONG CARDINAL ← 0, -- file size including leader page if it has one.
type: File.Type ← AccessFloppy.tFloppyLeaderPage, -- specify whether it has leader page.
next: LptNextFile ← NIL];
VolHints: TYPE = RECORD [names: SEQUENCE length: CARDINAL OF LONG STRING];
SizeHints: TYPE = RECORD [names: SEQUENCE length: CARDINAL OF CARDINAL];
-- global variables
Abort: ERROR [s: STRING] = CODE;
active: BOOLEAN ← FALSE;
atSource: PUBLIC CARDINAL ← 0;
attributes: AccessFloppy.Attributes ← NIL;
bufferSize: Space.PageCount ← 30;
dataVersion: CARDINAL = 02222; -- version of clientData
debug: BOOLEAN ← TRUE;
floppyWH: Window.Handle ← NIL;
formDisplay: ToolWindow.DisplayProcType ← NIL;
heraldName: STRING ← [50];
indicatorBox: Window.Box = [[10, 10], [16, 16]];
nullFile: Floppy.FileHandle;
opened: BOOLEAN ← FALSE;
--spaceHandle: Space.Handle ← Space.nullHandle;
toolData: DataHandle ← NIL;
vH: Floppy.VolumeHandle ← Floppy.nullVolumeHandle;
volumeID: Volume.ID ← Volume.nullID;
volumeOpen: BOOLEAN ← FALSE;
z: UNCOUNTED ZONE = Heap.systemZone;
SetOutcome: SIGNAL [value: Exec.Outcome] = CODE;
CleanUp: PROC =
BEGIN
current: LptNextFile ← toolData.fileList;
releaseData: MFile.ReleaseData ← [NIL, NIL];
WHILE current↑ # nullNextFile DO
file: MFile.Handle ← NIL;
scratchName: LONG STRING ← [120];
String.AppendString[scratchName, current.file];
String.AppendString[scratchName, ".Scratch$"L];
toolData.current ← current.next;
file ← MFile.Acquire[
scratchName, MFile.Access[delete], releaseData];
MFile.Delete[file];
--current.file ← Storage.FreeStringNil[current.file];
Storage.Free[current];
current ← toolData.current;
ENDLOOP;
toolData.fileList ← toolData.current ← Storage.FreeNodeNil[
toolData.current];
toolData.from ← Storage.FreeStringNil[toolData.from];
toolData.to ← Storage.FreeStringNil[toolData.to];
END; -- CleanUp.
<<
CopyCmd: PROCEDURE =
BEGIN
floppyOpened: BOOLEAN ← FALSE;
skip: BOOLEAN ← FALSE;
IF debug THEN {
Put.Line[toolData.fileSW, "AccessFloppy.Open...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[vH] ← OpenFloppy[];
IF ~opened THEN RETURN;
IF debug THEN {
Put.Line[toolData.fileSW, "Floppy.GetAttributes...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[] ← Floppy.GetAttributes[vH, toolData.floppyName];
toolData.numberOfFiles ← 0;
--IF toolData.to # NIL THENtoolData.to ← Storage.FreeStringNil[toolData.to];
-- toolData.to ← Storage.String[Floppy.maxCharactersInLabel];
IF debug THEN {
Put.Line[toolData.fileSW, "z.NEW[NextFile ← []...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
toolData.fileList ← z.NEW[NextFile ← []];
toolData.current ← toolData.fileList;
IF debug THEN {
Put.Line[toolData.fileSW, "AccessFloppyUtil.CreateBuffer..."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[spaceHandle, bufferSize] ← CreateBuffer[bufferSize];
IF debug THEN {
Put.Line[toolData.fileSW, ".FloppyToDisk...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
FloppyToDisk[];
[skip] ← FormatAndOpen[];
IF skip THEN RETURN;
-- now ask user remove current one, insert a new one, format and open it.
IF debug THEN {
Put.Line[toolData.fileSW, ".DiskToFloppy...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
DiskToFloppy[];
IF debug THEN {
Put.Line[toolData.fileSW, ".DiskToFloppy...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
CleanUp[]; -- trace fileList to delete disk file, release NextFile nodes, and release data.from and data.to strings.
IF debug THEN {
Put.Line[toolData.fileSW, ".DiskToFloppy...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
AccessFloppyUtil.DeleteBuffer[spaceHandle];
END;
-- from AccessFloppyUtil
CreateBuffer: PUBLIC PROC [size: Space.PageCount]
RETURNS [spH: Space.Handle, spSize: Space.PageCount] =
BEGIN
volID: Volume.ID;
volOpen: BOOLEAN ← FALSE;
spSize ← MIN[size, 200];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "toolData.volName...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
PutVolumeName[];
[volID, volOpen] ← ILT.GetVolumeID[toolData.volName];
IF ~volOpen THEN RETURN;
IF ~ILT.Confirm[] THEN RETURN;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, ".Space.Create...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
spH ← Space.Create[
spSize, Space.virtualMemory !
Space.InsufficientSpace =>
IF available # 0 THEN {spSize ← available; RETRY}];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, ".Space.Map...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
Space.Map[spH];
END; -- CreateBuffer.
DeleteBuffer: PUBLIC PROC [spH: Space.Handle] =
BEGIN
Space.Kill[spH];
Space.Unmap[spH];
Space.Delete[spH];
END; -- DeleteBuffer.
DiskToFloppy: PROC =
BEGIN
storeFile: Floppy.FileHandle ← nullFile;
FOR current: LptNextFile ← toolData.fileList, current.next WHILE current↑
# nullNextFile DO
handle: MStream.Handle ← NIL;
scratchName: LONG STRING ← [120];
String.AppendString[scratchName, current.file];
String.AppendString[scratchName, ".Scratch$"L];
handle ← MStream.ReadOnly[scratchName, [NIL, NIL]];
storeFile ← Floppy.CreateFile[vH, current.size, current.type];
StoreFilePiece[handle, storeFile, current.size];
handle.delete[handle];
ENDLOOP;
-- will have current points to a NextFile[NIL, NIL].
END; -- DiskToFloppy.
>>
DisplayFloppyName: PROCEDURE [] =
BEGIN
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "DisplayFile...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
FormSW.DisplayItem[toolData.paramSW, 3];
END; --DisplayFloppyName
EnumerateFloppyFiles: PROCEDURE [
v: Floppy.VolumeHandle, proc: EnumProc, pattern: LONG STRING] =
BEGIN
nullFile: Floppy.FileHandle = [volume: v, file: Floppy.nullFileID];
attributes: AccessFloppy.Attributes ← Heap.systemZone.NEW[
AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]];
name: LONG STRING = LOOPHOLE[@attributes.length];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "EnumerateFloppyFiles...."L];
--Process.Pause[Process.SecondsToTicks[5]];
};
FOR current: Floppy.FileHandle ← Floppy.GetNextFile[nullFile].nextFile,
Floppy.GetNextFile[current].nextFile WHILE current # nullFile DO
ENABLE UNWIND => Heap.systemZone.FREE[@attributes];
IF Floppy.GetFileAttributes[current].type #
AccessFloppy.tFloppyLeaderPage THEN LOOP;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "Floppy.GetNextFile"L];
--Process.Pause[Process.SecondsToTicks[5]];
Put.Text[ILT.toolData.fileSW, "Pattern = "L];
Put.Line[ILT.toolData.fileSW, pattern];
};
AccessFloppy.GetAttributes[current, attributes];
IF
--(pattern = NIL
--OR Exec.MatchPattern[string: name, pattern: pattern]) OR
proc[attributes, current, name] THEN {
Put.Line[ILT.toolData.fileSW, "Exited loop."L]; EXIT; };
ENDLOOP;
Heap.systemZone.FREE[@attributes];
END; --EnumerateFloppyFiles
FixDirectory: PUBLIC PROC [dir: LONG POINTER TO LONG STRING] =
BEGIN
IF dir↑ = NIL THEN RETURN;
SELECT dir[dir.length - 1] FROM '>, '# => RETURN; ENDCASE;
String.AppendCharAndGrow[dir, '>, z];
END; --FixDirectory
FloppyDelete: PUBLIC PROCEDURE [pattern: LONG STRING]
RETURNS [deleted: BOOLEAN] =
BEGIN
name: LONG STRING ← NIL;
vH: Floppy.VolumeHandle;
DeleteOne: EnumProc =
BEGIN
deleted ← TRUE;
Put.Text[ILT.toolData.msgSW, name];
Put.Text[ILT.toolData.msgSW, "... "L];
AccessFloppy.DeleteFile[
NSString.StringFromMesaString[name] !
AccessFloppy.Error =>
SELECT type FROM
fileNotFound => {
Put.Line[ILT.toolData.msgSW, "not found"L];
IF debug THEN
Process.Pause[Process.SecondsToTicks[5]];
GOTO error;
};
ENDCASE];
Put.Line[ILT.toolData.msgSW, "deleted"L];
IF debug THEN Process.Pause[Process.SecondsToTicks[10]];
RETURN[];
EXITS error => {deleted ← FALSE; RETURN[]; };
END; --DeleteOne
[vH] ← OpenFloppy[];
IF ~opened THEN RETURN;
BEGIN
ENABLE UNWIND => {AccessFloppy.Close[ ! Floppy.Error => CONTINUE]};
--name ← toolData.pattern;
--IF toolData.pattern = NIL THEN EXIT;
IF WildCards[pattern] THEN EnumerateFloppyFiles[vH, DeleteOne, pattern]
ELSE [] ← DeleteOne[NIL, [vH, Floppy.nullFileID], pattern];
END;
IF debug THEN {
Put.Text[ILT.toolData.fileSW, "AccessFloppy.Close"L];
Process.Pause[Process.SecondsToTicks[5]];
};
AccessFloppy.Close[];
END; --FloppyDelete
FloppyDuplicate: PUBLIC PROCEDURE =
BEGIN
END;
FloppyFormat: PROCEDURE [
nFiles: CARDINAL, label: LONG STRING, sides: Floppy.Sides,
density: Floppy.Density] RETURNS [gotError: BOOLEAN] =
BEGIN
gotError: BOOLEAN ← FALSE;
BEGIN
v: Floppy.VolumeHandle;
v ← AccessFloppy.Open[
!
Floppy.Error =>
SELECT error FROM
invalidFormat => GOTO virgin;
needsScavenging => {gotError ← TRUE; CONTINUE};
ENDCASE => gotError ← TRUE; ];
IF ~gotError THEN {
[] ← Floppy.GetAttributes[v, label];
Floppy.Close[v];
Put.Text[ILT.toolData.fileSW, "Floppy volume """L];
Put.Text[ILT.toolData.fileSW, label];
Put.Line[ILT.toolData.fileSW, """ already formatted"L];
}
ELSE
Put.Line[
toolData.fileSW,
"Floppy probably contains valid information"L];
EXITS virgin => NULL;
END;
Put.Line[
toolData.fileSW,
"Formatting will DESTROY all contents, confirm to continue"L];
IF ~ILT.Confirm[] THEN RETURN;
--label.length ← 0;
IF label = NIL THEN {
Put.Line[toolData.fileSW, "Please supply floppy name"];
Process.Pause[Process.SecondsToTicks[5]];
RETURN;
};
<< IF label # NIL THEN
toolData.floppyName ← String.CopyToNewString[
s: label, z: Heap.systemZone]
ELSE toolData.floppyName ← String.CopyToNewString[
s: "UnnamedFloppy"L, z: Heap.systemZone];
>>
IF label # NIL OR toolData.floppyName # NIL THEN {
Put.Text[toolData.fileSW, "label # Nil:"L];
Put.Text[toolData.fileSW, label];
Put.Line[toolData.fileSW, "<"L];
Process.Pause[Process.SecondsToTicks[5]];
toolData.floppyName ← label;
Put.Text[toolData.fileSW, "floppyName:"L];
Put.Text[toolData.fileSW, toolData.floppyName];
Put.Line[toolData.fileSW, "<"L];
Process.Pause[Process.SecondsToTicks[5]];
toolData.floppyName ← String.CopyToNewString[
s: label, z: Heap.systemZone];
Put.Text[toolData.fileSW, "floppyName:"L];
Put.Text[toolData.fileSW, toolData.floppyName];
Put.Line[toolData.fileSW, "<"L];
};
IF debug THEN {
Put.Line[ILT.toolData.fileSW, toolData.floppyName];
Process.Pause[Process.SecondsToTicks[5]];
};
IF ~ILT.Confirm[] THEN RETURN; --temp
Put.Text[toolData.fileSW, "Formatting... "L];
Floppy.Format[
0, nFiles, toolData.floppyName, density, sides !
Floppy.Error =>
SELECT error FROM
onlyOneSide => {sides ← one; RETRY};
onlySingleDensity => {density ← single; RETRY};
badDisk => {
Put.Line[
toolData.fileSW,
"Can't format this disk; may be write protecte"L];
gotError ← TRUE;
Process.Pause[Process.SecondsToTicks[5]];
GOTO noGood;
};
ENDCASE;
-- ERROR Abort["Can't format this disk; may be write protected"L];
Floppy.AlreadyFormatted => RESUME ];
Put.Line[toolData.fileSW, "...done"L];
EXITS noGood => RETURN;
END; -- FloppyFormat
FloppyInfo: PROCEDURE [] =
BEGIN
density: Floppy.Density;
sides: Floppy.Sides;
label: STRING ← [Floppy.maxCharactersInLabel];
freeSpace, largestBlock: LONG CARDINAL;
v: Floppy.VolumeHandle;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "InfoDisk...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[v] ← OpenFloppy[];
IF ~opened THEN RETURN;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "GetAttributes...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[freeSpace, largestBlock, , , density, sides] ← Floppy.GetAttributes[
v, label];
toolData.floppyName ← String.CopyToNewString[
s: label, z: Heap.systemZone];
Put.CR[toolData.fileSW];
Put.Text[toolData.fileSW, "Floppy """L];
Put.Text[toolData.fileSW, label];
Put.Text[toolData.fileSW, """; "L];
Put.Text[toolData.fileSW, IF sides = one THEN "single"L ELSE "double"L];
Put.Text[toolData.fileSW, " sided; "L];
Put.Text[
toolData.fileSW, IF density = single THEN "single"L ELSE "double"L];
Put.Line[toolData.fileSW, " density"L];
Put.LongDecimal[toolData.fileSW, freeSpace];
Put.Text[toolData.fileSW, " free pages; largest free block = "L];
Put.LongDecimal[toolData.fileSW, largestBlock];
Put.Line[toolData.fileSW, " pages"L];
AccessFloppy.Close[];
FormSW.DisplayItem[toolData.paramSW, 2];
END; --FloppyInfo
FloppyList: PROCEDURE [] =
BEGIN
pattern: LONG STRING ← NIL;
v: Floppy.VolumeHandle;
ListOne: EnumProc =
BEGIN
Put.CR[toolData.fileSW];
Put.Text[toolData.fileSW, name];
FOR i: CARDINAL IN [name.length + WritePartial[attributes]..24) DO
Put.Text[toolData.fileSW, " "]; ENDLOOP;
Put.Number[toolData.fileSW, attributes.type, [10, FALSE, TRUE, 5]];
Put.Text[toolData.fileSW, " "L];
Put.LongNumber[
toolData.fileSW, attributes.totalSizeInBytes, [
10, FALSE, TRUE, 9]];
Put.Text[toolData.fileSW, " "L];
Put.Date[toolData.fileSW, attributes.createDate, noSeconds];
Put.Text[toolData.fileSW, " "L];
Put.Date[toolData.fileSW, attributes.lastWrittenDate, noSeconds];
END; --ListOne
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "ListFiles: AccessFloppy.Open...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[v] ← OpenFloppy[];
IF ~opened THEN RETURN;
Put.Text[toolData.fileSW, " NAME "L]; --23
Put.Text[toolData.fileSW, " TYPE "L]; -- 5+2
Put.Text[toolData.fileSW, " LENGTH "L]; -- 9+2
Put.Text[toolData.fileSW, " CREATE "L]; -- 20+2
Put.Line[toolData.fileSW, " WRITE"L];
EnumerateFloppyFiles[
v, ListOne, "*"L !
UNWIND => {AccessFloppy.Close[ ! Floppy.Error => CONTINUE]}];
AccessFloppy.Close[];
END; --FloppyList
FloppyReadSysout: PUBLIC PROCEDURE [pattern: LONG STRING] RETURNS[BOOLEAN] =
BEGIN
attributes: AccessFloppy.Attributes ← NIL;
altName: LONG STRING ← NIL;
created: BOOLEAN ← FALSE;
failed: BOOLEAN ← FALSE;
file: File.File;
fFile: Floppy.FileHandle;
firstPage: File.PageNumber;
nextFile: LONG STRING ← ILT.toolData.filePathName;
readName: LONG STRING ← NIL;
switches: LONG STRING ← NIL;
v: Floppy.VolumeHandle;
--ReadOne: EnumProc =
ReadOne: PROCEDURE [
attributes: AccessFloppy.Attributes, fH: Floppy.FileHandle,
name: LONG STRING] RETURNS [stop: BOOLEAN ← FALSE] =
BEGIN
--mFile: MFile.Handle ← NIL;
type: MFile.Type ← unknown;
destName: LONG STRING ← NIL;
srcVFN, destVFN: FileName.VirtualFilename ← NIL;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "ReadOne"L];
Process.Pause[Process.SecondsToTicks[5]];
};
--InvertIndicator[];
IF name # NIL THEN srcVFN ← FileName.AllocVFN[name];
IF String.Length[altName] # 0 THEN
destVFN ← FileName.AllocVFN[altName]
ELSE destVFN ← FileName.AllocVFN["[dummy]"L];
IF String.Length[destVFN.name] = 0 THEN {
destName ← FileName.PackFilename[
srcVFN, FALSE, FALSE, TRUE, FALSE];
FileName.UnpackFilename[destName, destVFN];
FileName.FreeFilename[destName];
};
destName ← FileName.PackFilename[destVFN, FALSE, TRUE, TRUE, FALSE];
Put.Text[ILT.toolData.fileSW, name];
Put.Text[ILT.toolData.fileSW, "... "L];
IF attributes.clientDataLength = 2
AND attributes.clientData[0] = dataVersion THEN
type ← attributes.clientData[1];
Put.Text[ILT.toolData.fileSW, "copying to "L];
Put.Text[ILT.toolData.fileSW, destName];
[] ← WritePartial[attributes];
Put.Text[ILT.toolData.fileSW, "... "L];
IF debug THEN {
Put.LongDecimal[ILT.toolData.fileSW, attributes.totalSizeInBytes];
Process.Pause[Process.SecondsToTicks[10]];
};
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "Floppy.CopyToPilotFile"L];
Put.Decimal[ILT.toolData.fileSW, AccessFloppy.leaderLength];
Put.CR[ILT.toolData.fileSW];
Put.LongDecimal[ILT.toolData.fileSW, SpecialMFile.LeaderPages[]];
Put.CR[ILT.toolData.fileSW];
Put.LongDecimal[ILT.toolData.fileSW, attributes.offset];
Put.CR[ILT.toolData.fileSW];
Put.LongDecimal[ILT.toolData.fileSW, attributes.size];
Put.CR[ILT.toolData.fileSW];
Process.Pause[Process.SecondsToTicks[10]];
};
IF attributes.size # 0 THEN
Floppy.CopyToPilotFile[
floppyFile: fH,
pilotFile: file,
firstFloppyPage: AccessFloppy.leaderLength,
firstPilotPage: 0,
--SpecialMFile.LeaderPages[] + attributes.offset,
count: attributes.size
!
Floppy.Error => {
Put.Line[ILT.toolData.fileSW, "incompatibleSizes"L];
Process.Pause[Process.SecondsToTicks[10]];
}
];
Put.Line[ILT.toolData.fileSW, "copied"L];
--MFile.Release[mFile];
IF destVFN # NIL THEN FileName.FreeVFN[destVFN];
IF srcVFN # NIL THEN FileName.FreeVFN[srcVFN];
IF destName # NIL THEN FileName.FreeFilename[destName];
--EXITS return => NULL;
END; --ReadOne;
[v]← OpenFloppy[];
IF ~opened THEN RETURN[FALSE];
--IF String.Length[data.cmd.sourceName] # 0 THEN {
IF String.Length[ILT.toolData.filePathName] # 0 THEN {
Put.Text[ILT.toolData.fileSW, "Retrieving... "L];
Put.Line[ILT.toolData.fileSW, ILT.toolData.filePathName];
}
ELSE {
AccessFloppy.Close[ ! Floppy.Error => CONTINUE];
--ERROR Abort["Please enter source file name(s)."L];
Put.Line[ILT.toolData.msgSW, "Please enter source file name(s)."L];
};
atSource ← 0;
DO
ENABLE
UNWIND => {
IF altName # NIL THEN z.FREE[@altName];
IF readName # NIL THEN z.FREE[@readName];
z.FREE[@attributes];
AccessFloppy.Close[ ! Floppy.Error => CONTINUE]};
IF readName # NIL THEN z.FREE[@readName];
IF attributes = NIL THEN
attributes ← z.NEW[
AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]];
IF String.Length[altName] # 0 THEN FixDirectory[@altName];
readName ← String.MakeString[z, 80];
nextFile ← GetNextFilename[];
IF nextFile = NIL THEN EXIT;
String.AppendStringAndGrow[@readName, nextFile, z, 80];
[] ← Token.FreeTokenString[nextFile];
IF readName = NIL THEN EXIT ELSE IF readName.length = 0 THEN EXIT;
IF WildCards[readName] THEN {
EnumerateFloppyFiles[v, ReadOne, readName]}
ELSE {
fFile ← AccessFloppy.LookUp[
NSString.StringFromMesaString[readName], attributes !
AccessFloppy.Error =>
IF type = fileNotFound THEN {failed ← TRUE; CONTINUE}
ELSE Put.Line[ILT.toolData.fileSW, "Floppy Error"L]];
IF failed THEN {
Put.Text[ILT.toolData.msgSW, readName];
Put.Line[ILT.toolData.msgSW, " not found"L];
IF debug THEN Process.Pause[Process.SecondsToTicks[10]];
}
ELSE BEGIN
[volumeID, volumeOpen] ← ILT.GetVolumeID[ILT.toolData.volName];
[file, firstPage] ← OthelloOps.GetVolumeBootFile[volumeID, hardMicrocode];
IF (created ← file = File.nullFile) THEN
BEGIN
IF debug THEN Process.Pause[Process.SecondsToTicks[20]];
file ← File.Create[volumeID, attributes.totalSizeInBytes / 512 + 1, FileTypes.tUntypedFile !
Volume.InsufficientSpace => {
Put.Line[ILT.toolData.msgSW, " InsufficientSpace"L];
IF debug THEN Process.Pause[Process.SecondsToTicks[10]];
}];
END
ELSE
BEGIN
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "MakeUnbootable.."L];
Process.Pause[Process.SecondsToTicks[10]];
};
OthelloOps.MakeUnbootable[
file, hardMicrocode, OthelloDefs.leaderPages];
END;
END;
[] ← ReadOne[
attributes, fFile, NameFromAttributes[attributes]];
};
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "UserInput.UserAbort"L];
Process.Pause[Process.SecondsToTicks[5]];
};
IF UserInput.UserAbort[ILT.windowHandle] THEN {
Put.Text[ILT.toolData.fileSW, "User Abort! "L];
Put.Line[ILT.toolData.fileSW, "Aborted"L];
UserInput.ResetUserAbort[ILT.windowHandle];
EXIT};
ENDLOOP;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "z.FREE"L];
Process.Pause[Process.SecondsToTicks[5]];
};
z.FREE[@attributes];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "String.FreeString"L];
Process.Pause[Process.SecondsToTicks[5]];
};
IF readName # NIL THEN String.FreeString[z, readName];
IF altName # NIL THEN String.FreeString[z, altName];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "AccessFloppy.Close"L];
Process.Pause[Process.SecondsToTicks[5]];
};
AccessFloppy.Close[];
RETURN[~failed];
END; --FloppyRead
FloppyStuff: PUBLIC PROCEDURE =
BEGIN
aborted: BOOLEAN ← FALSE;
IF toolData = NIL THEN toolData ← Heap.systemZone.NEW[Data ← []];
IF attributes = NIL THEN
attributes ← z.NEW[
AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "FloppyStuff...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
floppyWH ← MakeTool[];
BEGIN
ENABLE {
Abort => {Put.Line[toolData.fileSW, s]; aborted ← TRUE; };
AccessFloppy.Error => {
Put.Text[toolData.fileSW, "unexpected "L];
WriteAccessFloppyError[type];
Put.CR[toolData.fileSW];
aborted ← TRUE;
};
AccessFloppy.InconsistentFile => {
Put.Line[toolData.fileSW, "AccessFloppy.InconsistentFile"L];
aborted ← TRUE;
};
AccessFloppy.InvalidVersion => {
Put.Line[toolData.fileSW, "AccessFloppy.InvalidVersion"L];
aborted ← TRUE;
};
AccessFloppy.NoRoomForClientData => {
Put.Line[toolData.fileSW, "AccessFloppy.NoRoomForClientData"L];
aborted ← TRUE;
};
Floppy.Error => {
IF error = writeInhibited THEN
Put.Line[toolData.fileSW, "Floppy is write protected"L]
ELSE {
Put.Text[toolData.fileSW, "unexpected "L];
WriteFloppyError[error];
Put.CR[toolData.fileSW];
};
aborted ← TRUE;
};
};
END;
END; --FloppyStuff
<<
FloppyToDisk: PROC =
BEGIN
handle: MStream.Handle ← NIL;
releaseData: MStream.ReleaseData ← [];
FOR current: Floppy.FileHandle ← Floppy.GetNextFile[nullFile].nextFile,
Floppy.GetNextFile[current].nextFile WHILE current # nullFile DO
scratchName: LONG STRING ← [120];
IF debug THEN {
Put.Line[toolData.fileSW, ".Floppy.GetFileAttributes...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[toolData.current.size, toolData.current.type] ←
Floppy.GetFileAttributes[current];
IF debug THEN {
Put.Line[
toolData.fileSW, ".AccessFloppy.GetFileAttributes...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
AccessFloppy.GetAttributes[current, attributes];
IF debug THEN {
Put.Line[toolData.fileSW, ".String.MakeString...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
toolData.current.file ← String.MakeString[
z, AccessFloppy.maxNameLength];
IF debug THEN {
Put.Line[
toolData.fileSW,
"AccessFloppyUtil.MesaStringFromAttributes...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
MesaStringFromAttributes[attributes, toolData.current.file];
IF debug THEN {
Put.Line[toolData.fileSW, ".String.AppendString...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
String.AppendString[scratchName, toolData.current.file];
String.AppendString[scratchName, ".Scratch$"L];
IF debug THEN {
Put.Line[toolData.fileSW, ".String.AppendString...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
handle ← MStream.ReadWrite[
name: scratchName, release: releaseData,
type: MFile.Type[unknown]];
attributes.size ← toolData.current.size; -- modify size to actual file size.
IF debug THEN {
Put.Line[toolData.fileSW, "RetrieveFilePiece..."L];
Process.Pause[Process.SecondsToTicks[5]];
};
RetrieveFilePiece[current, handle, attributes];
toolData.numberOfFiles ← toolData.numberOfFiles + 1;
toolData.current ← toolData.current.next ← z.NEW[NextFile ← []];
IF debug THEN {
Put.Line[toolData.fileSW, "handle.delete..."L];
Process.Pause[Process.SecondsToTicks[5]];
};
handle.delete[handle];
ENDLOOP;
-- will have current points to a NextFile[NIL, NIL].
END; -- FloppyToDisk.
>>
FloppyWrite: PUBLIC PROCEDURE [name: LONG STRING] =
BEGIN
attributes: AccessFloppy.Attributes ← NIL;
altName, switches: LONG STRING ← NIL;
fileType: File.Type ← FileTypes.tUntypedFile;
mFile: MFile.Handle;
--[] ← AccessFloppy.Open[! AccessFloppy.Error => ERROR Abort["Can't open floppy"L]];
[vH] ← OpenFloppy[];
IF ~opened THEN RETURN;
-- DO
BEGIN
ENABLE
UNWIND => {
IF mFile # NIL THEN MFile.Release[mFile];
Heap.systemZone.FREE[@attributes];
AccessFloppy.Close[ ! Floppy.Error => CONTINUE]};
fFile: Floppy.FileHandle;
failed: BOOLEAN ← FALSE;
mFileError: MFile.ErrorCode;
offset, length: CARDINAL;
IF attributes = NIL THEN
attributes ← Heap.systemZone.NEW[
AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]];
mFile ← NIL;
IF name = NIL AND switches = NIL THEN GOTO done;
[offset, length] ← ParsePartial[
name !
Token.SyntaxError => {
Put.Line[ILT.toolData.fileSW, name];
Put.Line[ILT.toolData.fileSW, " - bad name syntax"L];
--SetOutcome[error];
--LOOP;
}];
IF switches = NIL THEN altName ← name;
mFile ← MFile.ReadOnly[
name, [] ! MFile.Error => {mFileError ← code; CONTINUE}];
IF mFile = NIL THEN
SELECT mFileError FROM
noSuchFile => {
Put.Line[ILT.toolData.msgSW, " not found"L];
--SetOutcome[error];
--LOOP;
};
conflictingAccess => {
Put.Line[ILT.toolData.msgSW, " conflicting access"L];
--SetOutcome[error];
--LOOP;
};
ENDCASE => ERROR Abort[" unexpected MFile.Error"L];
MakeAttributes[mFile, altName, attributes, fileType];
attributes.offset ← offset;
attributes.size ← MIN[length, attributes.totalSize - offset];
--Put.Text[ILT.toolData.msgSW, name];
[] ← WritePartial[attributes];
Put.Text[ILT.toolData.msgSW, "... "L];
Put.Text[ILT.toolData.msgSW, "copying to "L];
Put.Text[ILT.toolData.msgSW, altName];
Put.Text[ILT.toolData.msgSW, "... "L];
IF debug THEN Process.Pause[Process.SecondsToTicks[10]];
fFile ← AccessFloppy.CreateFile[
attributes !
AccessFloppy.Error =>
IF type = nameInUse THEN {failed ← TRUE; CONTINUE};
Floppy.Error =>
SELECT error FROM
fileListFull => ERROR Abort["too many files"L];
insufficientSpace => ERROR Abort["floppy is full"L];
ENDCASE];
IF failed THEN {
Put.Line[
ILT.toolData.msgSW, "floppy file already exists - skipped"L];
Process.Pause[Process.SecondsToTicks[5]];
--SetOutcome[error];
}
ELSE {
IF attributes.size # 0 THEN
Floppy.CopyFromPilotFile[
floppyFile: fFile,
pilotFile: SpecialMFile.GetCapaWithAccess[mFile],
firstFloppyPage: AccessFloppy.leaderLength,
firstPilotPage: SpecialMFile.LeaderPages[] + offset,
count: attributes.size];
Put.Line[ILT.toolData.msgSW, "copied"L]};
Process.Pause[Process.SecondsToTicks[5]];
MFile.Release[mFile];
--ENDLOOP;
EXITS done => NULL;
END;
Heap.systemZone.FREE[@attributes];
AccessFloppy.Close[];
END; -- FloppyWrite
FormatAndOpen: PROC [] RETURNS [skip: BOOLEAN] =
BEGIN
density: Floppy.Density ← double;
sides: Floppy.Sides ← two;
nFile: CARDINAL ← 2 * toolData.numberOfFiles + 1;
ok: BOOLEAN;
skip ← TRUE;
Put.Line[toolData.fileSW, "Please Remove Floppy Disk, are you ready? "L];
IF ~ILT.Confirm[] THEN RETURN;
Put.Line[toolData.fileSW, "format..."L];
[ok] ← FloppyFormat[nFile, toolData.floppyName, sides, density];
IF ~ok THEN {CleanUp; RETURN};
Put.Line[toolData.fileSW, "...ted"L];
vH ← AccessFloppy.Open[];
nullFile ← [vH, Floppy.nullFileID];
skip ← FALSE;
END; -- FormatAndOpen.
FormSWDeleteProc: FormSW.ProcType =
BEGIN
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "FormSWDeleteProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[] ← FloppyDelete[toolData.pattern];
END; --FormSWDeleteProc
FormSWDuplicateProc: FormSW.ProcType =
BEGIN
IF debug THEN {
Put.Line[toolData.fileSW, "FormSWDuplicateProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
Put.Line[toolData.fileSW, "to be implemented"L];
FloppyDuplicate;
END; --FormSWDuplicateProc
FormSWFormatProc: FormSW.ProcType =
BEGIN
ok: BOOLEAN;
IF debug THEN {
Put.Line[toolData.fileSW, "FormSWFormatProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[ok] ← FloppyFormat[256, toolData.floppyName, default, default];
END; --FormSWFormatProc
FormSWInfoProc: FormSW.ProcType =
BEGIN
IF debug THEN {
Put.Line[toolData.fileSW, "FormSWInfoProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
FloppyInfo;
END; --FormSWInfoProc
FormSWListProc: FormSW.ProcType =
BEGIN
IF debug THEN {
Put.Line[toolData.fileSW, "FormSWListProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
FloppyList;
END; --FormSWListProc
FormSWReadProc: FormSW.ProcType =
BEGIN
IF debug THEN {
Put.Line[toolData.fileSW, "FormSWReadProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
Put.Line[toolData.fileSW, "to be implemented"L];
END; --FormSWReadProc
FormSWWriteProc: FormSW.ProcType =
BEGIN
IF debug THEN {
Put.Line[toolData.fileSW, "FormSWWriteProc...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
Put.Line[toolData.fileSW, "to be implemented"L];
FloppyWrite[toolData.pattern];
END; --FormSWWriteProc
FormSWQuitProc: FormSW.ProcType =
BEGIN
IF toolData # NIL THEN
BEGIN Tool.Destroy[floppyWH]; Heap.systemZone.FREE[@toolData]; END;
END; --FormSWQuitProc
FormSWVolHintsProc: FormSW.MenuProcType =
BEGIN
RETURN[
hints: DESCRIPTOR[
@ILT.toolData.volHints[0], ILT.toolData.volHints.length],
freeHintsProc: HintsNoLongerBusy, replace: TRUE];
END;
GetNextFilename: PUBLIC PROC RETURNS [fn: LONG STRING ← NIL] =
BEGIN
MyGet: PROC [Token.Handle] RETURNS [c: CHARACTER] =
BEGIN
IF atSource >= ILT.toolData.filePathName.length THEN c ← Ascii.NUL
ELSE
BEGIN
c ← ILT.toolData.filePathName[atSource];
atSource ← atSource + 1;
END;
END;
getObject: Token.Object ← [getChar: MyGet, break: Ascii.NUL];
IF atSource >= ILT.toolData.filePathName.length THEN RETURN[NIL];
fn ← Token.Item[h: @getObject, temporary: FALSE];
END; --GetNextFilename
HintsNoLongerBusy: FormSW.FreeHintsProcType = BEGIN END;
MesaStringFromAttributes: PUBLIC PROC [
attris: AccessFloppy.Attributes, name: LONG STRING] =
BEGIN -- should protect against a bogus attris (i.e., one from a non AccessFloppy file).
name.length ← 0;
IF attris = NIL THEN
RETURN WITH ERROR AccessFloppy.Error[invalidParameter];
IF attris.length > attris.maxlength THEN -- invalidAttributes?
RETURN WITH ERROR AccessFloppy.Error[invalidParameter];
IF name.maxlength < attris.length THEN
RETURN WITH ERROR AccessFloppy.Error[invalidParameter];
IF debug THEN {
Put.Line[toolData.fileSW, "Inline.LongCOPY...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
[] ← Inline.LongCOPY[
to: @name.text, nwords: attris.length / 2, from: @attris.name];
name.length ← attris.length;
IF name.length # 0 THEN -- pick up odd character.
name[name.length - 1] ← LOOPHOLE[attris.name[name.length - 1]];
END; -- MesaStringFromAttributes.
MakeAttributes: PROCEDURE [
file: MFile.Handle, name: LONG STRING,
attributes: AccessFloppy.Attributes, type: File.Type] =
BEGIN
attributes.version ← AccessFloppy.currentVersion;
attributes.type ← type;
attributes.lastWrittenDate ← Time.Current[];
attributes.name ← ALL[0];
attributes.clientDataLength ← 2;
attributes.clientData[0] ← dataVersion;
[length: attributes.totalSizeInBytes, create: attributes.createDate,
type: attributes.clientData[1]] ← MFile.GetProperties[file];
attributes.totalSize ← PagesFromBytes[attributes.totalSizeInBytes];
attributes.size ← attributes.totalSize;
attributes.length ← MIN[name.length, AccessFloppy.maxNameLength];
FOR i: CARDINAL IN [0..attributes.length) DO
attributes.name[i] ← LOOPHOLE[name[i]]; ENDLOOP
END; --MakeAttributes
MakeCommands: FormSW.ClientItemsProcType =
BEGIN OPEN FormSW;
tabs: ARRAY [0..5) OF CARDINAL ← [0, 20, 40, 60, 70];
nItems: CARDINAL = 8;
items ← AllocateItemDescriptor[nItems];
items[0] ← CommandItem[
tag: "Info"L, place: newLine, proc: FormSWInfoProc];
items[1] ← CommandItem[tag: "List"L, proc: FormSWListProc];
items[2] ← CommandItem[tag: "Read"L, proc: FormSWReadProc];
items[3] ← CommandItem[tag: "Write"L, proc: FormSWWriteProc];
items[4] ← CommandItem[
tag: "Format"L, place: newLine, proc: FormSWFormatProc];
items[5] ← CommandItem[tag: "Delete"L, proc: FormSWDeleteProc];
items[6] ← CommandItem[tag: "Duplicate"L, proc: FormSWDuplicateProc];
items[7] ← CommandItem[tag: "Quit"L, proc: FormSWQuitProc];
SetTagPlaces[items, DESCRIPTOR[tabs], FALSE];
RETURN[items, TRUE];
END; --MakeCommands
MakeParams: FormSW.ClientItemsProcType =
BEGIN OPEN FormSW;
i, nVols: CARDINAL;
tabs: ARRAY [0..4) OF CARDINAL ← [0, 30, 60, 75];
nItems: CARDINAL = 3;
items ← AllocateItemDescriptor[nItems];
nVols ← ILT.ListLogicalVolumes[];
String.Copy[toolData.volName, ILT.toolData.volHints[0]];
FOR i IN [0..nVols) DO
IF String.Equivalent[ILT.toolData.volHints[i], "Lisp"L] THEN
BEGIN
String.Replace[
@toolData.volName, ILT.toolData.volHints[i],
Heap.systemZone];
EXIT;
END;
ENDLOOP;
items[0] ← StringItem[
tag: "Source Volume"L, place: newLine, string: @toolData.volName,
inHeap: TRUE, menuProc: FormSWVolHintsProc];
items[1] ← StringItem[
tag: "Pattern"L, string: @toolData.pattern, inHeap: TRUE];
items[2] ← StringItem[
tag: "Floppy Name"L, string: @toolData.floppyName, place: newLine,
inHeap: TRUE];
SetTagPlaces[items, DESCRIPTOR[tabs], FALSE];
RETURN[items, TRUE]
END; --MakeParams
MakeSWs: Tool.MakeSWsProc =
BEGIN
addresses: ARRAY [0..4) OF ToolDriver.Address;
logName: STRING ← [20];
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "MakeSWs...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
Tool.UnusedLogName[unused: logName, root: "FloppyOptions.log"L];
toolData.msgSW ← Tool.MakeMsgSW[window: window, lines: 2];
toolData.paramSW ← Tool.MakeFormSW[window: window, formProc: MakeParams];
toolData.commandSW ← Tool.MakeFormSW[
window: window, formProc: MakeCommands];
--note: logName is compulsory, else it bombs
toolData.fileSW ← Tool.MakeFileSW[window: window, name: logName];
--Supervisor.AddDependency[client: agent, implementor: Event.toolWindow];
-- do the ToolDriver stuff
addresses ← [
[name: "msgSW"L, sw: toolData.msgSW],
--[name: "formSW"L, sw: toolData.formSW],
[name: "ParamSW"L, sw: toolData.paramSW], [
name: "CmdSW"L, sw: toolData.commandSW], [
name: "fileSW"L, sw: toolData.fileSW]];
ToolDriver.NoteSWs[
tool: "FloppyOptions"L, subwindows: DESCRIPTOR[addresses]];
END; --MakeSWs
MakeTool: PROCEDURE RETURNS [wh: Window.Handle] =
BEGIN
heraldName: STRING ← [80];
String.AppendString[heraldName, "XSIS:Xerox Floppy Option"L];
--String.AppendString[heraldName, " of "L];
--Time.Append[heraldName, Time.Unpack[Runtime.GetBcdTime[]]];
--heraldName.length ← heraldName.length - 3;
--String.AppendString[heraldName, " on Pilot Version "L];
--Version.Append[heraldName];
RETURN[
Tool.Create[
makeSWsProc: MakeSWs, initialState: default,
--clientTransition: Transit,
name: heraldName]];
--initialBox: [
--place: sw.BitmapPlace[[10, hisBox.dims.h]],
--dims: [hisBox.dims.w - 20, 180]]];
END; --MakeTool
NameFromAttributes: PROCEDURE [attributes: AccessFloppy.Attributes]
RETURNS [LONG STRING] = INLINE {RETURN[LOOPHOLE[@attributes.length]]};
OpenFloppy: PROCEDURE [] RETURNS [v: Floppy.VolumeHandle] =
BEGIN
IF debug THEN {
Put.Line[ILT.toolData.fileSW, "OpenFloppy...."L];
Process.Pause[Process.SecondsToTicks[5]];
};
opened ← TRUE;
v ← AccessFloppy.Open[
!
Floppy.Error =>
SELECT error FROM
notReady => {
Put.Line[ILT.toolData.msgSW, "Floppy Not Closed"L];
IF debug THEN Process.Pause[Process.SecondsToTicks[10]];
GOTO noGood;
};
invalidFormat => {
Put.Line[
ILT.toolData.msgSW, "Invalid Floppy Format"L];
GOTO noGood;
};
needsScavenging => {
Put.Line[
ILT.toolData.msgSW, "Floppy Needs Scavenging"L];
GOTO noGood;
};
ENDCASE];
EXITS noGood => opened ← FALSE;
END; -- OpenFloppy
ParsePartial: PROCEDURE [name: LONG STRING]
RETURNS [offset: CARDINAL ← 0, length: CARDINAL ← LAST[CARDINAL]] =
BEGIN
h: Token.Handle;
i: CARDINAL;
IF name = NIL THEN RETURN;
FOR i IN [1..name.length) DO
IF name[i] = '[ THEN EXIT; REPEAT FINISHED => RETURN ENDLOOP;
h ← Token.StringToHandle[name, i + 1];
BEGIN
ENABLE UNWIND => [] ← Token.FreeStringHandle[h];
offset ← Token.Decimal[h];
SELECT h.break FROM
'. =>
IF h.getChar[h] = '. THEN
length ← Token.Decimal[h] - offset + 1
ELSE ERROR Token.SyntaxError[NIL];
'! => length ← Token.Decimal[h];
'] => NULL;
ENDCASE => ERROR Token.SyntaxError[NIL];
END;
name.length ← i;
[] ← Token.FreeStringHandle[h];
END; --ParsePartial
PagesFromBytes: PROCEDURE [bytes: LONG CARDINAL] RETURNS [LONG CARDINAL] =
BEGIN
RETURN[
(bytes + Environment.bytesPerPage - 1) / Environment.bytesPerPage];
END; --PagesFromBytes
PutVolumeName: PROCEDURE [] =
BEGIN
Put.Text[toolData.fileSW, "Volume = "L];
Put.LongString[toolData.fileSW, toolData.volName];
Put.CR[toolData.fileSW];
END; --PutVolumeName
<<
RetrieveFilePiece: PROC [
floppyFile: Floppy.FileHandle, mStream: MStream.Handle,
attributes: AccessFloppy.Attributes] =
BEGIN
mFile: MFile.Handle ← NIL;
block: Environment.Block;
bufferSizeInBytes, bytesRemaining, bytesToRead, bytesTransfered:
AccessFloppy.LengthInBytes;
start, pagesToRead: File.PageNumber;
bytesTransfered ← 0;
-- starting page number of the floppy file, page count of the floppy file, and byte count of the floppy file.
start ← 0;
bytesRemaining ← attributes.size*Environment.bytesPerPage;
bufferSizeInBytes ← bufferSize*Environment.bytesPerPage;
-- set attributes
mFile ← MStream.GetFile[mStream];
MFile.SetTimes[
file: mFile, create: attributes.createDate,
write: attributes.lastWrittenDate];
MFile.SetType[mFile, MFile.Type[binary]];
MStream.SetLength[mStream, bytesRemaining];
-- set up block
block.blockPointer ← Space.LongPointer[spaceHandle];
block.startIndex ← 0;
--copy as many chunks of the standard buffer size as possible.....
UNTIL bytesRemaining = 0 DO
bytesToRead ← MIN[bytesRemaining, bufferSizeInBytes];
pagesToRead ← PagesFromBytes[bytesToRead];
Floppy.Read[floppyFile, start, pagesToRead, block.blockPointer];
block.stopIndexPlusOne ← Inline.LowHalf[bytesToRead];
mStream.put[mStream, block, FALSE];
start ← start + pagesToRead;
bytesTransfered ← bytesTransfered + bytesToRead;
bytesRemaining ← bytesRemaining - bytesToRead;
ENDLOOP;
END; -- RetrieveFilePiece.
StoreFilePiece: PROC [
mStream: MStream.Handle, floppyFile: Floppy.FileHandle,
size: File.PageNumber] =
BEGIN
-- store data from disk to floppy
block: Environment.Block;
bufferSizeInBytes, bytesRemaining, bytesToWrite, bytesTransfered:
AccessFloppy.LengthInBytes;
start, pagesToWrite: File.PageNumber;
why: Stream.CompletionCode ← normal;
bytesTransfered ← 0;
-- starting page number of the floppy file, page count of the floppy file, and byte count of the floppy file.
start ← 0;
bytesRemaining ← (size*Environment.bytesPerPage);
bufferSizeInBytes ← bufferSize*Environment.bytesPerPage;
-- set up block
block.blockPointer ← Space.LongPointer[spaceHandle];
block.startIndex ← 0;
bytesToWrite ← bytesRemaining;
--copy as many chunks of the standard buffer size as possible.....
UNTIL bytesRemaining = 0 OR why = endOfStream DO
bytesToWrite ← MIN[bytesRemaining, bufferSizeInBytes];
block.stopIndexPlusOne ← Inline.LowHalf[bytesToWrite];
[bytesToWrite, why, ] ← mStream.get[
mStream, block, Stream.defaultInputOptions];
pagesToWrite ← PagesFromBytes[bytesToWrite];
Floppy.Write[floppyFile, start, pagesToWrite, block.blockPointer];
start ← start + pagesToWrite;
bytesTransfered ← bytesTransfered + bytesToWrite;
bytesRemaining ← bytesRemaining - bytesToWrite;
ENDLOOP;
END; -- StoreFilePiece.
>>
Transit: ToolWindow.TransitionProcType =
BEGIN
SELECT TRUE FROM
old = inactive =>
BEGIN
IF toolData = NIL THEN
toolData ← Heap.systemZone.NEW[Data ← []];
IF attributes = NIL THEN
attributes ← z.NEW[
AccessFloppy
.AttributesRecord[AccessFloppy.maxDataSize]];
--UserInput.ResetUserAbort[window];
--data.logSW ← window;
-- data.window ← ToolWindow.WindowForSubwindow[window];
-- data.ttyWindow ← TTYSW.GetTTYHandle[window];
-- destroy ← FALSE;
active ← TRUE;
END;
new = inactive =>
BEGIN
IF toolData # NIL THEN
BEGIN
FormSW.Destroy[toolData.paramSW];
FormSW.Destroy[toolData.commandSW];
Heap.systemZone.FREE[@toolData];
END;
IF attributes # NIL THEN {
z.FREE[@attributes]; attributes ← NIL};
--ToolDriver.RemoveSWs[tool: "LispTool"L];
active ← FALSE;
END;
ENDCASE;
END; -- Transit
WriteAccessFloppyError: PROCEDURE [type: AccessFloppy.ErrorType] =
BEGIN
Put.Text[toolData.fileSW, "AccessFloppy.Error["L];
Put.Text[
toolData.fileSW,
SELECT type FROM
attributesNotAllowed => "attributesNotAllowed"L,
fileNotFound => "fileNotFound"L,
invalidParameter => "invalidParameter"L,
nameInUse => "nameInUse"L,
volumeNotOpen => "volumeNotOpen"L,
ENDCASE => "?"L];
Put.Text[toolData.fileSW, "]"L];
END; --WriteAccessFloppyError
WriteFloppyError: PROCEDURE [error: Floppy.ErrorType] =
BEGIN
Put.Text[toolData.fileSW, "Floppy.Error["L];
Put.Text[
toolData.fileSW,
SELECT error FROM
badDisk => "badDisk"L,
badSectors => "badSectors"L,
endOfFile => "endOfFile"L,
fileListFull => "fileListFull"L,
fileNotFound => "fileNotFound"L,
hardwareError => "hardwareError"L,
incompatibleSizes => "incompatibleSizes"L,
invalidFormat => "invalidFormat"L,
invalidPageNumber => "invalidPageNumber"L,
invalidVolumeHandle => "invalidVolumeHandle"L,
insufficientSpace => "insufficientSpace"L,
needsScavenging => "needsScavenging"L,
noSuchDrive => "noSuchDrive"L,
notReady => "notReady"L,
onlyOneSide => "onlyOneSide"L,
onlySingleDensity => "onlySingleDensity"L,
initialMicrocodeSpaceNotAvailable =>
"initialMicrocodeSpaceNotAvailable"L,
stringTooShort => "stringTooShort"L,
volumeNotOpen => "volumeNotOpen"L,
writeInhibited => "writeInhibited"L,
zeroSizeFile => "zeroSizeFile"L,
ENDCASE => "?"L];
Put.Line[toolData.fileSW, "]"L];
END; --WriteFloppyError
-- used by both ILT and subwindows
WritePartial: PROCEDURE [attributes: AccessFloppy.Attributes]
RETURNS [chars: CARDINAL ← 0] =
BEGIN
CountedNumber: PROCEDURE [n: LONG CARDINAL] RETURNS [CARDINAL] = {
s: STRING = [12];
String.AppendLongDecimal[s, n];
Put.Text[ILT.toolData.fileSW, s];
RETURN[s.length]};
IF attributes.offset # 0 OR attributes.size # attributes.totalSize THEN {
chars ← 4;
Put.Char[ILT.toolData.fileSW, '[];
chars ← chars + CountedNumber[attributes.offset];
-- Write[".."L];
chars ←
chars + CountedNumber[attributes.offset + attributes.size - 1];
Put.Char[ILT.toolData.fileSW, ']]};
END; --WritePartial
<<
WriteFiles: PROCEDURE [gSwitches: LONG STRING, h: Exec.Handle] =
BEGIN
attributes: AccessFloppy.Attributes ← NIL;
name, altName, switches: LONG STRING ← NIL;
fileType: File.Type ← FileTypes.tUntypedFile;
mFile: MFile.Handle;
Write: Format.StringProc = Exec.OutputProc[h];
IF gSwitches # NIL THEN
fileType ← [
String.StringToNumber[
gSwitches ! String.InvalidNumber => CONTINUE]];
[] ← AccessFloppy.Open[
! AccessFloppy.Error => ERROR Abort["Can't open floppy"L]];
DO
ENABLE
UNWIND => {
IF altName # name THEN
altName ← Exec.FreeTokenString[altName];
name ← Exec.FreeTokenString[name];
switches ← Exec.FreeTokenString[switches];
IF mFile # NIL THEN MFile.Release[mFile];
Heap.systemZone.FREE[@attributes];
AccessFloppy.Close[ ! Floppy.Error => CONTINUE]};
fFile: Floppy.FileHandle;
failed: BOOLEAN ← FALSE;
mFileError: MFile.ErrorCode;
offset, length: CARDINAL;
IF attributes = NIL THEN
attributes ← Heap.systemZone.NEW[
AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]];
mFile ← NIL;
IF altName # name THEN altName ← Exec.FreeTokenString[altName];
name ← Exec.FreeTokenString[name];
switches ← Exec.FreeTokenString[switches];
[name, switches] ← Exec.GetToken[h];
IF name = NIL AND switches = NIL THEN EXIT;
[offset, length] ← ParsePartial[
name !
Token.SyntaxError => {
Write[name];
Format.Line[Write, " - bad name syntax"L];
SetOutcome[error];
LOOP}];
IF switches # NIL AND switches.length # 0 THEN
SELECT switches[0] FROM
's => {
switches ← Exec.FreeTokenString[switches];
[altName, switches] ← Exec.GetToken[h]};
't => {
fileType ← [
String.StringToNumber[
name ! String.InvalidNumber => CONTINUE]];
switches ← Exec.FreeTokenString[switches];
LOOP};
ENDCASE
ELSE altName ← name;
mFile ← MFile.ReadOnly[
name, [] ! MFile.Error => {mFileError ← code; CONTINUE}];
IF mFile = NIL THEN
SELECT mFileError FROM
noSuchFile => {
Format.Line[Write, " not found"L];
SetOutcome[error];
LOOP};
conflictingAccess => {
Format.Line[Write, " conflicting access"L];
SetOutcome[error];
LOOP};
ENDCASE => ERROR Abort[" unexpected MFile.Error"L];
MakeAttributes[mFile, altName, attributes, fileType];
attributes.offset ← offset;
attributes.size ← MIN[length, attributes.totalSize - offset];
Write[name];
[] ← WritePartial[attributes];
Write["... "L];
Write["copying to "L];
Write[altName];
Write["... "L];
fFile ← AccessFloppy.CreateFile[
attributes !
AccessFloppy.Error =>
IF type = nameInUse THEN {failed ← TRUE; CONTINUE};
Floppy.Error =>
SELECT error FROM
fileListFull => ERROR Abort["too many files"L];
insufficientSpace => ERROR Abort["floppy is full"L];
ENDCASE];
IF failed THEN {
Format.Line[Write, "floppy file already exists - skipped"L];
SetOutcome[error]}
ELSE {
IF attributes.size # 0 THEN
Floppy.CopyFromPilotFile[
floppyFile: fFile,
pilotFile: SpecialMFile.GetCapaWithAccess[mFile],
firstFloppyPage: AccessFloppy.leaderLength,
firstPilotPage: SpecialMFile.LeaderPages[] + offset,
count: attributes.size];
Format.Line[Write, "copied"L]};
MFile.Release[mFile];
ENDLOOP;
Heap.systemZone.FREE[@attributes];
AccessFloppy.Close[];
END; -- WriteFiles
>>
WildCards: PROCEDURE [pattern: LONG STRING] RETURNS [BOOLEAN] =
BEGIN
IF pattern # NIL THEN
FOR i: CARDINAL IN [0..pattern.length) DO
SELECT pattern[i] FROM '*, '# => RETURN[TRUE]; ENDCASE;
ENDLOOP;
IF debug THEN {
Put.Line[ILT.toolData.fileSW, " NOT WildCards"L];
Process.Pause[Process.SecondsToTicks[5]];
};
RETURN[FALSE];
END;
END.