Browse Source

Merge branch 'master' into separate-int-word-sizes

gingerBill 2 years ago
parent
commit
49d1f6aca0

+ 19 - 14
.github/workflows/ci.yml

@@ -56,9 +56,9 @@ jobs:
     runs-on: macos-latest
     runs-on: macos-latest
     steps:
     steps:
       - uses: actions/checkout@v1
       - uses: actions/checkout@v1
-      - name: Download LLVM and setup PATH
+      - name: Download LLVM, botan and setup PATH
         run: |
         run: |
-          brew install llvm@11
+          brew install llvm@11 botan
           echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
           echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
           TMP_PATH=$(xcrun --show-sdk-path)/user/include
           TMP_PATH=$(xcrun --show-sdk-path)/user/include
           echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
           echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
@@ -87,6 +87,11 @@ jobs:
           cd tests/core
           cd tests/core
           make
           make
         timeout-minutes: 10
         timeout-minutes: 10
+      - name: Vendor library tests
+        run: |
+          cd tests/vendor
+          make
+        timeout-minutes: 10
       - name: Odin internals tests
       - name: Odin internals tests
         run: |
         run: |
           cd tests/internal
           cd tests/internal
@@ -99,13 +104,13 @@ jobs:
         run: ./odin check examples/all -vet -strict-style -target:linux_arm64
         run: ./odin check examples/all -vet -strict-style -target:linux_arm64
         timeout-minutes: 10
         timeout-minutes: 10
   build_windows:
   build_windows:
-    runs-on: windows-2019
+    runs-on: windows-2022
     steps:
     steps:
       - uses: actions/checkout@v1
       - uses: actions/checkout@v1
       - name: build Odin
       - name: build Odin
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           ./build.bat 1
           ./build.bat 1
       - name: Odin version
       - name: Odin version
         run: ./odin version
         run: ./odin version
@@ -116,65 +121,65 @@ jobs:
       - name: Odin check
       - name: Odin check
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           odin check examples/demo -vet
           odin check examples/demo -vet
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Odin run
       - name: Odin run
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           odin run examples/demo
           odin run examples/demo
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Odin run -debug
       - name: Odin run -debug
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           odin run examples/demo -debug
           odin run examples/demo -debug
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Odin check examples/all
       - name: Odin check examples/all
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           odin check examples/all -strict-style
           odin check examples/all -strict-style
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Core library tests
       - name: Core library tests
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           cd tests\core
           cd tests\core
           call build.bat
           call build.bat
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Vendor library tests
       - name: Vendor library tests
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           cd tests\vendor
           cd tests\vendor
           call build.bat
           call build.bat
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Odin internals tests
       - name: Odin internals tests
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           cd tests\internal
           cd tests\internal
           call build.bat
           call build.bat
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Odin documentation tests
       - name: Odin documentation tests
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           cd tests\documentation
           cd tests\documentation
           call build.bat
           call build.bat
         timeout-minutes: 10
         timeout-minutes: 10
       - name: core:math/big tests
       - name: core:math/big tests
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           cd tests\core\math\big
           cd tests\core\math\big
           call build.bat
           call build.bat
         timeout-minutes: 10
         timeout-minutes: 10
       - name: Odin check examples/all for Windows 32bits
       - name: Odin check examples/all for Windows 32bits
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           odin check examples/all -strict-style -target:windows_i386
           odin check examples/all -strict-style -target:windows_i386
         timeout-minutes: 10
         timeout-minutes: 10

+ 3 - 3
.github/workflows/nightly.yml

@@ -7,18 +7,18 @@ on:
 
 
 jobs:
 jobs:
   build_windows:
   build_windows:
-    runs-on: windows-2019
+    runs-on: windows-2022
     steps:
     steps:
       - uses: actions/checkout@v1
       - uses: actions/checkout@v1
       - name: build Odin
       - name: build Odin
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           ./build.bat 1 1
           ./build.bat 1 1
       - name: Odin run
       - name: Odin run
         shell: cmd
         shell: cmd
         run: |
         run: |
-          call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
           odin run examples/demo
           odin run examples/demo
       - name: Copy artifacts
       - name: Copy artifacts
         run: |
         run: |

+ 1 - 3
build_odin.sh

@@ -4,14 +4,12 @@ set -eu
 : ${CXX=clang++}
 : ${CXX=clang++}
 : ${CPPFLAGS=}
 : ${CPPFLAGS=}
 : ${CXXFLAGS=}
 : ${CXXFLAGS=}
-: ${INCLUDE_DIRECTORIES=}
 : ${LDFLAGS=}
 : ${LDFLAGS=}
 : ${ODIN_VERSION=dev-$(date +"%Y-%m")}
 : ${ODIN_VERSION=dev-$(date +"%Y-%m")}
 : ${GIT_SHA=}
 : ${GIT_SHA=}
 
 
 CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
 CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
 CXXFLAGS="$CXXFLAGS -std=c++14"
 CXXFLAGS="$CXXFLAGS -std=c++14"
-INCLUDE_DIRECTORIES="$INCLUDE_DIRECTORIES -Isrc/"
 LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
 LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
 
 
 if [ -d ".git" ]; then
 if [ -d ".git" ]; then
@@ -148,7 +146,7 @@ build_odin() {
 	esac
 	esac
 
 
 	set -x
 	set -x
-	$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $INCLUDE_DIRECTORIES $EXTRAFLAGS $LDFLAGS -o odin
+	$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
 	set +x
 	set +x
 }
 }
 
 

+ 5 - 0
core/bytes/buffer.odin

@@ -38,6 +38,11 @@ buffer_init_string :: proc(b: ^Buffer, s: string) {
 }
 }
 
 
 buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
 buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
+	if b.buf == nil {
+		b.buf = make([dynamic]byte, len, cap, allocator)
+		return
+	}
+
 	b.buf.allocator = allocator
 	b.buf.allocator = allocator
 	reserve(&b.buf, cap)
 	reserve(&b.buf, cap)
 	resize(&b.buf, len)
 	resize(&b.buf, len)

+ 73 - 0
core/encoding/hex/hex.odin

@@ -0,0 +1,73 @@
+package hex
+
+import "core:strings"
+
+encode :: proc(src: []byte, allocator := context.allocator) -> []byte #no_bounds_check {
+	dst := make([]byte, len(src) * 2, allocator)
+	for i, j := 0, 0; i < len(src); i += 1 {
+		v := src[i]
+		dst[j]   = HEXTABLE[v>>4]
+		dst[j+1] = HEXTABLE[v&0x0f]
+		j += 2
+	}
+
+	return dst
+}
+
+
+decode :: proc(src: []byte, allocator := context.allocator) -> (dst: []byte, ok: bool) #no_bounds_check {
+	if len(src) % 2 == 1 {
+		return
+	}
+
+	dst = make([]byte, len(src) / 2, allocator)
+	for i, j := 0, 1; j < len(src); j += 2 {
+		p := src[j-1]
+		q := src[j]
+
+		a := hex_digit(p) or_return
+		b := hex_digit(q) or_return
+
+		dst[i] = (a << 4) | b
+		i += 1
+	}
+
+	return dst, true
+}
+
+// Decodes the given sequence into one byte.
+// Should be called with one byte worth of the source, eg: 0x23 -> '#'.
+decode_sequence :: proc(str: string) -> (res: byte, ok: bool) {
+	str := str
+	if strings.has_prefix(str, "0x") || strings.has_prefix(str, "0X") {
+		str = str[2:]
+	}
+
+	if len(str) != 2 {
+		return 0, false
+	}
+
+	upper := hex_digit(str[0]) or_return
+	lower := hex_digit(str[1]) or_return
+
+	return upper << 4 | lower, true
+}
+
+@(private)
+HEXTABLE := [16]byte {
+	'0', '1', '2', '3',
+	'4', '5', '6', '7',
+	'8', '9', 'a', 'b',
+	'c', 'd', 'e', 'f',
+}
+
+@(private)
+hex_digit :: proc(char: byte) -> (u8, bool) {
+	switch char {
+	case '0' ..= '9': return char - '0', true
+	case 'a' ..= 'f': return char - 'a' + 10, true
+	case 'A' ..= 'F': return char - 'A' + 10, true
+	case:             return 0, false
+	}
+}
+

