file remove/rename; alloc bugfixes; string additions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 18 May 2022 11:21:35 +0000 (06:21 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 18 May 2022 11:21:35 +0000 (06:21 -0500)
15 files changed:
core/alloc/arena.onyx
core/alloc/auto_heap.onyx
core/io/reader.onyx
core/onyx/fs.onyx
core/os/dir.onyx
core/os/file.onyx
core/os/os.onyx
core/os/process.onyx
core/string.onyx
core/wasi/wasi_fs.onyx
include/bh.h
include/small_windows.h
src/onyx_runtime.c
tests/struct_use_pointer_member
tests/struct_use_pointer_member.onyx

index fba77287cc63a5fe34d2cb161798a5c4da08dda8..eaf8fdef041e31ded4e61cbd2095307a8d578abb 100644 (file)
@@ -130,8 +130,12 @@ auto :: #match {
         alloc :: package core.alloc
 
         arena := alloc.arena.make(alloc.heap_allocator, size);
+        old_allocator := #unquote dest;
         (#unquote dest) = alloc.arena.make_allocator(^arena);
-        defer alloc.arena.free(^arena);
+        defer {
+            alloc.arena.free(^arena);
+            (#unquote dest) = old_allocator;
+        }
     },
 
     macro (body: Code, size := 32 * 1024) -> i32 {
index fd8bc399ee80f55b7e088fd57380cb2620fc95ba..05349be238b6588b9812df2a11fea7bbf493183a 100644 (file)
@@ -56,8 +56,12 @@ auto :: #match {
         alloc :: package core.alloc
         
         auto_heap := alloc.heap.auto_heap_make();
+        old_allocator := context.allocator;
         context.allocator = alloc.heap.auto_heap_make_allocator(^auto_heap);
-        defer alloc.heap.auto_heap_free(^auto_heap);
+        defer {
+            alloc.heap.auto_heap_free(^auto_heap);
+            context.allocator = old_allocator;
+        }
     },
 
     macro (body: Code) -> i32 {
index 83b105865288673166843a53fe58bd7e083b1d52..56b406900eaac2c8d3fcff7e8f4d82ae0e5b0923 100644 (file)
@@ -35,6 +35,8 @@ Reader :: struct {
     advance_line :: advance_line;
     skip_whitespace :: skip_whitespace;
     skip_bytes :: skip_bytes;
+
+    lines :: lines;
 }
 
 reader_make :: (s: ^Stream, buffer_size := 4096, allocator := context.allocator) -> Reader {
@@ -535,6 +537,27 @@ skip_bytes :: (use reader: ^Reader, bytes: u32) -> (skipped: i32, err: Error) {
     return 0, .None;
 }
 
+lines :: (r: ^Reader, inplace := false) -> Iterator(str) {
+    Context :: struct {
+        r: ^Reader;
+        inplace: bool;
+    }
+
+    c := new(Context, allocator=context.temp_allocator);
+    c.r = r;
+    c.inplace = inplace;
+
+    next :: (use c: ^Context) -> (str, bool) {
+        line := r->read_line(consume_newline=true, inplace=inplace);
+
+        if line.count > 0 do return line, true;
+        else do return "", false;
+    }
+
+    return .{ c, next };
+}
+
+
 #local reader_consume_error :: (use reader: ^Reader) -> Error {
     defer error = .None;
     return error;
index 0585cb426052e4a166292b33c0345eb08601c642..ea0124c0ecc649f6eb718196d1bd97cad62d0e1c 100644 (file)
@@ -23,6 +23,8 @@ __file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError)
 
     __file_close :: (fd: FileData) -> os.FileError ---
     __file_exists :: (path: str) -> bool ---
+    __file_remove :: (path: str) -> bool ---
+    __file_rename :: (old_path: str, new_path: str) -> bool ---
 
     __file_seek  :: (handle: FileData.Handle, to: i32, whence: io.SeekFrom) -> i32 ---
     __file_tell  :: (handle: FileData.Handle) -> u32 ---
@@ -31,9 +33,10 @@ __file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError)
     __file_flush :: (handle: FileData.Handle) -> io.Error ---
     __file_size  :: (handle: FileData.Handle) -> u32 ---
 
-    __dir_open  :: (path: str, dir: ^DirectoryData) -> bool ---
-    __dir_close :: (dir: DirectoryData) -> void ---
-    __dir_read  :: (dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool ---
+    __dir_open   :: (path: str, dir: ^DirectoryData) -> bool ---
+    __dir_close  :: (dir: DirectoryData) -> void ---
+    __dir_read   :: (dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool ---
+    __dir_remove :: (path: str) -> bool ---
 }
 
 __file_stream_vtable := io.Stream_Vtable.{
index 863fce0e8aea8576985f1bb01b5646049dc74c95..b97c7878226451bee0f845ac03c6d1f304f91b34 100644 (file)
@@ -41,3 +41,5 @@ dir_read :: (dir: Directory, out_entry: ^DirectoryEntry) -> bool {
 }
 
 dir_exists :: fs.__file_exists
+dir_remove :: fs.__dir_remove
+dir_rename :: fs.__file_rename
\ No newline at end of file
index 0e8367ce0a082d62350d6eacc5c774643867b6fe..98026b55c53a60907cce286ee945c8c413225a9d 100644 (file)
@@ -24,18 +24,9 @@ File :: struct {
     use data   : fs.FileData;
 }
 
-// Are these even necessary??
-#local {
-    file_open :: (path: str, mode := OpenMode.Read) -> (fs.FileData, FileError) {
-        return fs.__file_open(path, mode);
-    }
-
-    file_close :: (file: fs.FileData) -> FileError {
-        return fs.__file_close(file);
-    }
-}
-
 file_exists :: fs.__file_exists
+remove_file :: fs.__file_remove
+rename_file :: fs.__file_rename
 
 get_contents_from_file :: (file: ^File) -> str {
     size := cast(u32) io.stream_size(file);
@@ -58,7 +49,7 @@ open :: (path: str, mode := OpenMode.Read) -> (os.FileError, File) {
         data   = .{},
     };
 
-    file_data, error := file_open(path, mode);
+    file_data, error := fs.__file_open(path, mode);
     if error != .None do return error, file;
 
     file.data = file_data;
@@ -67,7 +58,7 @@ open :: (path: str, mode := OpenMode.Read) -> (os.FileError, File) {
 }
 
 close :: (file: ^File) {
-    file_close(file.data);
+    fs.__file_close(file.data);
     file.stream.vtable = null;
 }
 
index 064be058a93a6562ebb1b1d9b8b0fc1f7520916f..6eb4c57a245327098e05d6b3e44dd15d3b98eb59 100644 (file)
@@ -7,6 +7,7 @@ package core.os
 
 #local {
     runtime :: package runtime
+    string  :: package core.string
 }
 
 list_directory :: (path: str) -> Iterator(DirectoryEntry) {
@@ -41,6 +42,24 @@ list_directory :: (path: str) -> Iterator(DirectoryEntry) {
     return .{ c, next, close };
 }
 
+remove_directory :: (path: str) -> bool {
+    // This is quite a bit of space, and could result in a stack overrun
+    // if the directory being deleted has a lot of descendents.
+    full_path_buffer: [512] u8;
+
+    for list_directory(path) {
+        full_path := string.concat(full_path_buffer, path, "/", it->name());
+
+        if it.type == .Directory {
+            if !remove_directory(full_path) do return false;
+        } else {
+            remove_file(full_path);
+        }
+    }
+
+    return dir_remove(path);    
+}
+
 exit :: (exitcode: i32) {
     runtime.__exit(exitcode);
 }
index 761865684252f56b4c072b61b1a686926884eebb..e685849b25818adf6993c8a10505f7881c3dec36 100644 (file)
@@ -37,12 +37,25 @@ process_destroy :: (use p: ^Process) => {
     __process_destroy(process_handle);
 }
 
+#local Process_Read_Error :: enum {
+    None         :: 0x00;
+    Process_Dead :: 0x01;
+    Unknown      :: 0x02; 
+}
+
 #local process_stream_vtable := io.Stream_Vtable.{
     read = (use p: ^Process, buffer: [] u8) -> (io.Error, u32) {
         // Read from the process stdout
         if cast(i64) process_handle == 0 do return .BadFile, 0;
 
         bytes_read := __process_read(process_handle, buffer);
+        if bytes_read < 0 {
+            switch cast(Process_Read_Error) -bytes_read {
+                case .None do return .None, 0;
+                case .Process_Dead do return .EOF, 0;
+                case .Unknown do return .BadFile, 0;
+            }
+        }
         return .None, bytes_read;
     },
 
index 682aa322ef9751b4b3e9889ba36b4a88b7ac95ac..dae084dca80b9d800b91a5fcf2c71645d8ab0332 100644 (file)
@@ -11,6 +11,12 @@ alloc_copy :: (original: str, allocator := context.allocator) -> str {
     return new_str;
 }
 
+temp_copy :: (original: str) -> str {
+    new_str := make([] u8, original.count, allocator=context.temp_allocator);
+    copy(original, new_str);
+    return new_str;
+}
+
 copy :: (orig: str, dest: str) {
     len := orig.count;
     if dest.count < len do len = dest.count;
@@ -189,6 +195,20 @@ ends_with :: (s: str, suffix: str) -> bool {
 
 is_empty :: macro (s: str) => s.count == 0 || s.data == null;
 
+index_of :: (s: str, c: u8) -> i32 {
+    for s.count {
+        if s[it] == c do return it;
+    }
+    return -1;
+}
+
+last_index_of :: (s: str, c: u8) -> i32 {
+    for range.{s.count, 0, -1} {
+        if s[it] == c do return it;
+    }
+    return -1;
+}
+
 strip_whitespace :: #match {
     (s: ^str) { strip_leading_whitespace(s); strip_trailing_whitespace(s); },
     (s:  str) => s |> strip_leading_whitespace() |> strip_trailing_whitespace()
index 7c7c2f6a3c8b4dc62af07187af05add3ab902c0c..b4b89709414e17eeb9da0f2ceda7a607ad078e20 100644 (file)
@@ -122,6 +122,16 @@ __file_exists :: (path: str) -> bool {
     return exists;
 }
 
+__file_remove :: (path: str) -> bool {
+    removed := false;
+    for .[3, 4] { // Trying both preopened directories
+        err := wasi.path_unlink_file(it, path);
+        if err == .Success do removed = true;
+    }
+
+    return removed;
+}
+
 __file_stream_vtable := io.Stream_Vtable.{
     seek = (use fs: ^os.File, to: i32, whence: io.SeekFrom) -> io.Error {
         // Currently, the new offset is just ignored.
index b187b96de7456ce6efc74eb506a2e789ee3331fc..58123d72ff05baad49b4b1ba27d4f307f9b19eeb 100644 (file)
@@ -377,6 +377,7 @@ i32 bh_file_write(bh_file* file, void* buffer, isize buff_size);
 void bh_file_flush(bh_file* file);
 i64 bh_file_size(bh_file* file);
 b32 bh_file_exists(char const* filename);
+b32 bh_file_remove(char const* filename);
 char* bh_path_get_full_name(char const* filename, bh_allocator a);
 char* bh_path_get_parent(char const* filename, bh_allocator a);
 char* bh_path_convert_separators(char* path);
@@ -1637,6 +1638,15 @@ b32 bh_file_exists(char const* filename) {
     return stat(filename, &s) != -1;
 }
 
+b32 bh_file_remove(char const* filename) {
+#if defined(_BH_WINDOWS)
+    return DeleteFileA(filename);
+
+#elif defined(_BH_LINUX)
+    return unlink(filename) == 0;
+#endif
+}
+
 char* bh_path_get_full_name(char const* filename, bh_allocator a) {
 #if defined(_BH_WINDOWS)
     char buffer[4096];
index 45d8c1c46b90211022d9dbd497568fbc52a956a4..fe2ba6fa4182e0a168c4f549141bd40c21079a8b 100644 (file)
@@ -418,6 +418,9 @@ GB_DLL_IMPORT BOOL   WINAPI FindClose       (HANDLE find_file);
 GB_DLL_IMPORT BOOL   WINAPI GetFileAttributesExW(wchar_t const *path, GET_FILEEX_INFO_LEVELS info_level_id, WIN32_FILE_ATTRIBUTE_DATA *data);
 GB_DLL_IMPORT BOOL   WINAPI CopyFileW(wchar_t const *old_f, wchar_t const *new_f, BOOL fail_if_exists);
 GB_DLL_IMPORT BOOL   WINAPI MoveFileW(wchar_t const *old_f, wchar_t const *new_f);
+GB_DLL_IMPORT BOOL   WINAPI DeleteFileA     (char const *path);
+GB_DLL_IMPORT BOOL   WINAPI RemoveDirectoryA(char const *path);
+GB_DLL_IMPORT BOOL   WINAPI MoveFileA       (char const *old_path, char const *new_path);
 
 GB_DLL_IMPORT DWORD  WINAPI GetFullPathNameA(char const *lpFileName, DWORD nBufferLength, char *lpBuffer, char **lpFilePart);
 
index 33410e0238507a9f66a02fab62656308599d9f4c..4144d0822e4a9aad686603abb4afc2a63282b3b9 100644 (file)
@@ -84,6 +84,18 @@ ONYX_DEF(__file_exists, (WASM_I32, WASM_I32), (WASM_I32)) {
     return NULL;
 }
 
+ONYX_DEF(__file_remove, (WASM_I32, WASM_I32), (WASM_I32)) {
+    char *path_ptr = ONYX_PTR(params->data[0].of.i32);
+    int   path_len = params->data[1].of.i32;
+
+    char path[512] = {0};
+    strncpy(path, path_ptr, path_len);
+    path[path_len] = 0;
+
+    results->data[0] = WASM_I32_VAL(bh_file_remove(path));
+    return NULL;
+}
+
 ONYX_DEF(__file_seek, (WASM_I64, WASM_I32, WASM_I32), (WASM_I32)) {
     i64 fd = params->data[0].of.i64;
     i32 offset = params->data[1].of.i32;
@@ -173,6 +185,32 @@ ONYX_DEF(__file_get_standard, (WASM_I32, WASM_I32), (WASM_I32)) {
     return NULL;
 }
 
+ONYX_DEF(__file_rename, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    char *old_path_ptr = ONYX_PTR(params->data[0].of.i32);
+    int   old_path_len = params->data[1].of.i32;
+
+    char old_path[512] = {0};
+    strncpy(old_path, old_path_ptr, old_path_len);
+    old_path[old_path_len] = 0;
+
+    char *new_path_ptr = ONYX_PTR(params->data[2].of.i32);
+    int   new_path_len = params->data[3].of.i32;
+
+    char new_path[512] = {0};
+    strncpy(new_path, new_path_ptr, new_path_len);
+    new_path[new_path_len] = 0;
+
+#ifdef _BH_WINDOWS
+    results->data[0] = WASM_I32_VAL(MoveFileA(old_path, new_path));
+    return NULL;
+#endif
+
+#ifdef _BH_LINUX
+    results->data[0] = WASM_I32_VAL(rename(old_path, new_path) == 0);
+    return NULL;
+#endif
+}
+
 //
 // Directories
 //
@@ -301,6 +339,24 @@ ONYX_DEF(__dir_close, (WASM_I64), ()) {
     return NULL;
 }
 
+ONYX_DEF(__dir_remove, (WASM_I32, WASM_I32), (WASM_I32)) {
+    char *path_ptr = ONYX_PTR(params->data[0].of.i32);
+    int   path_len = params->data[1].of.i32;
+
+    char path[512] = {0};
+    strncpy(path, path_ptr, path_len);
+    path[path_len] = 0;
+
+#ifdef _BH_WINDOWS
+    results->data[0] = WASM_I32_VAL(RemoveDirectoryA(path));
+    return NULL;
+#endif
+
+#ifdef _BH_LINUX
+    results->data[0] = WASM_I32_VAL(rmdir(path) == 0);
+    return NULL;
+#endif
+}
 
 //
 // THREADS
@@ -469,6 +525,7 @@ ONYX_DEF(__process_spawn, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (W
     process->magic_number = ONYX_PROCESS_MAGIC_NUMBER;
 
     #ifdef _BH_LINUX
+        // :Security - alloca a user controlled string.
         char **process_args = alloca(sizeof(char *) * (args_len + 2));
         byte_t* array_loc = ONYX_PTR(args_ptr);
         fori (i, 0, args_len) {
@@ -605,12 +662,20 @@ ONYX_DEF(__process_read, (WASM_I64, WASM_I32, WASM_I32), (WASM_I32)) {
     i32 bytes_read;
     #ifdef _BH_LINUX
         bytes_read = read(process->proc_to_host[0], buffer, output_len);
-        bytes_read = bh_max(bytes_read, 0);  // Silently consume errors
+        if (bytes_read < 0) {
+            switch (errno) {
+                case EAGAIN: bytes_read =  0; break;
+                case EBADF:  bytes_read = -1; break;
+                default:     bytes_read = -2; break;
+            }
+        }
     #endif
 
     #ifdef _BH_WINDOWS
         i32 success = ReadFile(process->proc_to_host_read, buffer, output_len, &bytes_read, NULL);
-        if (!success) bytes_read = 0;
+        if (!success) {
+            bytes_read = -1;
+        }
     #endif
 
     results->data[0] = WASM_I32_VAL(bytes_read);
@@ -1123,6 +1188,7 @@ ONYX_LIBRARY {
     ONYX_FUNC(__file_open_impl)
     ONYX_FUNC(__file_close)
     ONYX_FUNC(__file_exists)
+    ONYX_FUNC(__file_remove)
     ONYX_FUNC(__file_seek)
     ONYX_FUNC(__file_tell)
     ONYX_FUNC(__file_read)
@@ -1130,10 +1196,12 @@ ONYX_LIBRARY {
     ONYX_FUNC(__file_flush)
     ONYX_FUNC(__file_size)
     ONYX_FUNC(__file_get_standard)
+    ONYX_FUNC(__file_rename)
 
     ONYX_FUNC(__dir_open)
     ONYX_FUNC(__dir_read)
     ONYX_FUNC(__dir_close)
+    ONYX_FUNC(__dir_remove)
 
     ONYX_FUNC(__spawn_thread)
     ONYX_FUNC(__kill_thread)
index 260ae42896c6be3d1b7dc8d32eb7bbd464bd9474..d606442da5e8403144baa7e7aba17c0dd9e4d039 100644 (file)
@@ -1,2 +1,2 @@
 Hello, I am Billy!
-Go away!! func[52]
+Go away!! 0xEDF4
index bf0916351b4bc1ac43108050460ad921313b7825..c2b8d445baffb81fec79fb1568030cc569494acf 100644 (file)
@@ -19,7 +19,7 @@ nice_person := Person_Vtable.{
 
 mean_person := Person_Vtable.{
     greet = (use p: ^Person) {
-        printf("Go away!! {}\n", greet);
+        printf("Go away!! {}\n", ^greet);
     }
 }