import "io" manifest // positions in superblock { sb_first_dir_block = 1, sb_num_dir_blocks = 2, sb_first_free_block = 3, sb_total_num_blocks = 4 } manifest // directory entries { de_info = 0, de_block_number = 1, de_file_length = 2, de_name_start = 3, de_name_length = 20, sizeof_de = 8 } manifest { desired_dir_size = 4, num_de_per_block = 128 / sizeof_de } let sb_copy = vec(128); let discrd(block, memaddr) be { let r = devctl(dc$discread, 1, block, memaddr); if r < 0 then { out("\nERROR %d from disc read, block %d, mem %08X\n", r, block, memaddr); finish } } let discwr(block, memaddr) be { let r = devctl(dc$discwrite, 1, block, memaddr); if r < 0 then { out("\nERROR %d from disc write, block %d, mem %08X\n", r, block, memaddr); finish } } let format() be { let buff = vec(128); $memory_zero(sb_copy, 128); sb_copy ! sb_first_dir_block := 1; sb_copy ! sb_num_dir_blocks := desired_dir_size; sb_copy ! sb_first_free_block := desired_dir_size + 1; sb_copy ! sb_total_num_blocks := devctl(dc$disccheck, 1); discwr(0, sb_copy); $memory_zero(buff, 128); for i = 0 to 127 by 8 do buff ! i := 'X'; for i = 1 to desired_dir_size do discwr(i, buff); buff ! 0 := 'Firs'; buff ! 1 := 't fr'; buff ! 2 := 'ee b'; buff ! 3 := 'lock'; buff ! 4 := 0; discwr(desired_dir_size + 1, buff) } let startup() be { discrd(0, sb_copy) } let shutdown() be { discwr(0, sb_copy) } let get_free_blocks(num) be { let r = sb_copy ! sb_first_free_block; if r + num > sb_copy ! sb_total_num_blocks then { out("\nrun out of free blocks\n"); finish; } sb_copy ! sb_first_free_block +:= num; resultis r; } let print_name(ptr) be { for i = 0 to de_name_length - 1 do { let c = byte i of ptr; if c = 0 then return; outch(c) } } let copy_name(dst, src) be { let i = 0; while i < de_name_length do { let c = byte i of src; if c = 0 then break; byte i of dst := c; i +:= 1 } while i < de_name_length do { byte i of dst := 0; i +:= 1 } } let compare_name(a, b) be { let i = 0; while i < de_name_length do { let ca = byte i of a, cb = byte i of b; if ca <> cb then resultis ca - cb; if ca = 0 then resultis 0; i +:= 1 } resultis 0 } let write_dir_entry(ptr, info, name, block, len) be { let charnum = 0; ptr ! de_info := info; ptr ! de_block_number := block; ptr ! de_file_length := len; copy_name(ptr + de_name_start, name) } let create_directory_entry(info, name, block, len) be { let buff = vec(128); let dbn = sb_copy ! sb_first_dir_block; let last_dbn = dbn + sb_copy ! sb_num_dir_blocks - 1; let de_number = 0; while dbn <= last_dbn do { discrd(dbn, buff); for de = 0 to 127 by sizeof_de do { if buff ! (de + de_info) = 'X' then { write_dir_entry(buff + de, info, name, block, len); discwr(dbn, buff); resultis de_number } de_number +:= 1 } dbn +:= 1 } out("\nroot directory is full\n"); finish } let find_directory_entry(name, resultvec) be { let buff = vec(128); let dbn = sb_copy ! sb_first_dir_block; let last_dbn = dbn + sb_copy ! sb_num_dir_blocks - 1; let de_number = 0; while dbn <= last_dbn do { discrd(dbn, buff); for de_pos = 0 to 127 by sizeof_de do { let de_ptr = buff + de_pos; if de_ptr ! de_info <> 'X' then { if compare_name(name, de_ptr + de_name_start) = 0 then { $memory_move(resultvec, de_ptr, sizeof_de); resultis true } } de_number +:= 1 } dbn +:= 1 } resultis false } let write_file_content(blockn, char, length) be { let buff = vec(128), bpos = 0; for i = 1 to length do { byte bpos of buff := char; bpos +:= 1; if bpos = 512 then { discwr(blockn, buff); blockn +:= 1; bpos := 0 } } if bpos <> 0 then { while bpos < 512 do { byte bpos of buff := 0; bpos +:= 1 } discwr(blockn, buff); } } let make_file(name, letter, number) be { let buff = vec(128); let blks = (number + 511) / 512; let bn = get_free_blocks(blks); write_file_content(bn, letter, number); create_directory_entry('F', name, bn, number) } let show_file(name) be { let fileinfo = vec(sizeof_de), blocknum, length, buffer = vec(129); let r = find_directory_entry(name, fileinfo); if not r then { out("file %v not found\n", name); resultis false } blocknum := fileinfo ! de_block_number; length := fileinfo ! de_file_length; print_name(fileinfo + de_name_start); out(", block %d, length %d, info %c\n", blocknum, length, fileinfo ! de_info); while length >= 512 do { discrd(blocknum, buffer); buffer ! 128 := 0; outs(buffer); length -:= 512; blocknum +:= 1 } if length > 0 then { discrd(blocknum, buffer); byte length of buffer := 0; outs(buffer) } outch('\n') } let start() be // first test { let bn; format(); make_file("one", 'a', 500); make_file("two", 'b', 11); show_file("two"); shutdown() } /* let start() be // second test { let bn; startup(); make_file("three", 'c', 1028); make_file("four", 'd', 512); show_file("three"); shutdown() } let start() be // third test { let bn; startup(); show_file("four"); shutdown() } */