PACKET dir DEFINES (* Copyright (c) 1986, 87 *) (* Frank Klapper *) open dir, (* 02.03.88 *) insert dir entry, delete dir entry, init dir ds, file info, format dir, dir list, file exists, subdir exists, all files, all subdirs: LET max dir entrys = 1000; (*-------------------------------------------------------------------------*) INITFLAG VAR dir block ds used := FALSE; DATASPACE VAR dir block ds; BOUND STRUCT (ALIGN dummy, ROW 64 REAL daten) VAR dir block; REAL VAR last read dir block no; PROC init dir block io: last read dir block no := -1.0; IF NOT initialized (dir block ds used) THEN dir block ds := nilspace; dir block := dir block ds FI. END PROC init dir block io; PROC read dir block (REAL CONST block nr): IF last read dir block no <> block nr THEN last read dir block no := -1.0; read disk block and close work if error (dir block ds, 2, block nr); last read dir block no := block nr FI. END PROC read dir block; PROC write dir block (REAL CONST block nr): write disk block and close work if error (dir block ds, 2, block nr); last read dir block no := block nr. END PROC write dir block; PROC write dir block: IF last read dir block no < 0.0 THEN error stop ("Lesefehler") FI; write dir block (last read dir block no) END PROC write dir block; PROC get dir entry (TEXT VAR entry buffer, INT CONST block entry no): (* 0 <= block entry no <= 15 *) entry buffer := 32 * "."; INT CONST replace offset := 4 * block entry no; replace (entry buffer, 1, dir block.daten [replace offset + 1]); replace (entry buffer, 2, dir block.daten [replace offset + 2]); replace (entry buffer, 3, dir block.daten [replace offset + 3]); replace (entry buffer, 4, dir block.daten [replace offset + 4]). END PROC get dir entry; PROC put dir entry (TEXT CONST entry buffer, INT CONST block entry no): (* 0 <= block entry no <= 15 *) INT CONST offset := 4 * block entry no; dir block.daten [offset + 1] := entry buffer RSUB 1; dir block.daten [offset + 2] := entry buffer RSUB 2; dir block.daten [offset + 3] := entry buffer RSUB 3; dir block.daten [offset + 4] := entry buffer RSUB 4. END PROC put dir entry; (*-------------------------------------------------------------------------*) LET DIRPOS = REAL; (* 16.0 * msdos block nr + entry no *) (* 0 <= entry no <= 15 *) DIRPOS PROC dirpos (REAL CONST block nr, INT CONST entry nr): block nr * 16.0 + real (entry nr). END PROC dir pos; REAL PROC block no (DIRPOS CONST p): floor (p / 16.0) END PROC block no; INT PROC entry no (DIRPOS CONST p): int (p MOD 16.0) END PROC entry no; PROC incr (DIRPOS VAR p): p INCR 1.0. END PROC incr; (*-------------------------------------------------------------------------*) LET FREELIST = STRUCT (ROW max dir entrys DIRPOS stack, INT stacktop, DIRPOS begin of free area, end of dir, REAL dir root); (* erste Clusterno, 0 für Main Dir *) PROC init free list (FREELIST VAR flist, REAL CONST root): flist.stacktop := 0; flist.begin of free area := dir pos (9.0e99, 0); flist.end of dir := dir pos (-1.0, 0); flist.dir root := root. END PROC init free list; PROC store (FREELIST VAR flist, DIRPOS CONST free pos): flist.stacktop INCR 1; flist.stack [flist.stack top] := free pos. END PROC store; PROC store begin of free area (FREELIST VAR flist, DIRPOS CONST begin): flist.begin of free area := begin END PROC store begin of free area; PROC store end of dir (FREELIST VAR flist, DIRPOS CONST end): flist.end of dir := end END PROC store end of dir; DIRPOS PROC free dirpos (FREELIST VAR flist): enable stop; DIRPOS VAR result; IF flist.stacktop > 0 THEN pop ELIF NOT free area empty THEN first of free area ELIF expansion alloweded THEN allocate new dir cluster; result := free dirpos (flist) ELSE error stop ("Directory voll") FI; result. pop: result := flist.stack [flist.stacktop]; flist.stacktop DECR 1. free area empty: flist.begin of free area > flist.end of dir. first of free area: result := flist.begin of free area; incr (flist.begin of free area). expansion alloweded: flist.dir root >= 2.0. allocate new dir cluster: REAL CONST new dir cluster :: available fat entry; REAL VAR last entry no; search last entry no of fat chain; fat entry (new dir cluster, last fat chain entry); fat entry (last entry no, new dir cluster); write fat; store begin of free area (flist, dir pos (first new block, 0)); store end of dir (flist, dir pos (last new block, 15)); init new dir cluster. search last entry no of fat chain: last entry no := flist.dir root; WHILE NOT is last fat chain entry (fat entry (last entry no)) REP last entry no := fat entry (last entry no) PER. first new block: begin of cluster (new dir cluster). last new block: begin of cluster (new dir cluster) + real (sectors per cluster - 1). init new dir cluster: TEXT CONST empty dir entry :: 32 * ""0""; INT VAR i; FOR i FROM 0 UPTO 15 REP put dir entry (empty dir entry, i) PER; disable stop; REAL VAR block no := first new block; WHILE block no <= last new block REP write dir block (block no) PER. END PROC free dirpos; (*-------------------------------------------------------------------------*) LET FILEENTRY = STRUCT (TEXT date and time, REAL size, first cluster, DIRPOS dirpos), FILELIST = STRUCT (THESAURUS thes, ROW max dir entrys FILEENTRY entry); PROC init file list (FILELIST VAR flist): flist.thes := empty thesaurus. END PROC init file list; PROC store file entry (FILELIST VAR flist, TEXT CONST entry text, DIRPOS CONST position): INT VAR entry index; insert (flist.thes, file name, entry index); store file entry (flist.entry [entry index], entry text, position). file name: TEXT CONST name pre :: compress (subtext (entry text, 1, 8)), name post :: compress (subtext (entry text, 9, 11)); IF name post <> "" THEN name pre + "." + name post ELSE name pre FI. END PROC store file entry; PROC store file entry (FILEENTRY VAR fentry, TEXT CONST entry text, DIRPOS CONST position): fentry.first cluster := real (entry text ISUB 14); fentry.date and time := dos date + " " + dos time; fentry.size := dint (entry text ISUB 15, entry text ISUB 16); fentry.dirpos := position. dos date: day + "." + month + "." + year. day: text2 (code (entry text SUB 25) MOD 32). month: text2 (code (entry text SUB 25) DIV 32 + 8 * (code (entry text SUB 26) MOD 2)). year: text (80 + code (entry text SUB 26) DIV 2, 2). dos time: hour + ":" + minute. hour: text2 (code (entry text SUB 24) DIV 8). minute: text2 (code (entry text SUB 23) DIV 32 + 8 * (code (entry text SUB 24) MOD 8)). END PROC store file entry; TEXT PROC text2 (INT CONST intvalue): IF intvalue < 10 THEN "0" + text (intvalue) ELSE text (int value) FI. END PROC text2; DIRPOS PROC file entry pos (FILELIST CONST flist, TEXT CONST file name): INT CONST link index :: link (flist.thes, file name); IF link index = 0 THEN error stop ("Die Datei """ + file name + """ gibt es nicht") FI; flist.entry [link index].dir pos. END PROC file entry pos; PROC delete (FILELIST VAR flist, TEXT CONST file name): INT VAR dummy; delete (flist.thes, file name, dummy). END PROC delete; PROC file info (FILELIST CONST flist, TEXT CONST file name, REAL VAR first cluster no, storage): INT CONST link index :: link (flist.thes, file name); IF link index = 0 THEN error stop ("Die Datei """ + file name + """ gibt es nicht") FI; first cluster no := flist.entry [link index].first cluster; storage := flist.entry [link index].size END PROC file info; BOOL PROC contains (FILELIST VAR flist, TEXT CONST file name): flist.thes CONTAINS file name END PROC contains; PROC list (FILE VAR f, FILELIST CONST flist): INT VAR index := 0; TEXT VAR name; get (flist.thes, name, index); WHILE index > 0 REP list file; get (flist.thes, name, index) PER. list file: write (f, centered name); write (f, " "); write (f, text (flist.entry [index].size, 11, 0)); write (f, " Bytes belegt "); write (f, flist.entry [index].date and time); (*COND TEST*) write (f, " +++ "); write (f, text (flist.entry [index].first cluster)); (*ENDCOND*) line (f). centered name: INT VAR point pos := pos (name, "."); IF point pos > 0 THEN name pre + "." + name post ELSE text (name, 12) FI. name pre: text (subtext (name, 1, point pos - 1), 8). name post: text (subtext (name, point pos + 1, point pos + 4), 3). END PROC list; (*-------------------------------------------------------------------------*) LET DIRENTRY = REAL, DIRLIST = STRUCT (THESAURUS thes, ROW max dir entrys DIRENTRY entry); PROC init dir list (DIRLIST VAR dlist): dlist.thes := empty thesaurus. END PROC init dir list; PROC store subdir entry (DIRLIST VAR dlist, TEXT CONST entry text): INT VAR entry index; insert (dlist.thes, subdir name, entry index); dlist.entry [entry index] := real (entry text ISUB 14). subdir name: TEXT CONST name pre :: compress (subtext (entry text, 1, 8)), name post :: compress (subtext (entry text, 9, 11)); IF name post <> "" THEN name pre + "." + name post ELSE name pre FI. END PROC store subdir entry; REAL PROC first cluster of subdir (DIRLIST CONST dlist, TEXT CONST name): INT CONST link index := link (dlist.thes, name); IF link index = 0 THEN error stop ("Das Unterverzeichnis """ + name + """ gibt es nicht") FI; dlist.entry [link index]. END PROC first cluster of subdir; BOOL PROC contains (DIRLIST CONST dlist, TEXT CONST subdir name): dlist.thes CONTAINS subdir name END PROC contains; PROC list (FILE VAR f, DIRLIST CONST dlist): INT VAR index := 0; TEXT VAR name; get (dlist.thes, name, index); WHILE index > 0 REP list dir; get (dlist.thes, name, index) PER. list dir: write (f, centered name); write (f, "