home *** CD-ROM | disk | FTP | other *** search
- ⓪ IMPLEMENTATION MODULE FileManagement;
- ⓪ (*$R-,Y+*)
- ⓪ (*$H+*)
- ⓪
- ⓪ (*FROM InOut IMPORT WriteString, WriteLn, Read, WriteCard, WriteInt;*)
- ⓪
- ⓪
- ⓪ (* --------------------------------------------------------------------------
- ⓪!* System-Version: MOS 1.1
- ⓪!* --------------------------------------------------------------------------
- ⓪!* Version : 1.01
- ⓪!* --------------------------------------------------------------------------
- ⓪!* Text-Version : V#0262
- ⓪!* --------------------------------------------------------------------------
- ⓪!* Modul-Holder : Manuel Chakravarty
- ⓪!* --------------------------------------------------------------------------
- ⓪!* Copyright August 1988 by Manuel Chakravarty
- ⓪!* Vertriebsrechte für ATARI ST unter MEGAMAX Modula-2
- ⓪!* liegen bei Application Systems Heidelberg
- ⓪!* --------------------------------------------------------------------------
- ⓪!* MCH : Manuel Chakravarty
- ⓪!* DS : Dirk Steins
- ⓪!* --------------------------------------------------------------------------
- ⓪!* Datum Autor Version Bemerkung (Arbeitsbericht)
- ⓪!*
- ⓪!* 07.08.88 MCH V0.01 Erste Definitionen
- ⓪!* 08.08.88 MCH V0.01 'fileList' + 'insertFileInList'
- ⓪!* 09.08.88 MCH V0.01 Austesten der 'fileList'-Verwaltung + 'DeleteFiles'
- ⓪!* 09.08.88 MCH V0.02 Nochmal
- ⓪!* 10.08.88 MCH V0.02 'FormatDisk' (norm. SS und DS) + 'DeleteFiles'
- ⓪!* 11.08.88 MCH V0.02 'CopyFiles' läuft (Tra-Ra!)
- ⓪!* 24.08.88 MCH V0.03 'CountFilesAndDirs' extern
- ⓪!* 25.08.88 MCH V0.03 Geänderte Status-Verwaltung
- ⓪!* 27.08.88 MCH V0.03 'minExternalSpace' eingeführt.
- ⓪!* 28.08.88 MCH V0.04 'FileInformation' Def. + Imp.
- ⓪!* 11.08.88 MCH V0.04 Datum/Uhrzeit bleibt beim Kopieren erhalten
- ⓪!* 03.09.89 MCH V0.04 Fehlerbehandlung verbessert
- ⓪!* 11.09.89 TT V0.05 readIntoBuffer: Fehlerabfrage entfernt
- ⓪!* 30.6.90 DS V0.06 DestPath von Files wird bei geändertem Ordnername
- ⓪!* jetzt korrekt geändert. Änderungen sind gekenn-
- ⓪!* zeichnet mit %%.
- ⓪!* 24.10.90 TT V0.07 Doku im Def-Text korrigiert; FormatDrive mit
- ⓪!* mit Directory.Drive-Werten definiert (Def-Text);
- ⓪!* $H+ eingebaut
- ⓪!* 10.11.90 TT V0.07 $R-
- ⓪!* 11.03.91 TT V1.01 FileInformation berücksichtigt Ordner und kann
- ⓪!* auch Zeit/Datum neu setzen.
- ⓪!* 09.04.91 TT V1.02 FormatDisk wertet 'drive' nun richtig aus (bisher
- ⓪!* wurde bei 'drvA' LW B: formatiert.
- ⓪!* --------------------------------------------------------------------------
- ⓪!* Modul-Beschreibung:
- ⓪!*
- ⓪!* Dieses Modul stellt Routinen für die Dateiverwaltung zur Verfügung.
- ⓪!* --------------------------------------------------------------------------
- ⓪!*)
- ⓪
- ⓪ (* -- Wie sieht es mit Datum und Zeit bei Ordnern aus??????
- ⓪!* -- Wird beim Namenskonflikt von Ordnern ein neuer Name angegeben, so muß
- ⓪!* der DestPath der Ordnerelemente entsprechend geändert werden.
- ⓪!* Behoben Dirk Steins
- ⓪!* -- Tritt bei 'flushBufferElem' während des Schreibens ein Fehler auf, so
- ⓪!* ist nicht gewährleistet, daß das File anständig geschlossen wird.
- ⓪!* -- Evtl. 'queryFileList' exportieren (z.B für Modul-Loading in der Shell).
- ⓪!*)
- ⓪
- ⓪
- ⓪ FROM SYSTEM IMPORT ADDRESS, TSIZE,
- ⓪3ASSEMBLER, ADR;
- ⓪
- ⓪ FROM Storage IMPORT ALLOCATE, DEALLOCATE, MemAvail;
- ⓪
- ⓪ FROM Strings IMPORT Length, Concat, Append, Empty, Insert, Copy, StrEqual,
- ⓪4Assign;
- ⓪
- ⓪ IMPORT Strings, FastStrings, FuncStrings;
- ⓪
- ⓪ FROM MOSGlobals IMPORT OutOfMemory, GeneralErr, fOK, fFileNotFound,
- ⓪7fPathNotFound, fAccessDenied, fFileExists,
- ⓪7fDiskFull, fIllegalCall, DriveStr, PathStr,
- ⓪7FileStr;
- ⓪
- ⓪ FROM Clock IMPORT Time, Date;
- ⓪
- ⓪ FROM Directory IMPORT FileAttr, FileAttrSet, DirEntry,
- ⓪6SetFileAttr, Delete, Rename, GetDirEntry,
- ⓪6DirQuery, CreateDir, DeleteDir;
- ⓪
- ⓪ FROM FileNames IMPORT SplitPath;
- ⓪
- ⓪ FROM Files IMPORT File, Access, ReplaceMode,
- ⓪2Create, Open, Close, SetDateTime, GetDateTime, State,
- ⓪2GetStateMsg, ResetState, Remove;
- ⓪
- ⓪ FROM Binary IMPORT SeekMode,
- ⓪3ReadBytes, WriteBytes, FileSize, Seek, FilePos;
- ⓪
- ⓪ FROM Lists IMPORT List, CreateList, DeleteList, RemoveEntry, AppendEntry,
- ⓪2ResetList, NextEntry, PrevEntry, CurrentEntry, NoOfEntries;
- ⓪
- ⓪ FROM SysUtil0 IMPORT VarEqual;
- ⓪
- ⓪
- ⓪ CONST (* MOS const.s *)
- ⓪
- ⓪(noErrorTrap = 6;
- ⓪
- ⓪((* system call opcodes *)
- ⓪
- ⓪(flopwr = 9;
- ⓪(flopfmt = 10;
- ⓪(protobt = 18;
- ⓪(
- ⓪(xbios = 14;
- ⓪(
- ⓪((* misc *)
- ⓪(
- ⓪(filesAndSubdirs = FileAttrSet {subdirAttr};
- ⓪(
- ⓪(
- ⓪(minCopySpace = 10L * 1024L; (* 10k minimal *)
- ⓪(minExternalSpace= 30L * 1024L; (* 30k minimal for other prog.s *)
- ⓪((* erweitert auf 30k für Pfadlisten *)
- ⓪
- ⓪ TYPE ptrMaxStr = POINTER TO ARRAY[0..32767] OF CHAR;
- ⓪(str128 = ARRAY[0..127] OF CHAR;
- ⓪(fileName = ARRAY[0..11] OF CHAR;
- ⓪(ptrCardinal = POINTER TO CARDINAL;
- ⓪(
- ⓪(
- ⓪ TYPE statusRecord = RECORD
- ⓪<fileErrAlert: FileErrorAlertProc;
- ⓪<
- ⓪<showStatus : FileOpStatusProc;
- ⓪<noFiles : CARDINAL;
- ⓪:END;
- ⓪(ptrStatusRecord = POINTER TO statusRecord;
- ⓪(
- ⓪((* types for the copy buffer *)
- ⓪(
- ⓪(copyBufferElem = POINTER TO RECORD
- ⓪<next : copyBufferElem; (* NIL <=> not used *)
- ⓪<newPath : str128;
- ⓪<isSubdir: BOOLEAN;
- ⓪<date : Date; (* of creation *)
- ⓪<time : Time; (* of creation *)
- ⓪<seekPos : LONGCARD; (* append if > 0L *)
- ⓪<start : ADDRESS; (* start of data *)
- ⓪<length : LONGCARD; (* length of data *)
- ⓪:END;
- ⓪(
- ⓪(copyBuffer = POINTER TO RECORD
- ⓪<bottom, (* first buffer elem *)
- ⓪<next : copyBufferElem; (* next elem. to use *)
- ⓪<length : LONGCARD; (* buffer length *)
- ⓪<
- ⓪<status : statusRecord;
- ⓪<
- ⓪<feAlert : FileExistsAlertProc;
- ⓪<oldPathLen: CARDINAL;
- ⓪<newPath : str128;
- ⓪<
- ⓪<success : BOOLEAN; (* FALSE ~ Error *)
- ⓪:END;
- ⓪'
- ⓪
- ⓪ VAR voidO : BOOLEAN;
- ⓪(voidI : INTEGER;
- ⓪(voidFN: fileName;
- ⓪(void128: str128;
- ⓪(
- ⓪
- ⓪ CONST DebugInfo = FALSE;
- ⓪
- ⓪ (*$? DebugInfo:
- ⓪
- ⓪ PROCEDURE wLn (REF str: ARRAY OF CHAR);
- ⓪
- ⓪"BEGIN
- ⓪$WriteString (str); WriteLn;
- ⓪"END wLn;
- ⓪
- ⓪ PROCEDURE w (REF str: ARRAY OF CHAR);
- ⓪
- ⓪"BEGIN
- ⓪$WriteString (str);
- ⓪"END w;
- ⓪
- ⓪ PROCEDURE wc (c: LONGCARD);
- ⓪
- ⓪"BEGIN
- ⓪$WriteCard (c, 6);
- ⓪"END wc;
- ⓪
- ⓪ PROCEDURE wi (c: INTEGER);
- ⓪
- ⓪"BEGIN
- ⓪$WriteInt (c, 6);
- ⓪"END wi;
- ⓪
- ⓪ PROCEDURE wsiLn (REF str: ARRAY OF CHAR; i: INTEGER);
- ⓪
- ⓪"BEGIN
- ⓪$w (str); wi (i); WriteLn;
- ⓪"END wsiLn;
- ⓪
- ⓪ PROCEDURE wcsLn (l: LONGCARD; REF str: ARRAY OF CHAR);
- ⓪
- ⓪"BEGIN
- ⓪$wc (l); wLn (str);
- ⓪"END wcsLn;
- ⓪"
- ⓪ PROCEDURE wscLn (REF str: ARRAY OF CHAR; l: LONGCARD);
- ⓪
- ⓪"BEGIN
- ⓪$w (str); wc (l); WriteLn;
- ⓪"END wscLn;
- ⓪"
- ⓪ PROCEDURE Wait;
- ⓪
- ⓪"VAR ch: CHAR;
- ⓪"
- ⓪"BEGIN
- ⓪$Read (ch);
- ⓪"END Wait;
- ⓪!*)
- ⓪"
- ⓪8(* misc. proc.s *)
- ⓪8(* ============ *)
- ⓪
- ⓪ PROCEDURE reportOutOfMemory;
- ⓪
- ⓪"(*$L-*)
- ⓪"BEGIN
- ⓪$ASSEMBLER
- ⓪(TRAP #noErrorTrap
- ⓪(DC.W OutOfMemory - $4000
- ⓪$END;
- ⓪"END reportOutOfMemory;
- ⓪"(*$L=*)
- ⓪"
- ⓪ PROCEDURE reportPathFault;
- ⓪
- ⓪"(*$L-*)
- ⓪"BEGIN
- ⓪$ASSEMBLER
- ⓪(TRAP #noErrorTrap
- ⓪(DC.W GeneralErr - $C000
- ⓪(ACZ 'FileManagement: Illegal path!'
- ⓪(SYNC
- ⓪$END;
- ⓪"END reportPathFault;
- ⓪"(*$L=*)
- ⓪"
- ⓪
- ⓪ PROCEDURE isSubdir (attrs: FileAttrSet): BOOLEAN;
- ⓪
- ⓪"BEGIN
- ⓪$RETURN subdirAttr IN attrs
- ⓪"END isSubdir;
- ⓪
- ⓪
- ⓪ PROCEDURE GetFileAttr (REF name : ARRAY OF CHAR;
- ⓪7VAR attr : FileAttrSet;
- ⓪7VAR result: INTEGER);
- ⓪"
- ⓪"VAR entry: DirEntry;
- ⓪"
- ⓪"BEGIN
- ⓪$GetDirEntry (name, entry, result);
- ⓪&(* -> Directory.GetFileAttr geht nicht bei Subdirs. *)
- ⓪$attr := entry.attr;
- ⓪"END GetFileAttr;
- ⓪
- ⓪ PROCEDURE doShowStatus ( statusRecPtr: ptrStatusRecord;
- ⓪<ioRes : INTEGER;
- ⓪8VAR stop : BOOLEAN);
- ⓪
- ⓪"VAR report,
- ⓪(continue: BOOLEAN;
- ⓪(
- ⓪"BEGIN
- ⓪$WITH statusRecPtr^ DO
- ⓪$
- ⓪&report := (ioRes = fFileNotFound) OR (ioRes = fPathNotFound)
- ⓪0OR (ioRes = fAccessDenied) OR (ioRes = fDiskFull);
- ⓪&continue := (ioRes = fOK) OR (ioRes = fFileNotFound)
- ⓪2OR (ioRes = fPathNotFound) OR (ioRes = fAccessDenied)
- ⓪2OR (ioRes = fFileExists);
- ⓪$
- ⓪&IF report THEN fileErrAlert (ioRes) END;
- ⓪&stop := ~ continue;
- ⓪$
- ⓪&IF ~ stop THEN
- ⓪(IF noFiles > 0 THEN DEC (noFiles) END;
- ⓪(showStatus (noFiles, stop);
- ⓪&END;
- ⓪&
- ⓪$END;
- ⓪"END doShowStatus;
- ⓪
- ⓪
- ⓪0(* operations on the 'copyBuffer' *)
- ⓪0(* ============================== *)
- ⓪0
- ⓪
- ⓪ (* createCopyBuffer -- Alloc.s as much memory as possible and creates
- ⓪!* a 'copyBuffer' with it.
- ⓪!* 'useAllMem = FALSE' means to use 2/5 of the largest
- ⓪!* avaible mem. block, else the whole block is used.
- ⓪!* 'success = FALSE' means, not enough memory.
- ⓪!*)
- ⓪!
- ⓪ PROCEDURE createCopyBuffer (VAR cb : copyBuffer;
- ⓪@useAllMem: BOOLEAN;
- ⓪<VAR success : BOOLEAN);
- ⓪
- ⓪"PROCEDURE memAvail (): LONGCARD;
- ⓪"
- ⓪$VAR res: LONGCARD;
- ⓪"
- ⓪$BEGIN
- ⓪&IF useAllMem THEN
- ⓪(res := MemAvail ();
- ⓪(IF res < minExternalSpace THEN res := 0
- ⓪(ELSE res := res - minExternalSpace END;
- ⓪&ELSE
- ⓪(res := MemAvail () * 2L DIV 5L;
- ⓪(IF res < minExternalSpace THEN res := 0 END;
- ⓪&END;
- ⓪&
- ⓪&res := res - res MOD 2L; (* make even *)
- ⓪&
- ⓪&RETURN res
- ⓪$END memAvail;
- ⓪$
- ⓪
- ⓪"BEGIN
- ⓪$success := (memAvail () >= minCopySpace );
- ⓪$IF ~ success THEN RETURN END;
- ⓪$
- ⓪$NEW (cb);
- ⓪$WITH cb^ DO
- ⓪&length := memAvail (); (* take as much as possible *)
- ⓪&ALLOCATE (bottom, length);
- ⓪&next := bottom; (* next elem. to use is the first elem. *)
- ⓪&bottom^.next := NIL; (* first elem. is not yet in use *)
- ⓪$END;
- ⓪"END createCopyBuffer;
- ⓪
- ⓪ PROCEDURE deleteCopyBuffer (cb: copyBuffer);
- ⓪
- ⓪"BEGIN
- ⓪$DEALLOCATE (cb^.bottom, 0L);
- ⓪$DISPOSE (cb);
- ⓪"END deleteCopyBuffer;
- ⓪"
- ⓪
- ⓪ (* bufAvail -- Determines the maximum amount of bytes, that are avaible
- ⓪!* in the 'cb'.
- ⓪!*)
- ⓪
- ⓪ PROCEDURE bufAvail (cb: copyBuffer): LONGCARD;
- ⓪
- ⓪"BEGIN
- ⓪$RETURN cb^.length - (LONGCARD (cb^.next) - LONGCARD (cb^.bottom))
- ⓪+- SIZE (cb^.next^)
- ⓪"END bufAvail;
- ⓪"
- ⓪ (* flushCopyBuffer -- Writes the data in 'cb' to the destination.
- ⓪!*)
- ⓪
- ⓪((* %% added 27.6.90 DS *)
- ⓪((* pc: short for PathChange *)
- ⓪ (* The 'pcList' is the pathChangedList. In this list all path's
- ⓪!* which were changed during flushBuffer will be stored.
- ⓪!* This Types and vars are global because the 'pcList' is initialised in
- ⓪!* the procedure 'copyFiles'. And it has to be global because otherwise
- ⓪!* some entries would be forgotten.
- ⓪!*)
- ⓪!
- ⓪"TYPE pcEntry = RECORD
- ⓪>oldPath,
- ⓪>newPath : str128;
- ⓪<END;
- ⓪*pcPtr = POINTER TO pcEntry;
- ⓪*
- ⓪"VAR pcList : List;
- ⓪
- ⓪ PROCEDURE flushCopyBuffer (cb: copyBuffer);
- ⓪
- ⓪"VAR elem : copyBufferElem;
- ⓪(ioRes: INTEGER;
- ⓪(f : File;
- ⓪(mode : ReplaceMode;
- ⓪(path : str128;
- ⓪(fn,
- ⓪(orgFn, (* %% added 30.6.90 DS: is needed for the
- ⓪A* pcList and the original pathname in it.
- ⓪A*)
- ⓪(oldFn: fileName;
- ⓪(stop : BOOLEAN;
- ⓪(
- ⓪"PROCEDURE stateErr (): BOOLEAN;
- ⓪$
- ⓪$BEGIN
- ⓪&ioRes := State (f);
- ⓪&IF ioRes # fOK THEN ResetState (f) END;
- ⓪&RETURN ioRes # fOK
- ⓪$END stateErr;
- ⓪$
- ⓪((* %% added 27.6.90 DS *)
- ⓪"PROCEDURE insertChangeEntry (VAR path : ARRAY OF CHAR;
- ⓪?VAR old, new : ARRAY OF CHAR;
- ⓪?start : CARDINAL) : BOOLEAN;
- ⓪$(* inserts the newPath corresponding to oldPath in the
- ⓪%* pathList. If no oldPath is found a new entry is created.
- ⓪%* Creating a new entry is the normal case due to changes in
- ⓪%* development.
- ⓪%*)
- ⓪$VAR sPath : str128;
- ⓪(pc : pcPtr;
- ⓪"BEGIN
- ⓪$FastStrings.Concat (path, old, sPath);
- ⓪$ResetList (pcList);
- ⓪$REPEAT
- ⓪&pc := NextEntry (pcList);
- ⓪$UNTIL (pc = NIL) OR StrEqual (sPath, pc^.oldPath);
- ⓪$IF pc # NIL
- ⓪$THEN
- ⓪&FastStrings.Concat (path, new, sPath);
- ⓪&FastStrings.Assign (sPath, pc^.newPath);
- ⓪$ELSE
- ⓪&ALLOCATE (pc, TSIZE (pcEntry));
- ⓪&IF pc = NIL THEN reportOutOfMemory; RETURN FALSE END;
- ⓪&FastStrings.Concat (path, old, pc^.oldPath);
- ⓪&FastStrings.Concat (path, new, pc^.newPath);
- ⓪&AppendEntry (pcList, pc, voidO);
- ⓪&IF voidO THEN reportOutOfMemory; RETURN FALSE END;
- ⓪$END;
- ⓪$RETURN TRUE
- ⓪"END insertChangeEntry;
- ⓪"
- ⓪"(* %% added 27.6.90 DS *)
- ⓪"PROCEDURE TestAndChange (VAR path : ARRAY OF CHAR;
- ⓪;last : CARDINAL);
- ⓪"(* If path is in the pcList, path will be replaced by the newPath.
- ⓪#* this proc call's itself recursively to change previous changed
- ⓪#* parts of a path correct.
- ⓪#* 'last' is a control-parameter to pretend infinite loops. (i don't
- ⓪#* know if it's necessary).
- ⓪#*)
- ⓪%VAR p : INTEGER;
- ⓪)l : CARDINAL;
- ⓪)pc: pcPtr;
- ⓪)tPath : str128;
- ⓪)tName : fileName;
- ⓪"BEGIN
- ⓪$l := Length (path);
- ⓪$IF (l > 2) AND ~(l = last)
- ⓪$THEN
- ⓪&SplitPath (path, tPath, tName);
- ⓪&tPath[Length(tPath)-1] := 0c; (* '\' löschen *)
- ⓪&TestAndChange (tPath, l);
- ⓪&Append ('\',tPath, voidO); (* '\' wieder anfügen *)
- ⓪&FastStrings.Concat (tPath, tName, path);
- ⓪&ResetList (pcList);
- ⓪&REPEAT
- ⓪(pc := NextEntry (pcList);
- ⓪&UNTIL (pc = NIL) OR StrEqual (path, pc^.oldPath);
- ⓪&IF pc # NIL
- ⓪&THEN
- ⓪(FastStrings.Assign (pc^.newPath, path);
- ⓪&END;
- ⓪$END;
- ⓪"END TestAndChange;
- ⓪"
- ⓪"PROCEDURE flushOneElem;
- ⓪"
- ⓪$VAR pathChanged : BOOLEAN;
- ⓪"
- ⓪$BEGIN
- ⓪&WITH elem^ DO IF isSubdir THEN
- ⓪&
- ⓪((* %% added by DS 27.6.90: *)
- ⓪(SplitPath (newPath, path, orgFn);
- ⓪(TestAndChange (path, 0);
- ⓪(FastStrings.Concat (path, orgFn, newPath);
- ⓪*
- ⓪(pathChanged := FALSE;
- ⓪(
- ⓪(LOOP
- ⓪*CreateDir (newPath, ioRes);
- ⓪*IF ioRes = fAccessDenied THEN (* folder exists *)
- ⓪*
- ⓪,SplitPath (newPath, path, oldFn);
- ⓪,fn := oldFn;
- ⓪,IF ~ cb^.feAlert (fn) THEN ioRes := fFileExists; EXIT END;
- ⓪,
- ⓪,(* %% added by DS 27.6.90: *)
- ⓪,IF ~StrEqual (oldFn, fn)
- ⓪,THEN
- ⓪.pathChanged := TRUE
- ⓪,ELSE
- ⓪.ioRes := fFileExists;
- ⓪.EXIT
- ⓪,END;
- ⓪,
- ⓪,FastStrings.Concat (path, fn, newPath);
- ⓪,
- ⓪*ELSE EXIT END; (* success *)
- ⓪(END;
- ⓪(
- ⓪((* %% added by DS 27.6.90: *)
- ⓪(IF pathChanged THEN
- ⓪+IF ~insertChangeEntry (path, orgFn, fn, cb^.oldPathLen)
- ⓪+THEN stop := TRUE
- ⓪+END;
- ⓪(END;
- ⓪(
- ⓪&ELSE
- ⓪&
- ⓪(IF seekPos > 0L THEN (* append *)
- ⓪(
- ⓪*Open (f, newPath, writeOnly);
- ⓪*IF stateErr () THEN Remove (f); RETURN END;
- ⓪*Seek (f, seekPos, fromBegin);
- ⓪*IF stateErr () THEN Remove (f); RETURN END;
- ⓪*
- ⓪(ELSE (* new file *)
- ⓪*mode := noReplace;
- ⓪*
- ⓪*TestAndChange (newPath, 0);
- ⓪*
- ⓪*LOOP
- ⓪*
- ⓪,Create (f, newPath, writeOnly, mode);
- ⓪,IF State (f) = fFileExists THEN (* file exists *)
- ⓪,
- ⓪.ResetState (f);
- ⓪.SplitPath (newPath, path, oldFn);
- ⓪.fn := oldFn;
- ⓪.IF ~ cb^.feAlert (fn) THEN ioRes := fFileExists; RETURN END;
- ⓪.IF StrEqual (fn, oldFn) THEN mode := replaceOld
- ⓪.ELSE FastStrings.Concat (path, fn, newPath) END;
- ⓪.
- ⓪,ELSIF stateErr () THEN RETURN (* file error! *)
- ⓪,ELSE EXIT END; (* success *)
- ⓪,
- ⓪*END;
- ⓪*
- ⓪(END;
- ⓪(
- ⓪(WriteBytes (f, start, length);
- ⓪(IF stateErr () THEN Remove (f); RETURN END;
- ⓪(Close (f);
- ⓪(Open (f, newPath, writeOnly);
- ⓪(SetDateTime (f, date, time);
- ⓪((* IF stateErr () THEN Remove (f); RETURN END; *)
- ⓪(Close (f);
- ⓪(
- ⓪&END END;
- ⓪$END flushOneElem;
- ⓪$
- ⓪"BEGIN
- ⓪$elem := cb^.bottom;
- ⓪$LOOP
- ⓪&IF elem^.next = NIL THEN EXIT END;
- ⓪&
- ⓪&flushOneElem;
- ⓪&
- ⓪&doShowStatus (ADR (cb^.status), ioRes, stop); (* communicate *)
- ⓪&IF stop THEN cb^.success := FALSE; EXIT END;
- ⓪&
- ⓪&elem := elem^.next;
- ⓪$END;
- ⓪$
- ⓪$cb^.next := cb^.bottom; (* free buffer contens *)
- ⓪$cb^.next^.next := NIL;
- ⓪"END flushCopyBuffer;
- ⓪"
- ⓪
- ⓪ (* createCopyBufferElem -- Creates a new elem. in the 'copyBuffer', if
- ⓪!* there is not enough room to do so, the buffer
- ⓪!* is flushed first.
- ⓪!* Call only, if there are no open files.
- ⓪!*)
- ⓪
- ⓪ PROCEDURE createCopyBufferElem ( cb : copyBuffer;
- ⓪@VAR elem: copyBufferElem);
- ⓪
- ⓪"BEGIN
- ⓪$IF bufAvail (cb) < (minCopySpace DIV 2L) THEN
- ⓪&flushCopyBuffer (cb); IF ~ cb^.success THEN RETURN END;
- ⓪$END;
- ⓪$
- ⓪$WITH cb^ DO
- ⓪&elem := next;
- ⓪&next := copyBufferElem (LONGCARD (bottom) + length - SIZE (cb^.next^));
- ⓪&elem^.next := next;
- ⓪&elem^.next^.next := NIL; (* mark next elem as free *)
- ⓪&elem^.start := ADDRESS (elem) + ADDRESS (SIZE (elem^));
- ⓪&elem^.length := LONGCARD (elem^.next) - LONGCARD (elem^.start);
- ⓪$END;
- ⓪"END createCopyBufferElem;
- ⓪
- ⓪ (* deleteCopyBufferElem -- Deletes a 'copyBufferElem'. The element must
- ⓪!* be the last in the 'copyBuffer'!
- ⓪!*)
- ⓪
- ⓪ PROCEDURE deleteCopyBufferElem ( cb: copyBuffer;
- ⓪@VAR elem: copyBufferElem);
- ⓪
- ⓪"BEGIN
- ⓪$cb^.next := elem;
- ⓪$elem^.next := NIL;
- ⓪"END deleteCopyBufferElem;
- ⓪"
- ⓪ (* shrinkBufferElem -- Reduces the length of 'elem' to 'bytes' byte.
- ⓪!*
- ⓪!* ATTENTION: -- Could only be used for the last
- ⓪!* used element of a buffer.
- ⓪!* -- Length of the elem. and start of
- ⓪!* the next differ, if 'bytes' is odd.
- ⓪!*)
- ⓪
- ⓪ PROCEDURE shrinkBufferElem (cb : copyBuffer;
- ⓪<elem : copyBufferElem;
- ⓪<bytes: LONGCARD);
- ⓪
- ⓪"BEGIN
- ⓪$(* if not last used elem. or trying to enlarge elem. size
- ⓪%*)
- ⓪$IF (elem^.next^.next # NIL) OR (elem^.length < bytes) THEN HALT END;
- ⓪$
- ⓪$elem^.length := bytes;
- ⓪$elem^.next := ADDRESS (elem^.start) + ADDRESS (bytes + bytes MOD 2L);
- ⓪$elem^.next^.next := NIL;
- ⓪$cb^.next := elem^.next;
- ⓪"END shrinkBufferElem;
- ⓪"
- ⓪"
- ⓪ PROCEDURE readIntoBuffer (REF path: ARRAY OF CHAR;
- ⓪:VAR pos : LONGCARD;
- ⓪>cb : copyBuffer);
- ⓪
- ⓪"VAR f : File;
- ⓪(bufElem : copyBufferElem;
- ⓪(readBytes: LONGCARD;
- ⓪(success : BOOLEAN;
- ⓪"
- ⓪"PROCEDURE stateErr (): BOOLEAN;
- ⓪"
- ⓪$BEGIN
- ⓪&cb^.success := (State (f) = fOK);
- ⓪&IF ~ cb^.success THEN
- ⓪(cb^.status.fileErrAlert (State (f));
- ⓪(ResetState (f);
- ⓪(pos := 0L;
- ⓪(Close (f);
- ⓪(bufElem^.next := NIL;
- ⓪&END;
- ⓪&RETURN ~ cb^.success
- ⓪$END stateErr;
- ⓪$
- ⓪
- ⓪"BEGIN
- ⓪$
- ⓪$(* alloc. room in the buffer for the new file (or part of it).
- ⓪%*)
- ⓪%
- ⓪$createCopyBufferElem (cb, bufElem);
- ⓪$IF ~ cb^.success THEN
- ⓪$pos := 0L; RETURN END;
- ⓪$WITH bufElem^ DO
- ⓪&Copy (path, cb^.oldPathLen, Length (path) - cb^.oldPathLen, newPath,
- ⓪,voidO);
- ⓪&Insert (cb^.newPath, 0, newPath, success);
- ⓪&IF ~ success THEN
- ⓪(reportPathFault;
- ⓪(deleteCopyBufferElem (cb, bufElem);
- ⓪(pos := 0L;
- ⓪(RETURN
- ⓪&END;
- ⓪&isSubdir := FALSE;
- ⓪&seekPos := pos;
- ⓪&
- ⓪&Open (f, path, readOnly); IF stateErr () THEN RETURN END;
- ⓪&GetDateTime (f, date, time);
- ⓪&Seek (f, pos, fromBegin); IF stateErr () THEN RETURN END;
- ⓪&ReadBytes (f, start, length, readBytes); IF stateErr () THEN RETURN END;
- ⓪&pos := FilePos (f);
- ⓪&IF pos = FileSize (f) THEN pos := 0L END; (* EOF *)
- ⓪&Close (f);
- ⓪&
- ⓪&shrinkBufferElem (cb, bufElem, readBytes);
- ⓪&
- ⓪$END;
- ⓪"END readIntoBuffer;
- ⓪
- ⓪"
- ⓪0(* proc.s for query through file list *)
- ⓪0(* ================================== *)
- ⓪0
- ⓪0
- ⓪((* The following proc.s shouldn't directly or indirectly be
- ⓪)* recursive. Cause the caller is working with global var.s
- ⓪)*)
- ⓪)
- ⓪ TYPE fileHandleProc = PROCEDURE (REF (*file: *) ARRAY OF CHAR,
- ⓪I(*env : *) ADDRESS): BOOLEAN;
- ⓪(dirHandleProc = PROCEDURE (REF (*dir: *) ARRAY OF CHAR,
- ⓪I(*env: *) ADDRESS): BOOLEAN;
- ⓪I
- ⓪(oldPathLenToEnvProc = PROCEDURE ((*oldLen: *) CARDINAL,
- ⓪I(*env : *) ADDRESS);
- ⓪I
- ⓪(queryEnv = RECORD
- ⓪<handleFile: fileHandleProc;
- ⓪<handleDir : dirHandleProc;
- ⓪<handleEnv : ADDRESS;
- ⓪<dirFirst : BOOLEAN;
- ⓪<
- ⓪<stop : BOOLEAN;
- ⓪<pathChanged : BOOLEAN;
- ⓪<newPath : PathStr;
- ⓪:END;
- ⓪
- ⓪ VAR dontKnowANameEnv: queryEnv;
- ⓪(dontKnowANameStr: str128;
- ⓪(
- ⓪(
- ⓪
- ⓪ PROCEDURE dontKnowAName (REF path: ARRAY OF CHAR; entry: DirEntry): BOOLEAN;
- ⓪
- ⓪"VAR success: BOOLEAN;
- ⓪(ioRes : INTEGER;
- ⓪((* %% added 30.6.90 DS: because dontKnowAName calls itself recursively
- ⓪)* the following var has to be local. Otherwise some pathes will
- ⓪)* not be set correct! See remark 34 lines above!!
- ⓪)*)
- ⓪(dontKnowANameStr: str128;
- ⓪
- ⓪"BEGIN
- ⓪$IF entry.name[0] # '.' THEN WITH dontKnowANameEnv DO
- ⓪$
- ⓪&Concat (path, entry.name, dontKnowANameStr, success);
- ⓪&IF ~ success THEN reportPathFault; stop := TRUE; RETURN FALSE END;
- ⓪&IF isSubdir (entry.attr) THEN
- ⓪&
- ⓪(IF dirFirst THEN
- ⓪*stop := ~ handleDir (dontKnowANameStr, handleEnv);
- ⓪*IF stop THEN RETURN FALSE END;
- ⓪(END;
- ⓪(
- ⓪(Append ('\*.*', dontKnowANameStr, success);
- ⓪(IF ~ success THEN reportPathFault; stop := TRUE; RETURN FALSE END;
- ⓪(DirQuery (dontKnowANameStr, filesAndSubdirs, dontKnowAName, ioRes);
- ⓪(IF stop OR (ioRes # fOK) THEN stop := TRUE; RETURN FALSE END;
- ⓪(
- ⓪(IF ~ dirFirst THEN
- ⓪*Concat (path, entry.name, dontKnowANameStr, success);
- ⓪*stop := ~ handleDir (dontKnowANameStr, handleEnv);
- ⓪*IF stop THEN RETURN FALSE END;
- ⓪(END;
- ⓪(
- ⓪&ELSE stop := ~ handleFile (dontKnowANameStr, handleEnv) END;
- ⓪&
- ⓪&IF stop THEN RETURN FALSE END;
- ⓪&
- ⓪$END END;
- ⓪$
- ⓪$RETURN TRUE
- ⓪"END dontKnowAName;
- ⓪
- ⓪ PROCEDURE queryFileList (REF path : ARRAY OF CHAR;
- ⓪=files : List;
- ⓪=workOnFile : fileHandleProc;
- ⓪=workOnDir : dirHandleProc;
- ⓪=setOldPathLen : oldPathLenToEnvProc;
- ⓪=workEnv : ADDRESS;
- ⓪=workOnDirFirst: BOOLEAN);
- ⓪
- ⓪"VAR entry : ptrMaxStr;
- ⓪(str,
- ⓪(str2,
- ⓪(str3 : str128;
- ⓪(ioRes : INTEGER;
- ⓪(attrs : FileAttrSet;
- ⓪(success: BOOLEAN;
- ⓪
- ⓪"BEGIN
- ⓪$WITH dontKnowANameEnv DO
- ⓪$
- ⓪&handleFile := workOnFile;
- ⓪&handleDir := workOnDir;
- ⓪&handleEnv := workEnv;
- ⓪&dirFirst := workOnDirFirst;
- ⓪&stop := FALSE;
- ⓪&pathChanged := FALSE;
- ⓪&
- ⓪&IF path[0]#0C THEN
- ⓪(IF path [Length (path) - 1] = '\' THEN FastStrings.Assign (path, str3)
- ⓪(ELSE Concat (path, '\', str3, success) END;
- ⓪&ELSE str3 := '' END;
- ⓪&
- ⓪&ResetList (files);
- ⓪&entry := NextEntry (files);
- ⓪&WHILE entry # NIL DO
- ⓪&
- ⓪(FastStrings.Assign (entry^, str2); (* !!! 'entry^' by reference !!! *)
- ⓪(
- ⓪(Concat (str3, str2, str, success);
- ⓪(IF ~ success THEN reportPathFault; RETURN END;
- ⓪(
- ⓪(SplitPath (str, str2, voidFN);
- ⓪(setOldPathLen (Length (str2), workEnv);
- ⓪(
- ⓪(GetFileAttr (str, attrs, ioRes); IF ioRes # fOK THEN RETURN END;
- ⓪(IF isSubdir (attrs) THEN
- ⓪(
- ⓪*IF dirFirst THEN
- ⓪,IF ~ handleDir (str, handleEnv) THEN RETURN END
- ⓪*END;
- ⓪*
- ⓪*Concat (str, '\*.*', str2, success);
- ⓪*IF ~ success THEN reportPathFault; RETURN END;
- ⓪*DirQuery (str2, filesAndSubdirs, dontKnowAName, ioRes);
- ⓪*IF stop OR (ioRes # fOK) THEN RETURN END;
- ⓪(
- ⓪*IF ~ dirFirst THEN
- ⓪,IF ~ handleDir (str, handleEnv) THEN RETURN END
- ⓪*END;
- ⓪*
- ⓪(ELSE IF ~ handleFile (str, handleEnv) THEN RETURN END END;
- ⓪(
- ⓪(entry := NextEntry (files);
- ⓪&END;
- ⓪&
- ⓪$END;
- ⓪"END queryFileList;
- ⓪!
- ⓪!
- ⓪ PROCEDURE statusDummy (c: CARDINAL; VAR s: BOOLEAN);
- ⓪
- ⓪"BEGIN
- ⓪$s := FALSE;
- ⓪"END statusDummy;
- ⓪
- ⓪ PROCEDURE setLenDummy (c: CARDINAL; env: ADDRESS);
- ⓪
- ⓪"END setLenDummy;
- ⓪
- ⓪
- ⓪8(* proc.s for query *)
- ⓪8(* ================ *)
- ⓪
- ⓪ PROCEDURE countEntry (REF path: ARRAY OF CHAR; env: ADDRESS): BOOLEAN;
- ⓪
- ⓪"BEGIN
- ⓪$INC (env^); (* not clean, but saves a cast *)
- ⓪$RETURN TRUE
- ⓪"END countEntry;
- ⓪"
- ⓪ PROCEDURE deleteFile (REF path: ARRAY OF CHAR; env: ADDRESS): BOOLEAN;
- ⓪
- ⓪"VAR ioRes: INTEGER;
- ⓪(stop : BOOLEAN;
- ⓪
- ⓪"BEGIN
- ⓪$Delete (path, ioRes);
- ⓪$doShowStatus (env, ioRes, stop);
- ⓪$RETURN ~ stop
- ⓪"END deleteFile;
- ⓪"
- ⓪ PROCEDURE deleteDir (REF path: ARRAY OF CHAR; env: ADDRESS): BOOLEAN;
- ⓪
- ⓪"VAR ioRes: INTEGER;
- ⓪(stop : BOOLEAN;
- ⓪"
- ⓪"BEGIN
- ⓪$DeleteDir (path, ioRes);
- ⓪$doShowStatus (env, ioRes, stop);
- ⓪$RETURN ~ stop
- ⓪"END deleteDir;
- ⓪
- ⓪
- ⓪ PROCEDURE fileInBuffer (REF path: ARRAY OF CHAR; env: ADDRESS): BOOLEAN;
- ⓪
- ⓪"VAR cb : copyBuffer;
- ⓪(pos : LONGCARD;
- ⓪
- ⓪"BEGIN
- ⓪$cb := copyBuffer (env);
- ⓪$
- ⓪$pos := 0L;
- ⓪$REPEAT
- ⓪&readIntoBuffer (path, pos, cb);
- ⓪$UNTIL pos = 0L;
- ⓪$
- ⓪$RETURN cb^.success
- ⓪"END fileInBuffer;
- ⓪"
- ⓪ PROCEDURE dirInBuffer (REF path: ARRAY OF CHAR; env: ADDRESS): BOOLEAN;
- ⓪
- ⓪"VAR cb : copyBuffer;
- ⓪(bufElem: copyBufferElem;
- ⓪(success: BOOLEAN;
- ⓪(tPath : str128;
- ⓪(
- ⓪
- ⓪"BEGIN
- ⓪$cb := copyBuffer (env);
- ⓪$
- ⓪$createCopyBufferElem (cb, bufElem);
- ⓪$IF ~ cb^.success THEN RETURN FALSE END;
- ⓪$WITH bufElem^ DO
- ⓪&Concat (cb^.newPath,
- ⓪.FuncStrings.DelStr (path, 0, cb^.oldPathLen), tPath, success);
- ⓪&IF ~ success THEN
- ⓪(reportPathFault;
- ⓪(deleteCopyBufferElem (cb, bufElem);
- ⓪(RETURN FALSE
- ⓪&END;
- ⓪&FastStrings.Assign (tPath, newPath);
- ⓪&
- ⓪&isSubdir := TRUE;
- ⓪&
- ⓪$END;
- ⓪$
- ⓪$shrinkBufferElem (cb, bufElem, 0L);
- ⓪$
- ⓪$RETURN TRUE
- ⓪"END dirInBuffer;
- ⓪
- ⓪ PROCEDURE setOldPathLen (len: CARDINAL; env: ADDRESS);
- ⓪
- ⓪"VAR cb: copyBuffer;
- ⓪
- ⓪"BEGIN
- ⓪$cb := copyBuffer (env);
- ⓪$
- ⓪$cb^.oldPathLen := len;
- ⓪"END setOldPathLen;
- ⓪"
- ⓪"
- ⓪8(* Die exportierten Routinen *)
- ⓪8(* ========================= *)
- ⓪"
- ⓪ PROCEDURE CountFilesAndDirs (REF path: ARRAY OF CHAR;
- ⓪Al : List;
- ⓪=VAR no : CARDINAL);
- ⓪
- ⓪"BEGIN
- ⓪$no := 0;
- ⓪$queryFileList (path, l, countEntry, countEntry, setLenDummy, ADR (no),
- ⓪3TRUE);
- ⓪"END CountFilesAndDirs;
- ⓪"
- ⓪ PROCEDURE DeleteFiles (REF path : ARRAY OF CHAR;
- ⓪7files : List;
- ⓪7noFiles : CARDINAL;
- ⓪7showStatus : FileOpStatusProc;
- ⓪7fileErrAlert: FileErrorAlertProc);
- ⓪
- ⓪"VAR status: statusRecord;
- ⓪(stop : BOOLEAN;
- ⓪
- ⓪"BEGIN
- ⓪$showStatus (noFiles, stop); IF stop THEN RETURN END;
- ⓪&
- ⓪$status.fileErrAlert := fileErrAlert;
- ⓪$status.showStatus := showStatus;
- ⓪$status.noFiles := noFiles;
- ⓪$
- ⓪$queryFileList (path, files, deleteFile, deleteDir, setLenDummy,
- ⓪3ADR (status), FALSE);
- ⓪"END DeleteFiles;
- ⓪
- ⓪ PROCEDURE CopyFiles (REF path : ARRAY OF CHAR;
- ⓪5files : List;
- ⓪5noFiles : CARDINAL;
- ⓪5REF newPath : ARRAY OF CHAR;
- ⓪5deleteOld,
- ⓪5useAllMem : BOOLEAN;
- ⓪5feAlert : FileExistsAlertProc;
- ⓪5showStatus : FileOpStatusProc;
- ⓪5fileErrAlert: FileErrorAlertProc);
- ⓪
- ⓪"VAR buffer : copyBuffer;
- ⓪(len : CARDINAL;
- ⓪(success,
- ⓪(stop : BOOLEAN;
- ⓪(entry : pcPtr;
- ⓪
- ⓪"BEGIN
- ⓪$showStatus (noFiles, stop); IF stop THEN RETURN END;
- ⓪&
- ⓪$(* %% added 27.6.90 DS *)
- ⓪$CreateList (pcList, success);
- ⓪$IF success (* TRUE means error, but i don't wanted another var *)
- ⓪$THEN reportOutOfMemory; RETURN END;
- ⓪$
- ⓪$createCopyBuffer (buffer, useAllMem, success);
- ⓪$IF ~ success THEN reportOutOfMemory; RETURN END;
- ⓪$buffer^.feAlert := feAlert;
- ⓪$Assign (newPath, buffer^.newPath, success);
- ⓪$len := Length (newPath);
- ⓪$IF ~ success OR (len < 2) THEN
- ⓪&reportPathFault;
- ⓪&deleteCopyBuffer (buffer);
- ⓪&RETURN
- ⓪$END;
- ⓪$IF newPath[len - 1] # '\' THEN Append ('\', buffer^.newPath, voidO) END;
- ⓪$buffer^.status.fileErrAlert := fileErrAlert;
- ⓪$buffer^.status.showStatus := showStatus;
- ⓪$buffer^.status.noFiles := noFiles;
- ⓪$buffer^.success := TRUE;
- ⓪$
- ⓪$queryFileList (path, files, fileInBuffer, dirInBuffer, setOldPathLen,
- ⓪3buffer, TRUE);
- ⓪$flushCopyBuffer (buffer);
- ⓪$
- ⓪$deleteCopyBuffer (buffer);
- ⓪$
- ⓪$(* %% added 27.6.90 DS *)
- ⓪$(* delete pathList *)
- ⓪$ResetList (pcList);
- ⓪$entry := PrevEntry (pcList);
- ⓪$WHILE entry # NIL DO
- ⓪&RemoveEntry (pcList, voidO);
- ⓪&DEALLOCATE (entry, 0L);
- ⓪&entry := CurrentEntry (pcList);
- ⓪$END;
- ⓪$DeleteList (pcList, success)
- ⓪$
- ⓪"END CopyFiles;
- ⓪"
- ⓪ PROCEDURE FileInformation (REF name : ARRAY OF CHAR;
- ⓪;showFileInfo: FileInfoProc;
- ⓪;fileErrorAlt: FileErrorAlertProc);
- ⓪
- ⓪"VAR entry,
- ⓪(oldEntry: DirEntry;
- ⓪(ioRes : INTEGER;
- ⓪(path,
- ⓪(newName : str128;
- ⓪(f: File;
- ⓪(success : BOOLEAN;
- ⓪
- ⓪"PROCEDURE error (): BOOLEAN;
- ⓪$BEGIN
- ⓪&IF ioRes < fOK THEN fileErrorAlt (ioRes); RETURN TRUE END;
- ⓪&RETURN FALSE
- ⓪$END error;
- ⓪
- ⓪"PROCEDURE errorF (): BOOLEAN;
- ⓪$BEGIN
- ⓪&ioRes:= State (f);
- ⓪&RETURN error ()
- ⓪$END errorF;
- ⓪
- ⓪"BEGIN
- ⓪$GetDirEntry (name, entry, ioRes);
- ⓪$IF error () THEN RETURN END;
- ⓪$oldEntry := entry;
- ⓪$
- ⓪$showFileInfo (entry);
- ⓪$
- ⓪$SplitPath (name, path, voidFN);
- ⓪$Concat (path, entry.name, newName, success);
- ⓪$IF ~ success THEN reportPathFault; RETURN END;
- ⓪$
- ⓪$IF ~ StrEqual (entry.name, oldEntry.name) THEN
- ⓪&Rename (name, newName, ioRes);
- ⓪&IF error () THEN RETURN END;
- ⓪$END;
- ⓪$IF NOT (subdirAttr IN oldEntry.attr) THEN
- ⓪&IF ~VarEqual (entry.date, oldEntry.date)
- ⓪&OR ~VarEqual (entry.time, oldEntry.time) THEN
- ⓪(Open (f, newName, readOnly);
- ⓪(IF errorF () THEN RETURN END;
- ⓪(SetDateTime (f, entry.date, entry.time);
- ⓪(IF errorF () THEN RETURN END;
- ⓪(Close (f);
- ⓪(IF errorF () THEN RETURN END;
- ⓪&END;
- ⓪&IF (entry.attr # oldEntry.attr) THEN
- ⓪(SetFileAttr (newName, entry.attr, ioRes);
- ⓪(IF error () THEN RETURN END;
- ⓪&END;
- ⓪$END;
- ⓪"END FileInformation;
- ⓪
- ⓪ PROCEDURE FormatDisk ( drive : FormatDrive;
- ⓪:sides,
- ⓪:tracks,
- ⓪:sectorsPerTrack,
- ⓪:interleave : CARDINAL;
- ⓪:REF name : ARRAY OF CHAR;
- ⓪:showStatus : FileOpStatusProc;
- ⓪6VAR result : FormatResult);
- ⓪
- ⓪"CONST fmtBufferSize = 11L * 1024L;
- ⓪
- ⓪"VAR fmtBuffer : ADDRESS;
- ⓪"
- ⓪"PROCEDURE write(* (noSectors, side, track, sector: CARDINAL) on the A7 *);
- ⓪3
- ⓪$(*$L-*)
- ⓪$BEGIN
- ⓪&ASSEMBLER
- ⓪(MOVE.L (A7)+,(A3)+ ; save ret. addr.
- ⓪(
- ⓪(MOVE.W drive(A6),-(A7)
- ⓪(CLR.L -(A7) ; not used
- ⓪(MOVE.L fmtBuffer(A6),-(A7)
- ⓪(MOVE.W #flopwr,-(A7) ; write the boot sector
- ⓪(TRAP #xbios
- ⓪(LEA $14(A7),A7
- ⓪(
- ⓪(MOVE.L -(A3),-(A7) ; restore ret. addr.
- ⓪&END;
- ⓪$END write;
- ⓪$(*$L=*)
- ⓪
- ⓪"BEGIN
- ⓪$ASSEMBLER
- ⓪(MOVEM.L D4-D6,-(A7)
- ⓪(
- ⓪(SUBQ.W #1,drive(A6) ; 'drvA' ist 1
- ⓪(
- ⓪(MOVE.L result(A6),A0
- ⓪(MOVE.W #failedFR,(A0) ; be pessimistic
- ⓪#
- ⓪(; format media
- ⓪(;
- ⓪(; D6.W ~ counts tracks | D4.W ~ counts sides
- ⓪(
- ⓪(LEA fmtBuffer(A6),A0
- ⓪(MOVE.L A0,(A3)+
- ⓪(MOVE.L #fmtBufferSize,(A3)+
- ⓪(JSR ALLOCATE ; alloc. 'fmtBuffer'
- ⓪(TST.L fmtBuffer(A6)
- ⓪(BNE allocOk
- ⓪(
- ⓪(TRAP #noErrorTrap ; not enough memory avaible
- ⓪(DC.W OutOfMemory - $4000
- ⓪(BRA.W ende
- ⓪ allocOk
- ⓪(
- ⓪(MOVE.W tracks(A6),D6
- ⓪(SUBQ.W #1,D6
- ⓪ trackLoop
- ⓪
- ⓪(MOVE.W sides(A6),D4
- ⓪(SUBQ.W #1,D4
- ⓪ sideLoop
- ⓪
- ⓪(MOVE.W #$E5E5,-(A7) ; virgin word
- ⓪(MOVE.L #$87654321,-(A7) ; magic
- ⓪(MOVE.W interleave(A6),-(A7)
- ⓪(MOVE.W D4,-(A7)
- ⓪(MOVE.W D6,-(A7)
- ⓪(MOVE.W sectorsPerTrack(A6),-(A7)
- ⓪(MOVE.W drive(A6),-(A7)
- ⓪(CLR.L -(A7) ; not used
- ⓪(MOVE.L fmtBuffer(A6),-(A7)
- ⓪(MOVE.W #flopfmt,-(A7)
- ⓪(TRAP #xbios ; format one track
- ⓪(LEA $1A(A7),A7
- ⓪(TST.W D0
- ⓪(BNE.W stop ; bad sectors (no marking yet)
- ⓪
- ⓪(DBF D4,sideLoop
- ⓪(
- ⓪(MOVE.W D6,(A3)+
- ⓪(SUBQ.W #2,A7
- ⓪(MOVE.L A7,(A3)+
- ⓪(MOVE.L showStatus(A6),A0
- ⓪(JSR (A0)
- ⓪(TST.W (A7)+
- ⓪(BNE.W stop ; check user break
- ⓪
- ⓪(DBF D6, trackLoop
- ⓪(
- ⓪(; write boot sector
- ⓪(
- ⓪(MOVE.L fmtBuffer(A6),A0
- ⓪(MOVE.W #127,D0
- ⓪ clr1Loop
- ⓪(CLR.L (A0)+
- ⓪(DBF D0,clr1Loop
- ⓪(
- ⓪(CLR.W -(A7) ; not executable
- ⓪(MOVEQ #1,D0
- ⓪(ADD.W sides(A6),D0 ; 2 ~ SS, 3 ~ DS
- ⓪(MOVE.W D0,-(A7)
- ⓪(MOVE.L #$1000000,-(A7) ; random serial no.
- ⓪(MOVE.L fmtBuffer(A6),-(A7)
- ⓪(MOVE.W #protobt,-(A7) ; make a boot sector
- ⓪(TRAP #xbios
- ⓪(LEA $E(A7),A7
- ⓪(
- ⓪(MOVE.W #1,-(A7) ; one sector
- ⓪(CLR.W -(A7) ; side 1
- ⓪(CLR.W -(A7) ; track 0
- ⓪(MOVE.W #1,-(A7) ; sector 1
- ⓪(BSR write ; write boot sector
- ⓪(TST.W D0
- ⓪(BNE.W stop ; stop, if write err
- ⓪(
- ⓪(; write FATs
- ⓪(
- ⓪(MOVE.L fmtBuffer(A6),A0
- ⓪(MOVE.W #895,D0 ; clear 7 sectors
- ⓪ clr2Loop
- ⓪(CLR.L (A0)+
- ⓪(DBF D0,clr2Loop
- ⓪(MOVE.L fmtBuffer(A6),A0
- ⓪(MOVE.L #$F7FFFF00,(A0) ; FAT-start must be $F7 FF FF
- ⓪(
- ⓪(MOVE.W #5,-(A7) ; 5 sectors
- ⓪(CLR.W -(A7) ; side 1
- ⓪(CLR.W -(A7) ; track 0
- ⓪(MOVE.W #2,-(A7) ; sector 2
- ⓪(BSR write ; write FAT 1
- ⓪(TST.W D0
- ⓪(BNE.W stop ; stop, if write err
- ⓪(
- ⓪(MOVEQ #5,D6 ; 5 sectors
- ⓪(MOVE.W sectorsPerTrack(A6),D4
- ⓪(SUBQ.W #6,D4 ; 'sectorsPerTrack' - alreadyUsed -> D4
- ⓪(SUB.W D4,D6 ; remaining sectors -> D6
- ⓪(
- ⓪(MOVE.W D4,-(A7) ; x sectors
- ⓪(CLR.W -(A7) ; side 1
- ⓪(CLR.W -(A7) ; track 0
- ⓪(MOVE.W #7,-(A7) ; sector 7
- ⓪(BSR write ; write FAT 2 Part 1
- ⓪(TST.W D0
- ⓪(BNE stop ; stop, if write err
- ⓪(
- ⓪(MOVE.W sides(A6),D0 ; if two sides then
- ⓪(MOVEQ #1,D5 ; side 2, track 0
- ⓪(SUB.W D5,D0 ; else
- ⓪(SUB.W D0,D5 ; side 1, track 1
- ⓪(EXG.L D0,D4 ; D4 = side, D5 = track
- ⓪(
- ⓪(TST.W D6
- ⓪(BEQ noPart2 ; jump, if no sectors left
- ⓪(
- ⓪(MOVE.W D6,-(A7)
- ⓪(MOVE.W D4,-(A7)
- ⓪(MOVE.W D5,-(A7)
- ⓪(MOVE.W #1,-(A7) ; sector 1
- ⓪(MOVE.W drive(A6),-(A7)
- ⓪(CLR.L -(A7) ; not used
- ⓪(MULU #512,D0
- ⓪(ADD.L fmtBuffer(A6),D0
- ⓪(MOVE.L D0,-(A7) ; alreadyWrittenSecs * 512 + 'fmtBuffer'
- ⓪(MOVE.W #flopwr,-(A7) ; write the boot sector
- ⓪(TRAP #xbios
- ⓪(LEA $14(A7),A7
- ⓪(TST.W D0
- ⓪(BNE stop ; stop, if write err
- ⓪(
- ⓪ noPart2
- ⓪
- ⓪(; write root directory
- ⓪(
- ⓪(MOVE.L fmtBuffer(A6),A0
- ⓪(MOVE.L name(A6),A1 ; ADR (name) -> A1
- ⓪(MOVE.W name+4(A6),D1 ; HIGH (name) -> D1
- ⓪(MOVEQ #11,D0
- ⓪(
- ⓪(BRA nameStart
- ⓪ nameLoop
- ⓪(MOVE.B D2,(A0)+
- ⓪(SUBQ.W #1,D1
- ⓪(BMI nameSpaces
- ⓪ nameStart
- ⓪(MOVE.B (A1)+,D2
- ⓪(DBEQ D0,nameLoop
- ⓪(BNE nameOk
- ⓪(
- ⓪ nameSpaces
- ⓪(BRA nameSpcStart
- ⓪ nameSpcLoop
- ⓪(MOVE.B #' ',(A0)+
- ⓪ nameSpcStart
- ⓪(DBF D0,nameSpcLoop
- ⓪(
- ⓪ nameOk
- ⓪(MOVE.B #08,(A0)+ ; attribute set for volume label
- ⓪(
- ⓪(MOVE.W #7,-(A7) ; directory length = 7 sectors
- ⓪(MOVE.W D4,-(A7)
- ⓪(MOVE.W D5,-(A7)
- ⓪(ADDQ.W #1,D6
- ⓪(MOVE.W D6,-(A7)
- ⓪(BSR write ; write directory
- ⓪(TST.W D0
- ⓪(BNE stop ; stop, if write err
- ⓪(
- ⓪(MOVE.L result(A6),A0
- ⓪(MOVE.W #okFR,(A0) ; flag success!
- ⓪(
- ⓪ stop
- ⓪(LEA fmtBuffer(A6),A0
- ⓪(MOVE.L A0,(A3)+
- ⓪(CLR.L (A3)+
- ⓪(JSR DEALLOCATE ; dealloc. 'fmtBuffer'
- ⓪ ende
- ⓪(MOVEM.L (A7)+,D4-D6
- ⓪$END;
- ⓪"END FormatDisk;
- ⓪"
- ⓪ END FileManagement.
- ⓪ ə
- (* $FFEA89F2$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$00006B12$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96$FFF57E96Ç$00000A48T.......T.......T.......T.......T.......T.......T.......T.......T.......T.......$00000933$0000093E$0000094B$00000168$0000094B$000009B7$00006A40$00007088$000071F9$000071CE$00000933$00000A4B$000009C2$000009D2$00000A48$00006E6D¶Çâ*)
-