diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-12 23:16:06 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-12 23:16:06 +0100 |
| commit | 59fb74d2a2706898cca60e35874ecd2477202e71 (patch) | |
| tree | a27361bf046115b5bb44c3b9f44b59581e86dc71 /code | |
| parent | d4ba6b546632b3174533a2d099031362f74085e9 (diff) | |
Fix array bounds checking
Diffstat (limited to 'code')
| -rw-r--r-- | code/demo.odin | 7 | ||||
| -rw-r--r-- | code/file.odin | 20 | ||||
| -rw-r--r-- | code/print.odin | 128 | ||||
| -rw-r--r-- | code/runtime.odin | 18 |
4 files changed, 120 insertions, 53 deletions
diff --git a/code/demo.odin b/code/demo.odin index 6a1a9396a..64af72d26 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,9 +1,6 @@ #load "basic.odin" main :: proc() { - str := "Hellope" - - println(str, true, 6.28) - - println([4]int{1, 2, 3, 4}) + println("% % % %", "Hellope", true, 6.28, [4]int{1, 2, 3, 4}) + println("%0 %1 %0", "Hellope", 34) } diff --git a/code/file.odin b/code/file.odin index 7ee8770e0..dc97e909e 100644 --- a/code/file.odin +++ b/code/file.odin @@ -41,18 +41,18 @@ File_Standard :: type enum { COUNT, } -__std_file_set := false; -__std_files: [File_Standard.COUNT as int]File; -file_get_standard :: proc(std: File_Standard) -> ^File { - // using File_Standard; - if (!__std_file_set) { - using File_Standard - __std_files[INPUT] .handle = GetStdHandle(STD_INPUT_HANDLE) - __std_files[OUTPUT].handle = GetStdHandle(STD_OUTPUT_HANDLE) - __std_files[ERROR] .handle = GetStdHandle(STD_ERROR_HANDLE) - __std_file_set = true +__std_files := __set_file_standards(); + +__set_file_standards :: proc() -> [File_Standard.COUNT as int]File { + return [File_Standard.COUNT as int]File{ + File{handle = GetStdHandle(STD_INPUT_HANDLE)}, + File{handle = GetStdHandle(STD_OUTPUT_HANDLE)}, + File{handle = GetStdHandle(STD_ERROR_HANDLE)}, } +} + +file_get_standard :: proc(std: File_Standard) -> ^File { return ^__std_files[std] } diff --git a/code/print.odin b/code/print.odin index 41121dbae..2a32f3c9e 100644 --- a/code/print.odin +++ b/code/print.odin @@ -2,7 +2,7 @@ #load "win32.odin" #load "file.odin" -print_string_to_buffer :: proc(buf: ^[]byte, s: string) { +print_byte_buffer :: proc(buf: ^[]byte, b: []byte) { // NOTE(bill): This is quite a hack // TODO(bill): Should I allow the raw editing of a slice by exposing its // internal members? @@ -14,13 +14,20 @@ print_string_to_buffer :: proc(buf: ^[]byte, s: string) { slice := buf as ^Raw_Bytes if slice.len < slice.cap { - n := min(slice.cap-slice.len, len(s)) - offset := ptr_offset(slice.data, slice.len) - memory_copy(offset, ^s[0], n) - slice.len += n + n := min(slice.cap-slice.len, len(b)) + if n > 0 { + offset := ptr_offset(slice.data, slice.len) + memory_copy(offset, ^b[0], n) + slice.len += n + } } } +print_string_to_buffer :: proc(buf: ^[]byte, s: string) { + print_byte_buffer(buf, s as []byte) +} + + byte_reverse :: proc(b: []byte) { n := len(b) for i := 0; i < n/2; i++ { @@ -357,43 +364,100 @@ type_info_is_string :: proc(info: ^Type_Info) -> bool { return false } -print_to_buffer :: proc(buf: ^[]byte, args: ..any) { - prev_string := false - for i := 0; i < len(args); i++ { - arg := args[i] - is_string := arg.data != null && type_info_is_string(arg.type_info) - if i > 0 && !is_string && !prev_string { - // Add space between two non-string arguments - print_space_to_buffer(buf) + +print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) { + is_digit :: proc(r: rune) -> bool #inline { + return r >= #rune "0" && r <= #rune "9" + } + + parse_int :: proc(s: string, offset: int) -> (int, int) { + result := 0 + + for ; offset < len(s); offset++ { + c := s[offset] as rune + if !is_digit(c) { + break + } + + result *= 10 + result += (c - #rune "0") as int } - print_any_to_buffer(buf, arg) - prev_string = is_string + + return result, offset } -} -println_to_buffer :: proc(buf: ^[]byte, args: ..any) { - for i := 0; i < len(args); i++ { - arg := args[i] - if i > 0 { - print_space_to_buffer(buf) + prev := 0 + implicit_index := 0 + + for i := 0; i < len(fmt); i++ { + r := fmt[i] as rune + + if r != #rune "%" { + continue + } + + print_string_to_buffer(buf, fmt[prev:i]) + i++ // Skip % + if i >= len(fmt) { + return } - print_any_to_buffer(buf, arg) + + next := fmt[i] as rune + if next == #rune "%" { + print_string_to_buffer(buf, "%") + i++ + prev = i + continue + } + + index := implicit_index + set_prev := true + + if is_digit(next) { + index, i = parse_int(fmt, i) + } + + if 0 <= index && index < len(args) { + print_any_to_buffer(buf, args[index]) + implicit_index = index+1 + } else { + // TODO(bill): Error check index out bounds + print_string_to_buffer(buf, "<invalid>") + } + + prev = i } - print_nl_to_buffer(buf) + + print_string_to_buffer(buf, fmt[prev:]) } +PRINT_BUF_SIZE :: 1<<12 -print :: proc(args: ..any) { - data: [4096]byte +print_to_file :: proc(f: ^File, fmt: string, args: ..any) { + data: [PRINT_BUF_SIZE]byte buf := data[:0] - print_to_buffer(^buf, ..args) - file_write(file_get_standard(File_Standard.OUTPUT), buf) + print_to_buffer(^buf, fmt, ..args) + file_write(f, buf) } - -println :: proc(args: ..any) { - data: [4096]byte +println_to_file :: proc(f: ^File, fmt: string, args: ..any) { + data: [PRINT_BUF_SIZE]byte buf := data[:0] - println_to_buffer(^buf, ..args) - file_write(file_get_standard(File_Standard.OUTPUT), buf) + print_to_buffer(^buf, fmt, ..args) + print_nl_to_buffer(^buf) + file_write(f, buf) +} + + +print :: proc(fmt: string, args: ..any) { + print_to_file(file_get_standard(File_Standard.OUTPUT), fmt, ..args) +} +print_err :: proc(fmt: string, args: ..any) { + print_to_file(file_get_standard(File_Standard.ERROR), fmt, ..args) +} +println :: proc(fmt: string, args: ..any) { + println_to_file(file_get_standard(File_Standard.OUTPUT), fmt, ..args) +} +println_err :: proc(fmt: string, args: ..any) { + println_to_file(file_get_standard(File_Standard.ERROR), fmt, ..args) } diff --git a/code/runtime.odin b/code/runtime.odin index aedcdc9ba..5f42c39c5 100644 --- a/code/runtime.odin +++ b/code/runtime.odin @@ -290,17 +290,23 @@ __assert :: proc(msg: string) { __debug_trap() } -__abc_error :: proc(file: string, line, column: int, index, len: int) { - print(file, "(", line, ":", line, ") Index `", index, "` is of bounds range [0, ", len, ")\n") +__bounds_check_error :: proc(file: string, line, column: int, + index, count: int) { + println_err("%(%:%) Index % is out of bounds range [0, %)", + file, line, column, index, count) __debug_trap() } -__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) { - print(file, "(", line, ":", line, ") Invalid slice indices: [", low, ":", high, ":", max, "]\n") +__slice_expr_error :: proc(file: string, line, column: int, + low, high, max: int) { + print_err("%(%:%) Invalid slice indices: [%:%:%]\n", + file, line, column, low, high, max) __debug_trap() } -__substring_expr_error :: proc(file: string, line, column: int, low, high: int) { - print(file, "(", line, ":", line, ") Invalid substring indices: [", low, ":", high, "]\n") +__substring_expr_error :: proc(file: string, line, column: int, + low, high: int) { + print_err("%(%:%) Invalid substring indices: [%:%:%]\n", + file, line, column, low, high) __debug_trap() } |