From e296b050eeca33ef44eb71e00532a8f2f971cb01 Mon Sep 17 00:00:00 2001 From: Matias Fernandez Date: Wed, 17 Apr 2024 22:54:30 -0400 Subject: [PATCH 1/8] fix #soa '%#v' formatting --- core/fmt/fmt.odin | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index d3b9d7d69..7f432a6be 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1900,7 +1900,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St // fi.hash = false; fi.indent += 1 - if hash { + if !is_soa && hash { io.write_byte(fi.writer, '\n', &fi.n) } defer { @@ -1934,6 +1934,9 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^) } + if hash && n > 0 { + io.write_byte(fi.writer, '\n', &fi.n) + } for index in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } @@ -1942,9 +1945,23 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St if !hash && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) } + if hash { + fi.indent -= 1 + fmt_write_indent(fi) + fi.indent += 1 + } io.write_string(fi.writer, base_type_name, &fi.n) io.write_byte(fi.writer, '{', &fi.n) - defer io.write_byte(fi.writer, '}', &fi.n) + if hash { io.write_byte(fi.writer, '\n', &fi.n) } + defer { + if hash { + fi.indent -= 1 + fmt_write_indent(fi) + fi.indent += 1 + } + io.write_byte(fi.writer, '}', &fi.n) + if hash { io.write_string(fi.writer, ",\n", &fi.n) } + } fi.record_level += 1 defer fi.record_level -= 1 From c44f618b7dec82cf80609fd613c93ef91cf6a7ae Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Fri, 19 Apr 2024 15:17:21 +0300 Subject: [PATCH 2/8] fix(net): add `NOSIGNAL` to `send` options This is a better default than not having it, since it turns errors that would be signals into error values instead. We could take these as options but given that we currently don't I think this at the very least improves on the status quo. --- core/net/errors_linux.odin | 1 + core/net/socket_linux.odin | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/core/net/errors_linux.odin b/core/net/errors_linux.odin index 2370dd0d8..5e2c52aea 100644 --- a/core/net/errors_linux.odin +++ b/core/net/errors_linux.odin @@ -136,6 +136,7 @@ TCP_Send_Error :: enum c.int { Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7). Timeout = c.int(linux.Errno.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout. Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket. + Broken_Pipe = c.int(linux.Errno.EPIPE), // The peer has disconnected when we are trying to send to it } // TODO diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index ba48959fb..9c4342592 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -258,7 +258,7 @@ _send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) { for total_written < len(buf) { limit := min(int(max(i32)), len(buf) - total_written) remaining := buf[total_written:][:limit] - res, errno := linux.send(linux.Fd(tcp_sock), remaining, {}) + res, errno := linux.send(linux.Fd(tcp_sock), remaining, {.NOSIGNAL}) if errno != .NONE { return total_written, TCP_Send_Error(errno) } From 7b95562827290258c49e27c7ee8d7be53b7239fe Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Fri, 19 Apr 2024 15:29:28 +0300 Subject: [PATCH 3/8] feat(net): turn `EPIPE` into `Connection_Closed` --- core/net/errors_linux.odin | 1 - core/net/socket_linux.odin | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/net/errors_linux.odin b/core/net/errors_linux.odin index 5e2c52aea..2370dd0d8 100644 --- a/core/net/errors_linux.odin +++ b/core/net/errors_linux.odin @@ -136,7 +136,6 @@ TCP_Send_Error :: enum c.int { Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7). Timeout = c.int(linux.Errno.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout. Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket. - Broken_Pipe = c.int(linux.Errno.EPIPE), // The peer has disconnected when we are trying to send to it } // TODO diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index 9c4342592..d9b29fb3a 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -259,7 +259,9 @@ _send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) { limit := min(int(max(i32)), len(buf) - total_written) remaining := buf[total_written:][:limit] res, errno := linux.send(linux.Fd(tcp_sock), remaining, {.NOSIGNAL}) - if errno != .NONE { + if errno == .EPIPE { + return total_written, TCP_Send_Error.Connection_Closed + } else if errno != .NONE { return total_written, TCP_Send_Error(errno) } total_written += int(res) From efc84cd390e6773ee71e35bc851ce4f55f39c34a Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Fri, 19 Apr 2024 15:37:20 +0300 Subject: [PATCH 4/8] docs(net): add comment about `EPIPE` -> `Connection_Closed` --- core/net/socket_linux.odin | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index d9b29fb3a..ee3a41927 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -260,7 +260,9 @@ _send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) { remaining := buf[total_written:][:limit] res, errno := linux.send(linux.Fd(tcp_sock), remaining, {.NOSIGNAL}) if errno == .EPIPE { - return total_written, TCP_Send_Error.Connection_Closed + // If the peer is disconnected when we are trying to send we will get an `EPIPE` error, + // so we turn that into a clearer error + return total_written, .Connection_Closed } else if errno != .NONE { return total_written, TCP_Send_Error(errno) } From 68f663ea8585f0de6ca7d34ecf93031603f22cb6 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Fri, 19 Apr 2024 15:39:04 +0300 Subject: [PATCH 5/8] fix(net): fix return type for `send_tcp` Was `.Connection_Closed` but this is only inferrable if our return type is not a sub-union of another. --- core/net/socket_linux.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index ee3a41927..a4d75b92b 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -262,7 +262,7 @@ _send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) { if errno == .EPIPE { // If the peer is disconnected when we are trying to send we will get an `EPIPE` error, // so we turn that into a clearer error - return total_written, .Connection_Closed + return total_written, TCP_Send_Error.Connection_Closed } else if errno != .NONE { return total_written, TCP_Send_Error(errno) } From 0a16f7a6f1e3e40dfed7cb93725d325787bc948b Mon Sep 17 00:00:00 2001 From: Thomas la Cour Date: Tue, 26 Mar 2024 12:22:18 +0100 Subject: [PATCH 6/8] normalize_path --- src/build_settings.cpp | 6 ++---- src/string.cpp | 34 ++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b806adcd6..03a95a19b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -840,13 +840,11 @@ gb_internal String odin_root_dir(void) { char const *found = gb_get_env("ODIN_ROOT", a); if (found) { String path = path_to_full_path(a, make_string_c(found)); - if (path[path.len-1] != '/' && path[path.len-1] != '\\') { #if defined(GB_SYSTEM_WINDOWS) - path = concatenate_strings(a, path, WIN32_SEPARATOR_STRING); + path = normalize_path(a, path, WIN32_SEPARATOR_STRING); #else - path = concatenate_strings(a, path, NIX_SEPARATOR_STRING); + path = normalize_path(a, path, NIX_SEPARATOR_STRING); #endif - } global_module_path = path; global_module_path_set = true; diff --git a/src/string.cpp b/src/string.cpp index 3747f4564..b92dd589e 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -237,11 +237,16 @@ gb_internal String string_split_iterator(String_Iterator *it, const char sep) { return substring(it->str, start, end); } +gb_internal gb_inline bool is_separator(u8 const &ch) { + return (ch == '/' || ch == '\\'); +} + + gb_internal gb_inline isize string_extension_position(String const &str) { isize dot_pos = -1; isize i = str.len; while (i --> 0) { - if (str[i] == '\\' || str[i] == '/') + if (is_separator(str[i])) break; if (str[i] == '.') { dot_pos = i; @@ -332,8 +337,7 @@ gb_internal String filename_from_path(String s) { if (i > 0) { isize j = 0; for (j = s.len-1; j >= 0; j--) { - if (s[j] == '/' || - s[j] == '\\') { + if (is_separator(s[j])) { break; } } @@ -346,8 +350,7 @@ gb_internal String filename_from_path(String s) { gb_internal String filename_without_directory(String s) { isize j = 0; for (j = s.len-1; j >= 0; j--) { - if (s[j] == '/' || - s[j] == '\\') { + if (is_separator(s[j])) { break; } } @@ -410,7 +413,26 @@ gb_internal String copy_string(gbAllocator a, String const &s) { return make_string(data, s.len); } - +gb_internal String normalize_path(gbAllocator a, String const &path, String const &sep) { + String s; + if (sep.len < 1) { + return path; + } + if (path.len < 1) { + s = STR_LIT(""); + } else if (is_separator(path[path.len-1])) { + s = copy_string(a, path); + } else { + s = concatenate_strings(a, path, sep); + } + isize i; + for (i = 0; i < s.len; i++) { + if (is_separator(s.text[i])) { + s.text[i] = sep.text[0]; + } + } + return s; +} #if defined(GB_SYSTEM_WINDOWS) From ebb1a07dd081bb9210e093ebac89f692cb8200d6 Mon Sep 17 00:00:00 2001 From: Thomas la Cour Date: Tue, 26 Mar 2024 12:22:41 +0100 Subject: [PATCH 7/8] spelling --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 53103ce3a..4e8f64e05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -337,12 +337,12 @@ struct BuildFlag { String name; BuildFlagParamKind param_kind; u32 command_support; - bool allow_mulitple; + bool allow_multiple; }; -gb_internal void add_flag(Array *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_mulitple=false) { - BuildFlag flag = {kind, name, param_kind, command_support, allow_mulitple}; +gb_internal void add_flag(Array *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_multiple=false) { + BuildFlag flag = {kind, name, param_kind, command_support, allow_multiple}; array_add(build_flags, flag); } @@ -1358,7 +1358,7 @@ gb_internal bool parse_build_flags(Array args) { } } - if (!bf.allow_mulitple) { + if (!bf.allow_multiple) { set_flags[bf.kind] = ok; } } From 2a70faca146b752a5009b7a7bb68c488461e40bb Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Sun, 21 Apr 2024 22:37:04 +0200 Subject: [PATCH 8/8] Add printfln and eprintfln functions to fmt_js.odin --- core/fmt/fmt_js.odin | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/fmt/fmt_js.odin b/core/fmt/fmt_js.odin index c70b7c1c0..a0a890a9a 100644 --- a/core/fmt/fmt_js.odin +++ b/core/fmt/fmt_js.odin @@ -37,6 +37,8 @@ print :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w println :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stdout, args=args, sep=sep, flush=flush) } // printf formats according to the specififed format string and writes to stdout printf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush) } +// printfln formats according to the specified format string and writes to stdout, followed by a newline. +printfln :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush, newline=true) } // eprint formats using the default print settings and writes to stderr eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stderr, args=args, sep=sep, flush=flush) } @@ -44,3 +46,5 @@ eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint( eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stderr, args=args, sep=sep, flush=flush) } // eprintf formats according to the specififed format string and writes to stderr eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stderr, fmt, ..args, flush=flush) } +// eprintfln formats according to the specified format string and writes to stderr, followed by a newline. +eprintfln :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush, newline=true) }