mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
#import search rule: relative then core/
This commit is contained in:
@@ -31,32 +31,32 @@ set linker_flags= -incremental:no -opt:ref -subsystem:console
|
|||||||
|
|
||||||
if %release_mode% EQU 0 ( rem Debug
|
if %release_mode% EQU 0 ( rem Debug
|
||||||
set linker_flags=%linker_flags% -debug
|
set linker_flags=%linker_flags% -debug
|
||||||
set libs=%libs% ..\src\utf8proc\utf8proc_debug.lib
|
set libs=%libs% src\utf8proc\utf8proc_debug.lib
|
||||||
) else ( rem Release
|
) else ( rem Release
|
||||||
set linker_flags=%linker_flags%
|
set linker_flags=%linker_flags%
|
||||||
set libs=%libs% ..\src\utf8proc\utf8proc.lib
|
set libs=%libs% src\utf8proc\utf8proc.lib
|
||||||
)
|
)
|
||||||
|
|
||||||
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
|
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
|
||||||
set linker_settings=%libs% %linker_flags%
|
set linker_settings=%libs% %linker_flags%
|
||||||
|
|
||||||
|
|
||||||
set build_dir= "bin\"
|
rem set build_dir= "\"
|
||||||
if not exist %build_dir% mkdir %build_dir%
|
rem if not exist %build_dir% mkdir %build_dir%
|
||||||
pushd %build_dir%
|
rem pushd %build_dir%
|
||||||
del *.pdb > NUL 2> NUL
|
del *.pdb > NUL 2> NUL
|
||||||
del *.ilk > NUL 2> NUL
|
del *.ilk > NUL 2> NUL
|
||||||
|
|
||||||
del ..\misc\*.pdb > NUL 2> NUL
|
del ..\misc\*.pdb > NUL 2> NUL
|
||||||
del ..\misc\*.ilk > NUL 2> NUL
|
del ..\misc\*.ilk > NUL 2> NUL
|
||||||
|
|
||||||
cl %compiler_settings% "..\src\main.cpp" ^
|
cl %compiler_settings% "src\main.cpp" ^
|
||||||
/link %linker_settings% -OUT:%exe_name% ^
|
/link %linker_settings% -OUT:%exe_name% ^
|
||||||
&& odin run ..\code/demo.odin
|
&& odin run code/demo.odin
|
||||||
rem odin run ..\code/demo.odin
|
rem odin run code/demo.odin
|
||||||
|
|
||||||
|
|
||||||
:do_not_compile_exe
|
:do_not_compile_exe
|
||||||
popd
|
rem popd
|
||||||
:end_of_build
|
:end_of_build
|
||||||
|
|
||||||
|
|||||||
-583
@@ -1,583 +0,0 @@
|
|||||||
#import "os.odin" as os
|
|
||||||
|
|
||||||
print_byte_buffer :: proc(buf: ^[]byte, b: []byte) {
|
|
||||||
if buf.count < buf.capacity {
|
|
||||||
n := min(buf.capacity-buf.count, b.count)
|
|
||||||
if n > 0 {
|
|
||||||
offset := ptr_offset(buf.data, buf.count)
|
|
||||||
memory_copy(offset, ^b[0], n)
|
|
||||||
buf.count += n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_string_to_buffer :: proc(buf: ^[]byte, s: string) {
|
|
||||||
print_byte_buffer(buf, s as []byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
byte_reverse :: proc(b: []byte) {
|
|
||||||
n := b.count
|
|
||||||
for i := 0; i < n/2; i++ {
|
|
||||||
b[i], b[n-1-i] = b[n-1-i], b[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
encode_rune :: proc(r: rune) -> ([4]byte, int) {
|
|
||||||
buf: [4]byte
|
|
||||||
i := r as u32
|
|
||||||
mask: byte : 0x3f
|
|
||||||
if i <= 1<<7-1 {
|
|
||||||
buf[0] = r as byte
|
|
||||||
return buf, 1
|
|
||||||
}
|
|
||||||
if i <= 1<<11-1 {
|
|
||||||
buf[0] = 0xc0 | (r>>6) as byte
|
|
||||||
buf[1] = 0x80 | (r) as byte & mask
|
|
||||||
return buf, 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalid or Surrogate range
|
|
||||||
if i > 0x0010ffff ||
|
|
||||||
(i >= 0xd800 && i <= 0xdfff) {
|
|
||||||
r = 0xfffd
|
|
||||||
}
|
|
||||||
|
|
||||||
if i <= 1<<16-1 {
|
|
||||||
buf[0] = 0xe0 | (r>>12) as byte
|
|
||||||
buf[1] = 0x80 | (r>>6) as byte & mask
|
|
||||||
buf[2] = 0x80 | (r) as byte & mask
|
|
||||||
return buf, 3
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[0] = 0xf0 | (r>>18) as byte
|
|
||||||
buf[1] = 0x80 | (r>>12) as byte & mask
|
|
||||||
buf[2] = 0x80 | (r>>6) as byte & mask
|
|
||||||
buf[3] = 0x80 | (r) as byte & mask
|
|
||||||
return buf, 4
|
|
||||||
}
|
|
||||||
|
|
||||||
print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) {
|
|
||||||
b, n := encode_rune(r)
|
|
||||||
print_string_to_buffer(buf, b[:n] as string)
|
|
||||||
}
|
|
||||||
|
|
||||||
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune " ") }
|
|
||||||
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\n") }
|
|
||||||
|
|
||||||
print_int_to_buffer :: proc(buf: ^[]byte, i: int) {
|
|
||||||
print_int_base_to_buffer(buf, i, 10);
|
|
||||||
}
|
|
||||||
PRINT__NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
|
|
||||||
print_int_base_to_buffer :: proc(buffer: ^[]byte, i, base: int) {
|
|
||||||
|
|
||||||
buf: [65]byte
|
|
||||||
len := 0
|
|
||||||
negative := false
|
|
||||||
if i < 0 {
|
|
||||||
negative = true
|
|
||||||
i = -i
|
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
buf[len] = #rune "0"
|
|
||||||
len++
|
|
||||||
}
|
|
||||||
for i > 0 {
|
|
||||||
buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % base]
|
|
||||||
len++
|
|
||||||
i /= base
|
|
||||||
}
|
|
||||||
|
|
||||||
if negative {
|
|
||||||
buf[len] = #rune "-"
|
|
||||||
len++
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_reverse(buf[:len])
|
|
||||||
print_string_to_buffer(buffer, buf[:len] as string)
|
|
||||||
}
|
|
||||||
|
|
||||||
print_uint_to_buffer :: proc(buffer: ^[]byte, i: uint) {
|
|
||||||
print_uint_base_to_buffer(buffer, i, 10, 0, #rune " ")
|
|
||||||
}
|
|
||||||
print_uint_base_to_buffer :: proc(buffer: ^[]byte, i, base: uint, min_width: int, pad_char: byte) {
|
|
||||||
buf: [65]byte
|
|
||||||
len := 0
|
|
||||||
if i == 0 {
|
|
||||||
buf[len] = #rune "0"
|
|
||||||
len++
|
|
||||||
}
|
|
||||||
for i > 0 {
|
|
||||||
buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % base]
|
|
||||||
len++
|
|
||||||
i /= base
|
|
||||||
}
|
|
||||||
for len < min_width {
|
|
||||||
buf[len] = pad_char
|
|
||||||
len++
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_reverse(buf[:len])
|
|
||||||
print_string_to_buffer(buffer, buf[:len] as string)
|
|
||||||
}
|
|
||||||
|
|
||||||
print_bool_to_buffer :: proc(buffer: ^[]byte, b : bool) {
|
|
||||||
if b { print_string_to_buffer(buffer, "true") }
|
|
||||||
else { print_string_to_buffer(buffer, "false") }
|
|
||||||
}
|
|
||||||
|
|
||||||
print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline { print_uint_base_to_buffer(buffer, p as uint, 16, 0, #rune " ") }
|
|
||||||
|
|
||||||
print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
|
|
||||||
print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) }
|
|
||||||
|
|
||||||
print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
|
|
||||||
if f == 0 {
|
|
||||||
print_rune_to_buffer(buffer, #rune "0")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if f < 0 {
|
|
||||||
print_rune_to_buffer(buffer, #rune "-")
|
|
||||||
f = -f
|
|
||||||
}
|
|
||||||
|
|
||||||
print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) {
|
|
||||||
buf: [22]byte
|
|
||||||
len := 0
|
|
||||||
if i == 0 {
|
|
||||||
buf[len] = #rune "0"
|
|
||||||
len++
|
|
||||||
}
|
|
||||||
for i > 0 {
|
|
||||||
buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % 10]
|
|
||||||
len++
|
|
||||||
i /= 10
|
|
||||||
}
|
|
||||||
byte_reverse(buf[:len])
|
|
||||||
print_string_to_buffer(buffer, buf[:len] as string)
|
|
||||||
}
|
|
||||||
|
|
||||||
i := f as u64
|
|
||||||
print_u64_to_buffer(buffer, i)
|
|
||||||
f -= i as f64
|
|
||||||
|
|
||||||
print_rune_to_buffer(buffer, #rune ".")
|
|
||||||
|
|
||||||
mult := 10.0
|
|
||||||
for decimal_places := 6; decimal_places >= 0; decimal_places-- {
|
|
||||||
i = (f * mult) as u64
|
|
||||||
print_u64_to_buffer(buffer, i as u64)
|
|
||||||
f -= i as f64 / mult
|
|
||||||
mult *= 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|
||||||
if ti == null { return }
|
|
||||||
|
|
||||||
using Type_Info
|
|
||||||
match type info : ti {
|
|
||||||
case Named:
|
|
||||||
print_string_to_buffer(buf, info.name)
|
|
||||||
case Integer:
|
|
||||||
match {
|
|
||||||
case ti == type_info(int):
|
|
||||||
print_string_to_buffer(buf, "int")
|
|
||||||
case ti == type_info(uint):
|
|
||||||
print_string_to_buffer(buf, "uint")
|
|
||||||
default:
|
|
||||||
if info.signed {
|
|
||||||
print_string_to_buffer(buf, "i")
|
|
||||||
} else {
|
|
||||||
print_string_to_buffer(buf, "u")
|
|
||||||
}
|
|
||||||
print_int_to_buffer(buf, 8*info.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Float:
|
|
||||||
match info.size {
|
|
||||||
case 4: print_string_to_buffer(buf, "f32")
|
|
||||||
case 8: print_string_to_buffer(buf, "f64")
|
|
||||||
}
|
|
||||||
case String: print_string_to_buffer(buf, "string")
|
|
||||||
case Boolean: print_string_to_buffer(buf, "bool")
|
|
||||||
case Pointer:
|
|
||||||
print_string_to_buffer(buf, "^")
|
|
||||||
print_type_to_buffer(buf, info.elem)
|
|
||||||
case Procedure:
|
|
||||||
print_string_to_buffer(buf, "proc")
|
|
||||||
if info.params == null {
|
|
||||||
print_string_to_buffer(buf, "()")
|
|
||||||
} else {
|
|
||||||
count := (info.params as ^Tuple).fields.count
|
|
||||||
if count == 1 { print_string_to_buffer(buf, "(") }
|
|
||||||
print_type_to_buffer(buf, info.params)
|
|
||||||
if count == 1 { print_string_to_buffer(buf, ")") }
|
|
||||||
}
|
|
||||||
if info.results != null {
|
|
||||||
print_string_to_buffer(buf, " -> ")
|
|
||||||
print_type_to_buffer(buf, info.results)
|
|
||||||
}
|
|
||||||
case Tuple:
|
|
||||||
count := info.fields.count
|
|
||||||
if count != 1 { print_string_to_buffer(buf, "(") }
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
if i > 0 { print_string_to_buffer(buf, ", ") }
|
|
||||||
|
|
||||||
f := info.fields[i]
|
|
||||||
|
|
||||||
if f.name.count > 0 {
|
|
||||||
print_string_to_buffer(buf, f.name)
|
|
||||||
print_string_to_buffer(buf, ": ")
|
|
||||||
}
|
|
||||||
print_type_to_buffer(buf, f.type_info)
|
|
||||||
}
|
|
||||||
if count != 1 { print_string_to_buffer(buf, ")") }
|
|
||||||
|
|
||||||
case Array:
|
|
||||||
print_string_to_buffer(buf, "[")
|
|
||||||
print_int_to_buffer(buf, info.count)
|
|
||||||
print_string_to_buffer(buf, "]")
|
|
||||||
print_type_to_buffer(buf, info.elem)
|
|
||||||
case Slice:
|
|
||||||
print_string_to_buffer(buf, "[")
|
|
||||||
print_string_to_buffer(buf, "]")
|
|
||||||
print_type_to_buffer(buf, info.elem)
|
|
||||||
case Vector:
|
|
||||||
print_string_to_buffer(buf, "{")
|
|
||||||
print_int_to_buffer(buf, info.count)
|
|
||||||
print_string_to_buffer(buf, "}")
|
|
||||||
print_type_to_buffer(buf, info.elem)
|
|
||||||
|
|
||||||
case Struct:
|
|
||||||
print_string_to_buffer(buf, "struct ")
|
|
||||||
if info.packed { print_string_to_buffer(buf, "#packed ") }
|
|
||||||
if info.ordered { print_string_to_buffer(buf, "#ordered ") }
|
|
||||||
print_string_to_buffer(buf, "{")
|
|
||||||
for i := 0; i < info.fields.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
print_any_to_buffer(buf, info.fields[i].name)
|
|
||||||
print_string_to_buffer(buf, ": ")
|
|
||||||
print_type_to_buffer(buf, info.fields[i].type_info)
|
|
||||||
}
|
|
||||||
print_string_to_buffer(buf, "}")
|
|
||||||
|
|
||||||
case Union:
|
|
||||||
print_string_to_buffer(buf, "union {")
|
|
||||||
for i := 0; i < info.fields.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
print_any_to_buffer(buf, info.fields[i].name)
|
|
||||||
print_string_to_buffer(buf, ": ")
|
|
||||||
print_type_to_buffer(buf, info.fields[i].type_info)
|
|
||||||
}
|
|
||||||
print_string_to_buffer(buf, "}")
|
|
||||||
|
|
||||||
case Raw_Union:
|
|
||||||
print_string_to_buffer(buf, "raw_union {")
|
|
||||||
for i := 0; i < info.fields.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
print_any_to_buffer(buf, info.fields[i].name)
|
|
||||||
print_string_to_buffer(buf, ": ")
|
|
||||||
print_type_to_buffer(buf, info.fields[i].type_info)
|
|
||||||
}
|
|
||||||
print_string_to_buffer(buf, "}")
|
|
||||||
|
|
||||||
case Enum:
|
|
||||||
print_string_to_buffer(buf, "enum ")
|
|
||||||
print_type_to_buffer(buf, info.base)
|
|
||||||
print_string_to_buffer(buf, "{}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|
||||||
using Type_Info
|
|
||||||
match type info : arg.type_info {
|
|
||||||
case Named:
|
|
||||||
a: any
|
|
||||||
a.type_info = info.base
|
|
||||||
a.data = arg.data
|
|
||||||
match type b : info.base {
|
|
||||||
case Struct:
|
|
||||||
print_string_to_buffer(buf, info.name)
|
|
||||||
print_string_to_buffer(buf, "{")
|
|
||||||
for i := 0; i < b.fields.count; i++ {
|
|
||||||
f := b.fields[i];
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
print_any_to_buffer(buf, f.name)
|
|
||||||
print_string_to_buffer(buf, " = ")
|
|
||||||
v: any
|
|
||||||
v.type_info = f.type_info
|
|
||||||
v.data = ptr_offset(arg.data as ^byte, f.offset)
|
|
||||||
print_any_to_buffer(buf, v)
|
|
||||||
}
|
|
||||||
print_string_to_buffer(buf, "}")
|
|
||||||
|
|
||||||
default:
|
|
||||||
print_any_to_buffer(buf, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Integer:
|
|
||||||
if info.signed {
|
|
||||||
i: int = 0;
|
|
||||||
if arg.data != null {
|
|
||||||
match info.size {
|
|
||||||
case 1: i = (arg.data as ^i8)^ as int
|
|
||||||
case 2: i = (arg.data as ^i16)^ as int
|
|
||||||
case 4: i = (arg.data as ^i32)^ as int
|
|
||||||
case 8: i = (arg.data as ^i64)^ as int
|
|
||||||
case 16: i = (arg.data as ^i128)^ as int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print_int_to_buffer(buf, i)
|
|
||||||
} else {
|
|
||||||
i: uint = 0;
|
|
||||||
if arg.data != null {
|
|
||||||
match info.size {
|
|
||||||
case 1: i = (arg.data as ^u8)^ as uint
|
|
||||||
case 2: i = (arg.data as ^u16)^ as uint
|
|
||||||
case 4: i = (arg.data as ^u32)^ as uint
|
|
||||||
case 8: i = (arg.data as ^u64)^ as uint
|
|
||||||
case 16: i = (arg.data as ^u128)^ as uint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print_uint_to_buffer(buf, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Float:
|
|
||||||
f: f64 = 0
|
|
||||||
if arg.data != null {
|
|
||||||
match info.size {
|
|
||||||
case 4: f = (arg.data as ^f32)^ as f64
|
|
||||||
case 8: f = (arg.data as ^f64)^ as f64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print_f64_to_buffer(buf, f)
|
|
||||||
|
|
||||||
case String:
|
|
||||||
s := ""
|
|
||||||
if arg.data != null {
|
|
||||||
s = (arg.data as ^string)^
|
|
||||||
}
|
|
||||||
print_string_to_buffer(buf, s)
|
|
||||||
|
|
||||||
case Boolean:
|
|
||||||
v := false;
|
|
||||||
if arg.data != null {
|
|
||||||
v = (arg.data as ^bool)^
|
|
||||||
}
|
|
||||||
print_bool_to_buffer(buf, v)
|
|
||||||
|
|
||||||
case Pointer:
|
|
||||||
v := null;
|
|
||||||
if arg.data != null {
|
|
||||||
v = (arg.data as ^rawptr)^
|
|
||||||
}
|
|
||||||
print_pointer_to_buffer(buf, v)
|
|
||||||
|
|
||||||
case Enum:
|
|
||||||
v: any
|
|
||||||
v.data = arg.data
|
|
||||||
v.type_info = info.base
|
|
||||||
print_any_to_buffer(buf, v)
|
|
||||||
|
|
||||||
|
|
||||||
case Array:
|
|
||||||
print_string_to_buffer(buf, "[")
|
|
||||||
defer print_string_to_buffer(buf, "]")
|
|
||||||
|
|
||||||
for i := 0; i < info.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
elem: any
|
|
||||||
elem.data = (arg.data as int + i*info.elem_size) as rawptr
|
|
||||||
elem.type_info = info.elem
|
|
||||||
print_any_to_buffer(buf, elem)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Slice:
|
|
||||||
slice := arg.data as ^[]byte
|
|
||||||
print_string_to_buffer(buf, "[")
|
|
||||||
defer print_string_to_buffer(buf, "]")
|
|
||||||
|
|
||||||
for i := 0; i < slice.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
elem: any
|
|
||||||
elem.data = ptr_offset(slice.data, i*info.elem_size)
|
|
||||||
elem.type_info = info.elem
|
|
||||||
print_any_to_buffer(buf, elem)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Vector:
|
|
||||||
print_string_to_buffer(buf, "<")
|
|
||||||
defer print_string_to_buffer(buf, ">")
|
|
||||||
|
|
||||||
for i := 0; i < info.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
elem: any
|
|
||||||
elem.data = ptr_offset(arg.data as ^byte, i*info.elem_size)
|
|
||||||
elem.type_info = info.elem
|
|
||||||
print_any_to_buffer(buf, elem)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case Struct:
|
|
||||||
print_string_to_buffer(buf, "struct")
|
|
||||||
print_string_to_buffer(buf, "{")
|
|
||||||
defer print_string_to_buffer(buf, "}")
|
|
||||||
|
|
||||||
for i := 0; i < info.fields.count; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
print_string_to_buffer(buf, ", ")
|
|
||||||
}
|
|
||||||
print_any_to_buffer(buf, info.fields[i].name)
|
|
||||||
print_string_to_buffer(buf, " = ")
|
|
||||||
a: any
|
|
||||||
a.data = ptr_offset(arg.data as ^byte, info.fields[i].offset)
|
|
||||||
a.type_info = info.fields[i].type_info
|
|
||||||
print_any_to_buffer(buf, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
case Union:
|
|
||||||
print_string_to_buffer(buf, "(union)")
|
|
||||||
case Raw_Union:
|
|
||||||
print_string_to_buffer(buf, "(raw_union)")
|
|
||||||
case Procedure:
|
|
||||||
print_type_to_buffer(buf, arg.type_info)
|
|
||||||
print_string_to_buffer(buf, " @ 0x")
|
|
||||||
print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
|
||||||
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type_info_is_string :: proc(info: ^Type_Info) -> bool {
|
|
||||||
using Type_Info
|
|
||||||
if info == null {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
match type i : info {
|
|
||||||
case Named:
|
|
||||||
info = i.base
|
|
||||||
continue
|
|
||||||
case String:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 < s.count; offset++ {
|
|
||||||
c := s[offset] as rune
|
|
||||||
if !is_digit(c) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
result *= 10
|
|
||||||
result += (c - #rune "0") as int
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, offset
|
|
||||||
}
|
|
||||||
|
|
||||||
prev := 0
|
|
||||||
implicit_index := 0
|
|
||||||
|
|
||||||
for i := 0; i < fmt.count; i++ {
|
|
||||||
r := fmt[i] as rune
|
|
||||||
index := implicit_index
|
|
||||||
|
|
||||||
if r != #rune "%" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
print_string_to_buffer(buf, fmt[prev:i])
|
|
||||||
i++ // Skip %
|
|
||||||
if i < fmt.count {
|
|
||||||
next := fmt[i] as rune
|
|
||||||
|
|
||||||
if next == #rune "%" {
|
|
||||||
print_string_to_buffer(buf, "%")
|
|
||||||
i++
|
|
||||||
prev = i
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_digit(next) {
|
|
||||||
index, i = parse_int(fmt, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if 0 <= index && index < args.count {
|
|
||||||
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_to_file :: proc(f: ^os.File, fmt: string, args: ..any) {
|
|
||||||
data: [PRINT_BUF_SIZE]byte
|
|
||||||
buf := data[:0]
|
|
||||||
print_to_buffer(^buf, fmt, ..args)
|
|
||||||
os.write(f, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
println_to_file :: proc(f: ^os.File, fmt: string, args: ..any) {
|
|
||||||
data: [PRINT_BUF_SIZE]byte
|
|
||||||
buf := data[:0]
|
|
||||||
print_to_buffer(^buf, fmt, ..args)
|
|
||||||
print_nl_to_buffer(^buf)
|
|
||||||
os.write(f, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
print :: proc(fmt: string, args: ..any) {
|
|
||||||
print_to_file(os.get_standard_file(os.File_Standard.OUTPUT), fmt, ..args)
|
|
||||||
}
|
|
||||||
print_err :: proc(fmt: string, args: ..any) {
|
|
||||||
print_to_file(os.get_standard_file(os.File_Standard.ERROR), fmt, ..args)
|
|
||||||
}
|
|
||||||
println :: proc(fmt: string, args: ..any) {
|
|
||||||
println_to_file(os.get_standard_file(os.File_Standard.OUTPUT), fmt, ..args)
|
|
||||||
}
|
|
||||||
println_err :: proc(fmt: string, args: ..any) {
|
|
||||||
println_to_file(os.get_standard_file(os.File_Standard.ERROR), fmt, ..args)
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#foreign_system_library "opengl32"
|
|
||||||
|
|
||||||
ZERO :: 0x0000
|
|
||||||
ONE :: 0x0001
|
|
||||||
TRIANGLES :: 0x0004
|
|
||||||
BLEND :: 0x0be2
|
|
||||||
SRC_ALPHA :: 0x0302
|
|
||||||
ONE_MINUS_SRC_ALPHA :: 0x0303
|
|
||||||
TEXTURE_2D :: 0x0de1
|
|
||||||
RGBA8 :: 0x8058
|
|
||||||
UNSIGNED_BYTE :: 0x1401
|
|
||||||
BGRA_EXT :: 0x80e1
|
|
||||||
TEXTURE_MAX_LEVEL :: 0x813d
|
|
||||||
RGBA :: 0x1908
|
|
||||||
|
|
||||||
NEAREST :: 0x2600
|
|
||||||
LINEAR :: 0x2601
|
|
||||||
|
|
||||||
DEPTH_BUFFER_BIT :: 0x00000100
|
|
||||||
STENCIL_BUFFER_BIT :: 0x00000400
|
|
||||||
COLOR_BUFFER_BIT :: 0x00004000
|
|
||||||
|
|
||||||
TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
|
|
||||||
|
|
||||||
TEXTURE_MAG_FILTER :: 0x2800
|
|
||||||
TEXTURE_MIN_FILTER :: 0x2801
|
|
||||||
TEXTURE_WRAP_S :: 0x2802
|
|
||||||
TEXTURE_WRAP_T :: 0x2803
|
|
||||||
|
|
||||||
Clear :: proc(mask: u32) #foreign "glClear"
|
|
||||||
ClearColor :: proc(r, g, b, a: f32) #foreign "glClearColor"
|
|
||||||
Begin :: proc(mode: i32) #foreign "glBegin"
|
|
||||||
End :: proc() #foreign "glEnd"
|
|
||||||
Color3f :: proc(r, g, b: f32) #foreign "glColor3f"
|
|
||||||
Color4f :: proc(r, g, b, a: f32) #foreign "glColor4f"
|
|
||||||
Vertex2f :: proc(x, y: f32) #foreign "glVertex2f"
|
|
||||||
Vertex3f :: proc(x, y, z: f32) #foreign "glVertex3f"
|
|
||||||
TexCoord2f :: proc(u, v: f32) #foreign "glTexCoord2f"
|
|
||||||
LoadIdentity :: proc() #foreign "glLoadIdentity"
|
|
||||||
Ortho :: proc(left, right, bottom, top, near, far: f64) #foreign "glOrtho"
|
|
||||||
BlendFunc :: proc(sfactor, dfactor: i32) #foreign "glBlendFunc"
|
|
||||||
Enable :: proc(cap: i32) #foreign "glEnable"
|
|
||||||
Disable :: proc(cap: i32) #foreign "glDisable"
|
|
||||||
GenTextures :: proc(count: i32, result: ^u32) #foreign "glGenTextures"
|
|
||||||
TexParameteri :: proc(target, pname, param: i32) #foreign "glTexParameteri"
|
|
||||||
TexParameterf :: proc(target: i32, pname: i32, param: f32) #foreign "glTexParameterf"
|
|
||||||
BindTexture :: proc(target: i32, texture: u32) #foreign "glBindTexture"
|
|
||||||
TexImage2D :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign "glTexImage2D"
|
|
||||||
|
|
||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
#import "runtime.odin" as _ // TODO(bill): make the compile import this automatically
|
|
||||||
#import "win32.odin" as win32
|
|
||||||
|
|
||||||
File :: type struct {
|
|
||||||
Handle :: type win32.HANDLE
|
|
||||||
handle: Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
open :: proc(name: string) -> (File, bool) {
|
|
||||||
using win32
|
|
||||||
buf: [300]byte
|
|
||||||
copy(buf[:], name as []byte)
|
|
||||||
f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, 0, null)}
|
|
||||||
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
|
|
||||||
|
|
||||||
return f, success
|
|
||||||
}
|
|
||||||
|
|
||||||
create :: proc(name: string) -> (File, bool) {
|
|
||||||
using win32
|
|
||||||
buf: [300]byte
|
|
||||||
copy(buf[:], name as []byte)
|
|
||||||
f := File{
|
|
||||||
handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, null, CREATE_ALWAYS, 0, null),
|
|
||||||
}
|
|
||||||
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
|
|
||||||
return f, success
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
close :: proc(using f: ^File) {
|
|
||||||
win32.CloseHandle(handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
write :: proc(using f: ^File, buf: []byte) -> bool {
|
|
||||||
bytes_written: i32
|
|
||||||
return win32.WriteFile(handle, buf.data, buf.count as i32, ^bytes_written, null) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
File_Standard :: type enum {
|
|
||||||
INPUT,
|
|
||||||
OUTPUT,
|
|
||||||
ERROR,
|
|
||||||
COUNT,
|
|
||||||
}
|
|
||||||
|
|
||||||
__std_files := __set_file_standards();
|
|
||||||
|
|
||||||
__set_file_standards :: proc() -> [File_Standard.COUNT as int]File {
|
|
||||||
return [File_Standard.COUNT as int]File{
|
|
||||||
File{handle = win32.GetStdHandle(win32.STD_INPUT_HANDLE)},
|
|
||||||
File{handle = win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)},
|
|
||||||
File{handle = win32.GetStdHandle(win32.STD_ERROR_HANDLE)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_standard_file :: proc(std: File_Standard) -> ^File {
|
|
||||||
return ^__std_files[std]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
read_entire_file :: proc(name: string) -> (string, bool) {
|
|
||||||
buf: [300]byte
|
|
||||||
copy(buf[:], name as []byte)
|
|
||||||
|
|
||||||
f, file_ok := open(name)
|
|
||||||
if !file_ok {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
defer close(^f)
|
|
||||||
|
|
||||||
length: i64
|
|
||||||
file_size_ok := win32.GetFileSizeEx(f.handle as win32.HANDLE, ^length) != 0
|
|
||||||
if !file_size_ok {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
data := new_slice(u8, length)
|
|
||||||
if data.data == null {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
single_read_length: i32
|
|
||||||
total_read: i64
|
|
||||||
|
|
||||||
for total_read < length {
|
|
||||||
remaining := length - total_read
|
|
||||||
to_read: u32
|
|
||||||
MAX :: 1<<32-1
|
|
||||||
if remaining <= MAX {
|
|
||||||
to_read = remaining as u32
|
|
||||||
} else {
|
|
||||||
to_read = MAX
|
|
||||||
}
|
|
||||||
|
|
||||||
win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, null)
|
|
||||||
if single_read_length <= 0 {
|
|
||||||
free(data.data)
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
total_read += single_read_length as i64
|
|
||||||
}
|
|
||||||
|
|
||||||
return data as string, true
|
|
||||||
}
|
|
||||||
@@ -1,353 +0,0 @@
|
|||||||
#shared_global_scope
|
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
|
||||||
// The compiler relies upon this _exact_ order
|
|
||||||
Type_Info :: union {
|
|
||||||
Member :: struct #ordered {
|
|
||||||
name: string // can be empty if tuple
|
|
||||||
type_info: ^Type_Info
|
|
||||||
offset: int // offsets are not used in tuples
|
|
||||||
}
|
|
||||||
Record :: struct #ordered {
|
|
||||||
fields: []Member
|
|
||||||
packed: bool
|
|
||||||
ordered: bool
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Named: struct #ordered {
|
|
||||||
name: string
|
|
||||||
base: ^Type_Info
|
|
||||||
}
|
|
||||||
Integer: struct #ordered {
|
|
||||||
size: int // in bytes
|
|
||||||
signed: bool
|
|
||||||
}
|
|
||||||
Float: struct #ordered {
|
|
||||||
size: int // in bytes
|
|
||||||
}
|
|
||||||
String: struct #ordered {}
|
|
||||||
Boolean: struct #ordered {}
|
|
||||||
Pointer: struct #ordered {
|
|
||||||
elem: ^Type_Info
|
|
||||||
}
|
|
||||||
Procedure: struct #ordered {
|
|
||||||
params: ^Type_Info // Type_Info.Tuple
|
|
||||||
results: ^Type_Info // Type_Info.Tuple
|
|
||||||
variadic: bool
|
|
||||||
}
|
|
||||||
Array: struct #ordered {
|
|
||||||
elem: ^Type_Info
|
|
||||||
elem_size: int
|
|
||||||
count: int
|
|
||||||
}
|
|
||||||
Slice: struct #ordered {
|
|
||||||
elem: ^Type_Info
|
|
||||||
elem_size: int
|
|
||||||
}
|
|
||||||
Vector: struct #ordered {
|
|
||||||
elem: ^Type_Info
|
|
||||||
elem_size: int
|
|
||||||
count: int
|
|
||||||
}
|
|
||||||
Tuple: Record
|
|
||||||
Struct: Record
|
|
||||||
Union: Record
|
|
||||||
Raw_Union: Record
|
|
||||||
Enum: struct #ordered {
|
|
||||||
base: ^Type_Info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assume :: proc(cond: bool) #foreign "llvm.assume"
|
|
||||||
|
|
||||||
__debug_trap :: proc() #foreign "llvm.debugtrap"
|
|
||||||
__trap :: proc() #foreign "llvm.trap"
|
|
||||||
read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter"
|
|
||||||
|
|
||||||
bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16"
|
|
||||||
bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32"
|
|
||||||
bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64"
|
|
||||||
|
|
||||||
byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16"
|
|
||||||
byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32"
|
|
||||||
byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64"
|
|
||||||
|
|
||||||
fmuladd32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
|
|
||||||
fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
|
|
||||||
|
|
||||||
heap_alloc :: proc(len: int) -> rawptr {
|
|
||||||
c_malloc :: proc(len: int) -> rawptr #foreign "malloc"
|
|
||||||
return c_malloc(len)
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_free :: proc(ptr: rawptr) {
|
|
||||||
c_free :: proc(ptr: rawptr) #foreign "free"
|
|
||||||
c_free(ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
current_thread_id :: proc() -> int {
|
|
||||||
GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
|
|
||||||
return GetCurrentThreadId() as int
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_zero :: proc(data: rawptr, len: int) {
|
|
||||||
llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign "llvm.memset.p0i8.i64"
|
|
||||||
llvm_memset_64bit(data, 0, len, 1, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_compare :: proc(dst, src: rawptr, len: int) -> int {
|
|
||||||
// TODO(bill): make a faster `memory_compare`
|
|
||||||
a := slice_ptr(dst as ^byte, len)
|
|
||||||
b := slice_ptr(src as ^byte, len)
|
|
||||||
for i := 0; i < len; i++ {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
return (a[i] - b[i]) as int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_copy :: proc(dst, src: rawptr, len: int) #inline {
|
|
||||||
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
|
|
||||||
llvm_memmove_64bit(dst, src, len, 1, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
__string_eq :: proc(a, b: string) -> bool {
|
|
||||||
if a.count != b.count {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if ^a[0] == ^b[0] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return memory_compare(^a[0], ^b[0], a.count) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
__string_cmp :: proc(a, b : string) -> int {
|
|
||||||
// Translation of http://mgronhol.github.io/fast-strcmp/
|
|
||||||
n := min(a.count, b.count)
|
|
||||||
|
|
||||||
fast := n/size_of(int) + 1
|
|
||||||
offset := (fast-1)*size_of(int)
|
|
||||||
curr_block := 0
|
|
||||||
if n <= size_of(int) {
|
|
||||||
fast = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
la := slice_ptr(^a[0] as ^int, fast)
|
|
||||||
lb := slice_ptr(^b[0] as ^int, fast)
|
|
||||||
|
|
||||||
for ; curr_block < fast; curr_block++ {
|
|
||||||
if (la[curr_block] ~ lb[curr_block]) != 0 {
|
|
||||||
for pos := curr_block*size_of(int); pos < n; pos++ {
|
|
||||||
if (a[pos] ~ b[pos]) != 0 {
|
|
||||||
return a[pos] as int - b[pos] as int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; offset < n; offset++ {
|
|
||||||
if (a[offset] ~ b[offset]) != 0 {
|
|
||||||
return a[offset] as int - b[offset] as int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
__string_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) }
|
|
||||||
__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 }
|
|
||||||
__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 }
|
|
||||||
__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
|
|
||||||
__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
|
|
||||||
|
|
||||||
__print_err_str :: proc(s: string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
__print_err_int :: proc(i: int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__assert :: proc(msg: string) {
|
|
||||||
// TODO(bill): Write message
|
|
||||||
__print_err_str(msg)
|
|
||||||
__debug_trap()
|
|
||||||
}
|
|
||||||
|
|
||||||
__bounds_check_error :: proc(file: string, line, column: int,
|
|
||||||
index, count: int) {
|
|
||||||
if 0 <= index && index < count {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO(bill): Write message
|
|
||||||
// TODO(bill): Probably reduce the need for `print` in the runtime if possible
|
|
||||||
// fmt.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) {
|
|
||||||
if 0 <= low && low <= high && high <= max {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO(bill): Write message
|
|
||||||
// fmt.println_err("%(%:%) Invalid slice indices: [%:%:%]",
|
|
||||||
// file, line, column, low, high, max)
|
|
||||||
__debug_trap()
|
|
||||||
}
|
|
||||||
__substring_expr_error :: proc(file: string, line, column: int,
|
|
||||||
low, high: int) {
|
|
||||||
if 0 <= low && low <= high {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO(bill): Write message
|
|
||||||
// fmt.println_err("%(%:%) Invalid substring indices: [%:%:%]",
|
|
||||||
// file, line, column, low, high)
|
|
||||||
__debug_trap()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Allocator :: struct {
|
|
||||||
Mode :: enum {
|
|
||||||
ALLOC,
|
|
||||||
FREE,
|
|
||||||
FREE_ALL,
|
|
||||||
RESIZE,
|
|
||||||
}
|
|
||||||
Proc :: type proc(allocator_data: rawptr, mode: Mode,
|
|
||||||
size, alignment: int,
|
|
||||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr
|
|
||||||
|
|
||||||
|
|
||||||
procedure: Proc;
|
|
||||||
data: rawptr
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Context :: struct {
|
|
||||||
thread_id: int
|
|
||||||
|
|
||||||
allocator: Allocator
|
|
||||||
|
|
||||||
user_data: rawptr
|
|
||||||
user_index: int
|
|
||||||
}
|
|
||||||
|
|
||||||
#thread_local __context: Context
|
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_ALIGNMENT :: align_of({4}f32)
|
|
||||||
|
|
||||||
|
|
||||||
current_context :: proc() -> ^Context {
|
|
||||||
return ^__context
|
|
||||||
}
|
|
||||||
|
|
||||||
__check_context :: proc() {
|
|
||||||
c := current_context()
|
|
||||||
assert(c != null)
|
|
||||||
|
|
||||||
if c.allocator.procedure == null {
|
|
||||||
c.allocator = __default_allocator()
|
|
||||||
}
|
|
||||||
if c.thread_id == 0 {
|
|
||||||
c.thread_id = current_thread_id()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT) }
|
|
||||||
|
|
||||||
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
|
|
||||||
__check_context()
|
|
||||||
a := current_context().allocator
|
|
||||||
return a.procedure(a.data, Allocator.Mode.ALLOC, size, alignment, null, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
free :: proc(ptr: rawptr) #inline {
|
|
||||||
__check_context()
|
|
||||||
a := current_context().allocator
|
|
||||||
_ = a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
|
|
||||||
}
|
|
||||||
free_all :: proc() #inline {
|
|
||||||
__check_context()
|
|
||||||
a := current_context().allocator
|
|
||||||
_ = a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT) }
|
|
||||||
resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
|
|
||||||
a := current_context().allocator
|
|
||||||
return a.procedure(a.data, Allocator.Mode.RESIZE, new_size, alignment, ptr, old_size, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
|
||||||
if old_memory == null {
|
|
||||||
return alloc_align(new_size, alignment)
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_size == 0 {
|
|
||||||
free(old_memory)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_size == old_size {
|
|
||||||
return old_memory
|
|
||||||
}
|
|
||||||
|
|
||||||
new_memory := alloc_align(new_size, alignment)
|
|
||||||
if new_memory == null {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_copy(new_memory, old_memory, min(old_size, new_size));
|
|
||||||
free(old_memory)
|
|
||||||
return new_memory
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
|
||||||
size, alignment: int,
|
|
||||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
|
||||||
using Allocator.Mode
|
|
||||||
match mode {
|
|
||||||
case ALLOC:
|
|
||||||
return heap_alloc(size)
|
|
||||||
case RESIZE:
|
|
||||||
return default_resize_align(old_memory, old_size, size, alignment)
|
|
||||||
case FREE:
|
|
||||||
heap_free(old_memory)
|
|
||||||
return null
|
|
||||||
case FREE_ALL:
|
|
||||||
// NOTE(bill): Does nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
__default_allocator :: proc() -> Allocator {
|
|
||||||
return Allocator{
|
|
||||||
procedure = __default_allocator_proc,
|
|
||||||
data = null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-451
@@ -1,451 +0,0 @@
|
|||||||
#foreign_system_library "user32"
|
|
||||||
#foreign_system_library "gdi32"
|
|
||||||
|
|
||||||
HANDLE :: type rawptr
|
|
||||||
HWND :: type HANDLE
|
|
||||||
HDC :: type HANDLE
|
|
||||||
HINSTANCE :: type HANDLE
|
|
||||||
HICON :: type HANDLE
|
|
||||||
HCURSOR :: type HANDLE
|
|
||||||
HMENU :: type HANDLE
|
|
||||||
HBRUSH :: type HANDLE
|
|
||||||
HGDIOBJ :: type HANDLE
|
|
||||||
WPARAM :: type uint
|
|
||||||
LPARAM :: type int
|
|
||||||
LRESULT :: type int
|
|
||||||
ATOM :: type i16
|
|
||||||
BOOL :: type i32
|
|
||||||
WNDPROC :: type proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT
|
|
||||||
|
|
||||||
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE
|
|
||||||
|
|
||||||
CS_VREDRAW :: 0x0001
|
|
||||||
CS_HREDRAW :: 0x0002
|
|
||||||
CS_OWNDC :: 0x0020
|
|
||||||
CW_USEDEFAULT :: 0x80000000
|
|
||||||
|
|
||||||
WS_OVERLAPPED :: 0
|
|
||||||
WS_MAXIMIZEBOX :: 0x00010000
|
|
||||||
WS_MINIMIZEBOX :: 0x00020000
|
|
||||||
WS_THICKFRAME :: 0x00040000
|
|
||||||
WS_SYSMENU :: 0x00080000
|
|
||||||
WS_CAPTION :: 0x00C00000
|
|
||||||
WS_VISIBLE :: 0x10000000
|
|
||||||
WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
|
|
||||||
|
|
||||||
WM_DESTROY :: 0x0002
|
|
||||||
WM_CLOSE :: 0x0010
|
|
||||||
WM_QUIT :: 0x0012
|
|
||||||
WM_KEYDOWN :: 0x0100
|
|
||||||
WM_KEYUP :: 0x0101
|
|
||||||
|
|
||||||
PM_REMOVE :: 1
|
|
||||||
|
|
||||||
COLOR_BACKGROUND :: 1 as HBRUSH
|
|
||||||
BLACK_BRUSH :: 4
|
|
||||||
|
|
||||||
SM_CXSCREEN :: 0
|
|
||||||
SM_CYSCREEN :: 1
|
|
||||||
|
|
||||||
SW_SHOW :: 5
|
|
||||||
|
|
||||||
POINT :: struct #ordered {
|
|
||||||
x, y: i32
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WNDCLASSEXA :: struct #ordered {
|
|
||||||
size, style: u32
|
|
||||||
wnd_proc: WNDPROC
|
|
||||||
cls_extra, wnd_extra: i32
|
|
||||||
instance: HINSTANCE
|
|
||||||
icon: HICON
|
|
||||||
cursor: HCURSOR
|
|
||||||
background: HBRUSH
|
|
||||||
menu_name, class_name: ^u8
|
|
||||||
sm: HICON
|
|
||||||
}
|
|
||||||
|
|
||||||
MSG :: struct #ordered {
|
|
||||||
hwnd: HWND
|
|
||||||
message: u32
|
|
||||||
wparam: WPARAM
|
|
||||||
lparam: LPARAM
|
|
||||||
time: u32
|
|
||||||
pt: POINT
|
|
||||||
}
|
|
||||||
|
|
||||||
RECT :: struct #ordered {
|
|
||||||
left: i32
|
|
||||||
top: i32
|
|
||||||
right: i32
|
|
||||||
bottom: i32
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GetLastError :: proc() -> i32 #foreign #dll_import
|
|
||||||
ExitProcess :: proc(exit_code: u32) #foreign #dll_import
|
|
||||||
GetDesktopWindow :: proc() -> HWND #foreign #dll_import
|
|
||||||
GetCursorPos :: proc(p: ^POINT) -> i32 #foreign #dll_import
|
|
||||||
ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign #dll_import
|
|
||||||
GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign #dll_import
|
|
||||||
GetStockObject :: proc(fn_object: i32) -> HGDIOBJ #foreign #dll_import
|
|
||||||
PostQuitMessage :: proc(exit_code: i32) #foreign #dll_import
|
|
||||||
SetWindowTextA :: proc(hwnd: HWND, c_string: ^u8) -> BOOL #foreign #dll_import
|
|
||||||
|
|
||||||
QueryPerformanceFrequency :: proc(result: ^i64) -> i32 #foreign #dll_import
|
|
||||||
QueryPerformanceCounter :: proc(result: ^i64) -> i32 #foreign #dll_import
|
|
||||||
|
|
||||||
Sleep :: proc(ms: i32) -> i32 #foreign #dll_import
|
|
||||||
|
|
||||||
OutputDebugStringA :: proc(c_str: ^u8) #foreign #dll_import
|
|
||||||
|
|
||||||
|
|
||||||
RegisterClassExA :: proc(wc: ^WNDCLASSEXA) -> ATOM #foreign #dll_import
|
|
||||||
CreateWindowExA :: proc(ex_style: u32,
|
|
||||||
class_name, title: ^u8,
|
|
||||||
style: u32,
|
|
||||||
x, y, w, h: i32,
|
|
||||||
parent: HWND, menu: HMENU, instance: HINSTANCE,
|
|
||||||
param: rawptr) -> HWND #foreign #dll_import
|
|
||||||
|
|
||||||
ShowWindow :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign #dll_import
|
|
||||||
TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign #dll_import
|
|
||||||
DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign #dll_import
|
|
||||||
UpdateWindow :: proc(hwnd: HWND) -> BOOL #foreign #dll_import
|
|
||||||
PeekMessageA :: proc(msg: ^MSG, hwnd: HWND,
|
|
||||||
msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign #dll_import
|
|
||||||
|
|
||||||
DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign #dll_import
|
|
||||||
|
|
||||||
AdjustWindowRect :: proc(rect: ^RECT, style: u32, menu: BOOL) -> BOOL #foreign #dll_import
|
|
||||||
|
|
||||||
|
|
||||||
GetQueryPerformanceFrequency :: proc() -> i64 {
|
|
||||||
r: i64
|
|
||||||
QueryPerformanceFrequency(^r)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
GetCommandLineA :: proc() -> ^u8 #foreign #dll_import
|
|
||||||
GetSystemMetrics :: proc(index: i32) -> i32 #foreign #dll_import
|
|
||||||
GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
|
|
||||||
|
|
||||||
// File Stuff
|
|
||||||
|
|
||||||
CloseHandle :: proc(h: HANDLE) -> i32 #foreign #dll_import
|
|
||||||
GetStdHandle :: proc(h: i32) -> HANDLE #foreign #dll_import
|
|
||||||
CreateFileA :: proc(filename: ^u8, desired_access, share_mode: u32,
|
|
||||||
security: rawptr,
|
|
||||||
creation, flags_and_attribs: u32, template_file: HANDLE) -> HANDLE #foreign #dll_import
|
|
||||||
ReadFile :: proc(h: HANDLE, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> BOOL #foreign #dll_import
|
|
||||||
WriteFile :: proc(h: HANDLE, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> i32 #foreign #dll_import
|
|
||||||
|
|
||||||
GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^i64) -> BOOL #foreign #dll_import
|
|
||||||
|
|
||||||
FILE_SHARE_READ :: 0x00000001
|
|
||||||
FILE_SHARE_WRITE :: 0x00000002
|
|
||||||
FILE_SHARE_DELETE :: 0x00000004
|
|
||||||
FILE_GENERIC_ALL :: 0x10000000
|
|
||||||
FILE_GENERIC_EXECUTE :: 0x20000000
|
|
||||||
FILE_GENERIC_WRITE :: 0x40000000
|
|
||||||
FILE_GENERIC_READ :: 0x80000000
|
|
||||||
|
|
||||||
STD_INPUT_HANDLE :: -10
|
|
||||||
STD_OUTPUT_HANDLE :: -11
|
|
||||||
STD_ERROR_HANDLE :: -12
|
|
||||||
|
|
||||||
CREATE_NEW :: 1
|
|
||||||
CREATE_ALWAYS :: 2
|
|
||||||
OPEN_EXISTING :: 3
|
|
||||||
OPEN_ALWAYS :: 4
|
|
||||||
TRUNCATE_EXISTING :: 5
|
|
||||||
|
|
||||||
|
|
||||||
HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign #dll_import
|
|
||||||
HeapFree :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign #dll_import
|
|
||||||
GetProcessHeap :: proc() -> HANDLE #foreign #dll_import
|
|
||||||
|
|
||||||
|
|
||||||
HEAP_ZERO_MEMORY :: 0x00000008
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// GDI
|
|
||||||
|
|
||||||
BITMAPINFO :: struct #ordered {
|
|
||||||
HEADER :: struct #ordered {
|
|
||||||
size: u32
|
|
||||||
width, height: i32
|
|
||||||
planes, bit_count: i16
|
|
||||||
compression: u32
|
|
||||||
size_image: u32
|
|
||||||
x_pels_per_meter: i32
|
|
||||||
y_pels_per_meter: i32
|
|
||||||
clr_used: u32
|
|
||||||
clr_important: u32
|
|
||||||
}
|
|
||||||
using header: HEADER
|
|
||||||
colors: [1]RGBQUAD
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RGBQUAD :: struct #ordered {
|
|
||||||
blue, green, red, reserved: byte
|
|
||||||
}
|
|
||||||
|
|
||||||
BI_RGB :: 0
|
|
||||||
DIB_RGB_COLORS :: 0x00
|
|
||||||
SRCCOPY : u32 : 0x00cc0020
|
|
||||||
|
|
||||||
StretchDIBits :: proc(hdc: HDC,
|
|
||||||
x_dst, y_dst, width_dst, height_dst: i32,
|
|
||||||
x_src, y_src, width_src, header_src: i32,
|
|
||||||
bits: rawptr, bits_info: ^BITMAPINFO,
|
|
||||||
usage: u32,
|
|
||||||
rop: u32) -> i32 #foreign #dll_import
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Windows OpenGL
|
|
||||||
|
|
||||||
PFD_TYPE_RGBA :: 0
|
|
||||||
PFD_TYPE_COLORINDEX :: 1
|
|
||||||
PFD_MAIN_PLANE :: 0
|
|
||||||
PFD_OVERLAY_PLANE :: 1
|
|
||||||
PFD_UNDERLAY_PLANE :: -1
|
|
||||||
PFD_DOUBLEBUFFER :: 1
|
|
||||||
PFD_STEREO :: 2
|
|
||||||
PFD_DRAW_TO_WINDOW :: 4
|
|
||||||
PFD_DRAW_TO_BITMAP :: 8
|
|
||||||
PFD_SUPPORT_GDI :: 16
|
|
||||||
PFD_SUPPORT_OPENGL :: 32
|
|
||||||
PFD_GENERIC_FORMAT :: 64
|
|
||||||
PFD_NEED_PALETTE :: 128
|
|
||||||
PFD_NEED_SYSTEM_PALETTE :: 0x00000100
|
|
||||||
PFD_SWAP_EXCHANGE :: 0x00000200
|
|
||||||
PFD_SWAP_COPY :: 0x00000400
|
|
||||||
PFD_SWAP_LAYER_BUFFERS :: 0x00000800
|
|
||||||
PFD_GENERIC_ACCELERATED :: 0x00001000
|
|
||||||
PFD_DEPTH_DONTCARE :: 0x20000000
|
|
||||||
PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000
|
|
||||||
PFD_STEREO_DONTCARE :: 0x80000000
|
|
||||||
|
|
||||||
HGLRC :: type HANDLE
|
|
||||||
PROC :: type proc()
|
|
||||||
wglCreateContextAttribsARBType :: type proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC
|
|
||||||
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR :: struct #ordered {
|
|
||||||
size,
|
|
||||||
version,
|
|
||||||
flags: u32
|
|
||||||
|
|
||||||
pixel_type,
|
|
||||||
color_bits,
|
|
||||||
red_bits,
|
|
||||||
red_shift,
|
|
||||||
green_bits,
|
|
||||||
green_shift,
|
|
||||||
blue_bits,
|
|
||||||
blue_shift,
|
|
||||||
alpha_bits,
|
|
||||||
alpha_shift,
|
|
||||||
accum_bits,
|
|
||||||
accum_red_bits,
|
|
||||||
accum_green_bits,
|
|
||||||
accum_blue_bits,
|
|
||||||
accum_alpha_bits,
|
|
||||||
depth_bits,
|
|
||||||
stencil_bits,
|
|
||||||
aux_buffers,
|
|
||||||
layer_type,
|
|
||||||
reserved: byte
|
|
||||||
|
|
||||||
layer_mask,
|
|
||||||
visible_mask,
|
|
||||||
damage_mask: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
GetDC :: proc(h: HANDLE) -> HDC #foreign
|
|
||||||
SetPixelFormat :: proc(hdc: HDC, pixel_format: i32, pfd: ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import
|
|
||||||
ChoosePixelFormat :: proc(hdc: HDC, pfd: ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import
|
|
||||||
SwapBuffers :: proc(hdc: HDC) -> BOOL #foreign #dll_import
|
|
||||||
ReleaseDC :: proc(wnd: HWND, hdc: HDC) -> i32 #foreign #dll_import
|
|
||||||
|
|
||||||
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091
|
|
||||||
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092
|
|
||||||
WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126
|
|
||||||
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002
|
|
||||||
|
|
||||||
wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign #dll_import
|
|
||||||
wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign #dll_import
|
|
||||||
wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign #dll_import
|
|
||||||
wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign #dll_import
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GetKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
|
|
||||||
GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
|
|
||||||
|
|
||||||
is_key_down :: proc(key: Key_Code) -> bool {
|
|
||||||
return GetAsyncKeyState(key as i32) < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Key_Code :: enum i32 {
|
|
||||||
LBUTTON = 0x01,
|
|
||||||
RBUTTON = 0x02,
|
|
||||||
CANCEL = 0x03,
|
|
||||||
MBUTTON = 0x04,
|
|
||||||
|
|
||||||
BACK = 0x08,
|
|
||||||
TAB = 0x09,
|
|
||||||
|
|
||||||
CLEAR = 0x0C,
|
|
||||||
RETURN = 0x0D,
|
|
||||||
|
|
||||||
SHIFT = 0x10,
|
|
||||||
CONTROL = 0x11,
|
|
||||||
MENU = 0x12,
|
|
||||||
PAUSE = 0x13,
|
|
||||||
CAPITAL = 0x14,
|
|
||||||
|
|
||||||
KANA = 0x15,
|
|
||||||
HANGEUL = 0x15,
|
|
||||||
HANGUL = 0x15,
|
|
||||||
JUNJA = 0x17,
|
|
||||||
FINAL = 0x18,
|
|
||||||
HANJA = 0x19,
|
|
||||||
KANJI = 0x19,
|
|
||||||
|
|
||||||
ESCAPE = 0x1B,
|
|
||||||
|
|
||||||
CONVERT = 0x1C,
|
|
||||||
NONCONVERT = 0x1D,
|
|
||||||
ACCEPT = 0x1E,
|
|
||||||
MODECHANGE = 0x1F,
|
|
||||||
|
|
||||||
SPACE = 0x20,
|
|
||||||
PRIOR = 0x21,
|
|
||||||
NEXT = 0x22,
|
|
||||||
END = 0x23,
|
|
||||||
HOME = 0x24,
|
|
||||||
LEFT = 0x25,
|
|
||||||
UP = 0x26,
|
|
||||||
RIGHT = 0x27,
|
|
||||||
DOWN = 0x28,
|
|
||||||
SELECT = 0x29,
|
|
||||||
PRINT = 0x2A,
|
|
||||||
EXECUTE = 0x2B,
|
|
||||||
SNAPSHOT = 0x2C,
|
|
||||||
INSERT = 0x2D,
|
|
||||||
DELETE = 0x2E,
|
|
||||||
HELP = 0x2F,
|
|
||||||
|
|
||||||
NUM0 = #rune "0",
|
|
||||||
NUM1 = #rune "1",
|
|
||||||
NUM2 = #rune "2",
|
|
||||||
NUM3 = #rune "3",
|
|
||||||
NUM4 = #rune "4",
|
|
||||||
NUM5 = #rune "5",
|
|
||||||
NUM6 = #rune "6",
|
|
||||||
NUM7 = #rune "7",
|
|
||||||
NUM8 = #rune "8",
|
|
||||||
NUM9 = #rune "9",
|
|
||||||
|
|
||||||
A = #rune "A",
|
|
||||||
B = #rune "B",
|
|
||||||
C = #rune "C",
|
|
||||||
D = #rune "D",
|
|
||||||
E = #rune "E",
|
|
||||||
F = #rune "F",
|
|
||||||
G = #rune "G",
|
|
||||||
H = #rune "H",
|
|
||||||
I = #rune "I",
|
|
||||||
J = #rune "J",
|
|
||||||
K = #rune "K",
|
|
||||||
L = #rune "L",
|
|
||||||
M = #rune "M",
|
|
||||||
N = #rune "N",
|
|
||||||
O = #rune "O",
|
|
||||||
P = #rune "P",
|
|
||||||
Q = #rune "Q",
|
|
||||||
R = #rune "R",
|
|
||||||
S = #rune "S",
|
|
||||||
T = #rune "T",
|
|
||||||
U = #rune "U",
|
|
||||||
V = #rune "V",
|
|
||||||
W = #rune "W",
|
|
||||||
X = #rune "X",
|
|
||||||
Y = #rune "Y",
|
|
||||||
Z = #rune "Z",
|
|
||||||
|
|
||||||
LWIN = 0x5B,
|
|
||||||
RWIN = 0x5C,
|
|
||||||
APPS = 0x5D,
|
|
||||||
|
|
||||||
NUMPAD0 = 0x60,
|
|
||||||
NUMPAD1 = 0x61,
|
|
||||||
NUMPAD2 = 0x62,
|
|
||||||
NUMPAD3 = 0x63,
|
|
||||||
NUMPAD4 = 0x64,
|
|
||||||
NUMPAD5 = 0x65,
|
|
||||||
NUMPAD6 = 0x66,
|
|
||||||
NUMPAD7 = 0x67,
|
|
||||||
NUMPAD8 = 0x68,
|
|
||||||
NUMPAD9 = 0x69,
|
|
||||||
MULTIPLY = 0x6A,
|
|
||||||
ADD = 0x6B,
|
|
||||||
SEPARATOR = 0x6C,
|
|
||||||
SUBTRACT = 0x6D,
|
|
||||||
DECIMAL = 0x6E,
|
|
||||||
DIVIDE = 0x6F,
|
|
||||||
F1 = 0x70,
|
|
||||||
F2 = 0x71,
|
|
||||||
F3 = 0x72,
|
|
||||||
F4 = 0x73,
|
|
||||||
F5 = 0x74,
|
|
||||||
F6 = 0x75,
|
|
||||||
F7 = 0x76,
|
|
||||||
F8 = 0x77,
|
|
||||||
F9 = 0x78,
|
|
||||||
F10 = 0x79,
|
|
||||||
F11 = 0x7A,
|
|
||||||
F12 = 0x7B,
|
|
||||||
F13 = 0x7C,
|
|
||||||
F14 = 0x7D,
|
|
||||||
F15 = 0x7E,
|
|
||||||
F16 = 0x7F,
|
|
||||||
F17 = 0x80,
|
|
||||||
F18 = 0x81,
|
|
||||||
F19 = 0x82,
|
|
||||||
F20 = 0x83,
|
|
||||||
F21 = 0x84,
|
|
||||||
F22 = 0x85,
|
|
||||||
F23 = 0x86,
|
|
||||||
F24 = 0x87,
|
|
||||||
|
|
||||||
NUMLOCK = 0x90,
|
|
||||||
SCROLL = 0x91,
|
|
||||||
|
|
||||||
LSHIFT = 0xA0,
|
|
||||||
RSHIFT = 0xA1,
|
|
||||||
LCONTROL = 0xA2,
|
|
||||||
RCONTROL = 0xA3,
|
|
||||||
LMENU = 0xA4,
|
|
||||||
RMENU = 0xA5,
|
|
||||||
PROCESSKEY = 0xE5,
|
|
||||||
ATTN = 0xF6,
|
|
||||||
CRSEL = 0xF7,
|
|
||||||
EXSEL = 0xF8,
|
|
||||||
EREOF = 0xF9,
|
|
||||||
PLAY = 0xFA,
|
|
||||||
ZOOM = 0xFB,
|
|
||||||
NONAME = 0xFC,
|
|
||||||
PA1 = 0xFD,
|
|
||||||
OEM_CLEAR = 0xFE,
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -840,7 +840,11 @@ void init_type_info_types(Checker *c) {
|
|||||||
if (t_type_info == NULL) {
|
if (t_type_info == NULL) {
|
||||||
String type_info_str = make_string("Type_Info");
|
String type_info_str = make_string("Type_Info");
|
||||||
Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
|
Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
|
||||||
GB_ASSERT_MSG(e != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
|
if (e == NULL) {
|
||||||
|
gb_printf_err("Internal Compiler Error: Could not find type declaration for `Type_Info`\n");
|
||||||
|
gb_printf_err("Is `runtime.odin` missing from the `core` directory?\n");
|
||||||
|
gb_exit(1);
|
||||||
|
}
|
||||||
t_type_info = e->type;
|
t_type_info = e->type;
|
||||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||||
|
|
||||||
@@ -849,7 +853,10 @@ void init_type_info_types(Checker *c) {
|
|||||||
t_type_info_member = record->other_fields[0]->type;
|
t_type_info_member = record->other_fields[0]->type;
|
||||||
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
||||||
|
|
||||||
GB_ASSERT_MSG(record->field_count == 16, "Internal Compiler Error: Invalid `Type_Info` layout");
|
if (record->field_count != 16) {
|
||||||
|
gb_printf_err("Internal Compiler Error: Invalid `Type_Info` layout\n");
|
||||||
|
gb_exit(1);
|
||||||
|
}
|
||||||
t_type_info_named = record->fields[ 1]->type;
|
t_type_info_named = record->fields[ 1]->type;
|
||||||
t_type_info_integer = record->fields[ 2]->type;
|
t_type_info_integer = record->fields[ 2]->type;
|
||||||
t_type_info_float = record->fields[ 3]->type;
|
t_type_info_float = record->fields[ 3]->type;
|
||||||
|
|||||||
+61
-21
@@ -2741,6 +2741,45 @@ b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
|
||||||
|
isize str_len = base_dir.len+path.len;
|
||||||
|
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
||||||
|
defer (gb_free(gb_heap_allocator(), str));
|
||||||
|
|
||||||
|
gb_memcopy(str, base_dir.text, base_dir.len);
|
||||||
|
gb_memcopy(str+base_dir.len, path.text, path.len);
|
||||||
|
str[str_len] = '\0';
|
||||||
|
// HACK(bill): memory leak
|
||||||
|
char *path_str = gb_path_get_full_name(a, cast(char *)str);
|
||||||
|
return make_string(path_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get_fullpath_core(gbAllocator a, String path) {
|
||||||
|
char buf[300] = {};
|
||||||
|
u32 buf_len = GetModuleFileNameA(GetModuleHandleA(NULL), buf, gb_size_of(buf));
|
||||||
|
for (isize i = buf_len-1; i >= 0; i--) {
|
||||||
|
if (buf[i] == '\\' ||
|
||||||
|
buf[i] == '/') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
char core[] = "core/";
|
||||||
|
isize core_len = gb_size_of(core)-1;
|
||||||
|
|
||||||
|
isize str_len = buf_len + core_len + path.len;
|
||||||
|
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
||||||
|
defer (gb_free(gb_heap_allocator(), str));
|
||||||
|
|
||||||
|
gb_memcopy(str, buf, buf_len);
|
||||||
|
gb_memcopy(str+buf_len, core, core_len);
|
||||||
|
gb_memcopy(str+buf_len+core_len, path.text, path.len);
|
||||||
|
str[str_len] = '\0';
|
||||||
|
// HACK(bill): memory leak
|
||||||
|
char *path_str = gb_path_get_full_name(a, cast(char *)str);
|
||||||
|
return make_string(path_str);}
|
||||||
|
|
||||||
// NOTE(bill): Returns true if it's added
|
// NOTE(bill): Returns true if it's added
|
||||||
b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
|
b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
|
||||||
gb_for_array(i, p->system_libraries) {
|
gb_for_array(i, p->system_libraries) {
|
||||||
@@ -2803,6 +2842,7 @@ void parse_file(Parser *p, AstFile *f) {
|
|||||||
}
|
}
|
||||||
base_dir.len--;
|
base_dir.len--;
|
||||||
}
|
}
|
||||||
|
gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator
|
||||||
|
|
||||||
f->decls = parse_stmt_list(f);
|
f->decls = parse_stmt_list(f);
|
||||||
|
|
||||||
@@ -2819,25 +2859,27 @@ void parse_file(Parser *p, AstFile *f) {
|
|||||||
String file_str = id->relpath.string;
|
String file_str = id->relpath.string;
|
||||||
|
|
||||||
if (!is_import_path_valid(file_str)) {
|
if (!is_import_path_valid(file_str)) {
|
||||||
syntax_error(ast_node_token(node), "Invalid `load` path");
|
if (id->is_load) {
|
||||||
|
syntax_error(ast_node_token(node), "Invalid #load path");
|
||||||
|
} else {
|
||||||
|
syntax_error(ast_node_token(node), "Invalid #import path");
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
isize str_len = base_dir.len+file_str.len;
|
String import_file = {};
|
||||||
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
|
||||||
defer (gb_free(gb_heap_allocator(), str));
|
import_file = rel_path;
|
||||||
|
if (!gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
|
||||||
gb_memcopy(str, base_dir.text, base_dir.len);
|
String abs_path = get_fullpath_core(allocator, file_str);
|
||||||
gb_memcopy(str+base_dir.len, file_str.text, file_str.len);
|
if (gb_file_exists(cast(char *)abs_path.text)) {
|
||||||
str[str_len] = '\0';
|
import_file = abs_path;
|
||||||
// HACK(bill): memory leak
|
}
|
||||||
char *path_str = gb_path_get_full_name(gb_heap_allocator(), cast(char *)str);
|
}
|
||||||
String import_file = make_string(path_str);
|
|
||||||
|
|
||||||
id->fullpath = import_file;
|
id->fullpath = import_file;
|
||||||
if (!try_add_import_path(p, import_file, file_str, ast_node_token(node).pos)) {
|
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
||||||
// gb_free(gb_heap_allocator(), import_file.text);
|
|
||||||
}
|
|
||||||
} else if (node->kind == AstNode_ForeignSystemLibrary) {
|
} else if (node->kind == AstNode_ForeignSystemLibrary) {
|
||||||
auto *id = &node->ForeignSystemLibrary;
|
auto *id = &node->ForeignSystemLibrary;
|
||||||
String file_str = id->filepath.string;
|
String file_str = id->filepath.string;
|
||||||
@@ -2862,13 +2904,11 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
|
|||||||
gb_array_append(p->imports, init_imported_file);
|
gb_array_append(p->imports, init_imported_file);
|
||||||
p->init_fullpath = init_fullpath;
|
p->init_fullpath = init_fullpath;
|
||||||
|
|
||||||
// {
|
{
|
||||||
// // IMPORTANT TODO(bill): Don't embed this, do it relative to the .exe
|
String s = get_fullpath_core(gb_heap_allocator(), make_string("runtime.odin"));
|
||||||
// char *path = gb_path_get_full_name(gb_heap_allocator(), "W:/Odin/core/__runtime.odin");
|
ImportedFile runtime_file = {s, s, init_pos};
|
||||||
// String s = make_string(path);
|
gb_array_append(p->imports, runtime_file);
|
||||||
// ImportedFile runtime_file = {s, s, init_pos};
|
}
|
||||||
// gb_array_append(p->imports, runtime_file);
|
|
||||||
// }
|
|
||||||
|
|
||||||
gb_for_array(i, p->imports) {
|
gb_for_array(i, p->imports) {
|
||||||
String import_path = p->imports[i].path;
|
String import_path = p->imports[i].path;
|
||||||
|
|||||||
+2
-1
@@ -13,8 +13,9 @@ typedef struct String {
|
|||||||
gb_inline String make_string(u8 *text, isize len) {
|
gb_inline String make_string(u8 *text, isize len) {
|
||||||
String s;
|
String s;
|
||||||
s.text = text;
|
s.text = text;
|
||||||
if (len < 0)
|
if (len < 0) {
|
||||||
len = gb_strlen(cast(char *)text);
|
len = gb_strlen(cast(char *)text);
|
||||||
|
}
|
||||||
s.len = len;
|
s.len = len;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
main :: proc(args: []string) -> i32 {
|
|
||||||
if args.count < 2 {
|
|
||||||
io.println("Please specify a .odin file");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for arg_index := 1; arg_index < args.count; arg_index++ {
|
|
||||||
arg := args[arg_index];
|
|
||||||
filename := arg;
|
|
||||||
ext := filepath.path_extension(filename);
|
|
||||||
if (ext != "odin") {
|
|
||||||
io.println("File is not a .odin file");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
output_name := filepath.change_extension(filename, "c");
|
|
||||||
|
|
||||||
parser: Parser;
|
|
||||||
err: Error;
|
|
||||||
parser, err = make_parser(filename);
|
|
||||||
if err {
|
|
||||||
handle_error();
|
|
||||||
}
|
|
||||||
defer destroy_parser(*parser);
|
|
||||||
|
|
||||||
root_node := parse_statement_list(*parser, null);
|
|
||||||
|
|
||||||
code_generator: CodeGenerator;
|
|
||||||
code_generator, err = make_code_generator(*parser, root);
|
|
||||||
if err {
|
|
||||||
handle_error();
|
|
||||||
}
|
|
||||||
defer destroy_code_generator(*code_generator);
|
|
||||||
|
|
||||||
output: File;
|
|
||||||
output, err = file_create(output_nameu);
|
|
||||||
if err {
|
|
||||||
handle_error();
|
|
||||||
}
|
|
||||||
defer file_close(*output);
|
|
||||||
|
|
||||||
convert_to_c_code(*code_generator, root, *output);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user