Fix array bounds checking

This commit is contained in:
Ginger Bill
2016-09-12 23:16:06 +01:00
parent d4ba6b5466
commit 59fb74d2a2
8 changed files with 264 additions and 199 deletions
+2 -5
View File
@@ -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)
}
+10 -10
View File
@@ -41,18 +41,18 @@ File_Standard :: type enum {
COUNT,
}
__std_file_set := false;
__std_files: [File_Standard.COUNT as int]File;
__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 {
// 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
}
return ^__std_files[std]
}
+97 -33
View File
@@ -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_any_to_buffer(buf, arg)
prev_string = is_string
print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) {
is_digit :: proc(r: rune) -> bool #inline {
return r >= #rune "0" && r <= #rune "9"
}
}
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)
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)
return result, offset
}
print_nl_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
}
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_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)
}
+12 -6
View File
@@ -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()
}