diff --git a/uxn/file.ha b/uxn/file.ha new file mode 100644 index 0000000..f37c312 --- /dev/null +++ b/uxn/file.ha @@ -0,0 +1,473 @@ +use fmt; +use os; +use fs; +use io; +use bytes; +use bufio; +use strings; + +fn generate_dir_string(name: str) str = { + // fmt::println("Generating dir string!")!; + let list: []u8 = []; + const fs: *fs::fs = match(os::diropen(name)){ + case let f: *fs::fs => + yield f; + case let err: fs::error => + fmt::fatalf("Error opening directory: {}", fs::strerror(err)); + + }; + let iter: *fs::iterator = match(fs::iter(fs,".")){ + case let i: *fs::iterator => + yield i; + case let err: fs::error => + fmt::fatalf("No iterator in directory: {}", fs::strerror(err)); + // case null => + // fmt::fatalf("Null pointer when opening directory: {}", name); + + }; + for(let item => fs::next(iter)){ + match(item){ + case let d: fs::dirent => + //001a file.txt + //???? large_file.mp4 + // 0-f A file + // - A directory + // ? A file that is larger than 64kb + // ! A missing file + let leftstring = "!!!!"; + let namestring = d.name; + if(d.ftype == fs::mode::DIR){ + leftstring = "----"; + namestring = strings::concat(d.name,"/")!; + }else{ + const stat = fs::stat(fs,d.name)!; + const fsize = stat.sz: u32; + if(fsize <= 0xFFFF){ + leftstring = fmt::asprintf("{:x.4}",fsize)!; + }else { + leftstring = "????"; + }; + }; + const wholestring = strings::concat(strings::join(" ", leftstring, d.name)!, "\n")!; + const utf8 = strings::toutf8(wholestring); + for( let c .. utf8 ){ + append(list,c)!; + }; + case let err: fs::error => + fmt::fatalf("Error looking in directory: {}", fs::strerror(err)); + }; + }; + return strings::fromutf8(list)!; +}; + +fn read_file_to_addr(fi: u8, state: *uxn) void = { + const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } + else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; + const destaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xac],state.dev[0xad]); } + else { yield short_from_bytes(state.dev[0xbc],state.dev[0xbd]); }; + // fmt::printfln("Reading {} bytes to 0x{:x}", length, destaddr)!; + let bytesread = 0; + + if(!state.files[fi].dir){ + for(let i: u16 =0; i + bytesread += 1; + // fmt::printfln("Reading byte {}: from file",b)!; + state.ram[destaddr+i] = b; + case let eof: io::EOF => + break; + case let err: io::error => + fmt::fatalf("Error reading: {}", io::strerror(err)); + }; + }; + + }else { + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + let dirstring = generate_dir_string(name); + let dirstringiter = strings::iter(dirstring); + for(let i: u16 =0; i + yield r; + case done => + break; + }; + bytesread += 1; + state.ram[destaddr+i] = char: u8; + }; + // fmt::printf(dirstring)!; + }; + + if(fi == 0){ + state.dev[0xa2] = (bytesread >> 8): u8; + state.dev[0xa3] = (bytesread): u8; + }else if(fi ==1){ + state.dev[0xb2] = (bytesread >> 8): u8; + state.dev[0xb3] = (bytesread): u8; + }; + return; +}; +fn filestat_to_addr(fi: u8, state: *uxn) void = { + const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } + else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; + const destaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa4],state.dev[0xa5]); } + else { yield short_from_bytes(state.dev[0xb4],state.dev[0xb5]); }; + // fmt::printfln("Reading {} bytes to 0x{:x}", length, destaddr)!; + let bytesread = 0; + + if(!state.files[fi].dir){ + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + const stat = os::fstat(state.files[fi].file: io::file)!; + const fsize = stat.sz: u32; + const modestring = if(fsize <= 0xFFFF){ + yield fmt::asprintf("{:x.4}",fsize)!; + }else { + yield "????"; + }; + let modestringiter = strings::iter(modestring); + for(let i: u16 =0; i + yield r; + case done => + break; + }; + bytesread += 1; + state.ram[destaddr+i] = char: u8; + }; + for(let i: u16 =0; i + bytesread += 1; + // fmt::printfln("Reading byte {}: from file",b)!; + state.ram[destaddr+i] = b; + case let eof: io::EOF => + state.ram[destaddr+i] = 0; //This might need to be done differently + case let err: io::error => + fmt::fatalf("Error reading: {}", io::strerror(err)); + }; + }; + + }else { + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + let dfs = os::diropen(name)!; + let df = os::dirfile(dfs); + const stat = os::fstat(df)!; + const fsize = stat.sz: u32; + const modestring = if(fsize <= 0xFFFF){ + yield fmt::asprintf("{:x.4}",fsize)!; + }else { + yield "????"; + }; + let modestringiter = strings::iter(modestring); + for(let i: u16 =0; i + yield r; + case done => + break; + }; + bytesread += 1; + state.ram[destaddr+i] = char: u8; + }; + for(let i: u16 =0; i + bytesread += 1; + // fmt::printfln("Reading byte {}: from file",b)!; + state.ram[destaddr+i] = b; + case let eof: io::EOF => + state.ram[destaddr+i] = 0; //This might need to be done differently + case let err: io::error => + fmt::fatalf("Error reading: {}", io::strerror(err)); + }; + }; + }; + + if(fi == 0){ + state.dev[0xa2] = (bytesread >> 8): u8; + state.dev[0xa3] = (bytesread): u8; + }else if(fi ==1){ + state.dev[0xb2] = (bytesread >> 8): u8; + state.dev[0xb3] = (bytesread): u8; + }; + return; +}; +fn write_file_from_addr(fi: u8,state: *uxn) void = { + const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } + else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; + const srcaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xae],state.dev[0xaf]); } + else { yield short_from_bytes(state.dev[0xbe],state.dev[0xbf]); }; + const endaddr = srcaddr + length; + const appendf: bool = if(fi == 0) { yield state.dev[0xa7] != 0; } + else { yield state.dev[0xb7] != 0; }; + fmt::printfln("Writing {} bytes from 0x{:x}", length, srcaddr)!; + const bytes: []u8 = state.ram[srcaddr..endaddr]; + let byteswritten: u16 = 0; + + if(!state.files[fi].exists){ + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + const flags = if(appendf) { + state.files[fi].fappend = true; + yield (fs::flag::RDWR | fs::flag::APPEND); + } else { + yield fs::flag::RDWR; + }; + state.files[fi].file = match (os::create(name,fs::mode::USER_RW,flags)){ + case let f: io::file => + state.files[fi].exists = true; + yield f; + case let err: fs::error => + fmt::fatalf("Error creating file file: {}", fs::strerror(err)); + }; + }; + + + if(appendf && (state.files[fi].fappend == false)){ + //Rewrite File or adjust pointer + io::close(state.files[fi].file)!; + + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + state.files[fi].file = match (os::open(name,fs::flag::RDWR | fs::flag::APPEND)) { + case let file: io::file => + state.files[fi].exists = true; + state.files[fi].dir = false; + yield file; + case let err: fs::error => + //Try opening as dir + yield match(os::diropen(name)){ + case let f: *fs::fs => + let dfs = os::diropen(name)!; + let df = os::dirfile(dfs); + const stat = os::fstat(df)!; + state.files[fi].dir = fs::isdir(stat.mode); + if(state.files[fi].dir) { + state.files[fi].exists = true; + state.files[fi].dir = true; + + }; + io::close(df)!; + yield io::empty; + case let err: fs::error => + // fmt::printfln("Error opening {}: {}", name, fs::strerror(err))!; + if(fi == 0){ + state.dev[0xa2] = 0; + state.dev[0xa3] = 0; + }else if(fi ==1){ + state.dev[0xb2] = 0; + state.dev[0xb3] = 0; + }; + state.files[fi].exists = false; + state.files[fi].dir = false; + yield io::empty; + + }; + + + }; + state.files[fi].fappend = true; + }; + + if(!appendf && (state.files[fi].fappend == true)){ + + io::close(state.files[fi].file)!; + + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + state.files[fi].file = match (os::open(name,fs::flag::RDWR)) { + case let file: io::file => + state.files[fi].exists = true; + state.files[fi].dir = false; + yield file; + case let err: fs::error => + //Try opening as dir + yield match(os::diropen(name)){ + case let f: *fs::fs => + let dfs = os::diropen(name)!; + let df = os::dirfile(dfs); + const stat = os::fstat(df)!; + state.files[fi].dir = fs::isdir(stat.mode); + if(state.files[fi].dir) { + state.files[fi].exists = true; + state.files[fi].dir = true; + + }; + io::close(df)!; + yield io::empty; + case let err: fs::error => + // fmt::printfln("Error opening {}: {}", name, fs::strerror(err))!; + if(fi == 0){ + state.dev[0xa2] = 0; + state.dev[0xa3] = 0; + }else if(fi ==1){ + state.dev[0xb2] = 0; + state.dev[0xb3] = 0; + }; + state.files[fi].exists = false; + state.files[fi].dir = false; + yield io::empty; + + }; + + + }; + state.files[fi].fappend = false; + }; + + match (io::write(state.files[fi].file,bytes)){ + case let s: size => + byteswritten += s: u16; + fmt::printfln("Writing {} bytes to file",s)!; + case let err: io::error => + fmt::fatalf("Error writing file: {}", io::strerror(err)); + }; + + if(fi == 0){ + state.dev[0xa2] = (byteswritten >> 8): u8; + state.dev[0xa3] = (byteswritten): u8; + }else if(fi ==1){ + state.dev[0xb2] = (byteswritten >> 8): u8; + state.dev[0xb3] = (byteswritten): u8; + }; + return; +}; +fn set_file_name(fi: u8, state: *uxn) void = { + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + + io::close(state.files[fi].file)!; + state.files[fi].fappend = false; + // fmt::printfln("Opening file: {}",name)!; + state.files[fi].file = match (os::open(name,fs::flag::RDWR)) { + case let file: io::file => + state.files[fi].exists = true; + state.files[fi].dir = false; + yield file; + case let err: fs::error => + //Try opening as dir + yield match(os::diropen(name)){ + case let f: *fs::fs => + let dfs = os::diropen(name)!; + let df = os::dirfile(dfs); + const stat = os::fstat(df)!; + state.files[fi].dir = fs::isdir(stat.mode); + if(state.files[fi].dir) { + state.files[fi].exists = true; + state.files[fi].dir = true; + + }; + io::close(df)!; + yield io::empty; + case let err: fs::error => + // fmt::printfln("Error opening {}: {}", name, fs::strerror(err))!; + if(fi == 0){ + state.dev[0xa2] = 0; + state.dev[0xa3] = 0; + }else if(fi ==1){ + state.dev[0xb2] = 0; + state.dev[0xb3] = 0; + }; + state.files[fi].exists = false; + state.files[fi].dir = false; + yield io::empty; + + }; + + + }; + return; +}; + +fn delete_file(fi: u8, state: *uxn) void = { + let success: u8 = 0; + if(state.files[fi].exists){ + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; + if(!state.files[fi].dir){ + match(os::remove(name)) { + case void => + success = 1; + yield; + case let err: fs::error => + fmt::printf("Error deleting file: {}", fs::strerror(err))!; + }; + }else{ + match(os::rmdir(name)) { + case void => + success = 1; + yield; + case let err: fs::error => + fmt::printf("Error deleting dir: {}", fs::strerror(err))!; + }; + }; + }; + if(fi == 0){ + state.dev[0xa2] = 0; + state.dev[0xa3] = success; + }else if(fi ==1){ + state.dev[0xb2] = 0; + state.dev[0xb3] = success; + }; +}; diff --git a/uxn/uxn.ha b/uxn/uxn.ha index 72386dd..64da2bf 100644 --- a/uxn/uxn.ha +++ b/uxn/uxn.ha @@ -238,471 +238,6 @@ fn emu_deo(port: u8, value: u8, state: *uxn) void = { }; }; -fn generate_dir_string(name: str) str = { - // fmt::println("Generating dir string!")!; - let list: []u8 = []; - const fs: *fs::fs = match(os::diropen(name)){ - case let f: *fs::fs => - yield f; - case let err: fs::error => - fmt::fatalf("Error opening directory: {}", fs::strerror(err)); - - }; - let iter: *fs::iterator = match(fs::iter(fs,".")){ - case let i: *fs::iterator => - yield i; - case let err: fs::error => - fmt::fatalf("No iterator in directory: {}", fs::strerror(err)); - // case null => - // fmt::fatalf("Null pointer when opening directory: {}", name); - - }; - for(let item => fs::next(iter)){ - match(item){ - case let d: fs::dirent => - //001a file.txt - //???? large_file.mp4 - // 0-f A file - // - A directory - // ? A file that is larger than 64kb - // ! A missing file - let leftstring = "!!!!"; - let namestring = d.name; - if(d.ftype == fs::mode::DIR){ - leftstring = "----"; - namestring = strings::concat(d.name,"/")!; - }else{ - const stat = fs::stat(fs,d.name)!; - const fsize = stat.sz: u32; - if(fsize <= 0xFFFF){ - leftstring = fmt::asprintf("{:x.4}",fsize)!; - }else { - leftstring = "????"; - }; - }; - const wholestring = strings::concat(strings::join(" ", leftstring, d.name)!, "\n")!; - const utf8 = strings::toutf8(wholestring); - for( let c .. utf8 ){ - append(list,c)!; - }; - case let err: fs::error => - fmt::fatalf("Error looking in directory: {}", fs::strerror(err)); - }; - }; - return strings::fromutf8(list)!; -}; - -fn read_file_to_addr(fi: u8, state: *uxn) void = { - const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } - else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; - const destaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xac],state.dev[0xad]); } - else { yield short_from_bytes(state.dev[0xbc],state.dev[0xbd]); }; - // fmt::printfln("Reading {} bytes to 0x{:x}", length, destaddr)!; - let bytesread = 0; - - if(!state.files[fi].dir){ - for(let i: u16 =0; i - bytesread += 1; - // fmt::printfln("Reading byte {}: from file",b)!; - state.ram[destaddr+i] = b; - case let eof: io::EOF => - break; - case let err: io::error => - fmt::fatalf("Error reading: {}", io::strerror(err)); - }; - }; - - }else { - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - let dirstring = generate_dir_string(name); - let dirstringiter = strings::iter(dirstring); - for(let i: u16 =0; i - yield r; - case done => - break; - }; - bytesread += 1; - state.ram[destaddr+i] = char: u8; - }; - // fmt::printf(dirstring)!; - }; - - if(fi == 0){ - state.dev[0xa2] = (bytesread >> 8): u8; - state.dev[0xa3] = (bytesread): u8; - }else if(fi ==1){ - state.dev[0xb2] = (bytesread >> 8): u8; - state.dev[0xb3] = (bytesread): u8; - }; - return; -}; -fn filestat_to_addr(fi: u8, state: *uxn) void = { - const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } - else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; - const destaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa4],state.dev[0xa5]); } - else { yield short_from_bytes(state.dev[0xb4],state.dev[0xb5]); }; - // fmt::printfln("Reading {} bytes to 0x{:x}", length, destaddr)!; - let bytesread = 0; - - if(!state.files[fi].dir){ - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - const stat = os::fstat(state.files[fi].file: io::file)!; - const fsize = stat.sz: u32; - const modestring = if(fsize <= 0xFFFF){ - yield fmt::asprintf("{:x.4}",fsize)!; - }else { - yield "????"; - }; - let modestringiter = strings::iter(modestring); - for(let i: u16 =0; i - yield r; - case done => - break; - }; - bytesread += 1; - state.ram[destaddr+i] = char: u8; - }; - for(let i: u16 =0; i - bytesread += 1; - // fmt::printfln("Reading byte {}: from file",b)!; - state.ram[destaddr+i] = b; - case let eof: io::EOF => - state.ram[destaddr+i] = 0; //This might need to be done differently - case let err: io::error => - fmt::fatalf("Error reading: {}", io::strerror(err)); - }; - }; - - }else { - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - let dfs = os::diropen(name)!; - let df = os::dirfile(dfs); - const stat = os::fstat(df)!; - const fsize = stat.sz: u32; - const modestring = if(fsize <= 0xFFFF){ - yield fmt::asprintf("{:x.4}",fsize)!; - }else { - yield "????"; - }; - let modestringiter = strings::iter(modestring); - for(let i: u16 =0; i - yield r; - case done => - break; - }; - bytesread += 1; - state.ram[destaddr+i] = char: u8; - }; - for(let i: u16 =0; i - bytesread += 1; - // fmt::printfln("Reading byte {}: from file",b)!; - state.ram[destaddr+i] = b; - case let eof: io::EOF => - state.ram[destaddr+i] = 0; //This might need to be done differently - case let err: io::error => - fmt::fatalf("Error reading: {}", io::strerror(err)); - }; - }; - }; - - if(fi == 0){ - state.dev[0xa2] = (bytesread >> 8): u8; - state.dev[0xa3] = (bytesread): u8; - }else if(fi ==1){ - state.dev[0xb2] = (bytesread >> 8): u8; - state.dev[0xb3] = (bytesread): u8; - }; - return; -}; -fn write_file_from_addr(fi: u8,state: *uxn) void = { - const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } - else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; - const srcaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xae],state.dev[0xaf]); } - else { yield short_from_bytes(state.dev[0xbe],state.dev[0xbf]); }; - const endaddr = srcaddr + length; - const appendf: bool = if(fi == 0) { yield state.dev[0xa7] != 0; } - else { yield state.dev[0xb7] != 0; }; - fmt::printfln("Writing {} bytes from 0x{:x}", length, srcaddr)!; - const bytes: []u8 = state.ram[srcaddr..endaddr]; - let byteswritten: u16 = 0; - - if(!state.files[fi].exists){ - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - const flags = if(appendf) { - state.files[fi].fappend = true; - yield (fs::flag::RDWR | fs::flag::APPEND); - } else { - yield fs::flag::RDWR; - }; - state.files[fi].file = match (os::create(name,fs::mode::USER_RW,flags)){ - case let f: io::file => - state.files[fi].exists = true; - yield f; - case let err: fs::error => - fmt::fatalf("Error creating file file: {}", fs::strerror(err)); - }; - }; - - - if(appendf && (state.files[fi].fappend == false)){ - //Rewrite File or adjust pointer - io::close(state.files[fi].file)!; - - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - state.files[fi].file = match (os::open(name,fs::flag::RDWR | fs::flag::APPEND)) { - case let file: io::file => - state.files[fi].exists = true; - state.files[fi].dir = false; - yield file; - case let err: fs::error => - //Try opening as dir - yield match(os::diropen(name)){ - case let f: *fs::fs => - let dfs = os::diropen(name)!; - let df = os::dirfile(dfs); - const stat = os::fstat(df)!; - state.files[fi].dir = fs::isdir(stat.mode); - if(state.files[fi].dir) { - state.files[fi].exists = true; - state.files[fi].dir = true; - - }; - io::close(df)!; - yield io::empty; - case let err: fs::error => - // fmt::printfln("Error opening {}: {}", name, fs::strerror(err))!; - if(fi == 0){ - state.dev[0xa2] = 0; - state.dev[0xa3] = 0; - }else if(fi ==1){ - state.dev[0xb2] = 0; - state.dev[0xb3] = 0; - }; - state.files[fi].exists = false; - state.files[fi].dir = false; - yield io::empty; - - }; - - - }; - state.files[fi].fappend = true; - }; - - if(!appendf && (state.files[fi].fappend == true)){ - - io::close(state.files[fi].file)!; - - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - state.files[fi].file = match (os::open(name,fs::flag::RDWR)) { - case let file: io::file => - state.files[fi].exists = true; - state.files[fi].dir = false; - yield file; - case let err: fs::error => - //Try opening as dir - yield match(os::diropen(name)){ - case let f: *fs::fs => - let dfs = os::diropen(name)!; - let df = os::dirfile(dfs); - const stat = os::fstat(df)!; - state.files[fi].dir = fs::isdir(stat.mode); - if(state.files[fi].dir) { - state.files[fi].exists = true; - state.files[fi].dir = true; - - }; - io::close(df)!; - yield io::empty; - case let err: fs::error => - // fmt::printfln("Error opening {}: {}", name, fs::strerror(err))!; - if(fi == 0){ - state.dev[0xa2] = 0; - state.dev[0xa3] = 0; - }else if(fi ==1){ - state.dev[0xb2] = 0; - state.dev[0xb3] = 0; - }; - state.files[fi].exists = false; - state.files[fi].dir = false; - yield io::empty; - - }; - - - }; - state.files[fi].fappend = false; - }; - - match (io::write(state.files[fi].file,bytes)){ - case let s: size => - byteswritten += s: u16; - fmt::printfln("Writing {} bytes to file",s)!; - case let err: io::error => - fmt::fatalf("Error writing file: {}", io::strerror(err)); - }; - - if(fi == 0){ - state.dev[0xa2] = (byteswritten >> 8): u8; - state.dev[0xa3] = (byteswritten): u8; - }else if(fi ==1){ - state.dev[0xb2] = (byteswritten >> 8): u8; - state.dev[0xb3] = (byteswritten): u8; - }; - return; -}; -fn set_file_name(fi: u8, state: *uxn) void = { - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - - io::close(state.files[fi].file)!; - state.files[fi].fappend = false; - // fmt::printfln("Opening file: {}",name)!; - state.files[fi].file = match (os::open(name,fs::flag::RDWR)) { - case let file: io::file => - state.files[fi].exists = true; - state.files[fi].dir = false; - yield file; - case let err: fs::error => - //Try opening as dir - yield match(os::diropen(name)){ - case let f: *fs::fs => - let dfs = os::diropen(name)!; - let df = os::dirfile(dfs); - const stat = os::fstat(df)!; - state.files[fi].dir = fs::isdir(stat.mode); - if(state.files[fi].dir) { - state.files[fi].exists = true; - state.files[fi].dir = true; - - }; - io::close(df)!; - yield io::empty; - case let err: fs::error => - // fmt::printfln("Error opening {}: {}", name, fs::strerror(err))!; - if(fi == 0){ - state.dev[0xa2] = 0; - state.dev[0xa3] = 0; - }else if(fi ==1){ - state.dev[0xb2] = 0; - state.dev[0xb3] = 0; - }; - state.files[fi].exists = false; - state.files[fi].dir = false; - yield io::empty; - - }; - - - }; - return; -}; - -fn delete_file(fi: u8, state: *uxn) void = { - let success: u8 = 0; - if(state.files[fi].exists){ - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - if(!state.files[fi].dir){ - match(os::remove(name)) { - case void => - success = 1; - yield; - case let err: fs::error => - fmt::printf("Error deleting file: {}", fs::strerror(err))!; - }; - }else{ - match(os::rmdir(name)) { - case void => - success = 1; - yield; - case let err: fs::error => - fmt::printf("Error deleting dir: {}", fs::strerror(err))!; - }; - }; - }; - if(fi == 0){ - state.dev[0xa2] = 0; - state.dev[0xa3] = success; - }else if(fi ==1){ - state.dev[0xb2] = 0; - state.dev[0xb3] = success; - }; -}; fn deo_expansion(addr: u16, state: *uxn) void = { const op = state.ram[addr];