From: Brendan Hansen Date: Fri, 26 Aug 2022 18:59:38 +0000 (-0500) Subject: bugfixes and added file_stat X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=15be69db1933cdf8059a428f55cd256b6bf1ff9a;p=onyx.git bugfixes and added file_stat --- diff --git a/core/onyx/fs.onyx b/core/onyx/fs.onyx index 9ba45011..d98f798d 100644 --- a/core/onyx/fs.onyx +++ b/core/onyx/fs.onyx @@ -22,6 +22,7 @@ __file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError) __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData.Handle) -> os.FileError --- __file_close :: (fd: FileData) -> os.FileError --- + __file_stat :: (path: str, stat: ^os.FileStat) -> bool --- __file_exists :: (path: str) -> bool --- __file_remove :: (path: str) -> bool --- __file_rename :: (old_path: str, new_path: str) -> bool --- diff --git a/core/os/dir.onyx b/core/os/dir.onyx index 5594b588..6accbb32 100644 --- a/core/os/dir.onyx +++ b/core/os/dir.onyx @@ -5,20 +5,7 @@ package core.os Directory :: fs.DirectoryData; DirectoryEntry :: struct { - // Most of these types were stollen directly from - // man readdir(3), and the most reasonable types - // were used for Windows. - Type :: enum { - Unknown :: 0x00; - Block :: 0x01; - Char :: 0x02; - Directory :: 0x03; - RegularFile :: 0x04; - SymLink :: 0x05; - Other :: 0x06; - } - - type : Type; + type : FileType; identifier : u32; name_length : u32; name_data : [256] u8; diff --git a/core/os/file.onyx b/core/os/file.onyx index 98026b55..62534da8 100644 --- a/core/os/file.onyx +++ b/core/os/file.onyx @@ -24,7 +24,28 @@ File :: struct { use data : fs.FileData; } +// Most of these types were stollen directly from +// man readdir(3), and the most reasonable types +// were used for Windows. +FileType :: enum { + Unknown :: 0x00; + Block :: 0x01; + Char :: 0x02; + Directory :: 0x03; + RegularFile :: 0x04; + SymLink :: 0x05; + Other :: 0x06; +} + +// +// This is fairly minimal for right now. +FileStat :: struct { + size: i64; + type: FileType; +} + file_exists :: fs.__file_exists +file_stat :: fs.__file_stat remove_file :: fs.__file_remove rename_file :: fs.__file_rename @@ -102,7 +123,17 @@ with_file :: (path: str, mode := OpenMode.Read) -> Iterator(^File) { return .{ c, next, close_context }; } +is_file :: (path: str) -> bool { + s: FileStat; + if !file_stat(path, ^s) do return false; + return s.type == .RegularFile; +} +is_directory :: (path: str) -> bool { + s: FileStat; + if !file_stat(path, ^s) do return false; + return s.type == .Directory; +} file_logger_open :: (filename: str, allocator := context.allocator) -> Logger { diff --git a/core/string.onyx b/core/string.onyx index b4134f09..c4db484d 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -462,3 +462,20 @@ split :: (s: str, delim: u8, allocator := context.allocator) -> []str { return strarr[0 .. delim_count + 1]; } + +// +// Splits a string into two parts, divided by the +// first instance of the provided character. Either +// string can be empty if the first instance of the +// character occurs at the very beginning or end of +// the string, or if it does not occur at all. +// +bisect :: (s: str, c: u8) -> (str, str) { + index := index_of(s, c); + if index == -1 { + return s, ""; + } + + return s[0 .. index], s[index+1 .. s.length]; +} + diff --git a/core/wasi/wasi_fs.onyx b/core/wasi/wasi_fs.onyx index 6422ef46..4b6eadb5 100644 --- a/core/wasi/wasi_fs.onyx +++ b/core/wasi/wasi_fs.onyx @@ -110,6 +110,28 @@ __file_close :: (file: FileData) -> os.FileError { return .None; } +__file_stat :: (path: str, out: ^os.FileStat) -> bool { + fs: wasi.FileStat; + + exists := false; + for .[3, 4] { // Trying both preopened directories + err := wasi.path_filestat_get(it, .SymLinkFollow, path, ^fs); + if err == .Success { + exists = true; + out.size = ~~ fs.size; + + switch fs.filetype { + case .RegularFile do out.type = .RegularFile; + case .Directory do out.type = .Directory; + case .SymLink do out.type = .SymLink; + case #default do out.type = .Unknown; + } + } + } + + return exists; +} + __file_exists :: (path: str) -> bool { fs: wasi.FileStat; diff --git a/include/bh.h b/include/bh.h index b9f008dd..da5bbf3b 100644 --- a/include/bh.h +++ b/include/bh.h @@ -359,6 +359,15 @@ typedef struct bh_file_contents { isize line_count; } bh_file_contents; + +#define BH_FILE_TYPE_DIRECTORY 3 +#define BH_FILE_TYPE_FILE 4 +#define BH_FILE_TYPE_LINK 5 +typedef struct bh_file_stats { + isize size; + u32 file_type; +} bh_file_stats; + bh_file_error bh_file_get_standard(bh_file* file, bh_file_standard stand); bh_file_error bh_file_create(bh_file* file, char const* filename); @@ -377,6 +386,7 @@ i32 bh_file_read(bh_file* file, void* buffer, isize buff_size); 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_stat(char const* filename, bh_file_stats* stat); 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); @@ -1635,6 +1645,21 @@ b32 bh_file_contents_free(bh_file_contents* contents) { return 1; } +b32 bh_file_stat(char const* filename, bh_file_stats* out) { + struct stat s; + if (stat(filename, &s) == -1) { + return 0; + } + + out->size = s.st_size; + + if ((s.st_mode & S_IFMT) == S_IFDIR) out->file_type = BH_FILE_TYPE_DIRECTORY; + if ((s.st_mode & S_IFMT) == S_IFREG) out->file_type = BH_FILE_TYPE_FILE; + if ((s.st_mode & S_IFMT) == S_IFLNK) out->file_type = BH_FILE_TYPE_LINK; + + return 1; +} + b32 bh_file_exists(char const* filename) { struct stat s; return stat(filename, &s) != -1; diff --git a/include/parser.h b/include/parser.h index 054dd757..4c1e505a 100644 --- a/include/parser.h +++ b/include/parser.h @@ -37,6 +37,7 @@ typedef struct OnyxParser { b32 hit_unexpected_token : 1; b32 parse_calls : 1; + b32 inside_tag : 1; } OnyxParser; const char* onyx_ast_node_kind_string(AstKind kind); diff --git a/src/onyx_runtime.c b/src/onyx_runtime.c index 7827e1d3..8a7473e8 100644 --- a/src/onyx_runtime.c +++ b/src/onyx_runtime.c @@ -87,6 +87,19 @@ ONYX_DEF(__file_exists, (WASM_I32, WASM_I32), (WASM_I32)) { return NULL; } +ONYX_DEF(__file_stat, (WASM_I32, 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}; + path_len = bh_min(path_len, 511); + strncpy(path, path_ptr, path_len); + path[path_len] = 0; + + results->data[0] = WASM_I32_VAL(bh_file_stat(path, ONYX_PTR(params->data[2].of.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; @@ -1333,6 +1346,7 @@ ONYX_LIBRARY { ONYX_FUNC(__file_open_impl) ONYX_FUNC(__file_close) ONYX_FUNC(__file_exists) + ONYX_FUNC(__file_stat) ONYX_FUNC(__file_remove) ONYX_FUNC(__file_seek) ONYX_FUNC(__file_tell) diff --git a/src/parser.c b/src/parser.c index fae5d2b8..f41fe093 100644 --- a/src/parser.c +++ b/src/parser.c @@ -188,7 +188,18 @@ static void expect_no_stored_tags(OnyxParser *parser) { } static void flush_stored_tags(OnyxParser *parser, bh_arr(AstTyped *) *out_arr) { - if (bh_arr_length(parser->stored_tags) == 0) return; + // + // When inside_tag is true, no tags will be added to the element. + // This happens if you have a something like so, + // + // #tag "asdf" + // #tag handler.{ (x: i32) => x * 2 } + // foo :: () { ... } + // + // In this situation, the inner procedure defined in the second + // tag should NOT consume the "asdf" tag. + // + if (bh_arr_length(parser->stored_tags) == 0 || parser->inside_tag) return; bh_arr(AstTyped *) arr = *out_arr; @@ -2054,10 +2065,14 @@ static AstStructType* parse_struct(OnyxParser* parser) { while (parse_possible_directive(parser, "tag")) { if (meta_tags == NULL) bh_arr_new(global_heap_allocator, meta_tags, 1); + parser->inside_tag = 1; + do { AstTyped* expr = parse_expression(parser, 0); bh_arr_push(meta_tags, expr); } while (consume_token_if_next(parser, ',')); + + parser->inside_tag = 0; } member_is_used = consume_token_if_next(parser, Token_Type_Keyword_Use); @@ -3257,8 +3272,12 @@ static void parse_top_level_statement(OnyxParser* parser) { return; } else if (parse_possible_directive(parser, "tag")) { + parser->inside_tag = 1; + AstTyped *expr = parse_expression(parser, 0); bh_arr_push(parser->stored_tags, expr); + + parser->inside_tag = 0; return; } else {