+ 14 - 40
core/net/url.odin

@@ -19,7 +19,7 @@ package net
 import "core:strings"
 import "core:strings"
 import "core:strconv"
 import "core:strconv"
 import "core:unicode/utf8"
 import "core:unicode/utf8"
-import "core:mem"
+import "core:encoding/hex"
 
 
 split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string) {
 split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string) {
 	s := url
 	s := url
@@ -36,9 +36,11 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host,
 		s = s[:i]
 		s = s[:i]
 		if query_str != "" {
 		if query_str != "" {
 			queries_parts := strings.split(query_str, "&")
 			queries_parts := strings.split(query_str, "&")
+			defer delete(queries_parts)
 			queries = make(map[string]string, len(queries_parts), allocator)
 			queries = make(map[string]string, len(queries_parts), allocator)
 			for q in queries_parts {
 			for q in queries_parts {
 				parts := strings.split(q, "=")
 				parts := strings.split(q, "=")
+				defer delete(parts)
 				switch len(parts) {
 				switch len(parts) {
 				case 1:  queries[parts[0]] = ""        // NOTE(tetra): Query not set to anything, was but present.
 				case 1:  queries[parts[0]] = ""        // NOTE(tetra): Query not set to anything, was but present.
 				case 2:  queries[parts[0]] = parts[1]  // NOTE(tetra): Query set to something.
 				case 2:  queries[parts[0]] = parts[1]  // NOTE(tetra): Query set to something.
@@ -76,13 +78,19 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, allocat
 	}
 	}
 
 
 
 
-	if len(queries) > 0 do write_string(&b, "?")
+	query_length := len(queries)
+	if query_length > 0 do write_string(&b, "?")
+	i := 0
 	for query_name, query_value in queries {
 	for query_name, query_value in queries {
 		write_string(&b, query_name)
 		write_string(&b, query_name)
 		if query_value != "" {
 		if query_value != "" {
 			write_string(&b, "=")
 			write_string(&b, "=")
 			write_string(&b, query_value)
 			write_string(&b, query_value)
 		}
 		}
+		if i < query_length - 1 {
+			write_string(&b, "&")
+		}
+		i += 1
 	}
 	}
 
 
 	return to_string(b)
 	return to_string(b)
@@ -119,12 +127,10 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) -
 	builder_grow(&b, len(encoded_string))
 	builder_grow(&b, len(encoded_string))
 	defer if !ok do builder_destroy(&b)
 	defer if !ok do builder_destroy(&b)
 
 
-	stack_buf: [4]u8
-	pending := mem.buffer_from_slice(stack_buf[:])
 	s := encoded_string
 	s := encoded_string
 
 
 	for len(s) > 0 {
 	for len(s) > 0 {
-		i := index_rune(s, '%')
+		i := index_byte(s, '%')
 		if i == -1 {
 		if i == -1 {
 			write_string(&b, s) // no '%'s; the string is already decoded
 			write_string(&b, s) // no '%'s; the string is already decoded
 			break
 			break
@@ -137,47 +143,15 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) -
 		s = s[1:]
 		s = s[1:]
 
 
 		if s[0] == '%' {
 		if s[0] == '%' {
-			write_rune(&b, '%')
+			write_byte(&b, '%')
 			s = s[1:]
 			s = s[1:]
 			continue
 			continue
 		}
 		}
 
 
 		if len(s) < 2 do return // percent without encoded value
 		if len(s) < 2 do return // percent without encoded value
 
 
-		n: int
-		n, _ = strconv.parse_int(s[:2], 16)
-		switch n {
-		case 0x20:  write_rune(&b, ' ')
-		case 0x21:  write_rune(&b, '!')
-		case 0x23:  write_rune(&b, '#')
-		case 0x24:  write_rune(&b, '$')
-		case 0x25:  write_rune(&b, '%')
-		case 0x26:  write_rune(&b, '&')
-		case 0x27:  write_rune(&b, '\'')
-		case 0x28:  write_rune(&b, '(')
-		case 0x29:  write_rune(&b, ')')
-		case 0x2A:  write_rune(&b, '*')
-		case 0x2B:  write_rune(&b, '+')
-		case 0x2C:  write_rune(&b, ',')
-		case 0x2F:  write_rune(&b, '/')
-		case 0x3A:  write_rune(&b, ':')
-		case 0x3B:  write_rune(&b, ';')
-		case 0x3D:  write_rune(&b, '=')
-		case 0x3F:  write_rune(&b, '?')
-		case 0x40:  write_rune(&b, '@')
-		case 0x5B:  write_rune(&b, '[')
-		case 0x5D:  write_rune(&b, ']')
-		case:
-			// utf-8 bytes
-			// TODO(tetra): Audit this - 4 bytes???
-			append(&pending, s[0])
-			append(&pending, s[1])
-			if len(pending) == 4 {
-				r, _ := utf8.decode_rune(pending[:])
-				write_rune(&b, r)
-				clear(&pending)
-			}
-		}
+		val := hex.decode_sequence(s[:2]) or_return
+		write_byte(&b, val)
 		s = s[2:]
 		s = s[2:]
 	}
 	}
 
 

+ 27 - 10
core/os/file_windows.odin

@@ -220,6 +220,7 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
 
 
 @(private)
 @(private)
 MAX_RW :: 1<<30
 MAX_RW :: 1<<30
+ERROR_EOF :: 38
 
 
 @(private)
 @(private)
 pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
@@ -228,11 +229,6 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 		buf = buf[:MAX_RW]
 		buf = buf[:MAX_RW]
 
 
 	}
 	}
-	curr_offset, e := seek(fd, offset, 1)
-	if e != 0 {
-		return 0, e
-	}
-	defer seek(fd, curr_offset, 0)
 
 
 	o := win32.OVERLAPPED{
 	o := win32.OVERLAPPED{
 		OffsetHigh = u32(offset>>32),
 		OffsetHigh = u32(offset>>32),
@@ -243,6 +239,7 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 
 
 	h := win32.HANDLE(fd)
 	h := win32.HANDLE(fd)
 	done: win32.DWORD
 	done: win32.DWORD
+	e: Errno
 	if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
 	if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
 		e = Errno(win32.GetLastError())
 		e = Errno(win32.GetLastError())
 		done = 0
 		done = 0
@@ -256,11 +253,6 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 		buf = buf[:MAX_RW]
 		buf = buf[:MAX_RW]
 
 
 	}
 	}
-	curr_offset, e := seek(fd, offset, 1)
-	if e != 0 {
-		return 0, e
-	}
-	defer seek(fd, curr_offset, 0)
 
 
 	o := win32.OVERLAPPED{
 	o := win32.OVERLAPPED{
 		OffsetHigh = u32(offset>>32),
 		OffsetHigh = u32(offset>>32),
@@ -269,6 +261,7 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 
 
 	h := win32.HANDLE(fd)
 	h := win32.HANDLE(fd)
 	done: win32.DWORD
 	done: win32.DWORD
+	e: Errno
 	if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
 	if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
 		e = Errno(win32.GetLastError())
 		e = Errno(win32.GetLastError())
 		done = 0
 		done = 0
@@ -276,6 +269,16 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 	return int(done), e
 	return int(done), e
 }
 }
 
 
+/*
+read_at returns n: 0, err: 0 on EOF
+on Windows, read_at changes the position of the file cursor, on *nix, it does not.
+
+	bytes: [8]u8{}
+	read_at(fd, bytes, 0)
+	read(fd, bytes)
+
+will read from the location twice on *nix, and from two different locations on Windows
+*/
 read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
 read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
 	if offset < 0 {
 	if offset < 0 {
 		return 0, ERROR_NEGATIVE_OFFSET
 		return 0, ERROR_NEGATIVE_OFFSET
@@ -284,6 +287,10 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
 	b, offset := data, offset
 	b, offset := data, offset
 	for len(b) > 0 {
 	for len(b) > 0 {
 		m, e := pread(fd, b, offset)
 		m, e := pread(fd, b, offset)
+		if e == ERROR_EOF {
+			err = 0
+			break
+		}
 		if e != 0 {
 		if e != 0 {
 			err = e
 			err = e
 			break
 			break
@@ -294,6 +301,16 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
 	}
 	}
 	return
 	return
 }
 }
+
+/*
+on Windows, write_at changes the position of the file cursor, on *nix, it does not.
+
+	bytes: [8]u8{}
+	write_at(fd, bytes, 0)
+	write(fd, bytes)
+
+will write to the location twice on *nix, and to two different locations on Windows
+*/
 write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
 write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
 	if offset < 0 {
 	if offset < 0 {
 		return 0, ERROR_NEGATIVE_OFFSET
 		return 0, ERROR_NEGATIVE_OFFSET

+ 1 - 1
core/os/os.odin

@@ -194,7 +194,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 		ptr := uintptr(aligned_mem)
 		ptr := uintptr(aligned_mem)
 		aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 		aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 		diff := int(aligned_ptr - ptr)
 		diff := int(aligned_ptr - ptr)
-		if (size + diff) > space {
+		if (size + diff) > space || allocated_mem == nil {
 			return nil, .Out_Of_Memory
 			return nil, .Out_Of_Memory
 		}
 		}
 
 

+ 1 - 1
core/os/os2/env_linux.odin

@@ -3,7 +3,7 @@ package os2
 
 
 import "core:runtime"
 import "core:runtime"
 
 
-_get_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
+_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
 	//TODO
 	//TODO
 	return
 	return
 }
 }

+ 39 - 86
core/os/os2/file_linux.odin

@@ -9,19 +9,20 @@ import "core:sys/unix"
 
 
 INVALID_HANDLE :: -1
 INVALID_HANDLE :: -1
 
 
-_O_RDONLY    :: 0o0
-_O_WRONLY    :: 0o1
-_O_RDWR      :: 0o2
-_O_CREAT     :: 0o100
-_O_EXCL      :: 0o200
-_O_TRUNC     :: 0o1000
-_O_APPEND    :: 0o2000
-_O_NONBLOCK  :: 0o4000
-_O_LARGEFILE :: 0o100000
-_O_DIRECTORY :: 0o200000
-_O_NOFOLLOW  :: 0o400000
-_O_SYNC      :: 0o4010000
-_O_CLOEXEC   :: 0o2000000
+_O_RDONLY    :: 0o00000000
+_O_WRONLY    :: 0o00000001
+_O_RDWR      :: 0o00000002
+_O_CREAT     :: 0o00000100
+_O_EXCL      :: 0o00000200
+_O_NOCTTY    :: 0o00000400
+_O_TRUNC     :: 0o00001000
+_O_APPEND    :: 0o00002000
+_O_NONBLOCK  :: 0o00004000
+_O_LARGEFILE :: 0o00100000
+_O_DIRECTORY :: 0o00200000
+_O_NOFOLLOW  :: 0o00400000
+_O_SYNC      :: 0o04010000
+_O_CLOEXEC   :: 0o02000000
 _O_PATH      :: 0o10000000
 _O_PATH      :: 0o10000000
 
 
 _AT_FDCWD :: -100
 _AT_FDCWD :: -100
@@ -40,9 +41,12 @@ _file_allocator :: proc() -> runtime.Allocator {
 
 
 _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error) {
 _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error) {
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-	name_cstr := _name_to_cstring(name)
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 
 
-	flags_i: int
+	// Just default to using O_NOCTTY because needing to open a controlling
+	// terminal would be incredibly rare. This has no effect on files while
+	// allowing us to open serial devices.
+	flags_i: int = _O_NOCTTY
 	switch flags & O_RDONLY|O_WRONLY|O_RDWR {
 	switch flags & O_RDONLY|O_WRONLY|O_RDWR {
 	case O_RDONLY: flags_i = _O_RDONLY
 	case O_RDONLY: flags_i = _O_RDONLY
 	case O_WRONLY: flags_i = _O_WRONLY
 	case O_WRONLY: flags_i = _O_WRONLY
@@ -56,7 +60,7 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error
 	flags_i |= (_O_TRUNC * int(.Trunc in flags))
 	flags_i |= (_O_TRUNC * int(.Trunc in flags))
 	flags_i |= (_O_CLOEXEC * int(.Close_On_Exec in flags))
 	flags_i |= (_O_CLOEXEC * int(.Close_On_Exec in flags))
 
 
-	fd := unix.sys_open(name_cstr, flags_i, int(perm))
+	fd := unix.sys_open(name_cstr, flags_i, uint(perm))
 	if fd < 0 {
 	if fd < 0 {
 		return nil, _get_platform_error(fd)
 		return nil, _get_platform_error(fd)
 	}
 	}
@@ -196,10 +200,7 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
 }
 }
 
 
 _remove :: proc(name: string) -> Error {
 _remove :: proc(name: string) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 
 
 	fd := unix.sys_open(name_cstr, int(File_Flags.Read))
 	fd := unix.sys_open(name_cstr, int(File_Flags.Read))
 	if fd < 0 {
 	if fd < 0 {
@@ -214,40 +215,22 @@ _remove :: proc(name: string) -> Error {
 }
 }
 
 
 _rename :: proc(old_name, new_name: string) -> Error {
 _rename :: proc(old_name, new_name: string) -> Error {
-	old_name_cstr, old_allocated := _name_to_cstring(old_name)
-	new_name_cstr, new_allocated := _name_to_cstring(new_name)
-	defer if old_allocated {
-		delete(old_name_cstr)
-	}
-	defer if new_allocated {
-		delete(new_name_cstr)
-	}
+	old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
+	new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
 
 
 	return _ok_or_error(unix.sys_rename(old_name_cstr, new_name_cstr))
 	return _ok_or_error(unix.sys_rename(old_name_cstr, new_name_cstr))
 }
 }
 
 
 _link :: proc(old_name, new_name: string) -> Error {
 _link :: proc(old_name, new_name: string) -> Error {
-	old_name_cstr, old_allocated := _name_to_cstring(old_name)
-	new_name_cstr, new_allocated := _name_to_cstring(new_name)
-	defer if old_allocated {
-		delete(old_name_cstr)
-	}
-	defer if new_allocated {
-		delete(new_name_cstr)
-	}
+	old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
+	new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
 
 
 	return _ok_or_error(unix.sys_link(old_name_cstr, new_name_cstr))
 	return _ok_or_error(unix.sys_link(old_name_cstr, new_name_cstr))
 }
 }
 
 
 _symlink :: proc(old_name, new_name: string) -> Error {
 _symlink :: proc(old_name, new_name: string) -> Error {
-	old_name_cstr, old_allocated := _name_to_cstring(old_name)
-	new_name_cstr, new_allocated := _name_to_cstring(new_name)
-	defer if old_allocated {
-		delete(old_name_cstr)
-	}
-	defer if new_allocated {
-		delete(new_name_cstr)
-	}
+	old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
+	new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
 
 
 	return _ok_or_error(unix.sys_symlink(old_name_cstr, new_name_cstr))
 	return _ok_or_error(unix.sys_symlink(old_name_cstr, new_name_cstr))
 }
 }
@@ -271,26 +254,17 @@ _read_link_cstr :: proc(name_cstr: cstring, allocator: runtime.Allocator) -> (st
 }
 }
 
 
 _read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
 _read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	return _read_link_cstr(name_cstr, allocator)
 	return _read_link_cstr(name_cstr, allocator)
 }
 }
 
 
 _unlink :: proc(name: string) -> Error {
 _unlink :: proc(name: string) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	return _ok_or_error(unix.sys_unlink(name_cstr))
 	return _ok_or_error(unix.sys_unlink(name_cstr))
 }
 }
 
 
 _chdir :: proc(name: string) -> Error {
 _chdir :: proc(name: string) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	return _ok_or_error(unix.sys_chdir(name_cstr))
 	return _ok_or_error(unix.sys_chdir(name_cstr))
 }
 }
 
 
@@ -299,32 +273,23 @@ _fchdir :: proc(f: ^File) -> Error {
 }
 }
 
 
 _chmod :: proc(name: string, mode: File_Mode) -> Error {
 _chmod :: proc(name: string, mode: File_Mode) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
-	return _ok_or_error(unix.sys_chmod(name_cstr, int(mode)))
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
+	return _ok_or_error(unix.sys_chmod(name_cstr, uint(mode)))
 }
 }
 
 
 _fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
 _fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
-	return _ok_or_error(unix.sys_fchmod(f.impl.fd, int(mode)))
+	return _ok_or_error(unix.sys_fchmod(f.impl.fd, uint(mode)))
 }
 }
 
 
 // NOTE: will throw error without super user priviledges
 // NOTE: will throw error without super user priviledges
 _chown :: proc(name: string, uid, gid: int) -> Error {
 _chown :: proc(name: string, uid, gid: int) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	return _ok_or_error(unix.sys_chown(name_cstr, uid, gid))
 	return _ok_or_error(unix.sys_chown(name_cstr, uid, gid))
 }
 }
 
 
 // NOTE: will throw error without super user priviledges
 // NOTE: will throw error without super user priviledges
 _lchown :: proc(name: string, uid, gid: int) -> Error {
 _lchown :: proc(name: string, uid, gid: int) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	return _ok_or_error(unix.sys_lchown(name_cstr, uid, gid))
 	return _ok_or_error(unix.sys_lchown(name_cstr, uid, gid))
 }
 }
 
 
@@ -334,10 +299,7 @@ _fchown :: proc(f: ^File, uid, gid: int) -> Error {
 }
 }
 
 
 _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
 _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	times := [2]Unix_File_Time {
 	times := [2]Unix_File_Time {
 		{ atime._nsec, 0 },
 		{ atime._nsec, 0 },
 		{ mtime._nsec, 0 },
 		{ mtime._nsec, 0 },
@@ -354,18 +316,12 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
 }
 }
 
 
 _exists :: proc(name: string) -> bool {
 _exists :: proc(name: string) -> bool {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	return unix.sys_access(name_cstr, F_OK) == 0
 	return unix.sys_access(name_cstr, F_OK) == 0
 }
 }
 
 
 _is_file :: proc(name: string) -> bool {
 _is_file :: proc(name: string) -> bool {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	s: _Stat
 	s: _Stat
 	res := unix.sys_stat(name_cstr, &s)
 	res := unix.sys_stat(name_cstr, &s)
 	if res < 0 {
 	if res < 0 {
@@ -384,10 +340,7 @@ _is_file_fd :: proc(fd: int) -> bool {
 }
 }
 
 
 _is_dir :: proc(name: string) -> bool {
 _is_dir :: proc(name: string) -> bool {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	s: _Stat
 	s: _Stat
 	res := unix.sys_stat(name_cstr, &s)
 	res := unix.sys_stat(name_cstr, &s)
 	if res < 0 {
 	if res < 0 {

+ 1 - 1
core/os/os2/heap_linux.odin

@@ -166,7 +166,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 		ptr := uintptr(aligned_mem)
 		ptr := uintptr(aligned_mem)
 		aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 		aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 		diff := int(aligned_ptr - ptr)
 		diff := int(aligned_ptr - ptr)
-		if (size + diff) > space {
+		if (size + diff) > space || allocated_mem == nil {
 			return nil, .Out_Of_Memory
 			return nil, .Out_Of_Memory
 		}
 		}
 
 

+ 1 - 1
core/os/os2/heap_windows.odin

@@ -52,7 +52,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 		ptr := uintptr(aligned_mem)
 		ptr := uintptr(aligned_mem)
 		aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 		aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 		diff := int(aligned_ptr - ptr)
 		diff := int(aligned_ptr - ptr)
-		if (size + diff) > space {
+		if (size + diff) > space || allocated_mem == nil {
 			return nil, .Out_Of_Memory
 			return nil, .Out_Of_Memory
 		}
 		}
 
 

+ 5 - 17
core/os/os2/path_linux.odin

@@ -31,11 +31,8 @@ _mkdir :: proc(path: string, perm: File_Mode) -> Error {
 		return .Invalid_Argument
 		return .Invalid_Argument
 	}
 	}
 
 
-	path_cstr, allocated := _name_to_cstring(path)
-	defer if allocated {
-		delete(path_cstr)
-	}
-	return _ok_or_error(unix.sys_mkdir(path_cstr, int(perm & 0o777)))
+	path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
+	return _ok_or_error(unix.sys_mkdir(path_cstr, uint(perm & 0o777)))
 }
 }
 
 
 _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
 _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
@@ -49,7 +46,7 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
 		new_dfd := unix.sys_openat(dfd, cstring(&path[0]), _OPENDIR_FLAGS)
 		new_dfd := unix.sys_openat(dfd, cstring(&path[0]), _OPENDIR_FLAGS)
 		switch new_dfd {
 		switch new_dfd {
 		case -ENOENT:
 		case -ENOENT:
-			if res := unix.sys_mkdirat(dfd, cstring(&path[0]), perm); res < 0 {
+			if res := unix.sys_mkdirat(dfd, cstring(&path[0]), uint(perm)); res < 0 {
 				return _get_platform_error(res)
 				return _get_platform_error(res)
 			}
 			}
 			has_created^ = true
 			has_created^ = true
@@ -83,9 +80,6 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
 	} else {
 	} else {
 		path_bytes = make([]u8, len(path) + 1, context.temp_allocator)
 		path_bytes = make([]u8, len(path) + 1, context.temp_allocator)
 	}
 	}
-	defer if allocated {
-		delete(path_bytes)
-	}
 
 
 	// NULL terminate the byte slice to make it a valid cstring
 	// NULL terminate the byte slice to make it a valid cstring
 	copy(path_bytes, path)
 	copy(path_bytes, path)
@@ -182,10 +176,7 @@ _remove_all :: proc(path: string) -> Error {
 		return nil
 		return nil
 	}
 	}
 
 
-	path_cstr, allocated := _name_to_cstring(path)
-	defer if allocated {
-		delete(path_cstr)
-	}
+	path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
 
 
 	fd := unix.sys_open(path_cstr, _OPENDIR_FLAGS)
 	fd := unix.sys_open(path_cstr, _OPENDIR_FLAGS)
 	switch fd {
 	switch fd {
@@ -222,10 +213,7 @@ _getwd :: proc(allocator: runtime.Allocator) -> (string, Error) {
 }
 }
 
 
 _setwd :: proc(dir: string) -> Error {
 _setwd :: proc(dir: string) -> Error {
-	dir_cstr, allocated := _name_to_cstring(dir)
-	defer if allocated {
-		delete(dir_cstr)
-	}
+	dir_cstr := strings.clone_to_cstring(dir, context.temp_allocator)
 	return _ok_or_error(unix.sys_chdir(dir_cstr))
 	return _ok_or_error(unix.sys_chdir(dir_cstr))
 }
 }
 
 

+ 5 - 12
core/os/os2/stat_linux.odin

@@ -3,6 +3,7 @@ package os2
 
 
 import "core:time"
 import "core:time"
 import "core:runtime"
 import "core:runtime"
+import "core:strings"
 import "core:sys/unix"
 import "core:sys/unix"
 import "core:path/filepath"
 import "core:path/filepath"
 
 
@@ -112,10 +113,7 @@ _fstat_internal :: proc(fd: int, allocator: runtime.Allocator) -> (File_Info, Er
 
 
 // NOTE: _stat and _lstat are using _fstat to avoid a race condition when populating fullpath
 // NOTE: _stat and _lstat are using _fstat to avoid a race condition when populating fullpath
 _stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
 _stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 
 
 	fd := unix.sys_open(name_cstr, _O_RDONLY)
 	fd := unix.sys_open(name_cstr, _O_RDONLY)
 	if fd < 0 {
 	if fd < 0 {
@@ -126,10 +124,8 @@ _stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error)
 }
 }
 
 
 _lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
 _lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
+
 	fd := unix.sys_open(name_cstr, _O_RDONLY | _O_PATH | _O_NOFOLLOW)
 	fd := unix.sys_open(name_cstr, _O_RDONLY | _O_PATH | _O_NOFOLLOW)
 	if fd < 0 {
 	if fd < 0 {
 		return {}, _get_platform_error(fd)
 		return {}, _get_platform_error(fd)
@@ -143,10 +139,7 @@ _same_file :: proc(fi1, fi2: File_Info) -> bool {
 }
 }
 
 
 _stat_internal :: proc(name: string) -> (s: _Stat, res: int) {
 _stat_internal :: proc(name: string) -> (s: _Stat, res: int) {
-	name_cstr, allocated := _name_to_cstring(name)
-	defer if allocated {
-		delete(name_cstr)
-	}
+	name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
 	res = unix.sys_stat(name_cstr, &s)
 	res = unix.sys_stat(name_cstr, &s)
 	return
 	return
 }
 }

+ 6 - 6
core/os/os2/user.odin

@@ -8,12 +8,12 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
 	case .Windows:
 	case .Windows:
 		dir = get_env("LocalAppData", allocator)
 		dir = get_env("LocalAppData", allocator)
 		if dir != "" {
 		if dir != "" {
-			dir = strings.clone_safe(dir, allocator) or_return
+			dir = strings.clone(dir, allocator) or_return
 		}
 		}
 	case .Darwin:
 	case .Darwin:
 		dir = get_env("HOME", allocator)
 		dir = get_env("HOME", allocator)
 		if dir != "" {
 		if dir != "" {
-			dir = strings.concatenate_safe({dir, "/Library/Caches"}, allocator) or_return
+			dir = strings.concatenate({dir, "/Library/Caches"}, allocator) or_return
 		}
 		}
 	case: // All other UNIX systems
 	case: // All other UNIX systems
 		dir = get_env("XDG_CACHE_HOME", allocator)
 		dir = get_env("XDG_CACHE_HOME", allocator)
@@ -22,7 +22,7 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
 			if dir == "" {
 			if dir == "" {
 				return
 				return
 			}
 			}
-			dir = strings.concatenate_safe({dir, "/.cache"}, allocator) or_return
+			dir = strings.concatenate({dir, "/.cache"}, allocator) or_return
 		}
 		}
 	}
 	}
 	if dir == "" {
 	if dir == "" {
@@ -36,12 +36,12 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
 	case .Windows:
 	case .Windows:
 		dir = get_env("AppData", allocator)
 		dir = get_env("AppData", allocator)
 		if dir != "" {
 		if dir != "" {
-			dir = strings.clone_safe(dir, allocator) or_return
+			dir = strings.clone(dir, allocator) or_return
 		}
 		}
 	case .Darwin:
 	case .Darwin:
 		dir = get_env("HOME", allocator)
 		dir = get_env("HOME", allocator)
 		if dir != "" {
 		if dir != "" {
-			dir = strings.concatenate_safe({dir, "/Library/Application Support"}, allocator) or_return
+			dir = strings.concatenate({dir, "/Library/Application Support"}, allocator) or_return
 		}
 		}
 	case: // All other UNIX systems
 	case: // All other UNIX systems
 		dir = get_env("XDG_CACHE_HOME", allocator)
 		dir = get_env("XDG_CACHE_HOME", allocator)
@@ -50,7 +50,7 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
 			if dir == "" {
 			if dir == "" {
 				return
 				return
 			}
 			}
-			dir = strings.concatenate_safe({dir, "/.config"}, allocator) or_return
+			dir = strings.concatenate({dir, "/.config"}, allocator) or_return
 		}
 		}
 	}
 	}
 	if dir == "" {
 	if dir == "" {

+ 12 - 5
core/prof/spall/spall.odin

@@ -67,16 +67,15 @@ Buffer :: struct {
 BUFFER_DEFAULT_SIZE :: 0x10_0000
 BUFFER_DEFAULT_SIZE :: 0x10_0000
 
 
 
 
-context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_ok {
+context_create_with_scale :: proc(filename: string, precise_time: bool, timestamp_scale: f64) -> (ctx: Context, ok: bool) #optional_ok {
 	fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
 	fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
 	if err != os.ERROR_NONE {
 	if err != os.ERROR_NONE {
 		return
 		return
 	}
 	}
-	ctx.fd = fd
 
 
-	freq, freq_ok := time.tsc_frequency()
-	ctx.precise_time = freq_ok
-	ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
+	ctx.fd = fd
+	ctx.precise_time = precise_time
+	ctx.timestamp_scale = timestamp_scale
 
 
 	temp := [size_of(Manual_Header)]u8{}
 	temp := [size_of(Manual_Header)]u8{}
 	_build_header(temp[:], ctx.timestamp_scale)
 	_build_header(temp[:], ctx.timestamp_scale)
@@ -85,6 +84,14 @@ context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_o
 	return
 	return
 }
 }
 
 
+context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok {
+	freq, freq_ok := time.tsc_frequency(sleep)
+	timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
+	return context_create_with_scale(filename, freq_ok, timestamp_scale)
+}
+
+context_create :: proc{context_create_with_scale, context_create_with_sleep}
+
 context_destroy :: proc(ctx: ^Context) {
 context_destroy :: proc(ctx: ^Context) {
 	if ctx == nil {
 	if ctx == nil {
 		return
 		return

+ 1 - 1
core/runtime/core_builtin.odin

@@ -401,7 +401,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> int {
 		return 0
 		return 0
 	}
 	}
 	prev_len := len(array)
 	prev_len := len(array)
-	resize(array, len(array)+1)
+	resize(array, len(array)+1, loc)
 	return len(array)-prev_len
 	return len(array)-prev_len
 }
 }
 
 

+ 1 - 1
core/runtime/os_specific_windows.odin

@@ -112,7 +112,7 @@ _windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, ol
 	ptr := uintptr(aligned_mem)
 	ptr := uintptr(aligned_mem)
 	aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 	aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
 	diff := int(aligned_ptr - ptr)
 	diff := int(aligned_ptr - ptr)
-	if (size + diff) > space {
+	if (size + diff) > space || allocated_mem == nil {
 		return nil, .Out_Of_Memory
 		return nil, .Out_Of_Memory
 	}
 	}
 
 

+ 9 - 2
core/sys/info/cpu_intel.odin

@@ -38,7 +38,7 @@ cpu_name:     Maybe(string)
 @(init, private)
 @(init, private)
 init_cpu_features :: proc "c" () {
 init_cpu_features :: proc "c" () {
 	is_set :: #force_inline proc "c" (hwc: u32, value: u32) -> bool {
 	is_set :: #force_inline proc "c" (hwc: u32, value: u32) -> bool {
-		return hwc&value != 0
+		return hwc&(1 << value) != 0
 	}
 	}
 	try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, hwc: u32, value: u32) {
 	try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, hwc: u32, value: u32) {
 		if is_set(hwc, value) {
 		if is_set(hwc, value) {
@@ -74,8 +74,15 @@ init_cpu_features :: proc "c" () {
 		return
 		return
 	}
 	}
 
 
+	// In certain rare cases (reason unknown), XGETBV generates an
+	// illegal instruction, even if OSXSAVE is set per CPUID.
+	//
+	// When Chrome ran into this problem, the problem went away
+	// after they started checking both OSXSAVE and XSAVE.
+	//
+	// See: crbug.com/375968
 	os_supports_avx := false
 	os_supports_avx := false
-	if .os_xsave in set {
+	if .os_xsave in set && is_set(26, ecx1) {
 		eax, _ := xgetbv(0)
 		eax, _ := xgetbv(0)
 		os_supports_avx = is_set(1, eax) && is_set(2, eax)
 		os_supports_avx = is_set(1, eax) && is_set(2, eax)
 	}
 	}

+ 2 - 2
core/time/perf.odin

@@ -70,7 +70,7 @@ has_invariant_tsc :: proc "contextless" () -> bool {
 	return false
 	return false
 }
 }
 
 
-tsc_frequency :: proc "contextless" () -> (u64, bool) {
+tsc_frequency :: proc "contextless" (fallback_sleep := 2 * Second) -> (u64, bool) {
 	if !has_invariant_tsc() {
 	if !has_invariant_tsc() {
 		return 0, false
 		return 0, false
 	}
 	}
@@ -81,7 +81,7 @@ tsc_frequency :: proc "contextless" () -> (u64, bool) {
 		tsc_begin := intrinsics.read_cycle_counter()
 		tsc_begin := intrinsics.read_cycle_counter()
 		tick_begin := tick_now()
 		tick_begin := tick_now()
 
 
-		sleep(2 * Second)
+		sleep(fallback_sleep)
 
 
 		tsc_end := intrinsics.read_cycle_counter()
 		tsc_end := intrinsics.read_cycle_counter()
 		tick_end := tick_now()
 		tick_end := tick_now()

+ 6 - 0
core/time/time.odin

@@ -170,6 +170,12 @@ day :: proc "contextless" (t: Time) -> (day: int) {
 	return
 	return
 }
 }
 
 
+weekday :: proc "contextless" (t: Time) -> (weekday: Weekday) {
+    abs := _time_abs(t)
+    sec := (abs + u64(Weekday.Monday) * SECONDS_PER_DAY) % SECONDS_PER_WEEK
+    return Weekday(int(sec) / SECONDS_PER_DAY)
+}
+
 clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch }
 clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch }
 
 
 clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) {
 clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) {

+ 5 - 2
src/check_expr.cpp

@@ -7887,8 +7887,11 @@ gb_internal ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *no
 			rhs.type = right_type;
 			rhs.type = right_type;
 			rhs.mode = Addressing_Value;
 			rhs.mode = Addressing_Value;
 
 
-			// TODO(bill): better error message
-			if (!check_is_assignable_to(c, &rhs, end_type)) {
+			if (is_type_boolean(right_type) && is_type_boolean(end_type)) {
+				// NOTE(bill): allow implicit conversion between boolean types
+				// within 'or_return' to improve the experience using third-party code
+			} else if (!check_is_assignable_to(c, &rhs, end_type)) {
+				// TODO(bill): better error message
 				gbString a = type_to_string(right_type);
 				gbString a = type_to_string(right_type);
 				gbString b = type_to_string(end_type);
 				gbString b = type_to_string(end_type);
 				gbString ret_type = type_to_string(result_type);
 				gbString ret_type = type_to_string(result_type);

+ 14 - 3
src/error.cpp

@@ -8,8 +8,9 @@ struct ErrorCollector {
 	BlockingMutex     string_mutex;
 	BlockingMutex     string_mutex;
 	RecursiveMutex    block_mutex;
 	RecursiveMutex    block_mutex;
 
 
-	Array<u8> error_buffer;
-	Array<String> errors;
+	RecursiveMutex error_buffer_mutex;
+	Array<u8>      error_buffer;
+	Array<String>  errors;
 };
 };
 
 
 gb_global ErrorCollector global_error_collector;
 gb_global ErrorCollector global_error_collector;
@@ -119,6 +120,7 @@ gb_internal void begin_error_block(void) {
 }
 }
 
 
 gb_internal void end_error_block(void) {
 gb_internal void end_error_block(void) {
+	mutex_lock(&global_error_collector.error_buffer_mutex);
 	isize n = global_error_collector.error_buffer.count;
 	isize n = global_error_collector.error_buffer.count;
 	if (n > 0) {
 	if (n > 0) {
 		u8 *text = global_error_collector.error_buffer.data;
 		u8 *text = global_error_collector.error_buffer.data;
@@ -150,11 +152,16 @@ gb_internal void end_error_block(void) {
 		text = gb_alloc_array(permanent_allocator(), u8, n+1);
 		text = gb_alloc_array(permanent_allocator(), u8, n+1);
 		gb_memmove(text, global_error_collector.error_buffer.data, n);
 		gb_memmove(text, global_error_collector.error_buffer.data, n);
 		text[n] = 0;
 		text[n] = 0;
+
+
+		mutex_lock(&global_error_collector.error_out_mutex);
 		String s = {text, n};
 		String s = {text, n};
 		array_add(&global_error_collector.errors, s);
 		array_add(&global_error_collector.errors, s);
+		mutex_unlock(&global_error_collector.error_out_mutex);
+
 		global_error_collector.error_buffer.count = 0;
 		global_error_collector.error_buffer.count = 0;
 	}
 	}
-
+	mutex_unlock(&global_error_collector.error_buffer_mutex);
 	global_error_collector.in_block.store(false);
 	global_error_collector.in_block.store(false);
 	mutex_unlock(&global_error_collector.block_mutex);
 	mutex_unlock(&global_error_collector.block_mutex);
 }
 }
@@ -172,11 +179,15 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) {
 	isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va);
 	isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va);
 	isize n = len-1;
 	isize n = len-1;
 	if (global_error_collector.in_block) {
 	if (global_error_collector.in_block) {
+		mutex_lock(&global_error_collector.error_buffer_mutex);
+
 		isize cap = global_error_collector.error_buffer.count + n;
 		isize cap = global_error_collector.error_buffer.count + n;
 		array_reserve(&global_error_collector.error_buffer, cap);
 		array_reserve(&global_error_collector.error_buffer, cap);
 		u8 *data = global_error_collector.error_buffer.data + global_error_collector.error_buffer.count;
 		u8 *data = global_error_collector.error_buffer.data + global_error_collector.error_buffer.count;
 		gb_memmove(data, buf, n);
 		gb_memmove(data, buf, n);
 		global_error_collector.error_buffer.count += n;
 		global_error_collector.error_buffer.count += n;
+
+		mutex_unlock(&global_error_collector.error_buffer_mutex);
 	} else {
 	} else {
 		mutex_lock(&global_error_collector.error_out_mutex);
 		mutex_lock(&global_error_collector.error_out_mutex);
 		{
 		{

+ 6 - 4
src/llvm_backend_expr.cpp

@@ -2083,10 +2083,12 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		Type *elem = base_array_type(dst);
 		Type *elem = base_array_type(dst);
 		lbValue e = lb_emit_conv(p, value, elem);
 		lbValue e = lb_emit_conv(p, value, elem);
 		lbAddr v = lb_add_local_generated(p, t, false);
 		lbAddr v = lb_add_local_generated(p, t, false);
-		for (i64 i = 0; i < dst->Matrix.row_count; i++) {
-			isize j = cast(isize)i;
-			lbValue ptr = lb_emit_matrix_epi(p, v.addr, j, j);
-			lb_emit_store(p, ptr, e);
+		lbValue zero = lb_const_value(p->module, elem, exact_value_i64(0), true);
+		for (i64 j = 0; j < dst->Matrix.column_count; j++) {
+			for (i64 i = 0; i < dst->Matrix.row_count; i++) {
+				lbValue ptr = lb_emit_matrix_epi(p, v.addr, i, j);
+				lb_emit_store(p, ptr, i == j ? e : zero);
+			}
 		}
 		}
 
 
 
 

+ 1 - 1
src/parser.cpp

@@ -2462,7 +2462,7 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
 				}
 				}
 				is_raw_union = true;
 				is_raw_union = true;
 			} else if (tag.string == "no_copy") {
 			} else if (tag.string == "no_copy") {
-				if (is_packed) {
+				if (no_copy) {
 					syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
 					syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
 				}
 				}
 				no_copy = true;
 				no_copy = true;

+ 1 - 1
src/ptr_map.cpp

@@ -47,7 +47,7 @@ gb_internal gb_inline u32 ptr_map_hash_key(uintptr key) {
 	key = key ^ (key << 28);
 	key = key ^ (key << 28);
 	res = cast(u32)key;
 	res = cast(u32)key;
 #elif defined(GB_ARCH_32_BIT)
 #elif defined(GB_ARCH_32_BIT)
-	u32 state = ((u32)key) * 747796405u + 2891336453u;
+	u32 state = (cast(u32)key) * 747796405u + 2891336453u;
 	u32 word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
 	u32 word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
 	res = (word >> 22u) ^ word;
 	res = (word >> 22u) ^ word;
 #endif
 #endif

+ 93 - 0
tests/core/encoding/hex/test_core_hex.odin

@@ -0,0 +1,93 @@
+package test_core_hex
+
+import "core:encoding/hex"
+import "core:testing"
+import "core:fmt"
+import "core:os"
+import "core:bytes"
+
+TEST_count := 0
+TEST_fail  := 0
+
+when ODIN_TEST {
+	expect  :: testing.expect
+	log     :: testing.log
+} else {
+	expect  :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
+		TEST_count += 1
+		if !condition {
+			TEST_fail += 1
+			fmt.printf("[%v] %v\n", loc, message)
+			return
+		}
+	}
+	log     :: proc(t: ^testing.T, v: any, loc := #caller_location) {
+		fmt.printf("[%v] ", loc)
+		fmt.printf("log: %v\n", v)
+	}
+}
+
+main :: proc() {
+	t := testing.T{}
+
+	hex_encode(&t)
+	hex_decode(&t)
+	hex_decode_sequence(&t)
+
+	fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
+	if TEST_fail > 0 {
+		os.exit(1)
+	}
+}
+
+CASES :: [][2]string{
+	{"11", "3131"},
+	{"g", "67"},
+	{"Hello", "48656c6c6f"},
+}
+
+@(test)
+hex_encode :: proc(t: ^testing.T) {
+	for test in CASES {
+		encoded := string(hex.encode(transmute([]byte)test[0]))
+		expect(
+			t,
+			encoded == test[1],
+			fmt.tprintf("encode: %q -> %q (should be: %q)", test[0], encoded, test[1]),
+		)
+	}
+}
+
+@(test)
+hex_decode :: proc(t: ^testing.T) {
+	for test in CASES {
+		decoded, ok := hex.decode(transmute([]byte)test[1])
+		expect(t, ok, fmt.tprintf("decode: %q not ok", test[1]))
+		expect(
+			t,
+			string(decoded) == test[0],
+			fmt.tprintf("decode: %q -> %q (should be: %q)", test[1], string(decoded), test[0]),
+		)
+	}
+}
+
+@(test)
+hex_decode_sequence :: proc(t: ^testing.T) {
+	b, ok := hex.decode_sequence("0x23")
+	expect(t, ok, "decode_sequence: 0x23 not ok")
+	expect(t, b == '#', fmt.tprintf("decode_sequence: 0x23 -> %c (should be: %c)", b, '#'))
+
+	b, ok = hex.decode_sequence("0X3F")
+	expect(t, ok, "decode_sequence: 0X3F not ok")
+	expect(t, b == '?', fmt.tprintf("decode_sequence: 0X3F -> %c (should be: %c)", b, '?'))
+
+	b, ok = hex.decode_sequence("2a")
+	expect(t, ok, "decode_sequence: 2a not ok")
+	expect(t, b == '*', fmt.tprintf("decode_sequence: 2a -> %c (should be: %c)", b, '*'))
+
+	_, ok = hex.decode_sequence("1")
+	expect(t, !ok, "decode_sequence: 1 should be too short")
+
+	_, ok = hex.decode_sequence("123")
+	expect(t, !ok, "decode_sequence: 123 should be too long")
+}

+ 75 - 1
tests/core/net/test_core_net.odin

@@ -67,6 +67,9 @@ main :: proc() {
 		tcp_tests(t)
 		tcp_tests(t)
 	}
 	}
 
 
+	split_url_test(t)
+	join_url_test(t)
+
 	fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
 	fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
 
 
 	print_tracking_allocator_report()
 	print_tracking_allocator_report()
@@ -508,4 +511,75 @@ client_sends_server_data :: proc(t: ^testing.T) {
 	okay  = received == CONTENT
 	okay  = received == CONTENT
 	msg   = fmt.tprintf("Expected client to send \"{}\", got \"{}\"", CONTENT, received)
 	msg   = fmt.tprintf("Expected client to send \"{}\", got \"{}\"", CONTENT, received)
 	expect(t, okay, msg)
 	expect(t, okay, msg)
-}
+}
+
+URL_Test :: struct {
+	scheme, host, path: string,
+	queries: map[string]string,
+	url: string,
+}
+
+@test
+split_url_test :: proc(t: ^testing.T) {
+	test_cases := []URL_Test{
+		{ "http", "example.com", "/", {}, "http://example.com" },
+		{ "https", "odin-lang.org", "/", {}, "https://odin-lang.org" },
+		{ "https", "odin-lang.org", "/docs/", {}, "https://odin-lang.org/docs/" },
+		{ "https", "odin-lang.org", "/docs/overview", {}, "https://odin-lang.org/docs/overview" },
+		{ "http", "example.com", "/", {"a" = "b"}, "http://example.com?a=b" },
+		{ "http", "example.com", "/", {"a" = ""}, "http://example.com?a" },
+		{ "http", "example.com", "/", {"a" = "b", "c" = "d"}, "http://example.com?a=b&c=d" },
+		{ "http", "example.com", "/", {"a" = "", "c" = "d"}, "http://example.com?a&c=d" },
+		{ "http", "example.com", "/example", {"a" = "", "b" = ""}, "http://example.com/example?a&b" },
+	}
+
+	for test in test_cases {
+		scheme, host, path, queries := net.split_url(test.url)
+		defer {
+			delete(queries)
+			delete(test.queries)
+		}
+
+		msg := fmt.tprintf("Expected `net.split_url` to return %s, got %s", test.scheme, scheme)
+		expect(t, scheme == test.scheme, msg)
+		msg = fmt.tprintf("Expected `net.split_url` to return %s, got %s", test.host, host)
+		expect(t, host == test.host, msg)
+		msg = fmt.tprintf("Expected `net.split_url` to return %s, got %s", test.path, path)
+		expect(t, path == test.path, msg)
+		msg = fmt.tprintf("Expected `net.split_url` to return %d queries, got %d queries", len(test.queries), len(queries))
+		expect(t, len(queries) == len(test.queries), msg)
+		for k, v in queries {
+			expected := test.queries[k]
+			msg = fmt.tprintf("Expected `net.split_url` to return %s, got %s", expected, v)
+			expect(t, v == expected, msg)
+		}
+	}
+}
+
+
+@test
+join_url_test :: proc(t: ^testing.T) {
+	test_cases := []URL_Test{
+		{ "http", "example.com", "", {}, "http://example.com" },
+		{ "https", "odin-lang.org", "", {}, "https://odin-lang.org" },
+		{ "https", "odin-lang.org", "docs/", {}, "https://odin-lang.org/docs/" },
+		{ "https", "odin-lang.org", "/docs/overview", {}, "https://odin-lang.org/docs/overview" },
+		{ "http", "example.com", "", {"a" = "b"}, "http://example.com?a=b" },
+		{ "http", "example.com", "", {"a" = ""}, "http://example.com?a" },
+		{ "http", "example.com", "", {"a" = "b", "c" = "d"}, "http://example.com?a=b&c=d" },
+		{ "http", "example.com", "", {"a" = "", "c" = "d"}, "http://example.com?a&c=d" },
+		{ "http", "example.com", "example", {"a" = "", "b" = ""}, "http://example.com/example?a&b" },
+	}
+
+	for test in test_cases {
+		url := net.join_url(test.scheme, test.host, test.path, test.queries)
+		defer {
+			delete(url)
+			delete(test.queries)
+		}
+
+		okay := url == test.url
+		msg := fmt.tprintf("Expected `net.join_url` to return %s, got %s", test.url, url)
+		expect(t, okay, msg)
+	}
+}

+ 1 - 0
tests/issues/run.bat

@@ -9,6 +9,7 @@ set COMMON=-collection:tests=..\..
 
 
 ..\..\..\odin test ..\test_issue_829.odin %COMMON% -file || exit /b
 ..\..\..\odin test ..\test_issue_829.odin %COMMON% -file || exit /b
 ..\..\..\odin test ..\test_issue_1592.odin %COMMON% -file || exit /b
 ..\..\..\odin test ..\test_issue_1592.odin %COMMON% -file || exit /b
+..\..\..\odin test ..\test_issue_2056.odin %COMMON% -file || exit /b
 ..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file || exit /b
 ..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file || exit /b
 ..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug || exit /b
 ..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug || exit /b
 
 

+ 1 - 0
tests/issues/run.sh

@@ -10,6 +10,7 @@ set -x
 
 
 $ODIN test ../test_issue_829.odin  $COMMON -file
 $ODIN test ../test_issue_829.odin  $COMMON -file
 $ODIN test ../test_issue_1592.odin $COMMON -file
 $ODIN test ../test_issue_1592.odin $COMMON -file
+$ODIN test ../test_issue_2056.odin $COMMON -file
 $ODIN test ../test_issue_2087.odin $COMMON -file
 $ODIN test ../test_issue_2087.odin $COMMON -file
 $ODIN build ../test_issue_2113.odin $COMMON -file -debug
 $ODIN build ../test_issue_2113.odin $COMMON -file -debug
 
 

+ 22 - 0
tests/issues/test_issue_2056.odin

@@ -0,0 +1,22 @@
+// Tests issue #2056 https://github.com/odin-lang/Odin/issues/2056
+package test_issues
+
+import "core:fmt"
+import "core:testing"
+
+@test
+test_scalar_matrix_conversion :: proc(t: ^testing.T) {
+	l := f32(1.0)
+	m := (matrix[4,4]f32)(l)
+
+	for i in 0..<4 {
+		for j in 0..<4 {
+			if i == j {
+				testing.expect(t, m[i,j] == 1, fmt.tprintf("expected 1 at m[%d,%d], found %f\n", i, j, m[i,j]))
+			} else {
+				testing.expect(t, m[i,j] == 0, fmt.tprintf("expected 0 at m[%d,%d], found %f\n", i, j, m[i,j]))
+			}
+		}
+	}
+}
+

BIN
tests/vendor/botan-3.dll


BIN
tests/vendor/botan.dll


+ 5 - 5
tests/vendor/botan/test_vendor_botan.odin

@@ -70,8 +70,8 @@ main :: proc() {
     test_sha3_256(&t)
     test_sha3_256(&t)
     test_sha3_384(&t)
     test_sha3_384(&t)
     test_sha3_512(&t)
     test_sha3_512(&t)
-    test_shake_128(&t)
-    test_shake_256(&t)
+    // test_shake_128(&t)
+    // test_shake_256(&t)
     test_keccak_512(&t)
     test_keccak_512(&t)
     test_whirlpool(&t)
     test_whirlpool(&t)
     test_gost(&t)
     test_gost(&t)
@@ -79,9 +79,9 @@ main :: proc() {
     test_streebog_512(&t)
     test_streebog_512(&t)
     test_blake2b(&t)
     test_blake2b(&t)
     test_ripemd_160(&t)
     test_ripemd_160(&t)
-    test_tiger_128(&t)
-    test_tiger_160(&t)
-    test_tiger_192(&t)
+    // test_tiger_128(&t)
+    // test_tiger_160(&t)
+    // test_tiger_192(&t)
     test_sm3(&t)
     test_sm3(&t)
     test_skein512_256(&t)
     test_skein512_256(&t)
     test_skein512_512(&t)
     test_skein512_512(&t)

+ 2 - 2
vendor/README.md

@@ -143,7 +143,7 @@ Includes full bindings as well as wrappers to match the `core:crypto` API.
 See also LICENSE in the `commonmark` directory itself.
 See also LICENSE in the `commonmark` directory itself.
 Includes full bindings and Windows `.lib` and `.dll`.
 Includes full bindings and Windows `.lib` and `.dll`.
 
 
-## CommonMark
+## zlib
 
 
 [zlib](https://github.com/madler/zlib) data compression library
 [zlib](https://github.com/madler/zlib) data compression library
 
 
@@ -158,4 +158,4 @@ Includes full bindings.
 
 
 Used in: [bgfx](https://github.com/bkaradzic/bgfx), [Filament](https://github.com/google/filament), [gltfpack](https://github.com/zeux/meshoptimizer/tree/master/gltf), [raylib](https://github.com/raysan5/raylib), [Unigine](https://developer.unigine.com/en/docs/2.14.1/third_party?rlang=cpp#cgltf), and more!
 Used in: [bgfx](https://github.com/bkaradzic/bgfx), [Filament](https://github.com/google/filament), [gltfpack](https://github.com/zeux/meshoptimizer/tree/master/gltf), [raylib](https://github.com/raysan5/raylib), [Unigine](https://developer.unigine.com/en/docs/2.14.1/third_party?rlang=cpp#cgltf), and more!
 
 
-Se also LICENCE in `cgltf` directory itself.
+See also LICENCE in `cgltf` directory itself.

BIN
vendor/botan/bindings/botan-3.lib


BIN
vendor/botan/bindings/botan.lib


+ 5 - 3
vendor/botan/bindings/botan.odin

@@ -62,7 +62,7 @@ CRL_SIGN                  :: x509_cert_key_constraints(512)
 ENCIPHER_ONLY             :: x509_cert_key_constraints(256)
 ENCIPHER_ONLY             :: x509_cert_key_constraints(256)
 DECIPHER_ONLY             :: x509_cert_key_constraints(128)
 DECIPHER_ONLY             :: x509_cert_key_constraints(128)
 
 
-HASH_SHA1           :: "SHA1"
+HASH_SHA1           :: "SHA-1"
 HASH_SHA_224        :: "SHA-224"
 HASH_SHA_224        :: "SHA-224"
 HASH_SHA_256        :: "SHA-256"
 HASH_SHA_256        :: "SHA-256"
 HASH_SHA_384        :: "SHA-384"
 HASH_SHA_384        :: "SHA-384"
@@ -141,10 +141,12 @@ fpe_struct           :: struct{}
 fpe_t                :: ^fpe_struct
 fpe_t                :: ^fpe_struct
 
 
 when ODIN_OS == .Windows {
 when ODIN_OS == .Windows {
-    foreign import botan_lib "botan.lib"
+    foreign import botan_lib "botan-3.lib"
+} else when ODIN_OS == .Darwin {
+    foreign import botan_lib "system:botan-3"
 } else {
 } else {
     foreign import botan_lib "system:botan-2"
     foreign import botan_lib "system:botan-2"
-}
+} 
 
 
 @(default_calling_convention="c")
 @(default_calling_convention="c")
 @(link_prefix="botan_")
 @(link_prefix="botan_")

+ 1 - 1
vendor/lua/5.4/lua.odin

@@ -44,7 +44,7 @@ REGISTRYINDEX :: -MAXSTACK - 1000
 ** space (and to reserve some numbers for pseudo-indices).
 ** space (and to reserve some numbers for pseudo-indices).
 ** (It must fit into max(size_t)/32.)
 ** (It must fit into max(size_t)/32.)
 */
 */
-MAXSTACK :: 1000000 when size_of(rawptr) == 4 else 15000
+MAXSTACK :: 1000000 when size_of(rawptr) >= 4 else 15000
 
 
 
 
 /*
 /*